blob: 3d6a0f63d8730801235217fa12b365e1a0aadb6c [file] [log] [blame]
/*
* Copyright (C) 2021 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 "src/trace_processor/prelude/table_functions/experimental_flat_slice.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace trace_processor {
namespace {
class TableInseter {
public:
void Insert(int64_t ts, int64_t dur, uint32_t depth, TrackId track_id) {
tables::SliceTable::Row row;
row.ts = ts;
row.dur = dur;
row.depth = depth;
row.track_id = track_id;
rows_.emplace_back(std::move(row));
}
void Populate(tables::SliceTable& table) {
using R = tables::SliceTable::Row;
std::sort(rows_.begin(), rows_.end(),
[](const R& a, const R& b) { return a.ts < b.ts; });
for (const auto& row : rows_) {
table.Insert(row);
}
rows_.clear();
}
private:
std::vector<tables::SliceTable::Row> rows_;
};
class TableAsserter {
public:
TableAsserter(Table table) : table_(std::move(table)) {}
void NextSlice(int64_t ts, int64_t dur) {
++idx_;
ASSERT_LT(idx_, table_.row_count());
ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("ts")[idx_], ts)
<< "where idx_ = " << idx_;
ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("dur")[idx_], dur)
<< "where idx_ = " << idx_;
}
bool HasMoreSlices() { return idx_ + 1 < table_.row_count(); }
private:
Table table_;
uint32_t idx_ = std::numeric_limits<uint32_t>::max();
};
TEST(ExperimentalFlatSlice, Smoke) {
StringPool pool;
TableInseter inserter;
tables::SliceTable table(&pool);
// A simple stack on track 1.
inserter.Insert(100, 10, 0, TrackId{1});
inserter.Insert(104, 6, 1, TrackId{1});
inserter.Insert(107, 1, 2, TrackId{1});
// Back to back slices with a gap on track 2.
inserter.Insert(200, 10, 0, TrackId{2});
inserter.Insert(210, 10, 0, TrackId{2});
inserter.Insert(230, 10, 0, TrackId{2});
// Deep nesting on track 3.
inserter.Insert(300, 100, 0, TrackId{3});
inserter.Insert(301, 98, 1, TrackId{3});
inserter.Insert(302, 96, 2, TrackId{3});
inserter.Insert(303, 94, 3, TrackId{3});
inserter.Insert(304, 92, 4, TrackId{3});
inserter.Insert(305, 90, 5, TrackId{3});
// Populate the table.
inserter.Populate(table);
auto out = ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, 0, 400);
auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});
TableAsserter asserter(std::move(sorted));
// Track 1's slices.
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 100));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(100, 4));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(104, 3));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(107, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(108, 2));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 0));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 290));
// Track 2's slices.
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 200));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 160));
// Track 3's slices.
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 300));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(300, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(301, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(302, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(303, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(304, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(305, 90));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(395, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(396, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(397, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(398, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(399, 1));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(400, 0));
ASSERT_FALSE(asserter.HasMoreSlices());
}
TEST(ExperimentalFlatSlice, Bounds) {
StringPool pool;
TableInseter inserter;
tables::SliceTable table(&pool);
/// Our timebounds is between 200 and 300.
int64_t start = 200;
int64_t end = 300;
// Track 1 has all events inside bounds.
inserter.Insert(200, 10, 0, TrackId{1});
inserter.Insert(210, 10, 0, TrackId{1});
inserter.Insert(230, 10, 0, TrackId{1});
// Track 2 has a two stacks, first partially inside at start, second partially
// inside at end.
// First stack.
inserter.Insert(190, 20, 0, TrackId{2});
inserter.Insert(200, 9, 1, TrackId{2});
inserter.Insert(201, 1, 2, TrackId{2});
// Second stack.
inserter.Insert(290, 20, 0, TrackId{2});
inserter.Insert(299, 2, 1, TrackId{2});
inserter.Insert(300, 1, 2, TrackId{2});
// Track 3 has two stacks but *only* outside bounds.
inserter.Insert(190, 9, 0, TrackId{3});
inserter.Insert(195, 2, 1, TrackId{3});
inserter.Insert(300, 9, 0, TrackId{3});
inserter.Insert(301, 2, 1, TrackId{3});
// Track 4 has one stack which is partially inside at start.
inserter.Insert(190, 20, 0, TrackId{4});
inserter.Insert(201, 2, 1, TrackId{4});
// Populate the table.
inserter.Populate(table);
auto out =
ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, start, end);
auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});
TableAsserter asserter(std::move(sorted));
// Track 1's slices.
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 0));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 60));
// Track 2's slices.
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 90));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(290, 9));
ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(299, 1));
ASSERT_FALSE(asserter.HasMoreSlices());
}
} // namespace
} // namespace trace_processor
} // namespace perfetto