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