• 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/tables/macros.h"
18 
19 #include "test/gtest_and_gmock.h"
20 
21 namespace perfetto {
22 namespace trace_processor {
23 namespace {
24 
25 // @param arg_set_id {@joinable args.arg_set_id}
26 #define PERFETTO_TP_TEST_EVENT_TABLE_DEF(NAME, PARENT, C) \
27   NAME(TestEventTable, "event")                           \
28   PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C)            \
29   C(int64_t, ts, Column::Flag::kSorted)                   \
30   C(int64_t, arg_set_id)
31 PERFETTO_TP_TABLE(PERFETTO_TP_TEST_EVENT_TABLE_DEF);
32 
33 #define PERFETTO_TP_TEST_COUNTER_TABLE_DEF(NAME, PARENT, C) \
34   NAME(TestCounterTable, "counter")                         \
35   PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C)               \
36   C(std::optional<double>, value)
37 PERFETTO_TP_TABLE(PERFETTO_TP_TEST_COUNTER_TABLE_DEF);
38 
39 #define PERFETTO_TP_TEST_SLICE_TABLE_DEF(NAME, PARENT, C) \
40   NAME(TestSliceTable, "slice")                           \
41   PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C)             \
42   C(std::optional<int64_t>, dur)                          \
43   C(int64_t, depth)
44 PERFETTO_TP_TABLE(PERFETTO_TP_TEST_SLICE_TABLE_DEF);
45 
46 #define PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF(NAME, PARENT, C) \
47   NAME(TestCpuSliceTable, "cpu_slice")                        \
48   PARENT(PERFETTO_TP_TEST_SLICE_TABLE_DEF, C)                 \
49   C(int64_t, cpu)                                             \
50   C(int64_t, priority)                                        \
51   C(StringPool::Id, end_state)
52 PERFETTO_TP_TABLE(PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF);
53 
54 #define PERFETTO_TP_TEST_ARGS_TABLE_DEF(NAME, PARENT, C) \
55   NAME(TestArgsTable, "args")                            \
56   PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C)           \
57   C(uint32_t, arg_set_id, Column::Flag::kSetId | Column::Flag::kSorted)
58 PERFETTO_TP_TABLE(PERFETTO_TP_TEST_ARGS_TABLE_DEF);
59 
60 #define PERFETTO_TP_TEST_ARGS_CHILD_TABLE_DEF(NAME, PARENT, C) \
61   NAME(TestArgsChildTable, "args_child")                       \
62   PARENT(PERFETTO_TP_TEST_ARGS_TABLE_DEF, C)                   \
63   C(uint32_t, child_col)
64 PERFETTO_TP_TABLE(PERFETTO_TP_TEST_ARGS_CHILD_TABLE_DEF);
65 
66 TestEventTable::~TestEventTable() = default;
67 TestCounterTable::~TestCounterTable() = default;
68 TestSliceTable::~TestSliceTable() = default;
69 TestCpuSliceTable::~TestCpuSliceTable() = default;
70 TestArgsTable::~TestArgsTable() = default;
71 TestArgsChildTable::~TestArgsChildTable() = default;
72 
73 class TableMacrosUnittest : public ::testing::Test {
74  protected:
75   StringPool pool_;
76 
77   TestEventTable event_{&pool_, nullptr};
78   TestCounterTable counter_{&pool_, &event_};
79   TestSliceTable slice_{&pool_, &event_};
80   TestCpuSliceTable cpu_slice_{&pool_, &slice_};
81   TestArgsTable args_{&pool_, nullptr};
82   TestArgsChildTable args_child_{&pool_, &args_};
83 };
84 
TEST_F(TableMacrosUnittest,Name)85 TEST_F(TableMacrosUnittest, Name) {
86   ASSERT_STREQ(TestEventTable::Name(), "event");
87   ASSERT_STREQ(TestSliceTable::Name(), "slice");
88   ASSERT_STREQ(TestCpuSliceTable::Name(), "cpu_slice");
89 }
90 
TEST_F(TableMacrosUnittest,InsertParent)91 TEST_F(TableMacrosUnittest, InsertParent) {
92   auto id = event_.Insert(TestEventTable::Row(100, 0)).id;
93   ASSERT_EQ(id.value, 0u);
94   ASSERT_EQ(event_.type().GetString(0), "event");
95   ASSERT_EQ(event_.ts()[0], 100);
96   ASSERT_EQ(event_.arg_set_id()[0], 0);
97 
98   id = slice_.Insert(TestSliceTable::Row(200, 123, 10, 0)).id;
99   ASSERT_EQ(id.value, 1u);
100 
101   ASSERT_EQ(event_.type().GetString(1), "slice");
102   ASSERT_EQ(event_.ts()[1], 200);
103   ASSERT_EQ(event_.arg_set_id()[1], 123);
104   ASSERT_EQ(slice_.type().GetString(0), "slice");
105   ASSERT_EQ(slice_.ts()[0], 200);
106   ASSERT_EQ(slice_.arg_set_id()[0], 123);
107   ASSERT_EQ(slice_.dur()[0], 10);
108   ASSERT_EQ(slice_.depth()[0], 0);
109 
110   id = slice_.Insert(TestSliceTable::Row(210, 456, std::nullopt, 0)).id;
111   ASSERT_EQ(id.value, 2u);
112 
113   ASSERT_EQ(event_.type().GetString(2), "slice");
114   ASSERT_EQ(event_.ts()[2], 210);
115   ASSERT_EQ(event_.arg_set_id()[2], 456);
116   ASSERT_EQ(slice_.type().GetString(1), "slice");
117   ASSERT_EQ(slice_.ts()[1], 210);
118   ASSERT_EQ(slice_.arg_set_id()[1], 456);
119   ASSERT_EQ(slice_.dur()[1], std::nullopt);
120   ASSERT_EQ(slice_.depth()[1], 0);
121 }
122 
TEST_F(TableMacrosUnittest,InsertChild)123 TEST_F(TableMacrosUnittest, InsertChild) {
124   event_.Insert(TestEventTable::Row(100, 0));
125   slice_.Insert(TestSliceTable::Row(200, 123, 10, 0));
126 
127   auto reason = pool_.InternString("R");
128   auto id =
129       cpu_slice_.Insert(TestCpuSliceTable::Row(205, 456, 5, 1, 4, 1024, reason))
130           .id;
131   ASSERT_EQ(id.value, 2u);
132   ASSERT_EQ(event_.type().GetString(2), "cpu_slice");
133   ASSERT_EQ(event_.ts()[2], 205);
134   ASSERT_EQ(event_.arg_set_id()[2], 456);
135 
136   ASSERT_EQ(slice_.type().GetString(1), "cpu_slice");
137   ASSERT_EQ(slice_.ts()[1], 205);
138   ASSERT_EQ(slice_.arg_set_id()[1], 456);
139   ASSERT_EQ(slice_.dur()[1], 5);
140   ASSERT_EQ(slice_.depth()[1], 1);
141 
142   ASSERT_EQ(cpu_slice_.type().GetString(0), "cpu_slice");
143   ASSERT_EQ(cpu_slice_.ts()[0], 205);
144   ASSERT_EQ(cpu_slice_.arg_set_id()[0], 456);
145   ASSERT_EQ(cpu_slice_.dur()[0], 5);
146   ASSERT_EQ(cpu_slice_.depth()[0], 1);
147   ASSERT_EQ(cpu_slice_.cpu()[0], 4);
148   ASSERT_EQ(cpu_slice_.priority()[0], 1024);
149   ASSERT_EQ(cpu_slice_.end_state()[0], reason);
150   ASSERT_EQ(cpu_slice_.end_state().GetString(0), "R");
151 }
152 
TEST_F(TableMacrosUnittest,NullableLongComparision)153 TEST_F(TableMacrosUnittest, NullableLongComparision) {
154   slice_.Insert({});
155 
156   TestSliceTable::Row row;
157   row.dur = 100;
158   slice_.Insert(row);
159 
160   row.dur = 101;
161   slice_.Insert(row);
162 
163   row.dur = 200;
164   slice_.Insert(row);
165 
166   slice_.Insert({});
167 
168   Table out = slice_.Filter({slice_.dur().is_null()});
169   const auto* dur = out.GetColumnByName("dur");
170   ASSERT_EQ(out.row_count(), 2u);
171   ASSERT_EQ(dur->Get(0).type, SqlValue::kNull);
172   ASSERT_EQ(dur->Get(1).type, SqlValue::kNull);
173 
174   out = slice_.Filter({slice_.dur().is_not_null()});
175   dur = out.GetColumnByName("dur");
176   ASSERT_EQ(out.row_count(), 3u);
177   ASSERT_EQ(dur->Get(0).long_value, 100);
178   ASSERT_EQ(dur->Get(1).long_value, 101);
179   ASSERT_EQ(dur->Get(2).long_value, 200);
180 
181   out = slice_.Filter({slice_.dur().lt(101)});
182   dur = out.GetColumnByName("dur");
183   ASSERT_EQ(out.row_count(), 1u);
184   ASSERT_EQ(dur->Get(0).long_value, 100);
185 
186   out = slice_.Filter({slice_.dur().eq(101)});
187   dur = out.GetColumnByName("dur");
188   ASSERT_EQ(out.row_count(), 1u);
189   ASSERT_EQ(dur->Get(0).long_value, 101);
190 
191   out = slice_.Filter({slice_.dur().gt(101)});
192   dur = out.GetColumnByName("dur");
193   ASSERT_EQ(out.row_count(), 1u);
194   ASSERT_EQ(dur->Get(0).long_value, 200);
195 
196   out = slice_.Filter({slice_.dur().ne(100)});
197   dur = out.GetColumnByName("dur");
198   ASSERT_EQ(out.row_count(), 2u);
199   ASSERT_EQ(dur->Get(0).long_value, 101);
200   ASSERT_EQ(dur->Get(1).long_value, 200);
201 
202   out = slice_.Filter({slice_.dur().le(101)});
203   dur = out.GetColumnByName("dur");
204   ASSERT_EQ(out.row_count(), 2u);
205   ASSERT_EQ(dur->Get(0).long_value, 100);
206   ASSERT_EQ(dur->Get(1).long_value, 101);
207 
208   out = slice_.Filter({slice_.dur().ge(101)});
209   dur = out.GetColumnByName("dur");
210   ASSERT_EQ(out.row_count(), 2u);
211   ASSERT_EQ(dur->Get(0).long_value, 101);
212   ASSERT_EQ(dur->Get(1).long_value, 200);
213 }
214 
TEST_F(TableMacrosUnittest,NullableLongCompareWithDouble)215 TEST_F(TableMacrosUnittest, NullableLongCompareWithDouble) {
216   slice_.Insert({});
217 
218   TestSliceTable::Row row;
219   row.dur = 100;
220   slice_.Insert(row);
221 
222   row.dur = std::numeric_limits<int64_t>::max();
223   slice_.Insert(row);
224 
225   row.dur = std::numeric_limits<int64_t>::min();
226   slice_.Insert(row);
227 
228   Table out = slice_.Filter({slice_.dur().eq_value(SqlValue::Double(100.0))});
229   const Column* dur = out.GetColumnByName("dur");
230   ASSERT_EQ(out.row_count(), 1u);
231   ASSERT_EQ(dur->Get(0).long_value, 100);
232 
233   out = slice_.Filter({slice_.dur().le_value(SqlValue::Double(99.9999))});
234   dur = out.GetColumnByName("dur");
235   ASSERT_EQ(out.row_count(), 1u);
236   ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
237 
238   out = slice_.Filter({slice_.dur().ge_value(SqlValue::Double(99.9999))});
239   dur = out.GetColumnByName("dur");
240   ASSERT_EQ(out.row_count(), 2u);
241   ASSERT_EQ(dur->Get(0).long_value, 100);
242   ASSERT_EQ(dur->Get(1).long_value, std::numeric_limits<int64_t>::max());
243 
244   out = slice_.Filter({slice_.dur().eq_value(
245       SqlValue::Double(std::numeric_limits<int64_t>::min()))});
246   dur = out.GetColumnByName("dur");
247   ASSERT_EQ(out.row_count(), 1u);
248   ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
249 }
250 
TEST_F(TableMacrosUnittest,NullableLongCompareWrongType)251 TEST_F(TableMacrosUnittest, NullableLongCompareWrongType) {
252   slice_.Insert({});
253 
254   TestSliceTable::Row row;
255   row.dur = 100;
256   slice_.Insert(row);
257 
258   row.dur = 101;
259   slice_.Insert(row);
260 
261   row.dur = 200;
262   slice_.Insert(row);
263 
264   slice_.Insert({});
265 
266   Table out = slice_.Filter({slice_.dur().ne_value(SqlValue())});
267   ASSERT_EQ(out.row_count(), 0u);
268 
269   out = slice_.Filter({slice_.dur().eq_value(SqlValue::String("100"))});
270   ASSERT_EQ(out.row_count(), 0u);
271 }
272 
TEST_F(TableMacrosUnittest,NullableDoubleComparision)273 TEST_F(TableMacrosUnittest, NullableDoubleComparision) {
274   counter_.Insert({});
275 
276   TestCounterTable::Row row;
277   row.value = 100.0;
278   counter_.Insert(row);
279 
280   row.value = 101.0;
281   counter_.Insert(row);
282 
283   row.value = 200.0;
284   counter_.Insert(row);
285 
286   counter_.Insert({});
287 
288   Table out = counter_.Filter({counter_.value().is_null()});
289   const auto* value = out.GetColumnByName("value");
290   ASSERT_EQ(out.row_count(), 2u);
291   ASSERT_EQ(value->Get(0).type, SqlValue::kNull);
292   ASSERT_EQ(value->Get(1).type, SqlValue::kNull);
293 
294   out = counter_.Filter({counter_.value().is_not_null()});
295   value = out.GetColumnByName("value");
296   ASSERT_EQ(out.row_count(), 3u);
297   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
298   ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
299   ASSERT_DOUBLE_EQ(value->Get(2).double_value, 200);
300 
301   out = counter_.Filter({counter_.value().lt(101)});
302   value = out.GetColumnByName("value");
303   ASSERT_EQ(out.row_count(), 1u);
304   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
305 
306   out = counter_.Filter({counter_.value().eq(101)});
307   value = out.GetColumnByName("value");
308   ASSERT_EQ(out.row_count(), 1u);
309   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
310 
311   out = counter_.Filter({counter_.value().gt(101)});
312   value = out.GetColumnByName("value");
313   ASSERT_EQ(out.row_count(), 1u);
314   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 200);
315 
316   out = counter_.Filter({counter_.value().ne(100)});
317   value = out.GetColumnByName("value");
318   ASSERT_EQ(out.row_count(), 2u);
319   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
320   ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
321 
322   out = counter_.Filter({counter_.value().le(101)});
323   value = out.GetColumnByName("value");
324   ASSERT_EQ(out.row_count(), 2u);
325   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
326   ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
327 
328   out = counter_.Filter({counter_.value().ge(101)});
329   value = out.GetColumnByName("value");
330   ASSERT_EQ(out.row_count(), 2u);
331   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
332   ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
333 }
334 
TEST_F(TableMacrosUnittest,NullableDoubleCompareWithLong)335 TEST_F(TableMacrosUnittest, NullableDoubleCompareWithLong) {
336   counter_.Insert({});
337 
338   TestCounterTable::Row row;
339   row.value = 100.0;
340   counter_.Insert(row);
341 
342   row.value = 99.9999;
343   counter_.Insert(row);
344 
345   row.value = static_cast<double>(std::numeric_limits<int64_t>::min());
346   counter_.Insert(row);
347 
348   Table out = counter_.Filter({counter_.value().eq_value(SqlValue::Long(100))});
349   const Column* value = out.GetColumnByName("value");
350   ASSERT_EQ(out.row_count(), 1u);
351   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100.0);
352 
353   out = counter_.Filter({counter_.value().lt_value(SqlValue::Long(100))});
354   value = out.GetColumnByName("value");
355   ASSERT_EQ(out.row_count(), 2u);
356   ASSERT_DOUBLE_EQ(value->Get(0).double_value, 99.9999);
357   ASSERT_DOUBLE_EQ(value->Get(1).double_value,
358                    std::numeric_limits<int64_t>::min());
359 
360   out = counter_.Filter({counter_.value().eq_value(
361       SqlValue::Long(std::numeric_limits<int64_t>::min()))});
362   value = out.GetColumnByName("value");
363   ASSERT_EQ(out.row_count(), 1u);
364   ASSERT_DOUBLE_EQ(value->Get(0).double_value,
365                    std::numeric_limits<int64_t>::min());
366 }
367 
TEST_F(TableMacrosUnittest,StringComparision)368 TEST_F(TableMacrosUnittest, StringComparision) {
369   cpu_slice_.Insert({});
370 
371   TestCpuSliceTable::Row row;
372   row.end_state = pool_.InternString("R");
373   cpu_slice_.Insert(row);
374 
375   row.end_state = pool_.InternString("D");
376   cpu_slice_.Insert(row);
377 
378   cpu_slice_.Insert({});
379 
380   Table out = cpu_slice_.Filter({cpu_slice_.end_state().is_null()});
381   const auto* end_state = out.GetColumnByName("end_state");
382   ASSERT_EQ(out.row_count(), 2u);
383   ASSERT_EQ(end_state->Get(0).type, SqlValue::kNull);
384   ASSERT_EQ(end_state->Get(1).type, SqlValue::kNull);
385 
386   out = cpu_slice_.Filter({cpu_slice_.end_state().is_not_null()});
387   end_state = out.GetColumnByName("end_state");
388   ASSERT_EQ(out.row_count(), 2u);
389   ASSERT_STREQ(end_state->Get(0).string_value, "R");
390   ASSERT_STREQ(end_state->Get(1).string_value, "D");
391 
392   out = cpu_slice_.Filter({cpu_slice_.end_state().lt("R")});
393   end_state = out.GetColumnByName("end_state");
394   ASSERT_EQ(out.row_count(), 1u);
395   ASSERT_STREQ(end_state->Get(0).string_value, "D");
396 
397   out = cpu_slice_.Filter({cpu_slice_.end_state().eq("D")});
398   end_state = out.GetColumnByName("end_state");
399   ASSERT_EQ(out.row_count(), 1u);
400   ASSERT_STREQ(end_state->Get(0).string_value, "D");
401 
402   out = cpu_slice_.Filter({cpu_slice_.end_state().gt("D")});
403   end_state = out.GetColumnByName("end_state");
404   ASSERT_EQ(out.row_count(), 1u);
405   ASSERT_STREQ(end_state->Get(0).string_value, "R");
406 
407   out = cpu_slice_.Filter({cpu_slice_.end_state().ne("D")});
408   end_state = out.GetColumnByName("end_state");
409   ASSERT_EQ(out.row_count(), 1u);
410   ASSERT_STREQ(end_state->Get(0).string_value, "R");
411 
412   out = cpu_slice_.Filter({cpu_slice_.end_state().le("R")});
413   end_state = out.GetColumnByName("end_state");
414   ASSERT_EQ(out.row_count(), 2u);
415   ASSERT_STREQ(end_state->Get(0).string_value, "R");
416   ASSERT_STREQ(end_state->Get(1).string_value, "D");
417 
418   out = cpu_slice_.Filter({cpu_slice_.end_state().ge("D")});
419   end_state = out.GetColumnByName("end_state");
420   ASSERT_EQ(out.row_count(), 2u);
421   ASSERT_STREQ(end_state->Get(0).string_value, "R");
422   ASSERT_STREQ(end_state->Get(1).string_value, "D");
423 }
424 
TEST_F(TableMacrosUnittest,FilterIdThenOther)425 TEST_F(TableMacrosUnittest, FilterIdThenOther) {
426   TestCpuSliceTable::Row row;
427   row.cpu = 1;
428   row.end_state = pool_.InternString("D");
429 
430   cpu_slice_.Insert(row);
431   cpu_slice_.Insert(row);
432   cpu_slice_.Insert(row);
433 
434   auto out =
435       cpu_slice_.Filter({cpu_slice_.id().eq(0), cpu_slice_.end_state().eq("D"),
436                          cpu_slice_.cpu().eq(1)});
437   const auto* end_state = out.GetColumnByName("end_state");
438   const auto* cpu = out.GetColumnByName("cpu");
439 
440   ASSERT_EQ(out.row_count(), 1u);
441   ASSERT_EQ(cpu->Get(0).long_value, 1u);
442   ASSERT_STREQ(end_state->Get(0).string_value, "D");
443 }
444 
TEST_F(TableMacrosUnittest,Sort)445 TEST_F(TableMacrosUnittest, Sort) {
446   ASSERT_TRUE(event_.ts().IsSorted());
447 
448   event_.Insert(TestEventTable::Row(0 /* ts */, 100 /* arg_set_id */));
449   event_.Insert(TestEventTable::Row(1 /* ts */, 1 /* arg_set_id */));
450   event_.Insert(TestEventTable::Row(2 /* ts */, 3 /* arg_set_id */));
451 
452   Table out = event_.Sort({event_.arg_set_id().ascending()});
453   const auto* ts = out.GetColumnByName("ts");
454   const auto* arg_set_id = out.GetColumnByName("arg_set_id");
455 
456   ASSERT_FALSE(ts->IsSorted());
457   ASSERT_TRUE(arg_set_id->IsSorted());
458 
459   ASSERT_EQ(arg_set_id->Get(0).long_value, 1);
460   ASSERT_EQ(arg_set_id->Get(1).long_value, 3);
461   ASSERT_EQ(arg_set_id->Get(2).long_value, 100);
462 }
463 
TEST_F(TableMacrosUnittest,ChildDoesntInheritArgsSetFlag)464 TEST_F(TableMacrosUnittest, ChildDoesntInheritArgsSetFlag) {
465   ASSERT_FALSE(args_child_.arg_set_id().IsSetId());
466   ASSERT_FALSE(TestArgsChildTable::ComputeStaticSchema()
467                    .columns[args_child_.arg_set_id().index_in_table()]
468                    .is_set_id);
469 }
470 
471 }  // namespace
472 }  // namespace trace_processor
473 }  // namespace perfetto
474