10
10
11
11
#include " timing.h"
12
12
13
+ #include < cstdlib>
13
14
#include < string>
14
15
15
16
class ScudoTimingTest : public Test {
@@ -33,54 +34,228 @@ class ScudoTimingTest : public Test {
33
34
34
35
void printAllTimersStats () { Manager.printAll (); }
35
36
37
+ void getAllTimersStats (scudo::ScopedString &Str) { Manager.getAll (Str); }
38
+
36
39
scudo::TimingManager &getTimingManager () { return Manager; }
37
40
41
+ void testCallTimers () {
42
+ scudo::ScopedTimer Outer (getTimingManager (), " Level1" );
43
+ {
44
+ scudo::ScopedTimer Inner1 (getTimingManager (), Outer, " Level2" );
45
+ { scudo::ScopedTimer Inner2 (getTimingManager (), Inner1, " Level3" ); }
46
+ }
47
+ }
48
+
38
49
private:
39
50
scudo::TimingManager Manager;
40
51
};
41
52
42
- // Given that the output of statistics of timers are dumped through
43
- // `scudo::Printf` which is platform dependent, so we don't have a reliable way
44
- // to catch the output and verify the details. Now we only verify the number of
45
- // invocations on linux.
46
53
TEST_F (ScudoTimingTest, SimpleTimer) {
47
- #if SCUDO_LINUX
48
- testing::internal::LogToStderr ();
49
- testing::internal::CaptureStderr ();
50
- #endif
51
-
52
54
testIgnoredTimer ();
53
55
testChainedCalls ();
54
- printAllTimersStats ();
56
+ scudo::ScopedString Str;
57
+ getAllTimersStats (Str);
55
58
56
- #if SCUDO_LINUX
57
- std::string output = testing::internal::GetCapturedStderr ();
58
- EXPECT_TRUE (output.find (" testIgnoredTimer (1)" ) == std::string::npos);
59
- EXPECT_TRUE (output.find (" testChainedCalls (1)" ) != std::string::npos);
60
- EXPECT_TRUE (output.find (" testFunc2 (1)" ) != std::string::npos);
61
- EXPECT_TRUE (output.find (" testFunc1 (1)" ) != std::string::npos);
62
- #endif
59
+ std::string Output (Str.data ());
60
+ EXPECT_TRUE (Output.find (" testIgnoredTimer (1)" ) == std::string::npos);
61
+ EXPECT_TRUE (Output.find (" testChainedCalls (1)" ) != std::string::npos);
62
+ EXPECT_TRUE (Output.find (" testFunc2 (1)" ) != std::string::npos);
63
+ EXPECT_TRUE (Output.find (" testFunc1 (1)" ) != std::string::npos);
63
64
}
64
65
65
66
TEST_F (ScudoTimingTest, NestedTimer) {
66
- #if SCUDO_LINUX
67
- testing::internal::LogToStderr ();
68
- testing::internal::CaptureStderr ();
69
- #endif
70
-
71
67
{
72
68
scudo::ScopedTimer Outer (getTimingManager (), " Outer" );
73
69
{
74
70
scudo::ScopedTimer Inner1 (getTimingManager (), Outer, " Inner1" );
75
71
{ scudo::ScopedTimer Inner2 (getTimingManager (), Inner1, " Inner2" ); }
76
72
}
77
73
}
78
- printAllTimersStats ();
74
+ scudo::ScopedString Str;
75
+ getAllTimersStats (Str);
76
+
77
+ std::string Output (Str.data ());
78
+ EXPECT_TRUE (Output.find (" Outer (1)" ) != std::string::npos);
79
+ EXPECT_TRUE (Output.find (" Inner1 (1)" ) != std::string::npos);
80
+ EXPECT_TRUE (Output.find (" Inner2 (1)" ) != std::string::npos);
81
+ }
82
+
83
+ TEST_F (ScudoTimingTest, VerifyChainedTimerCalculations) {
84
+ {
85
+ scudo::ScopedTimer Outer (getTimingManager (), " Level1" );
86
+ sleep (1 );
87
+ {
88
+ scudo::ScopedTimer Inner1 (getTimingManager (), Outer, " Level2" );
89
+ sleep (2 );
90
+ {
91
+ scudo::ScopedTimer Inner2 (getTimingManager (), Inner1, " Level3" );
92
+ sleep (3 );
93
+ }
94
+ }
95
+ }
96
+ scudo::ScopedString Str;
97
+ getAllTimersStats (Str);
98
+ std::string Output (Str.data ());
99
+
100
+ // Get the individual timer values for the average and maximum, then
101
+ // verify that the timer values are being calculated properly.
102
+ Output = Output.substr (Output.find (' \n ' ) + 1 );
103
+ char *end;
104
+ unsigned long long Level1AvgNs = std::strtoull (Output.c_str (), &end, 10 );
105
+ ASSERT_TRUE (end != nullptr );
106
+ unsigned long long Level1MaxNs = std::strtoull (&end[6 ], &end, 10 );
107
+ ASSERT_TRUE (end != nullptr );
108
+ EXPECT_EQ (Level1AvgNs, Level1MaxNs);
109
+
110
+ Output = Output.substr (Output.find (' \n ' ) + 1 );
111
+ unsigned long long Level2AvgNs = std::strtoull (Output.c_str (), &end, 10 );
112
+ ASSERT_TRUE (end != nullptr );
113
+ unsigned long long Level2MaxNs = std::strtoull (&end[6 ], &end, 10 );
114
+ ASSERT_TRUE (end != nullptr );
115
+ EXPECT_EQ (Level2AvgNs, Level2MaxNs);
116
+
117
+ Output = Output.substr (Output.find (' \n ' ) + 1 );
118
+ unsigned long long Level3AvgNs = std::strtoull (Output.c_str (), &end, 10 );
119
+ ASSERT_TRUE (end != nullptr );
120
+ unsigned long long Level3MaxNs = std::strtoull (&end[6 ], &end, 10 );
121
+ ASSERT_TRUE (end != nullptr );
122
+ EXPECT_EQ (Level3AvgNs, Level3MaxNs);
123
+
124
+ EXPECT_GT (Level1AvgNs, Level2AvgNs);
125
+ EXPECT_GT (Level2AvgNs, Level3AvgNs);
126
+
127
+ // The time for the first timer needs to be at least six seconds.
128
+ EXPECT_GT (Level1AvgNs, 6000000000U );
129
+ // The time for the second timer needs to be at least five seconds.
130
+ EXPECT_GT (Level2AvgNs, 5000000000U );
131
+ // The time for the third timer needs to be at least three seconds.
132
+ EXPECT_GT (Level3AvgNs, 3000000000U );
133
+ // The time between the first and second timer needs to be at least one
134
+ // second.
135
+ EXPECT_GT (Level1AvgNs - Level2AvgNs, 1000000000U );
136
+ // The time between the second and third timer needs to be at least two
137
+ // second.
138
+ EXPECT_GT (Level2AvgNs - Level3AvgNs, 2000000000U );
139
+ }
140
+
141
+ TEST_F (ScudoTimingTest, VerifyMax) {
142
+ for (size_t i = 0 ; i < 3 ; i++) {
143
+ scudo::ScopedTimer Outer (getTimingManager (), " Level1" );
144
+ sleep (1 );
145
+ }
146
+ scudo::ScopedString Str;
147
+ getAllTimersStats (Str);
148
+ std::string Output (Str.data ());
149
+
150
+ Output = Output.substr (Output.find (' \n ' ) + 1 );
151
+ char *end;
152
+ unsigned long long AvgNs = std::strtoull (Output.c_str (), &end, 10 );
153
+ ASSERT_TRUE (end != nullptr );
154
+ unsigned long long MaxNs = std::strtoull (&end[6 ], &end, 10 );
155
+ ASSERT_TRUE (end != nullptr );
156
+
157
+ EXPECT_GT (MaxNs, AvgNs);
158
+ }
159
+
160
+ TEST_F (ScudoTimingTest, VerifyMultipleTimerCalls) {
161
+ for (size_t i = 0 ; i < 5 ; i++)
162
+ testCallTimers ();
163
+
164
+ scudo::ScopedString Str;
165
+ getAllTimersStats (Str);
166
+ std::string Output (Str.data ());
167
+ EXPECT_TRUE (Output.find (" Level1 (5)" ) != std::string::npos);
168
+ EXPECT_TRUE (Output.find (" Level2 (5)" ) != std::string::npos);
169
+ EXPECT_TRUE (Output.find (" Level3 (5)" ) != std::string::npos);
170
+ }
171
+
172
+ TEST_F (ScudoTimingTest, VerifyHeader) {
173
+ { scudo::ScopedTimer Outer (getTimingManager (), " Timer" ); }
174
+ scudo::ScopedString Str;
175
+ getAllTimersStats (Str);
176
+
177
+ std::string Output (Str.data ());
178
+ std::string Header (Output.substr (0 , Output.find (' \n ' )));
179
+ EXPECT_EQ (Header, " -- Average Operation Time -- -- Maximum Operation Time -- "
180
+ " -- Name (# of Calls) --" );
181
+ }
182
+
183
+ TEST_F (ScudoTimingTest, VerifyTimerFormat) {
184
+ testCallTimers ();
185
+ scudo::ScopedString Str;
186
+ getAllTimersStats (Str);
187
+ std::string Output (Str.data ());
188
+
189
+ // Check the top level line, should look similar to:
190
+ // 11718.0(ns) 11718(ns) Level1 (1)
191
+ Output = Output.substr (Output.find (' \n ' ) + 1 );
192
+
193
+ // Verify that the Average Operation Time is in the correct location.
194
+ EXPECT_EQ (" .0(ns) " , Output.substr (14 , 7 ));
195
+
196
+ // Verify that the Maximum Operation Time is in the correct location.
197
+ EXPECT_EQ (" (ns) " , Output.substr (45 , 5 ));
198
+
199
+ // Verify that the first timer name is in the correct location.
200
+ EXPECT_EQ (" Level1 (1)\n " , Output.substr (61 , 11 ));
201
+
202
+ // Check a chained timer, should look similar to:
203
+ // 5331.0(ns) 5331(ns) Level2 (1)
204
+ Output = Output.substr (Output.find (' \n ' ) + 1 );
205
+
206
+ // Verify that the Average Operation Time is in the correct location.
207
+ EXPECT_EQ (" .0(ns) " , Output.substr (14 , 7 ));
208
+
209
+ // Verify that the Maximum Operation Time is in the correct location.
210
+ EXPECT_EQ (" (ns) " , Output.substr (45 , 5 ));
211
+
212
+ // Verify that the first timer name is in the correct location.
213
+ EXPECT_EQ (" Level2 (1)\n " , Output.substr (61 , 13 ));
214
+
215
+ // Check a secondary chained timer, should look similar to:
216
+ // 814.0(ns) 814(ns) Level3 (1)
217
+ Output = Output.substr (Output.find (' \n ' ) + 1 );
218
+
219
+ // Verify that the Average Operation Time is in the correct location.
220
+ EXPECT_EQ (" .0(ns) " , Output.substr (14 , 7 ));
221
+
222
+ // Verify that the Maximum Operation Time is in the correct location.
223
+ EXPECT_EQ (" (ns) " , Output.substr (45 , 5 ));
224
+
225
+ // Verify that the first timer name is in the correct location.
226
+ EXPECT_EQ (" Level3 (1)\n " , Output.substr (61 , 15 ));
227
+ }
79
228
80
229
#if SCUDO_LINUX
81
- std::string output = testing::internal::GetCapturedStderr ();
82
- EXPECT_TRUE (output.find (" Outer (1)" ) != std::string::npos);
83
- EXPECT_TRUE (output.find (" Inner1 (1)" ) != std::string::npos);
84
- EXPECT_TRUE (output.find (" Inner2 (1)" ) != std::string::npos);
230
+ TEST_F (ScudoTimingTest, VerifyPrintMatchesGet) {
231
+ testing::internal::LogToStderr ();
232
+ testing::internal::CaptureStderr ();
233
+ testCallTimers ();
234
+
235
+ { scudo::ScopedTimer Outer (getTimingManager (), " Timer" ); }
236
+ printAllTimersStats ();
237
+ std::string PrintOutput = testing::internal::GetCapturedStderr ();
238
+ EXPECT_TRUE (PrintOutput.size () != 0 );
239
+
240
+ scudo::ScopedString Str;
241
+ getAllTimersStats (Str);
242
+ std::string GetOutput (Str.data ());
243
+ EXPECT_TRUE (GetOutput.size () != 0 );
244
+
245
+ EXPECT_EQ (PrintOutput, GetOutput);
246
+ }
85
247
#endif
248
+
249
+ #if SCUDO_LINUX
250
+ TEST_F (ScudoTimingTest, VerifyReporting) {
251
+ testing::internal::LogToStderr ();
252
+ testing::internal::CaptureStderr ();
253
+ // Every 100 calls generates a report, but run a few extra to verify the
254
+ // report happened at call 100.
255
+ for (size_t i = 0 ; i < 110 ; i++)
256
+ scudo::ScopedTimer Outer (getTimingManager (), " VerifyReportTimer" );
257
+
258
+ std::string Output = testing::internal::GetCapturedStderr ();
259
+ EXPECT_TRUE (Output.find (" VerifyReportTimer (100)" ) != std::string::npos);
86
260
}
261
+ #endif
0 commit comments