xref: /aosp_15_r20/external/perfetto/src/trace_processor/tables/py_tables_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 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 <cstdint>
18 #include <utility>
19 #include <vector>
20 
21 #include "src/trace_processor/containers/string_pool.h"
22 #include "src/trace_processor/db/column.h"
23 #include "src/trace_processor/db/column/types.h"
24 #include "src/trace_processor/db/column_storage.h"
25 #include "src/trace_processor/tables/py_tables_unittest_py.h"
26 
27 #include "test/gtest_and_gmock.h"
28 
29 namespace perfetto::trace_processor::tables {
30 
31 TestEventTable::~TestEventTable() = default;
32 TestEventChildTable::~TestEventChildTable() = default;
33 TestSliceTable::~TestSliceTable() = default;
34 TestArgsTable::~TestArgsTable() = default;
35 
36 namespace {
37 
38 class PyTablesUnittest : public ::testing::Test {
39  protected:
40   StringPool pool_;
41 
42   TestEventTable event_{&pool_};
43   TestEventChildTable event_child_{&pool_, &event_};
44   TestSliceTable slice_{&pool_, &event_};
45   TestArgsTable args_{&pool_};
46 };
47 
TEST_F(PyTablesUnittest,EventTableProprties)48 TEST_F(PyTablesUnittest, EventTableProprties) {
49   ASSERT_STREQ(TestEventTable::Name(), "event");
50 
51   ASSERT_EQ(TestEventTable::ColumnIndex::id, 0u);
52   ASSERT_EQ(TestEventTable::ColumnIndex::type, 1u);
53   ASSERT_EQ(TestEventTable::ColumnIndex::ts, 2u);
54   ASSERT_EQ(TestEventTable::ColumnIndex::arg_set_id, 3u);
55 
56   ASSERT_EQ(TestEventTable::ColumnFlag::ts,
57             ColumnLegacy::Flag::kSorted | ColumnLegacy::Flag::kNonNull);
58   ASSERT_EQ(TestEventTable::ColumnFlag::arg_set_id,
59             ColumnLegacy::Flag::kNonNull);
60 }
61 
TEST_F(PyTablesUnittest,ArgsTableProprties)62 TEST_F(PyTablesUnittest, ArgsTableProprties) {
63   ASSERT_STREQ(TestArgsTable::Name(), "args");
64 
65   ASSERT_EQ(TestArgsTable::ColumnIndex::id, 0u);
66   ASSERT_EQ(TestArgsTable::ColumnIndex::type, 1u);
67   ASSERT_EQ(TestArgsTable::ColumnIndex::arg_set_id, 2u);
68 
69   ASSERT_EQ(TestArgsTable::ColumnFlag::arg_set_id,
70             ColumnLegacy::Flag::kSorted | ColumnLegacy::Flag::kSetId |
71                 ColumnLegacy::Flag::kNonNull);
72 }
73 
TEST_F(PyTablesUnittest,InsertEvent)74 TEST_F(PyTablesUnittest, InsertEvent) {
75   event_.Insert(TestEventTable::Row(100, 0));
76 
77   ASSERT_EQ(pool_.Get(event_[0].type()).ToStdString(), "event");
78   ASSERT_EQ(event_[0].ts(), 100);
79   ASSERT_EQ(event_[0].arg_set_id(), 0u);
80 }
81 
TEST_F(PyTablesUnittest,InsertEventSpecifyCols)82 TEST_F(PyTablesUnittest, InsertEventSpecifyCols) {
83   TestEventTable::Row row;
84   row.ts = 100;
85   row.arg_set_id = 0;
86   event_.Insert(row);
87 
88   ASSERT_EQ(pool_.Get(event_[0].type()).ToStdString(), "event");
89   ASSERT_EQ(event_[0].ts(), 100);
90   ASSERT_EQ(event_[0].arg_set_id(), 0u);
91 }
92 
TEST_F(PyTablesUnittest,MutableColumn)93 TEST_F(PyTablesUnittest, MutableColumn) {
94   event_.Insert(TestEventTable::Row(100, 0));
95 
96   ASSERT_EQ(event_[0].ts(), 100);
97   ASSERT_EQ(event_[0].arg_set_id(), 0u);
98 }
99 
TEST_F(PyTablesUnittest,ShrinkToFit)100 TEST_F(PyTablesUnittest, ShrinkToFit) {
101   event_.Insert(TestEventTable::Row(100, 0));
102   event_.ShrinkToFit();
103 
104   // Unfortunately given the loose restrictions on shrink_to_fit provided by the
105   // standard library, we cannot really assert anything. Just call the method to
106   // ensure it doesn't cause crashes.
107 }
108 
TEST_F(PyTablesUnittest,FindById)109 TEST_F(PyTablesUnittest, FindById) {
110   auto id_and_row = event_.Insert(TestEventTable::Row(100, 0));
111 
112   auto row_ref = event_.FindById(id_and_row.id);
113   ASSERT_EQ(row_ref->ToRowNumber().row_number(), id_and_row.row);
114   ASSERT_EQ(row_ref->id(), id_and_row.id);
115   ASSERT_EQ(row_ref->ts(), 100);
116   ASSERT_EQ(row_ref->arg_set_id(), 0u);
117 }
118 
TEST_F(PyTablesUnittest,ChildFindById)119 TEST_F(PyTablesUnittest, ChildFindById) {
120   event_.Insert(TestEventTable::Row(50, 0));
121   auto id_and_row = slice_.Insert(TestSliceTable::Row(100, 0, 10));
122 
123   auto row_ref = slice_.FindById(id_and_row.id);
124   ASSERT_EQ(row_ref->ToRowNumber().row_number(), id_and_row.row);
125   ASSERT_EQ(row_ref->id(), id_and_row.id);
126   ASSERT_EQ(row_ref->ts(), 100);
127   ASSERT_EQ(row_ref->arg_set_id(), 0u);
128   ASSERT_EQ(row_ref->dur(), 10u);
129 }
TEST_F(PyTablesUnittest,ChildTableStatics)130 TEST_F(PyTablesUnittest, ChildTableStatics) {
131   ASSERT_EQ(TestSliceTable::ColumnFlag::dur, ColumnLegacy::Flag::kNonNull);
132   ASSERT_EQ(TestSliceTable::ColumnIndex::id, 0u);
133   ASSERT_EQ(TestSliceTable::ColumnIndex::type, 1u);
134   ASSERT_EQ(TestSliceTable::ColumnIndex::ts, 2u);
135   ASSERT_EQ(TestSliceTable::ColumnIndex::arg_set_id, 3u);
136   ASSERT_EQ(TestSliceTable::ColumnIndex::dur, 4u);
137 }
138 
TEST_F(PyTablesUnittest,ParentAndChildInsert)139 TEST_F(PyTablesUnittest, ParentAndChildInsert) {
140   event_.Insert(TestEventTable::Row(50, 0));
141   slice_.Insert(TestSliceTable::Row(100, 1, 10));
142   event_.Insert(TestEventTable::Row(150, 2));
143   slice_.Insert(TestSliceTable::Row(200, 3, 20));
144 
145   ASSERT_EQ(event_.row_count(), 4u);
146   ASSERT_EQ(event_[0].id(), TestEventTable::Id{0});
147   ASSERT_EQ(pool_.Get(event_[0].type()), "event");
148   ASSERT_EQ(event_[0].ts(), 50);
149 
150   ASSERT_EQ(event_[1].id(), TestEventTable::Id{1});
151   ASSERT_EQ(pool_.Get(event_[1].type()), "slice");
152   ASSERT_EQ(event_[1].ts(), 100);
153 
154   ASSERT_EQ(event_[2].id(), TestEventTable::Id{2});
155   ASSERT_EQ(pool_.Get(event_[2].type()), "event");
156   ASSERT_EQ(event_[2].ts(), 150);
157 
158   ASSERT_EQ(event_[3].id(), TestEventTable::Id{3});
159   ASSERT_EQ(pool_.Get(event_[3].type()), "slice");
160   ASSERT_EQ(event_[3].ts(), 200);
161 
162   ASSERT_EQ(slice_.row_count(), 2u);
163   ASSERT_EQ(slice_[0].id(), TestEventTable::Id{1});
164   ASSERT_EQ(pool_.Get(slice_[0].type()), "slice");
165   ASSERT_EQ(slice_[0].ts(), 100);
166   ASSERT_EQ(slice_[0].dur(), 10);
167 
168   ASSERT_EQ(slice_[1].id(), TestEventTable::Id{3});
169   ASSERT_EQ(pool_.Get(slice_[1].type()), "slice");
170   ASSERT_EQ(slice_[1].ts(), 200);
171   ASSERT_EQ(slice_[1].dur(), 20);
172 }
173 
TEST_F(PyTablesUnittest,Extend)174 TEST_F(PyTablesUnittest, Extend) {
175   event_.Insert(TestEventTable::Row(50, 0));
176   event_.Insert(TestEventTable::Row(100, 1));
177   event_.Insert(TestEventTable::Row(150, 2));
178 
179   ColumnStorage<int64_t> dur;
180   dur.Append(512);
181   dur.Append(1024);
182   dur.Append(2048);
183 
184   auto slice_ext = TestSliceTable::ExtendParent(event_, std::move(dur));
185   ASSERT_EQ(slice_ext->row_count(), 3u);
186   ASSERT_EQ((*slice_ext)[0].ts(), 50);
187   ASSERT_EQ((*slice_ext)[0].dur(), 512);
188   ASSERT_EQ((*slice_ext)[1].ts(), 100);
189   ASSERT_EQ((*slice_ext)[1].dur(), 1024);
190   ASSERT_EQ((*slice_ext)[2].ts(), 150);
191   ASSERT_EQ((*slice_ext)[2].dur(), 2048);
192 }
193 
TEST_F(PyTablesUnittest,SelectAndExtend)194 TEST_F(PyTablesUnittest, SelectAndExtend) {
195   event_.Insert(TestEventTable::Row(50, 0));
196   event_.Insert(TestEventTable::Row(100, 1));
197   event_.Insert(TestEventTable::Row(150, 2));
198 
199   std::vector<TestEventTable::RowNumber> rows;
200   rows.emplace_back(1);
201   ColumnStorage<int64_t> dur;
202   dur.Append(1024);
203 
204   auto slice_ext = TestSliceTable::SelectAndExtendParent(
205       event_, std::move(rows), std::move(dur));
206   ASSERT_EQ(slice_ext->row_count(), 1u);
207   ASSERT_EQ((*slice_ext)[0].ts(), 100);
208   ASSERT_EQ((*slice_ext)[0].dur(), 1024);
209 }
210 
TEST_F(PyTablesUnittest,SetIdColumns)211 TEST_F(PyTablesUnittest, SetIdColumns) {
212   StringPool pool;
213   TestArgsTable table{&pool};
214 
215   table.Insert(TestArgsTable::Row(0, 100));
216   table.Insert(TestArgsTable::Row(0, 200));
217   table.Insert(TestArgsTable::Row(2, 200));
218   table.Insert(TestArgsTable::Row(3, 300));
219   table.Insert(TestArgsTable::Row(4, 200));
220   table.Insert(TestArgsTable::Row(4, 500));
221   table.Insert(TestArgsTable::Row(4, 900));
222   table.Insert(TestArgsTable::Row(4, 200));
223   table.Insert(TestArgsTable::Row(8, 400));
224 
225   ASSERT_EQ(table.row_count(), 9u);
226   ASSERT_TRUE(table.arg_set_id().IsSetId());
227 
228   // Verify that not-present ids are not returned.
229   {
230     static constexpr uint32_t kFilterArgSetId = 1;
231     Query q;
232     q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
233     auto res = table.FilterToIterator(q);
234     ASSERT_TRUE(!res);
235   }
236   {
237     static constexpr uint32_t kFilterArgSetId = 9;
238     Query q;
239     q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
240     auto it = table.FilterToIterator(q);
241     ASSERT_TRUE(!it);
242   }
243 
244   // Verify that filtering equality for real arg set ids works as expected.
245   {
246     static constexpr uint32_t kFilterArgSetId = 4;
247     Query q;
248     q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
249     uint32_t cnt = 0;
250     for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
251       ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
252     }
253     ASSERT_EQ(cnt, 4u);
254   }
255   {
256     static constexpr uint32_t kFilterArgSetId = 0;
257     Query q;
258     q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
259     uint32_t cnt = 0;
260     for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
261       ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
262     }
263     ASSERT_EQ(cnt, 2u);
264   }
265   {
266     static constexpr uint32_t kFilterArgSetId = 8;
267     Query q;
268     q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
269     uint32_t cnt = 0;
270     for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
271       ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
272     }
273     ASSERT_EQ(cnt, 1u);
274   }
275 
276   // Verify that filtering equality for arg set ids after filtering another
277   // column works.
278   {
279     static constexpr uint32_t kFilterArgSetId = 4;
280     Query q;
281     q.constraints = {table.int_value().eq(200),
282                      table.arg_set_id().eq(kFilterArgSetId)};
283     uint32_t cnt = 0;
284     for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
285       ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
286     }
287     ASSERT_EQ(cnt, 2u);
288   }
289 }
290 
291 }  // namespace
292 }  // namespace perfetto::trace_processor::tables
293