xref: /aosp_15_r20/external/cronet/base/time/time_win_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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