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