1# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import contextlib
6import logging
7import platform
8import sys
9import unittest
10
11from py_trace_event import trace_time
12
13
14class TimerTest(unittest.TestCase):
15  # Helper methods.
16  @contextlib.contextmanager
17  def ReplacePlatformProcessorCall(self, f):
18    try:
19      old_proc = platform.processor
20      platform.processor = f
21      yield
22    finally:
23      platform.processor = old_proc
24
25  @contextlib.contextmanager
26  def ReplaceQPCCheck(self, f):
27    try:
28      old_qpc = trace_time.IsQPCUsable
29      trace_time.IsQPCUsable = f
30      yield
31    finally:
32      trace_time.IsQPCUsable = old_qpc
33
34  # Platform detection tests.
35  def testInitializeNowFunction_platformNotSupported(self):
36    with self.assertRaises(RuntimeError):
37      trace_time.InitializeNowFunction('invalid_platform')
38
39  def testInitializeNowFunction_windows(self):
40    if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
41            or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
42      return True
43    trace_time.InitializeNowFunction(sys.platform)
44    self.assertTrue(trace_time.GetClock() == trace_time._WIN_HIRES
45                    or trace_time.GetClock() == trace_time._WIN_LORES)
46
47  def testInitializeNowFunction_linux(self):
48    if not sys.platform.startswith(trace_time._PLATFORMS['linux']):
49      return True
50    trace_time.InitializeNowFunction(sys.platform)
51    self.assertEqual(trace_time.GetClock(), trace_time._LINUX_CLOCK)
52
53  def testInitializeNowFunction_mac(self):
54    if not sys.platform.startswith(trace_time._PLATFORMS['mac']):
55      return True
56    trace_time.InitializeNowFunction(sys.platform)
57    self.assertEqual(trace_time.GetClock(), trace_time._MAC_CLOCK)
58
59  # Windows Tests
60  def testIsQPCUsable_buggyAthlonProcReturnsFalse(self):
61    if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
62            or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
63      return True
64
65    def BuggyAthlonProc():
66      return 'AMD64 Family 15 Model 23 Stepping 6, AuthenticAMD'
67
68    with self.ReplacePlatformProcessorCall(BuggyAthlonProc):
69      self.assertFalse(trace_time.IsQPCUsable())
70
71  def testIsQPCUsable_returnsTrueOnWindows(self):
72    if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
73            or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
74      return True
75
76    def Proc():
77      return 'Intel64 Family 15 Model 23 Stepping 6, GenuineIntel'
78
79    with self.ReplacePlatformProcessorCall(Proc):
80      self.assertTrue(trace_time.IsQPCUsable())
81
82  def testGetWinNowFunction_QPC(self):
83    if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
84            or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
85      return True
86    # Test requires QPC to be available on platform.
87    if not trace_time.IsQPCUsable():
88      return True
89    self.assertGreater(trace_time.monotonic(), 0)
90
91  # Works even if QPC would work.
92  def testGetWinNowFunction_GetTickCount(self):
93    if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
94            or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
95      return True
96    with self.ReplaceQPCCheck(lambda: False):
97      self.assertGreater(trace_time.monotonic(), 0)
98
99  # Linux tests.
100  def testGetClockGetTimeClockNumber_linux(self):
101    self.assertEquals(trace_time.GetClockGetTimeClockNumber('linux'), 1)
102
103  def testGetClockGetTimeClockNumber_freebsd(self):
104    self.assertEquals(trace_time.GetClockGetTimeClockNumber('freebsd'), 4)
105
106  def testGetClockGetTimeClockNumber_bsd(self):
107    self.assertEquals(trace_time.GetClockGetTimeClockNumber('bsd'), 3)
108
109  def testGetClockGetTimeClockNumber_sunos(self):
110    self.assertEquals(trace_time.GetClockGetTimeClockNumber('sunos5'), 4)
111
112  # Smoke Test.
113  def testMonotonic(self):
114    time_one = trace_time.Now()
115    for _ in xrange(1000):
116      time_two = trace_time.Now()
117      self.assertLessEqual(time_one, time_two)
118      time_one = time_two
119
120
121if __name__ == '__main__':
122  logging.getLogger().setLevel(logging.DEBUG)
123  unittest.main(verbosity=2)
124