1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <windows.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <mmsystem.h>
10*6777b538SAndroid Build Coastguard Worker #include <process.h>
11*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
12*6777b538SAndroid Build Coastguard Worker #include <windows.foundation.h>
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker #include <algorithm>
15*6777b538SAndroid Build Coastguard Worker #include <cmath>
16*6777b538SAndroid Build Coastguard Worker #include <limits>
17*6777b538SAndroid Build Coastguard Worker #include <vector>
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/win/registry.h"
22*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
23*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker namespace base {
26*6777b538SAndroid Build Coastguard Worker namespace {
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker // For TimeDelta::ConstexprInitialization
29*6777b538SAndroid Build Coastguard Worker constexpr int kExpectedDeltaInMilliseconds = 10;
30*6777b538SAndroid Build Coastguard Worker constexpr TimeDelta kConstexprTimeDelta =
31*6777b538SAndroid Build Coastguard Worker Milliseconds(kExpectedDeltaInMilliseconds);
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker class MockTimeTicks : public TimeTicks {
34*6777b538SAndroid Build Coastguard Worker public:
Ticker()35*6777b538SAndroid Build Coastguard Worker static DWORD Ticker() {
36*6777b538SAndroid Build Coastguard Worker return static_cast<int>(InterlockedIncrement(&ticker_));
37*6777b538SAndroid Build Coastguard Worker }
38*6777b538SAndroid Build Coastguard Worker
InstallTicker()39*6777b538SAndroid Build Coastguard Worker static void InstallTicker() {
40*6777b538SAndroid Build Coastguard Worker old_tick_function_ = SetMockTickFunction(&Ticker);
41*6777b538SAndroid Build Coastguard Worker ticker_ = -5;
42*6777b538SAndroid Build Coastguard Worker }
43*6777b538SAndroid Build Coastguard Worker
UninstallTicker()44*6777b538SAndroid Build Coastguard Worker static void UninstallTicker() { SetMockTickFunction(old_tick_function_); }
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker private:
47*6777b538SAndroid Build Coastguard Worker static volatile LONG ticker_;
48*6777b538SAndroid Build Coastguard Worker static TickFunctionType old_tick_function_;
49*6777b538SAndroid Build Coastguard Worker };
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker volatile LONG MockTimeTicks::ticker_;
52*6777b538SAndroid Build Coastguard Worker MockTimeTicks::TickFunctionType MockTimeTicks::old_tick_function_;
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker HANDLE g_rollover_test_start;
55*6777b538SAndroid Build Coastguard Worker
RolloverTestThreadMain(void * param)56*6777b538SAndroid Build Coastguard Worker unsigned __stdcall RolloverTestThreadMain(void* param) {
57*6777b538SAndroid Build Coastguard Worker int64_t counter = reinterpret_cast<int64_t>(param);
58*6777b538SAndroid Build Coastguard Worker DWORD rv = WaitForSingleObject(g_rollover_test_start, INFINITE);
59*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(rv, WAIT_OBJECT_0);
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker TimeTicks last = TimeTicks::Now();
62*6777b538SAndroid Build Coastguard Worker for (int index = 0; index < counter; index++) {
63*6777b538SAndroid Build Coastguard Worker TimeTicks now = TimeTicks::Now();
64*6777b538SAndroid Build Coastguard Worker int64_t milliseconds = (now - last).InMilliseconds();
65*6777b538SAndroid Build Coastguard Worker // This is a tight loop; we could have looped faster than our
66*6777b538SAndroid Build Coastguard Worker // measurements, so the time might be 0 millis.
67*6777b538SAndroid Build Coastguard Worker EXPECT_GE(milliseconds, 0);
68*6777b538SAndroid Build Coastguard Worker EXPECT_LT(milliseconds, 250);
69*6777b538SAndroid Build Coastguard Worker last = now;
70*6777b538SAndroid Build Coastguard Worker }
71*6777b538SAndroid Build Coastguard Worker return 0;
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker #if defined(_M_ARM64) && defined(__clang__)
75*6777b538SAndroid Build Coastguard Worker #define ReadCycleCounter() _ReadStatusReg(ARM64_PMCCNTR_EL0)
76*6777b538SAndroid Build Coastguard Worker #else
77*6777b538SAndroid Build Coastguard Worker #define ReadCycleCounter() __rdtsc()
78*6777b538SAndroid Build Coastguard Worker #endif
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker // Measure the performance of the CPU cycle counter so that we can compare it to
81*6777b538SAndroid Build Coastguard Worker // the overhead of QueryPerformanceCounter. A hard-coded frequency is used
82*6777b538SAndroid Build Coastguard Worker // because we don't care about the accuracy of the results, we just need to do
83*6777b538SAndroid Build Coastguard Worker // the work. The amount of work is not exactly the same as in TimeTicks::Now
84*6777b538SAndroid Build Coastguard Worker // (some steps are skipped) but that doesn't seem to materially affect the
85*6777b538SAndroid Build Coastguard Worker // results.
GetTSC()86*6777b538SAndroid Build Coastguard Worker TimeTicks GetTSC() {
87*6777b538SAndroid Build Coastguard Worker // Using a fake cycle counter frequency for test purposes.
88*6777b538SAndroid Build Coastguard Worker return TimeTicks() + Microseconds(ReadCycleCounter() *
89*6777b538SAndroid Build Coastguard Worker Time::kMicrosecondsPerSecond / 10000000);
90*6777b538SAndroid Build Coastguard Worker }
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker } // namespace
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker // This test spawns many threads, and can occasionally fail due to resource
95*6777b538SAndroid Build Coastguard Worker // exhaustion in the presence of ASan.
96*6777b538SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
97*6777b538SAndroid Build Coastguard Worker #define MAYBE_WinRollover DISABLED_WinRollover
98*6777b538SAndroid Build Coastguard Worker #else
99*6777b538SAndroid Build Coastguard Worker #define MAYBE_WinRollover WinRollover
100*6777b538SAndroid Build Coastguard Worker #endif
TEST(TimeTicks,MAYBE_WinRollover)101*6777b538SAndroid Build Coastguard Worker TEST(TimeTicks, MAYBE_WinRollover) {
102*6777b538SAndroid Build Coastguard Worker // The internal counter rolls over at ~49days. We'll use a mock
103*6777b538SAndroid Build Coastguard Worker // timer to test this case.
104*6777b538SAndroid Build Coastguard Worker // Basic test algorithm:
105*6777b538SAndroid Build Coastguard Worker // 1) Set clock to rollover - N
106*6777b538SAndroid Build Coastguard Worker // 2) Create N threads
107*6777b538SAndroid Build Coastguard Worker // 3) Start the threads
108*6777b538SAndroid Build Coastguard Worker // 4) Each thread loops through TimeTicks() N times
109*6777b538SAndroid Build Coastguard Worker // 5) Each thread verifies integrity of result.
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker const int kThreads = 8;
112*6777b538SAndroid Build Coastguard Worker // Use int64_t so we can cast into a void* without a compiler warning.
113*6777b538SAndroid Build Coastguard Worker const int64_t kChecks = 10;
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker // It takes a lot of iterations to reproduce the bug!
116*6777b538SAndroid Build Coastguard Worker // (See bug 1081395)
117*6777b538SAndroid Build Coastguard Worker for (int loop = 0; loop < 4096; loop++) {
118*6777b538SAndroid Build Coastguard Worker // Setup
119*6777b538SAndroid Build Coastguard Worker MockTimeTicks::InstallTicker();
120*6777b538SAndroid Build Coastguard Worker g_rollover_test_start = CreateEvent(0, TRUE, FALSE, 0);
121*6777b538SAndroid Build Coastguard Worker HANDLE threads[kThreads];
122*6777b538SAndroid Build Coastguard Worker
123*6777b538SAndroid Build Coastguard Worker for (int index = 0; index < kThreads; index++) {
124*6777b538SAndroid Build Coastguard Worker void* argument = reinterpret_cast<void*>(kChecks);
125*6777b538SAndroid Build Coastguard Worker unsigned thread_id;
126*6777b538SAndroid Build Coastguard Worker threads[index] = reinterpret_cast<HANDLE>(_beginthreadex(
127*6777b538SAndroid Build Coastguard Worker NULL, 0, RolloverTestThreadMain, argument, 0, &thread_id));
128*6777b538SAndroid Build Coastguard Worker EXPECT_NE((HANDLE)NULL, threads[index]);
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker // Start!
132*6777b538SAndroid Build Coastguard Worker SetEvent(g_rollover_test_start);
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker // Wait for threads to finish
135*6777b538SAndroid Build Coastguard Worker for (int index = 0; index < kThreads; index++) {
136*6777b538SAndroid Build Coastguard Worker DWORD rv = WaitForSingleObject(threads[index], INFINITE);
137*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(rv, WAIT_OBJECT_0);
138*6777b538SAndroid Build Coastguard Worker // Since using _beginthreadex() (as opposed to _beginthread),
139*6777b538SAndroid Build Coastguard Worker // an explicit CloseHandle() is supposed to be called.
140*6777b538SAndroid Build Coastguard Worker CloseHandle(threads[index]);
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker CloseHandle(g_rollover_test_start);
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker // Teardown
146*6777b538SAndroid Build Coastguard Worker MockTimeTicks::UninstallTicker();
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker
TEST(TimeTicks,SubMillisecondTimers)150*6777b538SAndroid Build Coastguard Worker TEST(TimeTicks, SubMillisecondTimers) {
151*6777b538SAndroid Build Coastguard Worker // IsHighResolution() is false on some systems. Since the product still works
152*6777b538SAndroid Build Coastguard Worker // even if it's false, it makes this entire test questionable.
153*6777b538SAndroid Build Coastguard Worker if (!TimeTicks::IsHighResolution())
154*6777b538SAndroid Build Coastguard Worker return;
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker // Run kRetries attempts to see a sub-millisecond timer.
157*6777b538SAndroid Build Coastguard Worker constexpr int kRetries = 1000;
158*6777b538SAndroid Build Coastguard Worker for (int index = 0; index < kRetries; index++) {
159*6777b538SAndroid Build Coastguard Worker const TimeTicks start_time = TimeTicks::Now();
160*6777b538SAndroid Build Coastguard Worker TimeDelta delta;
161*6777b538SAndroid Build Coastguard Worker // Spin until the clock has detected a change.
162*6777b538SAndroid Build Coastguard Worker do {
163*6777b538SAndroid Build Coastguard Worker delta = TimeTicks::Now() - start_time;
164*6777b538SAndroid Build Coastguard Worker } while (delta.is_zero());
165*6777b538SAndroid Build Coastguard Worker if (!delta.InMilliseconds())
166*6777b538SAndroid Build Coastguard Worker return;
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker ADD_FAILURE() << "Never saw a sub-millisecond timer.";
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker
TEST(TimeTicks,TimeGetTimeCaps)171*6777b538SAndroid Build Coastguard Worker TEST(TimeTicks, TimeGetTimeCaps) {
172*6777b538SAndroid Build Coastguard Worker // Test some basic assumptions that we expect about how timeGetDevCaps works.
173*6777b538SAndroid Build Coastguard Worker
174*6777b538SAndroid Build Coastguard Worker TIMECAPS caps;
175*6777b538SAndroid Build Coastguard Worker MMRESULT status = timeGetDevCaps(&caps, sizeof(caps));
176*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<MMRESULT>(MMSYSERR_NOERROR), status);
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
179*6777b538SAndroid Build Coastguard Worker EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
180*6777b538SAndroid Build Coastguard Worker EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
181*6777b538SAndroid Build Coastguard Worker EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
182*6777b538SAndroid Build Coastguard Worker printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin, caps.wPeriodMax);
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker
TEST(TimeTicks,QueryPerformanceFrequency)185*6777b538SAndroid Build Coastguard Worker TEST(TimeTicks, QueryPerformanceFrequency) {
186*6777b538SAndroid Build Coastguard Worker // Test some basic assumptions that we expect about QPC.
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker LARGE_INTEGER frequency;
189*6777b538SAndroid Build Coastguard Worker BOOL rv = QueryPerformanceFrequency(&frequency);
190*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(TRUE, rv);
191*6777b538SAndroid Build Coastguard Worker EXPECT_GT(frequency.QuadPart, 1000000); // Expect at least 1MHz
192*6777b538SAndroid Build Coastguard Worker printf("QueryPerformanceFrequency is %5.2fMHz\n",
193*6777b538SAndroid Build Coastguard Worker frequency.QuadPart / 1000000.0);
194*6777b538SAndroid Build Coastguard Worker }
195*6777b538SAndroid Build Coastguard Worker
TEST(TimeTicks,TimerPerformance)196*6777b538SAndroid Build Coastguard Worker TEST(TimeTicks, TimerPerformance) {
197*6777b538SAndroid Build Coastguard Worker // Verify that various timer mechanisms can always complete quickly.
198*6777b538SAndroid Build Coastguard Worker // Note: This is a somewhat arbitrary test.
199*6777b538SAndroid Build Coastguard Worker const int kLoops = 500000;
200*6777b538SAndroid Build Coastguard Worker
201*6777b538SAndroid Build Coastguard Worker typedef TimeTicks (*TestFunc)();
202*6777b538SAndroid Build Coastguard Worker struct TestCase {
203*6777b538SAndroid Build Coastguard Worker TestFunc func;
204*6777b538SAndroid Build Coastguard Worker const char* description;
205*6777b538SAndroid Build Coastguard Worker };
206*6777b538SAndroid Build Coastguard Worker // Cheating a bit here: assumes sizeof(TimeTicks) == sizeof(Time)
207*6777b538SAndroid Build Coastguard Worker // in order to create a single test case list.
208*6777b538SAndroid Build Coastguard Worker static_assert(sizeof(TimeTicks) == sizeof(Time),
209*6777b538SAndroid Build Coastguard Worker "TimeTicks and Time must be the same size");
210*6777b538SAndroid Build Coastguard Worker std::vector<TestCase> cases;
211*6777b538SAndroid Build Coastguard Worker cases.push_back({reinterpret_cast<TestFunc>(&Time::Now), "Time::Now"});
212*6777b538SAndroid Build Coastguard Worker cases.push_back({&TimeTicks::Now, "TimeTicks::Now"});
213*6777b538SAndroid Build Coastguard Worker cases.push_back({&GetTSC, "CPUCycleCounter"});
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker if (ThreadTicks::IsSupported()) {
216*6777b538SAndroid Build Coastguard Worker ThreadTicks::WaitUntilInitialized();
217*6777b538SAndroid Build Coastguard Worker cases.push_back(
218*6777b538SAndroid Build Coastguard Worker {reinterpret_cast<TestFunc>(&ThreadTicks::Now), "ThreadTicks::Now"});
219*6777b538SAndroid Build Coastguard Worker }
220*6777b538SAndroid Build Coastguard Worker
221*6777b538SAndroid Build Coastguard Worker // Warm up the CPU to its full clock rate so that we get accurate timing
222*6777b538SAndroid Build Coastguard Worker // information.
223*6777b538SAndroid Build Coastguard Worker DWORD start_tick = GetTickCount();
224*6777b538SAndroid Build Coastguard Worker const DWORD kWarmupMs = 50;
225*6777b538SAndroid Build Coastguard Worker for (;;) {
226*6777b538SAndroid Build Coastguard Worker DWORD elapsed = GetTickCount() - start_tick;
227*6777b538SAndroid Build Coastguard Worker if (elapsed > kWarmupMs)
228*6777b538SAndroid Build Coastguard Worker break;
229*6777b538SAndroid Build Coastguard Worker }
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker for (const auto& test_case : cases) {
232*6777b538SAndroid Build Coastguard Worker TimeTicks start = TimeTicks::Now();
233*6777b538SAndroid Build Coastguard Worker for (int index = 0; index < kLoops; index++)
234*6777b538SAndroid Build Coastguard Worker test_case.func();
235*6777b538SAndroid Build Coastguard Worker TimeTicks stop = TimeTicks::Now();
236*6777b538SAndroid Build Coastguard Worker // Turning off the check for acceptible delays. Without this check,
237*6777b538SAndroid Build Coastguard Worker // the test really doesn't do much other than measure. But the
238*6777b538SAndroid Build Coastguard Worker // measurements are still useful for testing timers on various platforms.
239*6777b538SAndroid Build Coastguard Worker // The reason to remove the check is because the tests run on many
240*6777b538SAndroid Build Coastguard Worker // buildbots, some of which are VMs. These machines can run horribly
241*6777b538SAndroid Build Coastguard Worker // slow, and there is really no value for checking against a max timer.
242*6777b538SAndroid Build Coastguard Worker // const int kMaxTime = 35; // Maximum acceptible milliseconds for test.
243*6777b538SAndroid Build Coastguard Worker // EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
244*6777b538SAndroid Build Coastguard Worker printf("%s: %1.2fus per call\n", test_case.description,
245*6777b538SAndroid Build Coastguard Worker (stop - start).InMillisecondsF() * 1000 / kLoops);
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker #if !defined(ARCH_CPU_ARM64)
250*6777b538SAndroid Build Coastguard Worker // This test is disabled on Windows ARM64 systems because TSCTicksPerSecond is
251*6777b538SAndroid Build Coastguard Worker // only used in Chromium for QueryThreadCycleTime, and QueryThreadCycleTime
252*6777b538SAndroid Build Coastguard Worker // doesn't use a constant-rate timer on ARM64.
TEST(TimeTicks,TSCTicksPerSecond)253*6777b538SAndroid Build Coastguard Worker TEST(TimeTicks, TSCTicksPerSecond) {
254*6777b538SAndroid Build Coastguard Worker if (time_internal::HasConstantRateTSC()) {
255*6777b538SAndroid Build Coastguard Worker ThreadTicks::WaitUntilInitialized();
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker // Read the CPU frequency from the registry.
258*6777b538SAndroid Build Coastguard Worker base::win::RegKey processor_key(
259*6777b538SAndroid Build Coastguard Worker HKEY_LOCAL_MACHINE,
260*6777b538SAndroid Build Coastguard Worker L"Hardware\\Description\\System\\CentralProcessor\\0", KEY_QUERY_VALUE);
261*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(processor_key.Valid());
262*6777b538SAndroid Build Coastguard Worker DWORD processor_mhz_from_registry;
263*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
264*6777b538SAndroid Build Coastguard Worker processor_key.ReadValueDW(L"~MHz", &processor_mhz_from_registry));
265*6777b538SAndroid Build Coastguard Worker
266*6777b538SAndroid Build Coastguard Worker // Expect the measured TSC frequency to be similar to the processor
267*6777b538SAndroid Build Coastguard Worker // frequency from the registry (0.5% error).
268*6777b538SAndroid Build Coastguard Worker double tsc_mhz_measured = time_internal::TSCTicksPerSecond() / 1e6;
269*6777b538SAndroid Build Coastguard Worker EXPECT_NEAR(tsc_mhz_measured, processor_mhz_from_registry,
270*6777b538SAndroid Build Coastguard Worker 0.005 * processor_mhz_from_registry);
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker }
273*6777b538SAndroid Build Coastguard Worker #endif
274*6777b538SAndroid Build Coastguard Worker
TEST(TimeTicks,FromQPCValue)275*6777b538SAndroid Build Coastguard Worker TEST(TimeTicks, FromQPCValue) {
276*6777b538SAndroid Build Coastguard Worker if (!TimeTicks::IsHighResolution())
277*6777b538SAndroid Build Coastguard Worker return;
278*6777b538SAndroid Build Coastguard Worker
279*6777b538SAndroid Build Coastguard Worker LARGE_INTEGER frequency;
280*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(QueryPerformanceFrequency(&frequency));
281*6777b538SAndroid Build Coastguard Worker const int64_t ticks_per_second = frequency.QuadPart;
282*6777b538SAndroid Build Coastguard Worker ASSERT_GT(ticks_per_second, 0);
283*6777b538SAndroid Build Coastguard Worker
284*6777b538SAndroid Build Coastguard Worker // Generate the tick values to convert, advancing the tick count by varying
285*6777b538SAndroid Build Coastguard Worker // amounts. These values will ensure that both the fast and overflow-safe
286*6777b538SAndroid Build Coastguard Worker // conversion logic in FromQPCValue() is tested, and across the entire range
287*6777b538SAndroid Build Coastguard Worker // of possible QPC tick values.
288*6777b538SAndroid Build Coastguard Worker std::vector<int64_t> test_cases;
289*6777b538SAndroid Build Coastguard Worker test_cases.push_back(0);
290*6777b538SAndroid Build Coastguard Worker
291*6777b538SAndroid Build Coastguard Worker // Build the test cases.
292*6777b538SAndroid Build Coastguard Worker {
293*6777b538SAndroid Build Coastguard Worker const int kNumAdvancements = 100;
294*6777b538SAndroid Build Coastguard Worker int64_t ticks = 0;
295*6777b538SAndroid Build Coastguard Worker int64_t ticks_increment = 10;
296*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < kNumAdvancements; ++i) {
297*6777b538SAndroid Build Coastguard Worker test_cases.push_back(ticks);
298*6777b538SAndroid Build Coastguard Worker ticks += ticks_increment;
299*6777b538SAndroid Build Coastguard Worker ticks_increment = ticks_increment * 6 / 5;
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker test_cases.push_back(Time::kQPCOverflowThreshold - 1);
302*6777b538SAndroid Build Coastguard Worker test_cases.push_back(Time::kQPCOverflowThreshold);
303*6777b538SAndroid Build Coastguard Worker test_cases.push_back(Time::kQPCOverflowThreshold + 1);
304*6777b538SAndroid Build Coastguard Worker ticks = Time::kQPCOverflowThreshold + 10;
305*6777b538SAndroid Build Coastguard Worker ticks_increment = 10;
306*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < kNumAdvancements; ++i) {
307*6777b538SAndroid Build Coastguard Worker test_cases.push_back(ticks);
308*6777b538SAndroid Build Coastguard Worker ticks += ticks_increment;
309*6777b538SAndroid Build Coastguard Worker ticks_increment = ticks_increment * 6 / 5;
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker test_cases.push_back(std::numeric_limits<int64_t>::max());
312*6777b538SAndroid Build Coastguard Worker }
313*6777b538SAndroid Build Coastguard Worker
314*6777b538SAndroid Build Coastguard Worker // Test that the conversions using FromQPCValue() match those computed here
315*6777b538SAndroid Build Coastguard Worker // using simple floating-point arithmetic. The floating-point math provides
316*6777b538SAndroid Build Coastguard Worker // enough precision for all reasonable values to confirm that the
317*6777b538SAndroid Build Coastguard Worker // implementation is correct to the microsecond, and for "very large" values
318*6777b538SAndroid Build Coastguard Worker // it confirms that the answer is very close to correct.
319*6777b538SAndroid Build Coastguard Worker for (int64_t ticks : test_cases) {
320*6777b538SAndroid Build Coastguard Worker const double expected_microseconds_since_origin =
321*6777b538SAndroid Build Coastguard Worker (static_cast<double>(ticks) * Time::kMicrosecondsPerSecond) /
322*6777b538SAndroid Build Coastguard Worker ticks_per_second;
323*6777b538SAndroid Build Coastguard Worker const TimeTicks converted_value = TimeTicks::FromQPCValue(ticks);
324*6777b538SAndroid Build Coastguard Worker const double converted_microseconds_since_origin =
325*6777b538SAndroid Build Coastguard Worker (converted_value - TimeTicks()).InMicrosecondsF();
326*6777b538SAndroid Build Coastguard Worker // When we test with very large numbers we end up in a range where adjacent
327*6777b538SAndroid Build Coastguard Worker // double values are far apart - 512.0 apart in one test failure. In that
328*6777b538SAndroid Build Coastguard Worker // situation it makes no sense for our epsilon to be 1.0 - it should be
329*6777b538SAndroid Build Coastguard Worker // the difference between adjacent doubles.
330*6777b538SAndroid Build Coastguard Worker double epsilon = nextafter(expected_microseconds_since_origin, INFINITY) -
331*6777b538SAndroid Build Coastguard Worker expected_microseconds_since_origin;
332*6777b538SAndroid Build Coastguard Worker // Epsilon must be at least 1.0 because converted_microseconds_since_origin
333*6777b538SAndroid Build Coastguard Worker // comes from an integral value, and expected_microseconds_since_origin is
334*6777b538SAndroid Build Coastguard Worker // a double that is expected to be up to 0.999 larger. In addition, due to
335*6777b538SAndroid Build Coastguard Worker // multiple roundings in the double calculation the actual error can be
336*6777b538SAndroid Build Coastguard Worker // slightly larger than 1.0, even when the converted value is perfect. This
337*6777b538SAndroid Build Coastguard Worker // epsilon value was chosen because it is slightly larger than the error
338*6777b538SAndroid Build Coastguard Worker // seen in a test failure caused by the double rounding.
339*6777b538SAndroid Build Coastguard Worker epsilon = std::max(epsilon, 1.002);
340*6777b538SAndroid Build Coastguard Worker EXPECT_NEAR(expected_microseconds_since_origin,
341*6777b538SAndroid Build Coastguard Worker converted_microseconds_since_origin, epsilon)
342*6777b538SAndroid Build Coastguard Worker << "ticks=" << ticks << ", to be converted via logic path: "
343*6777b538SAndroid Build Coastguard Worker << (ticks < Time::kQPCOverflowThreshold ? "FAST" : "SAFE");
344*6777b538SAndroid Build Coastguard Worker }
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
TEST(TimeDelta,ConstexprInitialization)347*6777b538SAndroid Build Coastguard Worker TEST(TimeDelta, ConstexprInitialization) {
348*6777b538SAndroid Build Coastguard Worker // Make sure that TimeDelta works around crbug.com/635974
349*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kExpectedDeltaInMilliseconds, kConstexprTimeDelta.InMilliseconds());
350*6777b538SAndroid Build Coastguard Worker }
351*6777b538SAndroid Build Coastguard Worker
TEST(TimeDelta,FromFileTime)352*6777b538SAndroid Build Coastguard Worker TEST(TimeDelta, FromFileTime) {
353*6777b538SAndroid Build Coastguard Worker FILETIME ft;
354*6777b538SAndroid Build Coastguard Worker ft.dwLowDateTime = 1001;
355*6777b538SAndroid Build Coastguard Worker ft.dwHighDateTime = 0;
356*6777b538SAndroid Build Coastguard Worker
357*6777b538SAndroid Build Coastguard Worker // 100100 ns ~= 100 us.
358*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(Microseconds(100), TimeDelta::FromFileTime(ft));
359*6777b538SAndroid Build Coastguard Worker
360*6777b538SAndroid Build Coastguard Worker ft.dwLowDateTime = 0;
361*6777b538SAndroid Build Coastguard Worker ft.dwHighDateTime = 1;
362*6777b538SAndroid Build Coastguard Worker
363*6777b538SAndroid Build Coastguard Worker // 2^32 * 100 ns ~= 2^32 * 10 us.
364*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(Microseconds((1ull << 32) / 10), TimeDelta::FromFileTime(ft));
365*6777b538SAndroid Build Coastguard Worker }
366*6777b538SAndroid Build Coastguard Worker
TEST(TimeDelta,FromWinrtDateTime)367*6777b538SAndroid Build Coastguard Worker TEST(TimeDelta, FromWinrtDateTime) {
368*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::DateTime dt;
369*6777b538SAndroid Build Coastguard Worker dt.UniversalTime = 0;
370*6777b538SAndroid Build Coastguard Worker
371*6777b538SAndroid Build Coastguard Worker // 0 UniversalTime = no delta since epoch.
372*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(TimeDelta(), TimeDelta::FromWinrtDateTime(dt));
373*6777b538SAndroid Build Coastguard Worker
374*6777b538SAndroid Build Coastguard Worker dt.UniversalTime = 101;
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker // 101 * 100 ns ~= 10.1 microseconds.
377*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(Microseconds(10.1), TimeDelta::FromWinrtDateTime(dt));
378*6777b538SAndroid Build Coastguard Worker }
379*6777b538SAndroid Build Coastguard Worker
TEST(TimeDelta,ToWinrtDateTime)380*6777b538SAndroid Build Coastguard Worker TEST(TimeDelta, ToWinrtDateTime) {
381*6777b538SAndroid Build Coastguard Worker auto time_delta = Seconds(0);
382*6777b538SAndroid Build Coastguard Worker
383*6777b538SAndroid Build Coastguard Worker // No delta since epoch = 0 DateTime.
384*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, time_delta.ToWinrtDateTime().UniversalTime);
385*6777b538SAndroid Build Coastguard Worker
386*6777b538SAndroid Build Coastguard Worker time_delta = Microseconds(10);
387*6777b538SAndroid Build Coastguard Worker
388*6777b538SAndroid Build Coastguard Worker // 10 microseconds = 100 * 100 ns.
389*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(100, time_delta.ToWinrtDateTime().UniversalTime);
390*6777b538SAndroid Build Coastguard Worker }
391*6777b538SAndroid Build Coastguard Worker
TEST(TimeDelta,FromWinrtTimeSpan)392*6777b538SAndroid Build Coastguard Worker TEST(TimeDelta, FromWinrtTimeSpan) {
393*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::TimeSpan ts;
394*6777b538SAndroid Build Coastguard Worker ts.Duration = 0;
395*6777b538SAndroid Build Coastguard Worker
396*6777b538SAndroid Build Coastguard Worker // 0.
397*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(TimeDelta(), TimeDelta::FromWinrtTimeSpan(ts));
398*6777b538SAndroid Build Coastguard Worker
399*6777b538SAndroid Build Coastguard Worker ts.Duration = 101;
400*6777b538SAndroid Build Coastguard Worker
401*6777b538SAndroid Build Coastguard Worker // 101 * 100 ns ~= 10.1 microseconds.
402*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(Microseconds(10.1), TimeDelta::FromWinrtTimeSpan(ts));
403*6777b538SAndroid Build Coastguard Worker }
404*6777b538SAndroid Build Coastguard Worker
TEST(TimeDelta,ToWinrtTimeSpan)405*6777b538SAndroid Build Coastguard Worker TEST(TimeDelta, ToWinrtTimeSpan) {
406*6777b538SAndroid Build Coastguard Worker auto time_delta = Seconds(0);
407*6777b538SAndroid Build Coastguard Worker
408*6777b538SAndroid Build Coastguard Worker // 0.
409*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, time_delta.ToWinrtTimeSpan().Duration);
410*6777b538SAndroid Build Coastguard Worker
411*6777b538SAndroid Build Coastguard Worker time_delta = Microseconds(10);
412*6777b538SAndroid Build Coastguard Worker
413*6777b538SAndroid Build Coastguard Worker // 10 microseconds = 100 * 100 ns.
414*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(100, time_delta.ToWinrtTimeSpan().Duration);
415*6777b538SAndroid Build Coastguard Worker }
416*6777b538SAndroid Build Coastguard Worker
TEST(HighResolutionTimer,GetUsage)417*6777b538SAndroid Build Coastguard Worker TEST(HighResolutionTimer, GetUsage) {
418*6777b538SAndroid Build Coastguard Worker Time::ResetHighResolutionTimerUsage();
419*6777b538SAndroid Build Coastguard Worker
420*6777b538SAndroid Build Coastguard Worker // 0% usage since the timer isn't activated regardless of how much time has
421*6777b538SAndroid Build Coastguard Worker // elapsed.
422*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
423*6777b538SAndroid Build Coastguard Worker Sleep(10);
424*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker Time::ActivateHighResolutionTimer(true);
427*6777b538SAndroid Build Coastguard Worker Time::ResetHighResolutionTimerUsage();
428*6777b538SAndroid Build Coastguard Worker
429*6777b538SAndroid Build Coastguard Worker Sleep(20);
430*6777b538SAndroid Build Coastguard Worker // 100% usage since the timer has been activated entire time.
431*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(100.0, Time::GetHighResolutionTimerUsage());
432*6777b538SAndroid Build Coastguard Worker
433*6777b538SAndroid Build Coastguard Worker Time::ActivateHighResolutionTimer(false);
434*6777b538SAndroid Build Coastguard Worker Sleep(20);
435*6777b538SAndroid Build Coastguard Worker double usage1 = Time::GetHighResolutionTimerUsage();
436*6777b538SAndroid Build Coastguard Worker // usage1 should be about 50%.
437*6777b538SAndroid Build Coastguard Worker EXPECT_LT(usage1, 100.0);
438*6777b538SAndroid Build Coastguard Worker EXPECT_GT(usage1, 0.0);
439*6777b538SAndroid Build Coastguard Worker
440*6777b538SAndroid Build Coastguard Worker Time::ActivateHighResolutionTimer(true);
441*6777b538SAndroid Build Coastguard Worker Sleep(10);
442*6777b538SAndroid Build Coastguard Worker Time::ActivateHighResolutionTimer(false);
443*6777b538SAndroid Build Coastguard Worker double usage2 = Time::GetHighResolutionTimerUsage();
444*6777b538SAndroid Build Coastguard Worker // usage2 should be about 60%.
445*6777b538SAndroid Build Coastguard Worker EXPECT_LT(usage2, 100.0);
446*6777b538SAndroid Build Coastguard Worker EXPECT_GT(usage2, usage1);
447*6777b538SAndroid Build Coastguard Worker
448*6777b538SAndroid Build Coastguard Worker Time::ResetHighResolutionTimerUsage();
449*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
450*6777b538SAndroid Build Coastguard Worker }
451*6777b538SAndroid Build Coastguard Worker
452*6777b538SAndroid Build Coastguard Worker } // namespace base
453