• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "src/trace_processor/prelude/table_functions/experimental_flat_slice.h"
17 
18 #include "test/gtest_and_gmock.h"
19 
20 namespace perfetto {
21 namespace trace_processor {
22 namespace {
23 
24 class TableInseter {
25  public:
Insert(int64_t ts,int64_t dur,uint32_t depth,TrackId track_id)26   void Insert(int64_t ts, int64_t dur, uint32_t depth, TrackId track_id) {
27     tables::SliceTable::Row row;
28     row.ts = ts;
29     row.dur = dur;
30     row.depth = depth;
31     row.track_id = track_id;
32     rows_.emplace_back(std::move(row));
33   }
34 
Populate(tables::SliceTable & table)35   void Populate(tables::SliceTable& table) {
36     using R = tables::SliceTable::Row;
37     std::sort(rows_.begin(), rows_.end(),
38               [](const R& a, const R& b) { return a.ts < b.ts; });
39     for (const auto& row : rows_) {
40       table.Insert(row);
41     }
42     rows_.clear();
43   }
44 
45  private:
46   std::vector<tables::SliceTable::Row> rows_;
47 };
48 
49 class TableAsserter {
50  public:
TableAsserter(Table table)51   TableAsserter(Table table) : table_(std::move(table)) {}
52 
NextSlice(int64_t ts,int64_t dur)53   void NextSlice(int64_t ts, int64_t dur) {
54     ++idx_;
55     ASSERT_LT(idx_, table_.row_count());
56     ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("ts")[idx_], ts)
57         << "where idx_ = " << idx_;
58     ASSERT_EQ(table_.GetTypedColumnByName<int64_t>("dur")[idx_], dur)
59         << "where idx_ = " << idx_;
60   }
61 
HasMoreSlices()62   bool HasMoreSlices() { return idx_ + 1 < table_.row_count(); }
63 
64  private:
65   Table table_;
66   uint32_t idx_ = std::numeric_limits<uint32_t>::max();
67 };
68 
TEST(ExperimentalFlatSlice,Smoke)69 TEST(ExperimentalFlatSlice, Smoke) {
70   StringPool pool;
71   TableInseter inserter;
72   tables::SliceTable table(&pool);
73 
74   // A simple stack on track 1.
75   inserter.Insert(100, 10, 0, TrackId{1});
76   inserter.Insert(104, 6, 1, TrackId{1});
77   inserter.Insert(107, 1, 2, TrackId{1});
78 
79   // Back to back slices with a gap on track 2.
80   inserter.Insert(200, 10, 0, TrackId{2});
81   inserter.Insert(210, 10, 0, TrackId{2});
82   inserter.Insert(230, 10, 0, TrackId{2});
83 
84   // Deep nesting on track 3.
85   inserter.Insert(300, 100, 0, TrackId{3});
86   inserter.Insert(301, 98, 1, TrackId{3});
87   inserter.Insert(302, 96, 2, TrackId{3});
88   inserter.Insert(303, 94, 3, TrackId{3});
89   inserter.Insert(304, 92, 4, TrackId{3});
90   inserter.Insert(305, 90, 5, TrackId{3});
91 
92   // Populate the table.
93   inserter.Populate(table);
94 
95   auto out = ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, 0, 400);
96   auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});
97 
98   TableAsserter asserter(std::move(sorted));
99 
100   // Track 1's slices.
101   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 100));
102   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(100, 4));
103   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(104, 3));
104   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(107, 1));
105   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(108, 2));
106   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 0));
107   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(110, 290));
108 
109   // Track 2's slices.
110   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 200));
111   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
112   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
113   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
114   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
115   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
116   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 160));
117 
118   // Track 3's slices.
119   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(0, 300));
120   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(300, 1));
121   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(301, 1));
122   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(302, 1));
123   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(303, 1));
124   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(304, 1));
125   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(305, 90));
126   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(395, 1));
127   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(396, 1));
128   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(397, 1));
129   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(398, 1));
130   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(399, 1));
131   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(400, 0));
132 
133   ASSERT_FALSE(asserter.HasMoreSlices());
134 }
135 
TEST(ExperimentalFlatSlice,Bounds)136 TEST(ExperimentalFlatSlice, Bounds) {
137   StringPool pool;
138   TableInseter inserter;
139   tables::SliceTable table(&pool);
140 
141   /// Our timebounds is between 200 and 300.
142   int64_t start = 200;
143   int64_t end = 300;
144 
145   // Track 1 has all events inside bounds.
146   inserter.Insert(200, 10, 0, TrackId{1});
147   inserter.Insert(210, 10, 0, TrackId{1});
148   inserter.Insert(230, 10, 0, TrackId{1});
149 
150   // Track 2 has a two stacks, first partially inside at start, second partially
151   // inside at end.
152   // First stack.
153   inserter.Insert(190, 20, 0, TrackId{2});
154   inserter.Insert(200, 9, 1, TrackId{2});
155   inserter.Insert(201, 1, 2, TrackId{2});
156 
157   // Second stack.
158   inserter.Insert(290, 20, 0, TrackId{2});
159   inserter.Insert(299, 2, 1, TrackId{2});
160   inserter.Insert(300, 1, 2, TrackId{2});
161 
162   // Track 3 has two stacks but *only* outside bounds.
163   inserter.Insert(190, 9, 0, TrackId{3});
164   inserter.Insert(195, 2, 1, TrackId{3});
165 
166   inserter.Insert(300, 9, 0, TrackId{3});
167   inserter.Insert(301, 2, 1, TrackId{3});
168 
169   // Track 4 has one stack which is partially inside at start.
170   inserter.Insert(190, 20, 0, TrackId{4});
171   inserter.Insert(201, 2, 1, TrackId{4});
172 
173   // Populate the table.
174   inserter.Populate(table);
175 
176   auto out =
177       ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, start, end);
178   auto sorted = out->Sort({out->track_id().ascending(), out->ts().ascending()});
179 
180   TableAsserter asserter(std::move(sorted));
181 
182   // Track 1's slices.
183   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 0));
184   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 10));
185   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 0));
186   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(210, 10));
187   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(220, 10));
188   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(230, 10));
189   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(240, 60));
190 
191   // Track 2's slices.
192   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(200, 90));
193   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(290, 9));
194   ASSERT_NO_FATAL_FAILURE(asserter.NextSlice(299, 1));
195 
196   ASSERT_FALSE(asserter.HasMoreSlices());
197 }
198 
199 }  // namespace
200 }  // namespace trace_processor
201 }  // namespace perfetto
202