1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <string> 6 7 #include "base/strings/string_number_conversions.h" 8 #include "base/time/time.h" 9 #include "chrome/browser/performance_monitor/metric.h" 10 #include "chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 namespace performance_monitor { 14 15 class PerformanceMonitorUtilTest : public ::testing::Test { 16 protected: 17 // Helper method in order to access the otherwise-private AggregateInterval 18 // method within the aggregation classes, so that we can test specific 19 // aggregation methods without the extra burden of interval separation (which 20 // is tested separately). 21 scoped_ptr<Database::MetricVector> AggregateSingleInterval( 22 MetricType type, 23 const Database::MetricVector* metrics, 24 const base::Time& start, 25 const base::TimeDelta& resolution, 26 AggregationMethod method) { 27 const base::Time kMaxTime = base::Time::FromDoubleT(100); 28 Database::MetricVector::const_iterator metric = metrics->begin(); 29 while (metric != metrics->end() && metric->time < start) 30 ++metric; 31 32 scoped_ptr<Aggregator> aggregator; 33 switch (method) { 34 case AGGREGATION_METHOD_NONE: 35 aggregator.reset(new NoAggregation()); 36 break; 37 case AGGREGATION_METHOD_MEDIAN: 38 aggregator.reset(new MedianAggregation()); 39 break; 40 case AGGREGATION_METHOD_MEAN: 41 aggregator.reset(new MeanAggregation()); 42 break; 43 default: 44 NOTREACHED(); 45 return scoped_ptr<Database::MetricVector>(); 46 } 47 return aggregator->AggregateInterval( 48 type, &metric, metrics->end(), start, kMaxTime, resolution); 49 } 50 }; 51 52 TEST_F(PerformanceMonitorUtilTest, AggregateMetricEmptyTest) { 53 Database::MetricVector metric_vector; 54 const base::Time data_time = base::Time::FromDoubleT(1); 55 metric_vector.push_back(Metric(METRIC_CPU_USAGE, data_time, 1)); 56 57 const base::Time results_time = base::Time::FromDoubleT(3); 58 const base::TimeDelta resolution = base::TimeDelta::FromSeconds(1); 59 scoped_ptr<Database::MetricVector> aggregated_metric = 60 AggregateSingleInterval(METRIC_CPU_USAGE, 61 &metric_vector, 62 results_time, 63 resolution, 64 AGGREGATION_METHOD_MEAN); 65 ASSERT_EQ(0u, aggregated_metric->size()); 66 aggregated_metric = AggregateSingleInterval(METRIC_CPU_USAGE, 67 &metric_vector, 68 results_time, 69 resolution, 70 AGGREGATION_METHOD_MEDIAN); 71 ASSERT_EQ(0u, aggregated_metric->size()); 72 } 73 74 TEST_F(PerformanceMonitorUtilTest, AggregateMetricSimpleTest) { 75 const base::Time data_time = base::Time::FromDoubleT(2); 76 const base::Time results_time = base::Time::FromDoubleT(1); 77 const base::TimeDelta results_resolution = base::TimeDelta::FromSeconds(2); 78 79 const double value = 3.14; 80 Database::MetricVector metric_vector; 81 metric_vector.push_back(Metric(METRIC_CPU_USAGE, data_time, value)); 82 Database::MetricVector aggregated_metric = 83 *AggregateSingleInterval(METRIC_CPU_USAGE, 84 &metric_vector, 85 results_time, 86 results_resolution, 87 AGGREGATION_METHOD_MEAN); 88 89 ASSERT_EQ(1u, aggregated_metric.size()); 90 EXPECT_EQ(results_time + results_resolution, aggregated_metric[0].time); 91 EXPECT_EQ(value, aggregated_metric[0].value); 92 93 aggregated_metric = *AggregateSingleInterval(METRIC_CPU_USAGE, 94 &metric_vector, 95 results_time, 96 results_resolution, 97 AGGREGATION_METHOD_MEDIAN); 98 ASSERT_EQ(1u, aggregated_metric.size()); 99 EXPECT_EQ(results_time + results_resolution, aggregated_metric[0].time); 100 EXPECT_EQ(value, aggregated_metric[0].value); 101 } 102 103 TEST_F(PerformanceMonitorUtilTest, AggregateMetricDenseTest) { 104 base::Time current_data_time = base::Time::FromDoubleT(2); 105 const base::TimeDelta data_resolution = base::TimeDelta::FromSeconds(1); 106 const base::Time results_time = base::Time::FromDoubleT(6); 107 const base::TimeDelta results_resolution = base::TimeDelta::FromSeconds(4); 108 double current_value = 1; 109 int num_points = 12; 110 Database::MetricVector metric_vector; 111 112 for (int i = 0; i < num_points; ++i) { 113 metric_vector.push_back(Metric(METRIC_CPU_USAGE, 114 current_data_time, 115 current_value)); 116 current_value *= 2; 117 current_data_time += data_resolution; 118 } 119 Database::MetricVector aggregated_metric = 120 *AggregateSingleInterval(METRIC_CPU_USAGE, 121 &metric_vector, 122 results_time, 123 results_resolution, 124 AGGREGATION_METHOD_MEAN); 125 // The first 4 points get ignored because they are before the start time. 126 // The remaining 8 points are aggregated into two data points. 127 ASSERT_EQ(2u, aggregated_metric.size()); 128 EXPECT_EQ(results_time + results_resolution, aggregated_metric[0].time); 129 EXPECT_DOUBLE_EQ((32 + 64 + 128 + 256) / 4.0, aggregated_metric[0].value); 130 EXPECT_EQ(results_time + (2 * results_resolution), 131 aggregated_metric[1].time); 132 // Since we don't have data for the time of 14, we stretch out the 2048. 133 EXPECT_DOUBLE_EQ((512 + 1024 + 2048 + 2048) / 4.0, 134 aggregated_metric[1].value); 135 136 aggregated_metric = *AggregateSingleInterval(METRIC_CPU_USAGE, 137 &metric_vector, 138 results_time, 139 results_resolution, 140 AGGREGATION_METHOD_MEDIAN); 141 ASSERT_EQ(2u, aggregated_metric.size()); 142 EXPECT_EQ(results_time + results_resolution, aggregated_metric[0].time); 143 EXPECT_EQ(results_time + 2 * results_resolution, 144 aggregated_metric[1].time); 145 EXPECT_EQ(48, aggregated_metric[0].value); 146 EXPECT_EQ(768, aggregated_metric[1].value); 147 } 148 149 TEST_F(PerformanceMonitorUtilTest, AggregateMetricSparseTest) { 150 Database::MetricVector metric_vector; 151 152 const base::Time data_time1 = base::Time::FromDoubleT(20); 153 const double value1 = 3.14; 154 metric_vector.push_back(Metric(METRIC_CPU_USAGE, data_time1, value1)); 155 const base::Time data_time2 = base::Time::FromDoubleT(40); 156 const double value2 = 6.28; 157 metric_vector.push_back(Metric(METRIC_CPU_USAGE, data_time2, value2)); 158 const base::Time data_time3 = base::Time::FromDoubleT(60); 159 const double value3 = 9.42; 160 metric_vector.push_back(Metric(METRIC_CPU_USAGE, data_time3, value3)); 161 162 const base::Time results_time = base::Time::FromDoubleT(19); 163 const base::TimeDelta results_resolution = base::TimeDelta::FromSeconds(2); 164 Database::MetricVector aggregated_metric = 165 *AggregateSingleInterval(METRIC_CPU_USAGE, 166 &metric_vector, 167 results_time, 168 results_resolution, 169 AGGREGATION_METHOD_MEAN); 170 171 // The first aggregation point is split between the first value and the second 172 // value. The second is split between the second and third. The third doesn't 173 // have any data after it so the aggregation is the same value. 174 ASSERT_EQ(3u, aggregated_metric.size()); 175 EXPECT_EQ(results_time + 1 * results_resolution, 176 aggregated_metric[0].time); 177 EXPECT_EQ((value1 + value2) / 2, aggregated_metric[0].value); 178 EXPECT_EQ(results_time + 11 * results_resolution, 179 aggregated_metric[1].time); 180 EXPECT_EQ((value2 + value3) / 2, aggregated_metric[1].value); 181 EXPECT_EQ(results_time + 21 * results_resolution, 182 aggregated_metric[2].time); 183 EXPECT_EQ(value3, aggregated_metric[2].value); 184 185 // For median values, we go from [start, end). Thus, since each of these are 186 // one window apart, each value will have it's own window. 187 aggregated_metric = *AggregateSingleInterval(METRIC_CPU_USAGE, 188 &metric_vector, 189 results_time, 190 results_resolution, 191 AGGREGATION_METHOD_MEDIAN); 192 ASSERT_EQ(3u, aggregated_metric.size()); 193 EXPECT_EQ(results_time + 1 * results_resolution, 194 aggregated_metric[0].time); 195 EXPECT_EQ(value1, aggregated_metric[0].value); 196 EXPECT_EQ(results_time + 11 * results_resolution, 197 aggregated_metric[1].time); 198 EXPECT_EQ(value2, aggregated_metric[1].value); 199 EXPECT_EQ(results_time + 21 * results_resolution, 200 aggregated_metric[2].time); 201 EXPECT_EQ(value3, aggregated_metric[2].value); 202 } 203 204 TEST_F(PerformanceMonitorUtilTest, AggregateMetricMultipleIntervals) { 205 base::Time current_data_time = base::Time::FromDoubleT(1); 206 Database::MetricVector metric_vector; 207 208 const int kNumMetrics = 20; 209 for (int i = 0; i < kNumMetrics; ++i) { 210 metric_vector.push_back(Metric(METRIC_CPU_USAGE, 211 current_data_time, 212 i + 1)); 213 current_data_time += base::TimeDelta::FromSeconds(1); 214 } 215 216 std::vector<TimeRange> time_ranges; 217 time_ranges.push_back(TimeRange(base::Time::FromDoubleT(2), 218 base::Time::FromDoubleT(10))); 219 time_ranges.push_back(TimeRange(base::Time::FromDoubleT(12), 220 base::Time::FromDoubleT(22))); 221 222 std::vector<Database::MetricVector> results = 223 *AggregateMetric(METRIC_CPU_USAGE, 224 &metric_vector, 225 base::Time::FromDoubleT(2), 226 time_ranges, 227 base::TimeDelta::FromSeconds(1), 228 AGGREGATION_METHOD_NONE); 229 230 ASSERT_EQ(2u, results.size()); 231 Database::MetricVector metric_series = results[0]; 232 ASSERT_EQ(9u, metric_series.size()); 233 double expected = 2; 234 for (Database::MetricVector::const_iterator iter = metric_series.begin(); 235 iter != metric_series.end(); ++iter) { 236 EXPECT_EQ(expected, iter->value); 237 EXPECT_EQ(base::Time::FromDoubleT(expected), iter->time); 238 ++expected; 239 } 240 241 metric_series = results[1]; 242 ASSERT_EQ(9u, metric_series.size()); 243 expected = 12; 244 for (Database::MetricVector::const_iterator iter = metric_series.begin(); 245 iter != metric_series.end(); ++iter) { 246 EXPECT_EQ(expected, iter->value); 247 EXPECT_EQ(base::Time::FromDoubleT(expected), iter->time); 248 ++expected; 249 } 250 } 251 252 } // namespace performance_monitor 253