1 // Copyright (c) 2006-2008 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.
10 #include "testing/gtest/include/gtest/gtest.h"
13 using base::TimeDelta
;
14 using base::TimeTicks
;
18 class MockTimeTicks
: public TimeTicks
{
20 static DWORD
Ticker() {
21 return static_cast<int>(InterlockedIncrement(&ticker_
));
24 static void InstallTicker() {
25 old_tick_function_
= SetMockTickFunction(&Ticker
);
29 static void UninstallTicker() {
30 SetMockTickFunction(old_tick_function_
);
34 static volatile LONG ticker_
;
35 static TickFunctionType old_tick_function_
;
38 volatile LONG
MockTimeTicks::ticker_
;
39 MockTimeTicks::TickFunctionType
MockTimeTicks::old_tick_function_
;
41 HANDLE g_rollover_test_start
;
43 unsigned __stdcall
RolloverTestThreadMain(void* param
) {
44 int64 counter
= reinterpret_cast<int64
>(param
);
45 DWORD rv
= WaitForSingleObject(g_rollover_test_start
, INFINITE
);
46 EXPECT_EQ(rv
, WAIT_OBJECT_0
);
48 TimeTicks last
= TimeTicks::Now();
49 for (int index
= 0; index
< counter
; index
++) {
50 TimeTicks now
= TimeTicks::Now();
51 int64 milliseconds
= (now
- last
).InMilliseconds();
52 // This is a tight loop; we could have looped faster than our
53 // measurements, so the time might be 0 millis.
54 EXPECT_GE(milliseconds
, 0);
55 EXPECT_LT(milliseconds
, 250);
63 TEST(TimeTicks
, WinRollover
) {
64 // The internal counter rolls over at ~49days. We'll use a mock
65 // timer to test this case.
66 // Basic test algorithm:
67 // 1) Set clock to rollover - N
68 // 2) Create N threads
69 // 3) Start the threads
70 // 4) Each thread loops through TimeTicks() N times
71 // 5) Each thread verifies integrity of result.
73 const int kThreads
= 8;
74 // Use int64 so we can cast into a void* without a compiler warning.
75 const int64 kChecks
= 10;
77 // It takes a lot of iterations to reproduce the bug!
79 for (int loop
= 0; loop
< 4096; loop
++) {
81 MockTimeTicks::InstallTicker();
82 g_rollover_test_start
= CreateEvent(0, TRUE
, FALSE
, 0);
83 HANDLE threads
[kThreads
];
85 for (int index
= 0; index
< kThreads
; index
++) {
86 void* argument
= reinterpret_cast<void*>(kChecks
);
88 threads
[index
] = reinterpret_cast<HANDLE
>(
89 _beginthreadex(NULL
, 0, RolloverTestThreadMain
, argument
, 0,
91 EXPECT_NE((HANDLE
)NULL
, threads
[index
]);
95 SetEvent(g_rollover_test_start
);
97 // Wait for threads to finish
98 for (int index
= 0; index
< kThreads
; index
++) {
99 DWORD rv
= WaitForSingleObject(threads
[index
], INFINITE
);
100 EXPECT_EQ(rv
, WAIT_OBJECT_0
);
103 CloseHandle(g_rollover_test_start
);
106 MockTimeTicks::UninstallTicker();
110 TEST(TimeTicks
, SubMillisecondTimers
) {
111 // Loop for a bit getting timers quickly. We want to
112 // see at least one case where we get a new sample in
113 // less than one millisecond.
114 bool saw_submillisecond_timer
= false;
115 int64 min_timer
= 1000;
116 TimeTicks last_time
= TimeTicks::HighResNow();
117 for (int index
= 0; index
< 1000; index
++) {
118 TimeTicks now
= TimeTicks::HighResNow();
119 TimeDelta delta
= now
- last_time
;
120 if (delta
.InMicroseconds() > 0 &&
121 delta
.InMicroseconds() < 1000) {
122 if (min_timer
> delta
.InMicroseconds())
123 min_timer
= delta
.InMicroseconds();
124 saw_submillisecond_timer
= true;
128 EXPECT_TRUE(saw_submillisecond_timer
);
129 printf("Min timer is: %ldus\n", static_cast<long>(min_timer
));
132 TEST(TimeTicks
, TimeGetTimeCaps
) {
133 // Test some basic assumptions that we expect about how timeGetDevCaps works.
136 MMRESULT status
= timeGetDevCaps(&caps
, sizeof(caps
));
137 EXPECT_EQ(TIMERR_NOERROR
, status
);
138 if (status
!= TIMERR_NOERROR
) {
139 printf("Could not get timeGetDevCaps\n");
143 EXPECT_GE(static_cast<int>(caps
.wPeriodMin
), 1);
144 EXPECT_GT(static_cast<int>(caps
.wPeriodMax
), 1);
145 EXPECT_GE(static_cast<int>(caps
.wPeriodMin
), 1);
146 EXPECT_GT(static_cast<int>(caps
.wPeriodMax
), 1);
147 printf("timeGetTime range is %d to %dms\n", caps
.wPeriodMin
,
151 TEST(TimeTicks
, QueryPerformanceFrequency
) {
152 // Test some basic assumptions that we expect about QPC.
154 LARGE_INTEGER frequency
;
155 BOOL rv
= QueryPerformanceFrequency(&frequency
);
157 EXPECT_GT(frequency
.QuadPart
, 1000000); // Expect at least 1MHz
158 printf("QueryPerformanceFrequency is %5.2fMHz\n",
159 frequency
.QuadPart
/ 1000000.0);
162 TEST(TimeTicks
, TimerPerformance
) {
163 // Verify that various timer mechanisms can always complete quickly.
164 // Note: This is a somewhat arbitrary test.
165 const int kLoops
= 10000;
166 // Due to the fact that these run on bbots, which are horribly slow,
167 // we can't really make any guarantees about minimum runtime.
168 // Really, we want these to finish in ~10ms, and that is generous.
169 const int kMaxTime
= 35; // Maximum acceptible milliseconds for test.
171 typedef TimeTicks (*TestFunc
)();
176 // Cheating a bit here: assumes sizeof(TimeTicks) == sizeof(Time)
177 // in order to create a single test case list.
178 COMPILE_ASSERT(sizeof(TimeTicks
) == sizeof(Time
),
179 test_only_works_with_same_sizes
);
181 { reinterpret_cast<TestFunc
>(Time::Now
), "Time::Now" },
182 { TimeTicks::Now
, "TimeTicks::Now" },
183 { TimeTicks::HighResNow
, "TimeTicks::HighResNow" },
188 while (cases
[test_case
].func
) {
189 TimeTicks start
= TimeTicks::HighResNow();
190 for (int index
= 0; index
< kLoops
; index
++)
191 cases
[test_case
].func();
192 TimeTicks stop
= TimeTicks::HighResNow();
193 // Turning off the check for acceptible delays. Without this check,
194 // the test really doesn't do much other than measure. But the
195 // measurements are still useful for testing timers on various platforms.
196 // The reason to remove the check is because the tests run on many
197 // buildbots, some of which are VMs. These machines can run horribly
198 // slow, and there is really no value for checking against a max timer.
199 //EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
200 printf("%s: %1.2fus per call\n", cases
[test_case
].description
,
201 (stop
- start
).InMillisecondsF() * 1000 / kLoops
);