1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #include <android-base/file.h>
19 #include <android-base/test_utils.h>
20 #include <androidfw/Util.h>
21
22 #include "TestHelpers.h"
23
24 #include <androidfw/ResourceTimer.h>
25
26 namespace android {
27
28 namespace {
29
30 // Create a reading in us. This is a convenience function to avoid multiplying by 1000
31 // everywhere.
US(int us)32 unsigned int US(int us) {
33 return us * 1000;
34 }
35
36 }
37
TEST(ResourceTimerTest,TimerBasic)38 TEST(ResourceTimerTest, TimerBasic) {
39 ResourceTimer::Timer timer;
40 ASSERT_THAT(timer.count, 0);
41 ASSERT_THAT(timer.total, 0);
42
43 for (int i = 1; i <= 100; i++) {
44 timer.record(US(i));
45 }
46 ASSERT_THAT(timer.count, 100);
47 ASSERT_THAT(timer.total, US((101 * 100)/2));
48 ASSERT_THAT(timer.mintime, US(1));
49 ASSERT_THAT(timer.maxtime, US(100));
50 ASSERT_THAT(timer.pvalues.p50.floor, 0);
51 ASSERT_THAT(timer.pvalues.p50.nominal, 0);
52 ASSERT_THAT(timer.largest[0], US(100));
53 ASSERT_THAT(timer.largest[1], US(99));
54 ASSERT_THAT(timer.largest[2], US(98));
55 ASSERT_THAT(timer.largest[3], US(97));
56 ASSERT_THAT(timer.largest[4], US(96));
57 timer.compute();
58 ASSERT_THAT(timer.pvalues.p50.floor, US(49));
59 ASSERT_THAT(timer.pvalues.p50.nominal, US(50));
60 ASSERT_THAT(timer.pvalues.p90.floor, US(89));
61 ASSERT_THAT(timer.pvalues.p90.nominal, US(90));
62 ASSERT_THAT(timer.pvalues.p95.floor, US(94));
63 ASSERT_THAT(timer.pvalues.p95.nominal, US(95));
64 ASSERT_THAT(timer.pvalues.p99.floor, US(98));
65 ASSERT_THAT(timer.pvalues.p99.nominal, US(99));
66
67 // Test reset functionality. All values should be zero after the reset. Computing pvalues
68 // after the result should also yield zeros.
69 timer.reset();
70 ASSERT_THAT(timer.count, 0);
71 ASSERT_THAT(timer.total, 0);
72 ASSERT_THAT(timer.mintime, US(0));
73 ASSERT_THAT(timer.maxtime, US(0));
74 ASSERT_THAT(timer.pvalues.p50.floor, US(0));
75 ASSERT_THAT(timer.pvalues.p50.nominal, US(0));
76 ASSERT_THAT(timer.largest[0], US(0));
77 ASSERT_THAT(timer.largest[1], US(0));
78 ASSERT_THAT(timer.largest[2], US(0));
79 ASSERT_THAT(timer.largest[3], US(0));
80 ASSERT_THAT(timer.largest[4], US(0));
81 timer.compute();
82 ASSERT_THAT(timer.pvalues.p50.floor, US(0));
83 ASSERT_THAT(timer.pvalues.p50.nominal, US(0));
84 ASSERT_THAT(timer.pvalues.p90.floor, US(0));
85 ASSERT_THAT(timer.pvalues.p90.nominal, US(0));
86 ASSERT_THAT(timer.pvalues.p95.floor, US(0));
87 ASSERT_THAT(timer.pvalues.p95.nominal, US(0));
88 ASSERT_THAT(timer.pvalues.p99.floor, US(0));
89 ASSERT_THAT(timer.pvalues.p99.nominal, US(0));
90
91 // Test again, adding elements in reverse.
92 for (int i = 100; i >= 1; i--) {
93 timer.record(US(i));
94 }
95 ASSERT_THAT(timer.count, 100);
96 ASSERT_THAT(timer.total, US((101 * 100)/2));
97 ASSERT_THAT(timer.mintime, US(1));
98 ASSERT_THAT(timer.maxtime, US(100));
99 ASSERT_THAT(timer.pvalues.p50.floor, 0);
100 ASSERT_THAT(timer.pvalues.p50.nominal, 0);
101 timer.compute();
102 ASSERT_THAT(timer.pvalues.p50.floor, US(49));
103 ASSERT_THAT(timer.pvalues.p50.nominal, US(50));
104 ASSERT_THAT(timer.pvalues.p90.floor, US(89));
105 ASSERT_THAT(timer.pvalues.p90.nominal, US(90));
106 ASSERT_THAT(timer.pvalues.p95.floor, US(94));
107 ASSERT_THAT(timer.pvalues.p95.nominal, US(95));
108 ASSERT_THAT(timer.pvalues.p99.floor, US(98));
109 ASSERT_THAT(timer.pvalues.p99.nominal, US(99));
110 ASSERT_THAT(timer.largest[0], US(100));
111 ASSERT_THAT(timer.largest[1], US(99));
112 ASSERT_THAT(timer.largest[2], US(98));
113 ASSERT_THAT(timer.largest[3], US(97));
114 ASSERT_THAT(timer.largest[4], US(96));
115 }
116
TEST(ResourceTimerTest,TimerLimit)117 TEST(ResourceTimerTest, TimerLimit) {
118 ResourceTimer::Timer timer;
119
120 // Event truncation means that a time of 1050us will be stored in the 1000us
121 // bucket. Since there is a single event, all p-values lie in the same range.
122 timer.record(US(1050));
123 timer.compute();
124 ASSERT_THAT(timer.pvalues.p50.floor, US(900));
125 ASSERT_THAT(timer.pvalues.p50.nominal, US(1000));
126 ASSERT_THAT(timer.pvalues.p90.floor, US(900));
127 ASSERT_THAT(timer.pvalues.p90.nominal, US(1000));
128 ASSERT_THAT(timer.pvalues.p95.floor, US(900));
129 ASSERT_THAT(timer.pvalues.p95.nominal, US(1000));
130 ASSERT_THAT(timer.pvalues.p99.floor, US(900));
131 ASSERT_THAT(timer.pvalues.p99.nominal, US(1000));
132 }
133
TEST(ResourceTimerTest,TimerCopy)134 TEST(ResourceTimerTest, TimerCopy) {
135 ResourceTimer::Timer source;
136 for (int i = 1; i <= 100; i++) {
137 source.record(US(i));
138 }
139 ResourceTimer::Timer timer;
140 ResourceTimer::Timer::copy(timer, source, true);
141 ASSERT_THAT(source.count, 0);
142 ASSERT_THAT(source.total, 0);
143 // compute() is not normally be called on a reset timer, but it should work and it should return
144 // all zeros.
145 source.compute();
146 ASSERT_THAT(source.pvalues.p50.floor, US(0));
147 ASSERT_THAT(source.pvalues.p50.nominal, US(0));
148 ASSERT_THAT(source.pvalues.p90.floor, US(0));
149 ASSERT_THAT(source.pvalues.p90.nominal, US(0));
150 ASSERT_THAT(source.pvalues.p95.floor, US(0));
151 ASSERT_THAT(source.pvalues.p95.nominal, US(0));
152 ASSERT_THAT(source.pvalues.p99.floor, US(0));
153 ASSERT_THAT(source.pvalues.p99.nominal, US(0));
154 ASSERT_THAT(source.largest[0], US(0));
155 ASSERT_THAT(source.largest[1], US(0));
156 ASSERT_THAT(source.largest[2], US(0));
157 ASSERT_THAT(source.largest[3], US(0));
158 ASSERT_THAT(source.largest[4], US(0));
159
160 timer.compute();
161 ASSERT_THAT(timer.pvalues.p50.floor, US(49));
162 ASSERT_THAT(timer.pvalues.p50.nominal, US(50));
163 ASSERT_THAT(timer.pvalues.p90.floor, US(89));
164 ASSERT_THAT(timer.pvalues.p90.nominal, US(90));
165 ASSERT_THAT(timer.pvalues.p95.floor, US(94));
166 ASSERT_THAT(timer.pvalues.p95.nominal, US(95));
167 ASSERT_THAT(timer.pvalues.p99.floor, US(98));
168 ASSERT_THAT(timer.pvalues.p99.nominal, US(99));
169 ASSERT_THAT(timer.largest[0], US(100));
170 ASSERT_THAT(timer.largest[1], US(99));
171 ASSERT_THAT(timer.largest[2], US(98));
172 ASSERT_THAT(timer.largest[3], US(97));
173 ASSERT_THAT(timer.largest[4], US(96));
174
175 // Call compute a second time. The values must be the same.
176 timer.compute();
177 ASSERT_THAT(timer.pvalues.p50.floor, US(49));
178 ASSERT_THAT(timer.pvalues.p50.nominal, US(50));
179 ASSERT_THAT(timer.pvalues.p90.floor, US(89));
180 ASSERT_THAT(timer.pvalues.p90.nominal, US(90));
181 ASSERT_THAT(timer.pvalues.p95.floor, US(94));
182 ASSERT_THAT(timer.pvalues.p95.nominal, US(95));
183 ASSERT_THAT(timer.pvalues.p99.floor, US(98));
184 ASSERT_THAT(timer.pvalues.p99.nominal, US(99));
185 ASSERT_THAT(timer.largest[0], US(100));
186 ASSERT_THAT(timer.largest[1], US(99));
187 ASSERT_THAT(timer.largest[2], US(98));
188 ASSERT_THAT(timer.largest[3], US(97));
189 ASSERT_THAT(timer.largest[4], US(96));
190
191 // Modify the source. If timer and source share histogram arrays, this will introduce an
192 // error.
193 for (int i = 1; i <= 100; i++) {
194 source.record(US(i));
195 }
196 // Call compute a third time. The values must be the same.
197 timer.compute();
198 ASSERT_THAT(timer.pvalues.p50.floor, US(49));
199 ASSERT_THAT(timer.pvalues.p50.nominal, US(50));
200 ASSERT_THAT(timer.pvalues.p90.floor, US(89));
201 ASSERT_THAT(timer.pvalues.p90.nominal, US(90));
202 ASSERT_THAT(timer.pvalues.p95.floor, US(94));
203 ASSERT_THAT(timer.pvalues.p95.nominal, US(95));
204 ASSERT_THAT(timer.pvalues.p99.floor, US(98));
205 ASSERT_THAT(timer.pvalues.p99.nominal, US(99));
206 ASSERT_THAT(timer.largest[0], US(100));
207 ASSERT_THAT(timer.largest[1], US(99));
208 ASSERT_THAT(timer.largest[2], US(98));
209 ASSERT_THAT(timer.largest[3], US(97));
210 ASSERT_THAT(timer.largest[4], US(96));
211 }
212
213 // Verify that if too many oversize entries are reported, the percentile values cannot be computed
214 // and are set to zero.
TEST(ResourceTimerTest,TimerOversize)215 TEST(ResourceTimerTest, TimerOversize) {
216 static const int oversize = US(2 * 1000 * 1000);
217
218 ResourceTimer::Timer timer;
219 for (int i = 1; i <= 100; i++) {
220 timer.record(US(i));
221 }
222
223 // Insert enough oversize values to invalidate the p90, p95, and p99 percentiles. The p50 is
224 // still computable.
225 for (int i = 1; i <= 50; i++) {
226 timer.record(oversize);
227 }
228 ASSERT_THAT(timer.largest[0], oversize);
229 ASSERT_THAT(timer.largest[1], oversize);
230 ASSERT_THAT(timer.largest[2], oversize);
231 ASSERT_THAT(timer.largest[3], oversize);
232 ASSERT_THAT(timer.largest[4], oversize);
233 timer.compute();
234 ASSERT_THAT(timer.pvalues.p50.floor, US(74));
235 ASSERT_THAT(timer.pvalues.p50.nominal, US(75));
236 ASSERT_THAT(timer.pvalues.p90.floor, 0);
237 ASSERT_THAT(timer.pvalues.p90.nominal, 0);
238 ASSERT_THAT(timer.pvalues.p95.floor, 0);
239 ASSERT_THAT(timer.pvalues.p95.nominal, 0);
240 ASSERT_THAT(timer.pvalues.p99.floor, 0);
241 ASSERT_THAT(timer.pvalues.p99.nominal, 0);
242 }
243
244
245 } // namespace android
246