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