summaryrefslogtreecommitdiffstats
path: root/base/time_win_unittest.cc
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-15 17:16:48 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-15 17:16:48 +0000
commitf5f36152e843a215629f3991da644f8da37e02ff (patch)
treec9dafdaaef442446e6d2d74f3a4e68fd104b6f47 /base/time_win_unittest.cc
parent4e486eb3962f64f3f9d4b9ae71d030edd4c01a5b (diff)
downloadchromium_src-f5f36152e843a215629f3991da644f8da37e02ff.zip
chromium_src-f5f36152e843a215629f3991da644f8da37e02ff.tar.gz
chromium_src-f5f36152e843a215629f3991da644f8da37e02ff.tar.bz2
Renaming the following files to include the _win suffix:
scoped_comptr*.* scoped_bstr*.* addition: time_unittest_win.cc -> time_win_unittest.cc BUG=6409 Also renaming the scoped_comptr class to ScopedComPtr to conform with chromium style (and not boost as before). Review URL: http://codereview.chromium.org/18054 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8098 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/time_win_unittest.cc')
-rw-r--r--base/time_win_unittest.cc204
1 files changed, 204 insertions, 0 deletions
diff --git a/base/time_win_unittest.cc b/base/time_win_unittest.cc
new file mode 100644
index 0000000..4b63f6b
--- /dev/null
+++ b/base/time_win_unittest.cc
@@ -0,0 +1,204 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+#include <mmsystem.h>
+#include <process.h>
+
+#include "base/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::Time;
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace {
+
+class MockTimeTicks : public TimeTicks {
+ public:
+ static DWORD Ticker() {
+ return static_cast<int>(InterlockedIncrement(&ticker_));
+ }
+
+ static void InstallTicker() {
+ old_tick_function_ = SetMockTickFunction(&Ticker);
+ ticker_ = -5;
+ }
+
+ static void UninstallTicker() {
+ SetMockTickFunction(old_tick_function_);
+ }
+
+ private:
+ static volatile LONG ticker_;
+ static TickFunctionType old_tick_function_;
+};
+
+volatile LONG MockTimeTicks::ticker_;
+MockTimeTicks::TickFunctionType MockTimeTicks::old_tick_function_;
+
+HANDLE g_rollover_test_start;
+
+unsigned __stdcall RolloverTestThreadMain(void* param) {
+ int64 counter = reinterpret_cast<int64>(param);
+ DWORD rv = WaitForSingleObject(g_rollover_test_start, INFINITE);
+ EXPECT_EQ(rv, WAIT_OBJECT_0);
+
+ TimeTicks last = TimeTicks::Now();
+ for (int index = 0; index < counter; index++) {
+ TimeTicks now = TimeTicks::Now();
+ int64 milliseconds = (now - last).InMilliseconds();
+ // This is a tight loop; we could have looped faster than our
+ // measurements, so the time might be 0 millis.
+ EXPECT_GE(milliseconds, 0);
+ EXPECT_LT(milliseconds, 250);
+ last = now;
+ }
+ return 0;
+}
+
+} // namespace
+
+TEST(TimeTicks, WinRollover) {
+ // The internal counter rolls over at ~49days. We'll use a mock
+ // timer to test this case.
+ // Basic test algorithm:
+ // 1) Set clock to rollover - N
+ // 2) Create N threads
+ // 3) Start the threads
+ // 4) Each thread loops through TimeTicks() N times
+ // 5) Each thread verifies integrity of result.
+
+ const int kThreads = 8;
+ // Use int64 so we can cast into a void* without a compiler warning.
+ const int64 kChecks = 10;
+
+ // It takes a lot of iterations to reproduce the bug!
+ // (See bug 1081395)
+ for (int loop = 0; loop < 4096; loop++) {
+ // Setup
+ MockTimeTicks::InstallTicker();
+ g_rollover_test_start = CreateEvent(0, TRUE, FALSE, 0);
+ HANDLE threads[kThreads];
+
+ for (int index = 0; index < kThreads; index++) {
+ void* argument = reinterpret_cast<void*>(kChecks);
+ unsigned thread_id;
+ threads[index] = reinterpret_cast<HANDLE>(
+ _beginthreadex(NULL, 0, RolloverTestThreadMain, argument, 0,
+ &thread_id));
+ EXPECT_NE((HANDLE)NULL, threads[index]);
+ }
+
+ // Start!
+ SetEvent(g_rollover_test_start);
+
+ // Wait for threads to finish
+ for (int index = 0; index < kThreads; index++) {
+ DWORD rv = WaitForSingleObject(threads[index], INFINITE);
+ EXPECT_EQ(rv, WAIT_OBJECT_0);
+ }
+
+ CloseHandle(g_rollover_test_start);
+
+ // Teardown
+ MockTimeTicks::UninstallTicker();
+ }
+}
+
+TEST(TimeTicks, SubMillisecondTimers) {
+ // Loop for a bit getting timers quickly. We want to
+ // see at least one case where we get a new sample in
+ // less than one millisecond.
+ bool saw_submillisecond_timer = false;
+ int64 min_timer = 1000;
+ TimeTicks last_time = TimeTicks::HighResNow();
+ for (int index = 0; index < 1000; index++) {
+ TimeTicks now = TimeTicks::HighResNow();
+ TimeDelta delta = now - last_time;
+ if (delta.InMicroseconds() > 0 &&
+ delta.InMicroseconds() < 1000) {
+ if (min_timer > delta.InMicroseconds())
+ min_timer = delta.InMicroseconds();
+ saw_submillisecond_timer = true;
+ }
+ last_time = now;
+ }
+ EXPECT_TRUE(saw_submillisecond_timer);
+ printf("Min timer is: %dus\n", min_timer);
+}
+
+TEST(TimeTicks, TimeGetTimeCaps) {
+ // Test some basic assumptions that we expect about how timeGetDevCaps works.
+
+ TIMECAPS caps;
+ MMRESULT status = timeGetDevCaps(&caps, sizeof(caps));
+ EXPECT_EQ(TIMERR_NOERROR, status);
+ if (status != TIMERR_NOERROR) {
+ printf("Could not get timeGetDevCaps\n");
+ return;
+ }
+
+ EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
+ EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
+ EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
+ EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
+ printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin,
+ caps.wPeriodMax);
+}
+
+TEST(TimeTicks, QueryPerformanceFrequency) {
+ // Test some basic assumptions that we expect about QPC.
+
+ LARGE_INTEGER frequency;
+ BOOL rv = QueryPerformanceFrequency(&frequency);
+ EXPECT_EQ(TRUE, rv);
+ EXPECT_GT(frequency.QuadPart, 1000000); // Expect at least 1MHz
+ printf("QueryPerformanceFrequency is %5.2fMHz\n",
+ frequency.QuadPart / 1000000.0);
+}
+
+TEST(TimeTicks, TimerPerformance) {
+ // Verify that various timer mechanisms can always complete quickly.
+ // Note: This is a somewhat arbitrary test.
+ const int kLoops = 10000;
+ // Due to the fact that these run on bbots, which are horribly slow,
+ // we can't really make any guarantees about minimum runtime.
+ // Really, we want these to finish in ~10ms, and that is generous.
+ const int kMaxTime = 35; // Maximum acceptible milliseconds for test.
+
+ typedef TimeTicks (*TestFunc)();
+ struct TestCase {
+ TestFunc func;
+ char *description;
+ };
+ // Cheating a bit here: assumes sizeof(TimeTicks) == sizeof(Time)
+ // in order to create a single test case list.
+ COMPILE_ASSERT(sizeof(TimeTicks) == sizeof(Time),
+ test_only_works_with_same_sizes);
+ TestCase cases[] = {
+ { reinterpret_cast<TestFunc>(Time::Now), "Time::Now" },
+ { TimeTicks::Now, "TimeTicks::Now" },
+ { TimeTicks::HighResNow, "TimeTicks::HighResNow" },
+ { NULL, "" }
+ };
+
+ int test_case = 0;
+ while (cases[test_case].func) {
+ TimeTicks start = TimeTicks::HighResNow();
+ for (int index = 0; index < kLoops; index++)
+ cases[test_case].func();
+ TimeTicks stop = TimeTicks::HighResNow();
+ // Turning off the check for acceptible delays. Without this check,
+ // the test really doesn't do much other than measure. But the
+ // measurements are still useful for testing timers on various platforms.
+ // The reason to remove the check is because the tests run on many
+ // buildbots, some of which are VMs. These machines can run horribly
+ // slow, and there is really no value for checking against a max timer.
+ //EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
+ printf("%s: %1.2fus per call\n", cases[test_case].description,
+ (stop - start).InMillisecondsF() * 1000 / kLoops);
+ test_case++;
+ }
+}