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