1 /*
2 * Copyright (C) 2018 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 #include <chrono>
18 #include <numeric>
19
20 #include <gtest/gtest.h>
21 #include <gmock/gmock.h>
22 #include "ringbuffer.h"
23 using namespace testing;
24 using namespace std::chrono_literals;
25
26 template <typename Rep, typename Per>
toNsecs(std::chrono::duration<Rep,Per> time)27 nsecs_t toNsecs(std::chrono::duration<Rep, Per> time) {
28 return std::chrono::duration_cast<std::chrono::nanoseconds>(time).count();
29 }
30
31 template <typename Rep, typename Per>
toMs(std::chrono::duration<Rep,Per> time)32 uint64_t toMs(std::chrono::duration<Rep, Per> time) {
33 return std::chrono::duration_cast<std::chrono::milliseconds>(time).count();
34 }
35
36 struct TimeKeeperWrapper : histogram::TimeKeeper {
TimeKeeperWrapperTimeKeeperWrapper37 TimeKeeperWrapper(std::shared_ptr<histogram::TimeKeeper> const &tk) : tk(tk) {}
current_timeTimeKeeperWrapper38 nsecs_t current_time() const final { return tk->current_time(); }
39 std::shared_ptr<histogram::TimeKeeper> const tk;
40 };
41
42 struct TickingTimeKeeper : histogram::TimeKeeper {
tickTickingTimeKeeper43 void tick() { fake_time = fake_time + toNsecs(1ms); }
44
increment_byTickingTimeKeeper45 void increment_by(std::chrono::nanoseconds inc) { fake_time = fake_time + inc.count(); }
46
current_timeTickingTimeKeeper47 nsecs_t current_time() const final { return fake_time; }
48
49 private:
50 nsecs_t mutable fake_time = 0;
51 };
52
insertFrameIncrementTimeline(histogram::Ringbuffer & rb,TickingTimeKeeper & tk,drm_msm_hist & frame)53 void insertFrameIncrementTimeline(histogram::Ringbuffer &rb, TickingTimeKeeper &tk,
54 drm_msm_hist &frame) {
55 rb.insert(frame);
56 tk.tick();
57 }
58
59 class RingbufferTestCases : public ::testing::Test {
SetUp()60 void SetUp() {
61 for (auto i = 0u; i < HIST_V_SIZE; i++) {
62 frame0.data[i] = fill_frame0;
63 frame1.data[i] = fill_frame1;
64 frame2.data[i] = fill_frame2;
65 frame3.data[i] = fill_frame3;
66 frame4.data[i] = fill_frame4;
67 frame_saturate.data[i] = std::numeric_limits<uint32_t>::max();
68 }
69 }
70
71 protected:
createFilledRingbuffer(std::shared_ptr<TickingTimeKeeper> const & tk)72 std::unique_ptr<histogram::Ringbuffer> createFilledRingbuffer(
73 std::shared_ptr<TickingTimeKeeper> const &tk) {
74 auto rb = histogram::Ringbuffer::create(4, std::make_unique<TimeKeeperWrapper>(tk));
75 insertFrameIncrementTimeline(*rb, *tk, frame0);
76 insertFrameIncrementTimeline(*rb, *tk, frame1);
77 insertFrameIncrementTimeline(*rb, *tk, frame2);
78 insertFrameIncrementTimeline(*rb, *tk, frame3);
79 return rb;
80 }
81
82 uint64_t fill_frame0 = 9;
83 uint64_t fill_frame1 = 11;
84 uint64_t fill_frame2 = 303;
85 uint64_t fill_frame3 = 1030;
86 uint64_t fill_frame4 = 112200;
87 drm_msm_hist frame0;
88 drm_msm_hist frame1;
89 drm_msm_hist frame2;
90 drm_msm_hist frame3;
91 drm_msm_hist frame4;
92 drm_msm_hist frame_saturate;
93
94 int numFrames = 0;
95 std::array<uint64_t, HIST_V_SIZE> bins;
96 };
97
TEST_F(RingbufferTestCases,ZeroSizedRingbufferReturnsNull)98 TEST_F(RingbufferTestCases, ZeroSizedRingbufferReturnsNull) {
99 EXPECT_THAT(histogram::Ringbuffer::create(0, std::make_unique<TickingTimeKeeper>()),
100 Eq(nullptr));
101 }
102
TEST_F(RingbufferTestCases,NullTimekeeperReturnsNull)103 TEST_F(RingbufferTestCases, NullTimekeeperReturnsNull) {
104 EXPECT_THAT(histogram::Ringbuffer::create(10, nullptr), Eq(nullptr));
105 }
106
TEST_F(RingbufferTestCases,CollectionWithNoFrames)107 TEST_F(RingbufferTestCases, CollectionWithNoFrames) {
108 auto rb = histogram::Ringbuffer::create(1, std::make_unique<TickingTimeKeeper>());
109
110 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
111 EXPECT_THAT(numFrames, Eq(0));
112 EXPECT_THAT(bins, Each(0));
113 }
114
TEST_F(RingbufferTestCases,SimpleTest)115 TEST_F(RingbufferTestCases, SimpleTest) {
116 static constexpr int numInsertions = 3u;
117 auto tk = std::make_shared<TickingTimeKeeper>();
118 auto rb = histogram::Ringbuffer::create(numInsertions, std::make_unique<TimeKeeperWrapper>(tk));
119
120 drm_msm_hist frame;
121 for (auto i = 0u; i < HIST_V_SIZE; i++) {
122 frame.data[i] = i;
123 }
124
125 insertFrameIncrementTimeline(*rb, *tk, frame);
126 insertFrameIncrementTimeline(*rb, *tk, frame);
127 insertFrameIncrementTimeline(*rb, *tk, frame);
128
129 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
130
131 ASSERT_THAT(bins.size(), Eq(HIST_V_SIZE));
132 for (auto i = 0u; i < bins.size(); i++) {
133 EXPECT_THAT(bins[i], Eq(toMs(3ms) * i));
134 }
135 }
136
TEST_F(RingbufferTestCases,TestEvictionSingle)137 TEST_F(RingbufferTestCases, TestEvictionSingle) {
138 int fill_frame0 = 9;
139 int fill_frame1 = 111;
140 drm_msm_hist frame0;
141 drm_msm_hist frame1;
142 for (auto i = 0u; i < HIST_V_SIZE; i++) {
143 frame0.data[i] = fill_frame0;
144 frame1.data[i] = fill_frame1;
145 }
146
147 auto tk = std::make_shared<TickingTimeKeeper>();
148 auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
149
150 insertFrameIncrementTimeline(*rb, *tk, frame0);
151
152 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
153 EXPECT_THAT(numFrames, Eq(1));
154 EXPECT_THAT(bins, Each(fill_frame0));
155
156 insertFrameIncrementTimeline(*rb, *tk, frame1);
157 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
158 EXPECT_THAT(numFrames, Eq(1));
159 EXPECT_THAT(bins, Each(fill_frame1));
160 }
161
TEST_F(RingbufferTestCases,TestEvictionMultiple)162 TEST_F(RingbufferTestCases, TestEvictionMultiple) {
163 auto tk = std::make_shared<TickingTimeKeeper>();
164 auto rb = histogram::Ringbuffer::create(3, std::make_unique<TimeKeeperWrapper>(tk));
165
166 insertFrameIncrementTimeline(*rb, *tk, frame0);
167 insertFrameIncrementTimeline(*rb, *tk, frame1);
168 insertFrameIncrementTimeline(*rb, *tk, frame2);
169
170 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
171 EXPECT_THAT(numFrames, Eq(3));
172 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2));
173
174 insertFrameIncrementTimeline(*rb, *tk, frame3);
175 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
176 EXPECT_THAT(numFrames, Eq(3));
177 EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
178
179 insertFrameIncrementTimeline(*rb, *tk, frame0);
180 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
181 EXPECT_THAT(numFrames, Eq(3));
182 EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3 + fill_frame0));
183 }
184
TEST_F(RingbufferTestCases,TestResizeToZero)185 TEST_F(RingbufferTestCases, TestResizeToZero) {
186 auto rb = histogram::Ringbuffer::create(4, std::make_unique<TickingTimeKeeper>());
187 EXPECT_FALSE(rb->resize(0));
188 }
189
TEST_F(RingbufferTestCases,TestResizeDown)190 TEST_F(RingbufferTestCases, TestResizeDown) {
191 auto tk = std::make_shared<TickingTimeKeeper>();
192 auto rb = createFilledRingbuffer(tk);
193
194 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
195 EXPECT_THAT(numFrames, Eq(4));
196 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
197
198 auto rc = rb->resize(2);
199 EXPECT_THAT(rc, Eq(true));
200 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
201 EXPECT_THAT(numFrames, Eq(2));
202 EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
203
204 insertFrameIncrementTimeline(*rb, *tk, frame0);
205 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
206 EXPECT_THAT(numFrames, Eq(2));
207 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame3));
208 }
209
TEST_F(RingbufferTestCases,TestResizeUp)210 TEST_F(RingbufferTestCases, TestResizeUp) {
211 auto tk = std::make_shared<TickingTimeKeeper>();
212 auto rb = histogram::Ringbuffer::create(2, std::make_unique<TimeKeeperWrapper>(tk));
213
214 insertFrameIncrementTimeline(*rb, *tk, frame0);
215 insertFrameIncrementTimeline(*rb, *tk, frame1);
216
217 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
218 EXPECT_THAT(numFrames, Eq(2));
219 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1));
220
221 auto rc = rb->resize(3);
222 EXPECT_THAT(rc, Eq(true));
223 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
224 EXPECT_THAT(numFrames, Eq(2));
225 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1));
226
227 insertFrameIncrementTimeline(*rb, *tk, frame2);
228 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
229 EXPECT_THAT(numFrames, Eq(3));
230 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2));
231
232 insertFrameIncrementTimeline(*rb, *tk, frame3);
233 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
234 EXPECT_THAT(numFrames, Eq(3));
235 EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
236 }
237
TEST_F(RingbufferTestCases,TestTimestampFiltering)238 TEST_F(RingbufferTestCases, TestTimestampFiltering) {
239 auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
240
241 std::tie(numFrames, bins) = rb->collect_after(toNsecs(1500us));
242 EXPECT_THAT(numFrames, Eq(2));
243 EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
244
245 std::tie(numFrames, bins) = rb->collect_after(toNsecs(45000us));
246 EXPECT_THAT(numFrames, Eq(0));
247
248 std::tie(numFrames, bins) = rb->collect_after(0);
249 EXPECT_THAT(numFrames, Eq(4));
250 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
251 }
252
TEST_F(RingbufferTestCases,TestTimestampFilteringSameTimestamp)253 TEST_F(RingbufferTestCases, TestTimestampFilteringSameTimestamp) {
254 auto tk = std::make_shared<TickingTimeKeeper>();
255 auto rb = histogram::Ringbuffer::create(4, std::make_unique<TimeKeeperWrapper>(tk));
256 insertFrameIncrementTimeline(*rb, *tk, frame0);
257 insertFrameIncrementTimeline(*rb, *tk, frame1);
258 insertFrameIncrementTimeline(*rb, *tk, frame2);
259 rb->insert(frame3);
260 rb->insert(frame4);
261 tk->tick();
262
263 std::tie(numFrames, bins) = rb->collect_after(toNsecs(3ms));
264 EXPECT_THAT(numFrames, Eq(2));
265 EXPECT_THAT(bins, Each(fill_frame4));
266 }
267
TEST_F(RingbufferTestCases,TestFrameFiltering)268 TEST_F(RingbufferTestCases, TestFrameFiltering) {
269 auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
270
271 std::tie(numFrames, bins) = rb->collect_max(2);
272 EXPECT_THAT(numFrames, Eq(2));
273 EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
274
275 std::tie(numFrames, bins) = rb->collect_max(0);
276 EXPECT_THAT(numFrames, Eq(0));
277 EXPECT_THAT(bins, Each(0));
278
279 std::tie(numFrames, bins) = rb->collect_max(3);
280 EXPECT_THAT(numFrames, Eq(3));
281 EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
282
283 std::tie(numFrames, bins) = rb->collect_max(8);
284 EXPECT_THAT(numFrames, Eq(4));
285 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
286 }
287
TEST_F(RingbufferTestCases,TestTimestampAndFrameFiltering)288 TEST_F(RingbufferTestCases, TestTimestampAndFrameFiltering) {
289 auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
290
291 std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(1500us), 1);
292 EXPECT_THAT(numFrames, Eq(1));
293 EXPECT_THAT(bins, Each(fill_frame3));
294
295 std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(2500us), 0);
296 EXPECT_THAT(numFrames, Eq(0));
297 EXPECT_THAT(bins, Each(0));
298
299 std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(10ms), 100);
300 EXPECT_THAT(numFrames, Eq(0));
301 EXPECT_THAT(bins, Each(0));
302
303 std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(0ns), 10);
304 EXPECT_THAT(numFrames, Eq(4));
305 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
306 }
307
TEST_F(RingbufferTestCases,TestTimestampAndFrameFilteringAndResize)308 TEST_F(RingbufferTestCases, TestTimestampAndFrameFilteringAndResize) {
309 auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
310
311 std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(500us), 1);
312 EXPECT_THAT(numFrames, Eq(1));
313 EXPECT_THAT(bins, Each(fill_frame3));
314
315 std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(500us), 10);
316 EXPECT_THAT(numFrames, Eq(3));
317 EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
318
319 rb->resize(2);
320 std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(500us), 10);
321 EXPECT_THAT(numFrames, Eq(2));
322 EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
323 }
324
TEST_F(RingbufferTestCases,TestCumulativeCounts)325 TEST_F(RingbufferTestCases, TestCumulativeCounts) {
326 auto tk = std::make_shared<TickingTimeKeeper>();
327 auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
328 insertFrameIncrementTimeline(*rb, *tk, frame0);
329
330 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
331 EXPECT_THAT(numFrames, Eq(1));
332 EXPECT_THAT(bins, Each(fill_frame0));
333
334 insertFrameIncrementTimeline(*rb, *tk, frame1);
335 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
336 EXPECT_THAT(numFrames, Eq(1));
337 EXPECT_THAT(bins, Each(fill_frame1));
338
339 std::tie(numFrames, bins) = rb->collect_cumulative();
340 EXPECT_THAT(numFrames, Eq(2));
341 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1));
342 rb->insert(frame2);
343 auto weight0 = std::chrono::duration_cast<std::chrono::nanoseconds>(1h);
344 tk->increment_by(weight0);
345
346 std::tie(numFrames, bins) = rb->collect_cumulative();
347 EXPECT_THAT(numFrames, Eq(3));
348 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + (fill_frame2 *
349 std::chrono::duration_cast<std::chrono::milliseconds>(weight0).count())));
350
351 auto weight1 = std::chrono::duration_cast<std::chrono::nanoseconds>(2min);
352 tk->increment_by(weight1);
353 std::tie(numFrames, bins) = rb->collect_cumulative();
354 EXPECT_THAT(numFrames, Eq(3));
355 EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + (fill_frame2 *
356 std::chrono::duration_cast<std::chrono::milliseconds>(weight0 + weight1).count())));
357 }
358
TEST_F(RingbufferTestCases,TestCumulativeCountsEmpty)359 TEST_F(RingbufferTestCases, TestCumulativeCountsEmpty) {
360 auto tk = std::make_shared<TickingTimeKeeper>();
361 auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
362 std::tie(numFrames, bins) = rb->collect_cumulative();
363 EXPECT_THAT(numFrames, Eq(0));
364 }
365
TEST_F(RingbufferTestCases,TestCumulativeCountsSaturate)366 TEST_F(RingbufferTestCases, TestCumulativeCountsSaturate) {
367 auto tk = std::make_shared<TickingTimeKeeper>();
368 auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
369 insertFrameIncrementTimeline(*rb, *tk, frame_saturate);
370 auto eon = std::chrono::nanoseconds(std::numeric_limits<uint64_t>::max());
371 tk->increment_by(eon);
372 std::tie(numFrames, bins) = rb->collect_cumulative();
373 EXPECT_THAT(numFrames, Eq(1));
374 EXPECT_THAT(bins, Each(std::numeric_limits<uint64_t>::max()));
375 }
376
TEST_F(RingbufferTestCases,TimeWeightingTest)377 TEST_F(RingbufferTestCases, TimeWeightingTest) {
378 static constexpr int numInsertions = 4u;
379 auto tk = std::make_shared<TickingTimeKeeper>();
380 auto rb = histogram::Ringbuffer::create(numInsertions, std::make_unique<TimeKeeperWrapper>(tk));
381
382 auto weight0 = std::chrono::duration_cast<std::chrono::nanoseconds>(1ms);
383 auto weight1 = std::chrono::duration_cast<std::chrono::nanoseconds>(1h);
384 auto weight2 = std::chrono::duration_cast<std::chrono::nanoseconds>(1s);
385 using gigasecond = std::chrono::duration<uint64_t, std::giga>;
386 auto weight3 = std::chrono::duration_cast<std::chrono::nanoseconds>(gigasecond(4));
387
388 rb->insert(frame0);
389 tk->increment_by(weight0);
390 rb->insert(frame1);
391 tk->increment_by(weight1);
392 rb->insert(frame2);
393 tk->increment_by(weight2);
394 rb->insert(frame3);
395 tk->increment_by(weight3);
396
397 std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
398
399 ASSERT_THAT(bins.size(), Eq(HIST_V_SIZE));
400 uint64_t expected_weight = fill_frame0 * toMs(weight0) + fill_frame1 * toMs(weight1) +
401 fill_frame2 * toMs(weight2) + fill_frame3 * toMs(weight3);
402 for (auto i = 0u; i < bins.size(); i++) {
403 EXPECT_THAT(bins[i], Eq(expected_weight));
404 }
405 }
406
main(int argc,char ** argv)407 int main(int argc, char** argv) {
408 ::testing::InitGoogleTest(&argc, argv);
409 return RUN_ALL_TESTS();
410 }
411