You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
14 KiB
414 lines
14 KiB
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <chrono>
|
|
#include <numeric>
|
|
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
#include "ringbuffer.h"
|
|
using namespace testing;
|
|
using namespace std::chrono_literals;
|
|
|
|
template <typename Rep, typename Per>
|
|
nsecs_t toNsecs(std::chrono::duration<Rep, Per> time) {
|
|
return std::chrono::duration_cast<std::chrono::nanoseconds>(time).count();
|
|
}
|
|
|
|
template <typename Rep, typename Per>
|
|
uint64_t toMs(std::chrono::duration<Rep, Per> time) {
|
|
return std::chrono::duration_cast<std::chrono::milliseconds>(time).count();
|
|
}
|
|
|
|
struct TimeKeeperWrapper : histogram::TimeKeeper {
|
|
TimeKeeperWrapper(std::shared_ptr<histogram::TimeKeeper> const &tk) : tk(tk) {}
|
|
nsecs_t current_time() const final { return tk->current_time(); }
|
|
std::shared_ptr<histogram::TimeKeeper> const tk;
|
|
};
|
|
|
|
struct TickingTimeKeeper : histogram::TimeKeeper {
|
|
void tick() { fake_time = fake_time + toNsecs(1ms); }
|
|
|
|
void increment_by(std::chrono::nanoseconds inc) { fake_time = fake_time + inc.count(); }
|
|
|
|
nsecs_t current_time() const final { return fake_time; }
|
|
|
|
private:
|
|
nsecs_t mutable fake_time = 0;
|
|
};
|
|
|
|
void insertFrameIncrementTimeline(histogram::Ringbuffer &rb, TickingTimeKeeper &tk,
|
|
drm_msm_hist &frame) {
|
|
rb.insert(frame);
|
|
tk.tick();
|
|
}
|
|
|
|
class RingbufferTestCases : public ::testing::Test {
|
|
void SetUp() {
|
|
for (auto i = 0u; i < HIST_V_SIZE; i++) {
|
|
frame0.data[i] = fill_frame0;
|
|
frame1.data[i] = fill_frame1;
|
|
frame2.data[i] = fill_frame2;
|
|
frame3.data[i] = fill_frame3;
|
|
frame4.data[i] = fill_frame4;
|
|
frame_saturate.data[i] = std::numeric_limits<uint32_t>::max();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
std::unique_ptr<histogram::Ringbuffer> createFilledRingbuffer(
|
|
std::shared_ptr<TickingTimeKeeper> const &tk) {
|
|
auto rb = histogram::Ringbuffer::create(4, std::make_unique<TimeKeeperWrapper>(tk));
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame1);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame2);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame3);
|
|
return rb;
|
|
}
|
|
|
|
uint64_t fill_frame0 = 9;
|
|
uint64_t fill_frame1 = 11;
|
|
uint64_t fill_frame2 = 303;
|
|
uint64_t fill_frame3 = 1030;
|
|
uint64_t fill_frame4 = 112200;
|
|
drm_msm_hist frame0;
|
|
drm_msm_hist frame1;
|
|
drm_msm_hist frame2;
|
|
drm_msm_hist frame3;
|
|
drm_msm_hist frame4;
|
|
drm_msm_hist frame_saturate;
|
|
|
|
int numFrames = 0;
|
|
std::array<uint64_t, HIST_V_SIZE> bins;
|
|
};
|
|
|
|
TEST_F(RingbufferTestCases, ZeroSizedRingbufferReturnsNull) {
|
|
EXPECT_THAT(histogram::Ringbuffer::create(0, std::make_unique<TickingTimeKeeper>()), Eq(nullptr));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, NullTimekeeperReturnsNull) {
|
|
EXPECT_THAT(histogram::Ringbuffer::create(10, nullptr), Eq(nullptr));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, CollectionWithNoFrames) {
|
|
auto rb = histogram::Ringbuffer::create(1, std::make_unique<TickingTimeKeeper>());
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(0));
|
|
EXPECT_THAT(bins, Each(0));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, SimpleTest) {
|
|
static constexpr int numInsertions = 3u;
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(numInsertions, std::make_unique<TimeKeeperWrapper>(tk));
|
|
|
|
drm_msm_hist frame;
|
|
for (auto i = 0u; i < HIST_V_SIZE; i++) {
|
|
frame.data[i] = i;
|
|
}
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
|
|
ASSERT_THAT(bins.size(), Eq(HIST_V_SIZE));
|
|
for (auto i = 0u; i < bins.size(); i++) {
|
|
EXPECT_THAT(bins[i], Eq(toMs(3ms) * i));
|
|
}
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestEvictionSingle) {
|
|
int fill_frame0 = 9;
|
|
int fill_frame1 = 111;
|
|
drm_msm_hist frame0;
|
|
drm_msm_hist frame1;
|
|
for (auto i = 0u; i < HIST_V_SIZE; i++) {
|
|
frame0.data[i] = fill_frame0;
|
|
frame1.data[i] = fill_frame1;
|
|
}
|
|
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(1));
|
|
EXPECT_THAT(bins, Each(fill_frame0));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame1);
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(1));
|
|
EXPECT_THAT(bins, Each(fill_frame1));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestEvictionMultiple) {
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(3, std::make_unique<TimeKeeperWrapper>(tk));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame1);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame2);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame3);
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3 + fill_frame0));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestResizeToZero) {
|
|
auto rb = histogram::Ringbuffer::create(4, std::make_unique<TickingTimeKeeper>());
|
|
EXPECT_FALSE(rb->resize(0));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestResizeDown) {
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = createFilledRingbuffer(tk);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(4));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
|
|
|
|
auto rc = rb->resize(2);
|
|
EXPECT_THAT(rc, Eq(true));
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame3));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestResizeUp) {
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(2, std::make_unique<TimeKeeperWrapper>(tk));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame1);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1));
|
|
|
|
auto rc = rb->resize(3);
|
|
EXPECT_THAT(rc, Eq(true));
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame2);
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame3);
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestTimestampFiltering) {
|
|
auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
|
|
|
|
std::tie(numFrames, bins) = rb->collect_after(toNsecs(1500us));
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_after(toNsecs(45000us));
|
|
EXPECT_THAT(numFrames, Eq(0));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_after(0);
|
|
EXPECT_THAT(numFrames, Eq(4));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestTimestampFilteringSameTimestamp) {
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(4, std::make_unique<TimeKeeperWrapper>(tk));
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame1);
|
|
insertFrameIncrementTimeline(*rb, *tk, frame2);
|
|
rb->insert(frame3);
|
|
rb->insert(frame4);
|
|
tk->tick();
|
|
|
|
std::tie(numFrames, bins) = rb->collect_after(toNsecs(3ms));
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame4));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestFrameFiltering) {
|
|
auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max(2);
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max(0);
|
|
EXPECT_THAT(numFrames, Eq(0));
|
|
EXPECT_THAT(bins, Each(0));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max(3);
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max(8);
|
|
EXPECT_THAT(numFrames, Eq(4));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestTimestampAndFrameFiltering) {
|
|
auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(1500us), 1);
|
|
EXPECT_THAT(numFrames, Eq(1));
|
|
EXPECT_THAT(bins, Each(fill_frame3));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(2500us), 0);
|
|
EXPECT_THAT(numFrames, Eq(0));
|
|
EXPECT_THAT(bins, Each(0));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(10ms), 100);
|
|
EXPECT_THAT(numFrames, Eq(0));
|
|
EXPECT_THAT(bins, Each(0));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(0ns), 10);
|
|
EXPECT_THAT(numFrames, Eq(4));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 + fill_frame2 + fill_frame3));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestTimestampAndFrameFilteringAndResize) {
|
|
auto rb = createFilledRingbuffer(std::make_shared<TickingTimeKeeper>());
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(500us), 1);
|
|
EXPECT_THAT(numFrames, Eq(1));
|
|
EXPECT_THAT(bins, Each(fill_frame3));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(500us), 10);
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame1 + fill_frame2 + fill_frame3));
|
|
|
|
rb->resize(2);
|
|
std::tie(numFrames, bins) = rb->collect_max_after(toNsecs(500us), 10);
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame2 + fill_frame3));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestCumulativeCounts) {
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
|
|
insertFrameIncrementTimeline(*rb, *tk, frame0);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(1));
|
|
EXPECT_THAT(bins, Each(fill_frame0));
|
|
|
|
insertFrameIncrementTimeline(*rb, *tk, frame1);
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
EXPECT_THAT(numFrames, Eq(1));
|
|
EXPECT_THAT(bins, Each(fill_frame1));
|
|
|
|
std::tie(numFrames, bins) = rb->collect_cumulative();
|
|
EXPECT_THAT(numFrames, Eq(2));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1));
|
|
rb->insert(frame2);
|
|
auto weight0 = std::chrono::duration_cast<std::chrono::nanoseconds>(1h);
|
|
tk->increment_by(weight0);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_cumulative();
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(bins, Each(fill_frame0 + fill_frame1 +
|
|
(fill_frame2 *
|
|
std::chrono::duration_cast<std::chrono::milliseconds>(weight0).count())));
|
|
|
|
auto weight1 = std::chrono::duration_cast<std::chrono::nanoseconds>(2min);
|
|
tk->increment_by(weight1);
|
|
std::tie(numFrames, bins) = rb->collect_cumulative();
|
|
EXPECT_THAT(numFrames, Eq(3));
|
|
EXPECT_THAT(
|
|
bins,
|
|
Each(fill_frame0 + fill_frame1 +
|
|
(fill_frame2 *
|
|
std::chrono::duration_cast<std::chrono::milliseconds>(weight0 + weight1).count())));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestCumulativeCountsEmpty) {
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
|
|
std::tie(numFrames, bins) = rb->collect_cumulative();
|
|
EXPECT_THAT(numFrames, Eq(0));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TestCumulativeCountsSaturate) {
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(1, std::make_unique<TimeKeeperWrapper>(tk));
|
|
insertFrameIncrementTimeline(*rb, *tk, frame_saturate);
|
|
auto eon = std::chrono::nanoseconds(std::numeric_limits<uint64_t>::max());
|
|
tk->increment_by(eon);
|
|
std::tie(numFrames, bins) = rb->collect_cumulative();
|
|
EXPECT_THAT(numFrames, Eq(1));
|
|
EXPECT_THAT(bins, Each(std::numeric_limits<uint64_t>::max()));
|
|
}
|
|
|
|
TEST_F(RingbufferTestCases, TimeWeightingTest) {
|
|
static constexpr int numInsertions = 4u;
|
|
auto tk = std::make_shared<TickingTimeKeeper>();
|
|
auto rb = histogram::Ringbuffer::create(numInsertions, std::make_unique<TimeKeeperWrapper>(tk));
|
|
|
|
auto weight0 = std::chrono::duration_cast<std::chrono::nanoseconds>(1ms);
|
|
auto weight1 = std::chrono::duration_cast<std::chrono::nanoseconds>(1h);
|
|
auto weight2 = std::chrono::duration_cast<std::chrono::nanoseconds>(1s);
|
|
using gigasecond = std::chrono::duration<uint64_t, std::giga>;
|
|
auto weight3 = std::chrono::duration_cast<std::chrono::nanoseconds>(gigasecond(4));
|
|
|
|
rb->insert(frame0);
|
|
tk->increment_by(weight0);
|
|
rb->insert(frame1);
|
|
tk->increment_by(weight1);
|
|
rb->insert(frame2);
|
|
tk->increment_by(weight2);
|
|
rb->insert(frame3);
|
|
tk->increment_by(weight3);
|
|
|
|
std::tie(numFrames, bins) = rb->collect_ringbuffer_all();
|
|
|
|
ASSERT_THAT(bins.size(), Eq(HIST_V_SIZE));
|
|
uint64_t expected_weight = fill_frame0 * toMs(weight0) + fill_frame1 * toMs(weight1) +
|
|
fill_frame2 * toMs(weight2) + fill_frame3 * toMs(weight3);
|
|
for (auto i = 0u; i < bins.size(); i++) {
|
|
EXPECT_THAT(bins[i], Eq(expected_weight));
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|