OLD | NEW |
| (Empty) |
1 // Copyright 2003-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Timer unittest | |
17 | |
18 #include <cmath> | |
19 #include "omaha/base/time.h" | |
20 #include "omaha/base/timer.h" | |
21 #include "omaha/testing/unit_test.h" | |
22 | |
23 namespace omaha { | |
24 | |
25 // The accuracy of the unit test measurements is expected to be within 50 ms. | |
26 // The error varies depending on how the unit test process gets scheduled. | |
27 // The timer test is prone to failing when run by Pulse. Consider diabling the | |
28 // test completely. | |
29 const int kErrorMs = 50; | |
30 | |
31 // The tests that use the Timer class are flaky (see warning in timer.h), | |
32 // and Timer isn't used in production Omaha code, so we leave out everything | |
33 // but the LowResTimer test. | |
34 // TODO(omaha): Is there a better way to do this? Maybe not run on build system? | |
35 #if 0 | |
36 | |
37 class TimerTest : public testing::Test { | |
38 protected: | |
39 // Set up a test so that we can measure the same time interval using the | |
40 // low and high resolution timers. If the difference between them is too | |
41 // big then we consider that the high resolution time is busted and we | |
42 // stop running the unit tests. | |
43 // The high resolution timer may have undefined behavior, see the header | |
44 // file for more comments. | |
45 static void SetUpTestCase() { | |
46 const int kSleepMs = 100; | |
47 const int kDiffMs = 1; | |
48 LowResTimer t(false); | |
49 Timer u(false); | |
50 t.Start(); | |
51 u.Start(); | |
52 ::Sleep(kSleepMs); | |
53 busted_ = abs(t.GetMilliseconds()- u.GetMilliseconds()) >= kErrorMs; | |
54 } | |
55 | |
56 void PrintError() { | |
57 // This is going to print "Test Foo is busted but passed." | |
58 printf("is busted but "); | |
59 } | |
60 | |
61 static bool busted_; | |
62 }; | |
63 | |
64 bool TimerTest::busted_ = false; | |
65 | |
66 #endif // #if 0 | |
67 | |
68 TEST(TimerTest, LowResTimer) { | |
69 // This test was flaky on the build machine. | |
70 // TODO(omaha): Is this still the case? Can we improve the test? | |
71 if (omaha::IsBuildSystem()) { | |
72 return; | |
73 } | |
74 | |
75 LowResTimer t(false); | |
76 | |
77 const int kSleep1 = 100; | |
78 t.Start(); | |
79 ::Sleep(kSleep1); | |
80 uint32 elapsedMs = t.Stop(); | |
81 | |
82 // For the first run of the timer the elapsed value must be equal to | |
83 // the timer interval. | |
84 EXPECT_EQ(elapsedMs, t.GetMilliseconds()); | |
85 | |
86 // About 100 ms now. | |
87 EXPECT_NEAR(kSleep1, elapsedMs, kErrorMs); | |
88 | |
89 // Test the accessors of different time units. | |
90 EXPECT_DOUBLE_EQ(t.GetSeconds() * 1000, t.GetMilliseconds()); | |
91 | |
92 const int kSleep2 = 10; | |
93 t.Start(); | |
94 ::Sleep(kSleep2); | |
95 elapsedMs = t.Stop(); | |
96 EXPECT_NEAR(kSleep2, elapsedMs, kErrorMs); | |
97 | |
98 // About 110 ms now. | |
99 EXPECT_NEAR(kSleep1 + kSleep2, t.GetMilliseconds(), 2 * kErrorMs); | |
100 | |
101 const int kSleep3 = 50; | |
102 t.Start(); | |
103 ::Sleep(kSleep3); | |
104 elapsedMs = t.Stop(); | |
105 EXPECT_NEAR(kSleep3, elapsedMs, kErrorMs); | |
106 | |
107 // About 160 ms now. | |
108 EXPECT_NEAR(kSleep1 + kSleep2 + kSleep3, t.GetMilliseconds(), 3 * kErrorMs); | |
109 | |
110 t.Reset(); | |
111 EXPECT_EQ(0, t.GetMilliseconds()); | |
112 } | |
113 | |
114 // Tests disabled, see comment at top of file. | |
115 #if 0 | |
116 // Test that values from RTDSC change quickly. | |
117 TEST_F(TimerTest, RTDSC) { | |
118 uint32 last = 0; | |
119 for (int i = 0; i < 10; ++i) { | |
120 uint64 counter = Timer::GetRdtscCounter(); | |
121 uint32 a = *(reinterpret_cast<uint32 *>(&counter)); | |
122 ASSERT_NE(a, last); | |
123 last = a; | |
124 } | |
125 } | |
126 | |
127 // Compare everything as ms units for uniformity. | |
128 | |
129 TEST_F(TimerTest, Timer) { | |
130 if (busted_) { | |
131 PrintError(); | |
132 return; | |
133 } | |
134 | |
135 Timer t(false); | |
136 | |
137 const int kSleep1 = 100; | |
138 t.Start(); | |
139 ::Sleep(kSleep1); | |
140 time64 elapsed = t.Stop(); | |
141 | |
142 // For the first run of the timer the elapsed value must be equal to | |
143 // the timer interval. | |
144 EXPECT_DOUBLE_EQ(t.PerfCountToNanoSeconds(elapsed) / 1000000, | |
145 t.GetNanoseconds() / 1000000); | |
146 | |
147 // About 100 ms now. | |
148 EXPECT_NEAR(kSleep1, t.PerfCountToNanoSeconds(elapsed) / 1000000, kErrorMs); | |
149 | |
150 // Test the accessors of different time units. | |
151 EXPECT_DOUBLE_EQ(t.GetSeconds() * 1000, t.GetMilliseconds()); | |
152 EXPECT_DOUBLE_EQ(t.GetMilliseconds() * 1000, t.GetMicroseconds()); | |
153 EXPECT_DOUBLE_EQ(t.GetMicroseconds() * 1000, t.GetNanoseconds()); | |
154 | |
155 EXPECT_NEAR(t.Get100Nanoseconds() * 100.0, t.GetNanoseconds(), 100); | |
156 | |
157 const int kSleep2 = 10; | |
158 t.Start(); | |
159 ::Sleep(kSleep2); | |
160 elapsed = t.Stop(); | |
161 EXPECT_NEAR(kSleep2, t.PerfCountToNanoSeconds(elapsed) / 1000000, kErrorMs); | |
162 | |
163 // About 110 ms now. | |
164 EXPECT_NEAR(kSleep1 + kSleep2, t.GetMilliseconds(), 2 * kErrorMs); | |
165 | |
166 const int kSleep3 = 50; | |
167 t.Start(); | |
168 ::Sleep(kSleep3); | |
169 elapsed = t.Stop(); | |
170 EXPECT_NEAR(kSleep3, t.PerfCountToNanoSeconds(elapsed) / 1000000, kErrorMs); | |
171 | |
172 // About 160 ms now. | |
173 EXPECT_NEAR(kSleep1 + kSleep2 + kSleep3, t.GetMilliseconds(), 3 * kErrorMs); | |
174 | |
175 t.Reset(); | |
176 EXPECT_DOUBLE_EQ(0, t.GetMilliseconds()); | |
177 } | |
178 | |
179 TEST_F(TimerTest, TimerSplit) { | |
180 if (busted_) { | |
181 PrintError(); | |
182 return; | |
183 } | |
184 | |
185 const int kSleep1 = 50; | |
186 const int kSleep2 = 125; | |
187 const int kSleep3 = 25; | |
188 | |
189 double split1(0), split2(0), split3(0); | |
190 double elapsed1(0), elapsed2(0); | |
191 | |
192 Timer t(false); | |
193 t.Start(); | |
194 ::Sleep(kSleep1); | |
195 t.Split(&split1, &elapsed1); | |
196 EXPECT_NEAR(split1, kSleep1, kErrorMs); | |
197 EXPECT_NEAR(elapsed1, kSleep1, kErrorMs); | |
198 EXPECT_DOUBLE_EQ(split1, elapsed1); | |
199 | |
200 ::Sleep(kSleep2); | |
201 t.Split(&split2, &elapsed2); | |
202 EXPECT_NEAR(split2, kSleep2, kErrorMs); | |
203 EXPECT_DOUBLE_EQ(split1 + split2, elapsed2); | |
204 | |
205 ::Sleep(kSleep3); | |
206 t.Split(&split3, NULL); | |
207 t.Stop(); | |
208 EXPECT_NEAR(split3, kSleep3, kErrorMs); | |
209 EXPECT_NEAR(split1 + split2 + split3, t.GetMilliseconds(), kErrorMs); | |
210 } | |
211 | |
212 // Time QueryPerformanceCounter | |
213 TEST_F(TimerTest, QueryPerformanceCounter) { | |
214 if (busted_) { | |
215 PrintError(); | |
216 return; | |
217 } | |
218 | |
219 Timer t(false); | |
220 t.Start(); | |
221 | |
222 const int kIterations = 100; | |
223 LARGE_INTEGER count = {0}; | |
224 for (int i = 0; i < kIterations; i++) { | |
225 ASSERT_TRUE(::QueryPerformanceCounter(&count)); | |
226 } | |
227 | |
228 t.Stop(); | |
229 | |
230 // Expect the call to take anywhere up to 1000 nano seconds. | |
231 EXPECT_NEAR(t.GetNanoseconds() / kIterations, 500, 500); | |
232 } | |
233 #endif // #if 0 | |
234 | |
235 } // namespace omaha | |
OLD | NEW |