1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21#include <memory>
22
23#include "metrics/metrics_library_mock.h"
24#include "metrics/timer.h"
25#include "metrics/timer_mock.h"
26
27using ::testing::_;
28using ::testing::Return;
29
30namespace chromeos_metrics {
31
32namespace {
33const int64_t kStime1MSec = 1400;
34const int64_t kEtime1MSec = 3000;
35const int64_t kDelta1MSec = 1600;
36
37const int64_t kStime2MSec = 4200;
38const int64_t kEtime2MSec = 5000;
39const int64_t kDelta2MSec = 800;
40
41const int64_t kStime3MSec = 6600;
42const int64_t kEtime3MSec = 6800;
43const int64_t kDelta3MSec = 200;
44}  // namespace
45
46class TimerTest : public testing::Test {
47 public:
48  TimerTest() : clock_wrapper_mock_(new ClockWrapperMock()) {}
49
50 protected:
51  virtual void SetUp() {
52    EXPECT_EQ(Timer::kTimerStopped, timer_.timer_state_);
53    stime += base::TimeDelta::FromMilliseconds(kStime1MSec);
54    etime += base::TimeDelta::FromMilliseconds(kEtime1MSec);
55    stime2 += base::TimeDelta::FromMilliseconds(kStime2MSec);
56    etime2 += base::TimeDelta::FromMilliseconds(kEtime2MSec);
57    stime3 += base::TimeDelta::FromMilliseconds(kStime3MSec);
58    etime3 += base::TimeDelta::FromMilliseconds(kEtime3MSec);
59  }
60
61  virtual void TearDown() {}
62
63  Timer timer_;
64  std::unique_ptr<ClockWrapperMock> clock_wrapper_mock_;
65  base::TimeTicks stime, etime, stime2, etime2, stime3, etime3;
66};
67
68TEST_F(TimerTest, StartStop) {
69  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
70      .WillOnce(Return(stime))
71      .WillOnce(Return(etime));
72  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
73  ASSERT_TRUE(timer_.Start());
74  ASSERT_TRUE(timer_.start_time_ == stime);
75  ASSERT_TRUE(timer_.HasStarted());
76  ASSERT_TRUE(timer_.Stop());
77  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
78
79  base::TimeDelta elapsed_time;
80  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
81  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
82            elapsed_time.InMilliseconds());
83
84  ASSERT_FALSE(timer_.HasStarted());
85}
86
87TEST_F(TimerTest, ReStart) {
88  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
89      .WillOnce(Return(stime))
90      .WillOnce(Return(etime));
91  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
92  timer_.Start();
93  base::TimeTicks buffer = timer_.start_time_;
94  timer_.Start();
95  ASSERT_FALSE(timer_.start_time_ == buffer);
96}
97
98TEST_F(TimerTest, Reset) {
99  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
100      .WillOnce(Return(stime));
101  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
102  timer_.Start();
103  ASSERT_TRUE(timer_.Reset());
104  ASSERT_FALSE(timer_.HasStarted());
105}
106
107TEST_F(TimerTest, SeparatedTimers) {
108  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
109      .WillOnce(Return(stime))
110      .WillOnce(Return(etime))
111      .WillOnce(Return(stime2))
112      .WillOnce(Return(etime2));
113  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
114  ASSERT_TRUE(timer_.Start());
115  ASSERT_TRUE(timer_.Stop());
116  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
117  ASSERT_TRUE(timer_.Start());
118  ASSERT_TRUE(timer_.start_time_ == stime2);
119  ASSERT_TRUE(timer_.Stop());
120  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
121  ASSERT_FALSE(timer_.HasStarted());
122
123  base::TimeDelta elapsed_time;
124  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
125  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
126            elapsed_time.InMilliseconds());
127}
128
129TEST_F(TimerTest, InvalidStop) {
130  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
131      .WillOnce(Return(stime))
132      .WillOnce(Return(etime));
133  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
134  ASSERT_FALSE(timer_.Stop());
135  // Now we try it again, but after a valid start/stop.
136  timer_.Start();
137  timer_.Stop();
138  base::TimeDelta elapsed_time = timer_.elapsed_time_;
139  ASSERT_FALSE(timer_.Stop());
140  ASSERT_TRUE(elapsed_time == timer_.elapsed_time_);
141}
142
143TEST_F(TimerTest, InvalidElapsedTime) {
144  base::TimeDelta elapsed_time;
145  ASSERT_FALSE(timer_.GetElapsedTime(&elapsed_time));
146}
147
148TEST_F(TimerTest, PauseStartStopResume) {
149  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
150      .WillOnce(Return(stime))
151      .WillOnce(Return(stime2))
152      .WillOnce(Return(etime2))
153      .WillOnce(Return(stime3))
154      .WillOnce(Return(etime3));
155  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
156  ASSERT_TRUE(timer_.Pause());  // Starts timer paused.
157  ASSERT_TRUE(timer_.start_time_ == stime);
158  ASSERT_TRUE(timer_.HasStarted());
159
160  ASSERT_TRUE(timer_.Start());  // Restarts timer.
161  ASSERT_TRUE(timer_.start_time_ == stime2);
162  ASSERT_TRUE(timer_.HasStarted());
163
164  ASSERT_TRUE(timer_.Stop());
165  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
166  ASSERT_FALSE(timer_.HasStarted());
167  base::TimeDelta elapsed_time;
168  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
169  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
170            elapsed_time.InMilliseconds());
171
172  ASSERT_TRUE(timer_.Resume());
173  ASSERT_TRUE(timer_.HasStarted());
174  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
175  ASSERT_EQ(kDelta3MSec, elapsed_time.InMilliseconds());
176}
177
178TEST_F(TimerTest, ResumeStartStopPause) {
179  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
180      .WillOnce(Return(stime))
181      .WillOnce(Return(stime2))
182      .WillOnce(Return(etime2))
183      .WillOnce(Return(stime3));
184  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
185  ASSERT_TRUE(timer_.Resume());
186  ASSERT_TRUE(timer_.start_time_ == stime);
187  ASSERT_TRUE(timer_.HasStarted());
188
189  ASSERT_TRUE(timer_.Start());
190  ASSERT_TRUE(timer_.start_time_ == stime2);
191  ASSERT_TRUE(timer_.HasStarted());
192
193  ASSERT_TRUE(timer_.Stop());
194  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
195  ASSERT_FALSE(timer_.HasStarted());
196  base::TimeDelta elapsed_time;
197  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
198  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
199            elapsed_time.InMilliseconds());
200
201  ASSERT_TRUE(timer_.Pause());
202  ASSERT_TRUE(timer_.HasStarted());
203  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
204  ASSERT_EQ(0, elapsed_time.InMilliseconds());
205}
206
207TEST_F(TimerTest, StartResumeStop) {
208  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
209      .WillOnce(Return(stime))
210      .WillOnce(Return(etime));
211  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
212  ASSERT_TRUE(timer_.Start());
213  ASSERT_TRUE(timer_.start_time_ == stime);
214  ASSERT_TRUE(timer_.HasStarted());
215
216  ASSERT_FALSE(timer_.Resume());
217  ASSERT_TRUE(timer_.start_time_ == stime);
218  ASSERT_TRUE(timer_.HasStarted());
219
220  ASSERT_TRUE(timer_.Stop());
221  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
222  ASSERT_FALSE(timer_.HasStarted());
223  base::TimeDelta elapsed_time;
224  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
225  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
226            elapsed_time.InMilliseconds());
227}
228
229TEST_F(TimerTest, StartPauseStop) {
230  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
231      .WillOnce(Return(stime))
232      .WillOnce(Return(etime));
233  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
234  ASSERT_TRUE(timer_.Start());
235  ASSERT_TRUE(timer_.start_time_ == stime);
236  ASSERT_TRUE(timer_.HasStarted());
237
238  ASSERT_TRUE(timer_.Pause());
239  ASSERT_TRUE(timer_.HasStarted());
240  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
241  base::TimeDelta elapsed_time;
242  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
243  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
244            elapsed_time.InMilliseconds());
245
246  ASSERT_TRUE(timer_.Stop());
247  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
248  ASSERT_FALSE(timer_.HasStarted());
249  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
250  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
251            elapsed_time.InMilliseconds());
252}
253
254TEST_F(TimerTest, StartPauseResumeStop) {
255  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
256      .WillOnce(Return(stime))
257      .WillOnce(Return(etime))
258      .WillOnce(Return(stime2))
259      .WillOnce(Return(etime2));
260  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
261  ASSERT_TRUE(timer_.Start());
262  ASSERT_TRUE(timer_.start_time_ == stime);
263  ASSERT_TRUE(timer_.HasStarted());
264
265  ASSERT_TRUE(timer_.Pause());
266  ASSERT_TRUE(timer_.HasStarted());
267  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
268  base::TimeDelta elapsed_time;
269  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
270  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
271            elapsed_time.InMilliseconds());
272
273  ASSERT_TRUE(timer_.Resume());
274  ASSERT_TRUE(timer_.HasStarted());
275
276  ASSERT_TRUE(timer_.Stop());
277  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec + kDelta2MSec);
278  ASSERT_FALSE(timer_.HasStarted());
279  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
280  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
281            elapsed_time.InMilliseconds());
282}
283
284TEST_F(TimerTest, PauseStop) {
285  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
286      .WillOnce(Return(stime));
287  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
288  ASSERT_TRUE(timer_.Pause());
289  ASSERT_TRUE(timer_.start_time_ == stime);
290  ASSERT_TRUE(timer_.HasStarted());
291  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), 0);
292
293  ASSERT_TRUE(timer_.Stop());
294  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), 0);
295  ASSERT_FALSE(timer_.HasStarted());
296  base::TimeDelta elapsed_time;
297  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
298  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
299            elapsed_time.InMilliseconds());
300}
301
302TEST_F(TimerTest, PauseResumeStop) {
303  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
304      .WillOnce(Return(stime))
305      .WillOnce(Return(stime2))
306      .WillOnce(Return(etime2));
307  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
308  ASSERT_TRUE(timer_.Pause());
309  ASSERT_TRUE(timer_.start_time_ == stime);
310  ASSERT_TRUE(timer_.HasStarted());
311
312  ASSERT_TRUE(timer_.Resume());
313  ASSERT_TRUE(timer_.HasStarted());
314
315  ASSERT_TRUE(timer_.Stop());
316  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
317  ASSERT_FALSE(timer_.HasStarted());
318  base::TimeDelta elapsed_time;
319  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
320  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
321            elapsed_time.InMilliseconds());
322}
323
324TEST_F(TimerTest, StartPauseResumePauseStop) {
325  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
326      .WillOnce(Return(stime))
327      .WillOnce(Return(etime))
328      .WillOnce(Return(stime2))
329      .WillOnce(Return(stime3))
330      .WillOnce(Return(etime3));
331  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
332  ASSERT_TRUE(timer_.Start());
333  ASSERT_TRUE(timer_.start_time_ == stime);
334  ASSERT_TRUE(timer_.HasStarted());
335
336  ASSERT_TRUE(timer_.Pause());
337  ASSERT_TRUE(timer_.HasStarted());
338  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
339  base::TimeDelta elapsed_time;
340  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
341  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
342            elapsed_time.InMilliseconds());
343
344  ASSERT_TRUE(timer_.Resume());
345  ASSERT_TRUE(timer_.HasStarted());
346  // Make sure GetElapsedTime works while we're running.
347  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
348  ASSERT_EQ(kDelta1MSec + kStime3MSec - kStime2MSec,
349            elapsed_time.InMilliseconds());
350
351  ASSERT_TRUE(timer_.Pause());
352  ASSERT_TRUE(timer_.HasStarted());
353  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
354            kDelta1MSec + kEtime3MSec - kStime2MSec);
355  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
356  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
357            elapsed_time.InMilliseconds());
358
359  ASSERT_TRUE(timer_.Stop());
360  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
361            kDelta1MSec + kEtime3MSec - kStime2MSec);
362  ASSERT_FALSE(timer_.HasStarted());
363  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
364  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
365            elapsed_time.InMilliseconds());
366}
367
368TEST_F(TimerTest, StartPauseResumePauseResumeStop) {
369  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
370      .WillOnce(Return(stime))
371      .WillOnce(Return(etime))
372      .WillOnce(Return(stime2))
373      .WillOnce(Return(etime2))
374      .WillOnce(Return(stime3))
375      .WillOnce(Return(etime3));
376  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
377  ASSERT_TRUE(timer_.Start());
378  ASSERT_TRUE(timer_.start_time_ == stime);
379  ASSERT_TRUE(timer_.HasStarted());
380
381  ASSERT_TRUE(timer_.Pause());
382  ASSERT_TRUE(timer_.HasStarted());
383  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
384  base::TimeDelta elapsed_time;
385  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
386  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
387            elapsed_time.InMilliseconds());
388
389  ASSERT_TRUE(timer_.Resume());
390  ASSERT_TRUE(timer_.HasStarted());
391
392  ASSERT_TRUE(timer_.Pause());
393  ASSERT_TRUE(timer_.HasStarted());
394  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec + kDelta2MSec);
395  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
396  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
397            elapsed_time.InMilliseconds());
398
399  ASSERT_TRUE(timer_.Resume());
400  ASSERT_TRUE(timer_.HasStarted());
401
402  ASSERT_TRUE(timer_.Stop());
403  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
404            kDelta1MSec + kDelta2MSec + kDelta3MSec);
405  ASSERT_FALSE(timer_.HasStarted());
406  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
407  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
408            elapsed_time.InMilliseconds());
409}
410
411static const char kMetricName[] = "test-timer";
412static const int kMinSample = 0;
413static const int kMaxSample = 120 * 1E6;
414static const int kNumBuckets = 50;
415
416class TimerReporterTest : public testing::Test {
417 public:
418  TimerReporterTest() : timer_reporter_(kMetricName, kMinSample, kMaxSample,
419                                        kNumBuckets),
420                        clock_wrapper_mock_(new ClockWrapperMock()) {}
421
422 protected:
423  virtual void SetUp() {
424    timer_reporter_.set_metrics_lib(&lib_);
425    EXPECT_EQ(timer_reporter_.histogram_name_, kMetricName);
426    EXPECT_EQ(timer_reporter_.min_, kMinSample);
427    EXPECT_EQ(timer_reporter_.max_, kMaxSample);
428    EXPECT_EQ(timer_reporter_.num_buckets_, kNumBuckets);
429    stime += base::TimeDelta::FromMilliseconds(kStime1MSec);
430    etime += base::TimeDelta::FromMilliseconds(kEtime1MSec);
431  }
432
433  virtual void TearDown() {
434    timer_reporter_.set_metrics_lib(nullptr);
435  }
436
437  TimerReporter timer_reporter_;
438  MetricsLibraryMock lib_;
439  std::unique_ptr<ClockWrapperMock> clock_wrapper_mock_;
440  base::TimeTicks stime, etime;
441};
442
443TEST_F(TimerReporterTest, StartStopReport) {
444  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
445      .WillOnce(Return(stime))
446      .WillOnce(Return(etime));
447  timer_reporter_.clock_wrapper_.reset(clock_wrapper_mock_.release());
448  EXPECT_CALL(lib_, SendToUMA(kMetricName, kDelta1MSec, kMinSample, kMaxSample,
449                              kNumBuckets)).WillOnce(Return(true));
450  ASSERT_TRUE(timer_reporter_.Start());
451  ASSERT_TRUE(timer_reporter_.Stop());
452  ASSERT_TRUE(timer_reporter_.ReportMilliseconds());
453}
454
455TEST_F(TimerReporterTest, InvalidReport) {
456  ASSERT_FALSE(timer_reporter_.ReportMilliseconds());
457}
458
459}  // namespace chromeos_metrics
460
461int main(int argc, char **argv) {
462  testing::InitGoogleTest(&argc, argv);
463  return RUN_ALL_TESTS();
464}
465