15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mmsystem.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <process.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockTimeTicks : public TimeTicks {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static DWORD Ticker() {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<int>(InterlockedIncrement(&ticker_));
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void InstallTicker() {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_tick_function_ = SetMockTickFunction(&Ticker);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ticker_ = -5;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void UninstallTicker() {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetMockTickFunction(old_tick_function_);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static volatile LONG ticker_;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static TickFunctionType old_tick_function_;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)volatile LONG MockTimeTicks::ticker_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MockTimeTicks::TickFunctionType MockTimeTicks::old_tick_function_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HANDLE g_rollover_test_start;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned __stdcall RolloverTestThreadMain(void* param) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 counter = reinterpret_cast<int64>(param);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD rv = WaitForSingleObject(g_rollover_test_start, INFINITE);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(rv, WAIT_OBJECT_0);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeTicks last = TimeTicks::Now();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int index = 0; index < counter; index++) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeTicks now = TimeTicks::Now();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 milliseconds = (now - last).InMilliseconds();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is a tight loop; we could have looped faster than our
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // measurements, so the time might be 0 millis.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GE(milliseconds, 0);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LT(milliseconds, 250);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last = now;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(TimeTicks, WinRollover) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The internal counter rolls over at ~49days.  We'll use a mock
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // timer to test this case.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Basic test algorithm:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   1) Set clock to rollover - N
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   2) Create N threads
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   3) Start the threads
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   4) Each thread loops through TimeTicks() N times
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   5) Each thread verifies integrity of result.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kThreads = 8;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use int64 so we can cast into a void* without a compiler warning.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int64 kChecks = 10;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It takes a lot of iterations to reproduce the bug!
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (See bug 1081395)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int loop = 0; loop < 4096; loop++) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Setup
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockTimeTicks::InstallTicker();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_rollover_test_start = CreateEvent(0, TRUE, FALSE, 0);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HANDLE threads[kThreads];
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int index = 0; index < kThreads; index++) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* argument = reinterpret_cast<void*>(kChecks);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned thread_id;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      threads[index] = reinterpret_cast<HANDLE>(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        _beginthreadex(NULL, 0, RolloverTestThreadMain, argument, 0,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &thread_id));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_NE((HANDLE)NULL, threads[index]);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start!
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetEvent(g_rollover_test_start);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait for threads to finish
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int index = 0; index < kThreads; index++) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DWORD rv = WaitForSingleObject(threads[index], INFINITE);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(rv, WAIT_OBJECT_0);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseHandle(g_rollover_test_start);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Teardown
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockTimeTicks::UninstallTicker();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(TimeTicks, SubMillisecondTimers) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // HighResNow doesn't work on some systems.  Since the product still works
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // even if it doesn't work, it makes this entire test questionable.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!TimeTicks::IsHighResClockWorking())
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kRetries = 1000;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool saw_submillisecond_timer = false;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run kRetries attempts to see a sub-millisecond timer.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int index = 0; index < 1000; index++) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeTicks last_time = TimeTicks::HighResNow();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeDelta delta;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Spin until the clock has detected a change.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta = TimeTicks::HighResNow() - last_time;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (delta.InMicroseconds() == 0);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delta.InMicroseconds() < 1000) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      saw_submillisecond_timer = true;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(saw_submillisecond_timer);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(TimeTicks, TimeGetTimeCaps) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test some basic assumptions that we expect about how timeGetDevCaps works.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TIMECAPS caps;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MMRESULT status = timeGetDevCaps(&caps, sizeof(caps));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(TIMERR_NOERROR, status);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status != TIMERR_NOERROR) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("Could not get timeGetDevCaps\n");
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    caps.wPeriodMax);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(TimeTicks, QueryPerformanceFrequency) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test some basic assumptions that we expect about QPC.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LARGE_INTEGER frequency;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL rv = QueryPerformanceFrequency(&frequency);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(TRUE, rv);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(frequency.QuadPart, 1000000);  // Expect at least 1MHz
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("QueryPerformanceFrequency is %5.2fMHz\n",
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frequency.QuadPart / 1000000.0);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(TimeTicks, TimerPerformance) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that various timer mechanisms can always complete quickly.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:  This is a somewhat arbitrary test.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kLoops = 10000;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Due to the fact that these run on bbots, which are horribly slow,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we can't really make any guarantees about minimum runtime.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Really, we want these to finish in ~10ms, and that is generous.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kMaxTime = 35;  // Maximum acceptible milliseconds for test.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef TimeTicks (*TestFunc)();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestCase {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestFunc func;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *description;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cheating a bit here:  assumes sizeof(TimeTicks) == sizeof(Time)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in order to create a single test case list.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(sizeof(TimeTicks) == sizeof(Time),
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 test_only_works_with_same_sizes);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCase cases[] = {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { reinterpret_cast<TestFunc>(Time::Now), "Time::Now" },
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { TimeTicks::Now, "TimeTicks::Now" },
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { TimeTicks::HighResNow, "TimeTicks::HighResNow" },
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { NULL, "" }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int test_case = 0;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (cases[test_case].func) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeTicks start = TimeTicks::HighResNow();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int index = 0; index < kLoops; index++)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cases[test_case].func();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeTicks stop = TimeTicks::HighResNow();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Turning off the check for acceptible delays.  Without this check,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the test really doesn't do much other than measure.  But the
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // measurements are still useful for testing timers on various platforms.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The reason to remove the check is because the tests run on many
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buildbots, some of which are VMs.  These machines can run horribly
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // slow, and there is really no value for checking against a max timer.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("%s: %1.2fus per call\n", cases[test_case].description,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (stop - start).InMillisecondsF() * 1000 / kLoops);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_case++;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(TimeTicks, Drift) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If QPC is disabled, this isn't measuring anything.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!TimeTicks::IsHighResClockWorking())
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kIterations = 100;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 total_drift = 0;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kIterations; ++i) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 drift_microseconds = TimeTicks::GetQPCDriftMicroseconds();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the drift never exceeds our limit.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LT(drift_microseconds, 50000);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sleep for a few milliseconds (note that it means 1000 microseconds).
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we check the drift too frequently, it's going to increase
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // monotonically, making our measurement less realistic.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::PlatformThread::Sleep(
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds((i % 2 == 0) ? 1 : 2));
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_drift += drift_microseconds;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity check. We expect some time drift to occur, especially across
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number of iterations we do.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0, total_drift);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("average time drift in microseconds: %lld\n",
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         total_drift / kIterations);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
240