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