|  | /* | 
|  | * Copyright (C) 2019 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #include "src/trace_processor/tables/macros.h" | 
|  |  | 
|  | #include "test/gtest_and_gmock.h" | 
|  |  | 
|  | namespace perfetto { | 
|  | namespace trace_processor { | 
|  | namespace { | 
|  |  | 
|  | // @param arg_set_id {@joinable args.arg_set_id} | 
|  | #define PERFETTO_TP_TEST_EVENT_TABLE_DEF(NAME, PARENT, C) \ | 
|  | NAME(TestEventTable, "event")                           \ | 
|  | PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C)            \ | 
|  | C(int64_t, ts, Column::Flag::kSorted)                   \ | 
|  | C(int64_t, arg_set_id) | 
|  | PERFETTO_TP_TABLE(PERFETTO_TP_TEST_EVENT_TABLE_DEF); | 
|  |  | 
|  | #define PERFETTO_TP_TEST_COUNTER_TABLE_DEF(NAME, PARENT, C) \ | 
|  | NAME(TestCounterTable, "counter")                         \ | 
|  | PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C)               \ | 
|  | C(std::optional<double>, value) | 
|  | PERFETTO_TP_TABLE(PERFETTO_TP_TEST_COUNTER_TABLE_DEF); | 
|  |  | 
|  | #define PERFETTO_TP_TEST_SLICE_TABLE_DEF(NAME, PARENT, C) \ | 
|  | NAME(TestSliceTable, "slice")                           \ | 
|  | PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C)             \ | 
|  | C(std::optional<int64_t>, dur)                          \ | 
|  | C(int64_t, depth) | 
|  | PERFETTO_TP_TABLE(PERFETTO_TP_TEST_SLICE_TABLE_DEF); | 
|  |  | 
|  | #define PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF(NAME, PARENT, C) \ | 
|  | NAME(TestCpuSliceTable, "cpu_slice")                        \ | 
|  | PARENT(PERFETTO_TP_TEST_SLICE_TABLE_DEF, C)                 \ | 
|  | C(int64_t, cpu)                                             \ | 
|  | C(int64_t, priority)                                        \ | 
|  | C(StringPool::Id, end_state) | 
|  | PERFETTO_TP_TABLE(PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF); | 
|  |  | 
|  | #define PERFETTO_TP_TEST_ARGS_TABLE_DEF(NAME, PARENT, C) \ | 
|  | NAME(TestArgsTable, "args")                            \ | 
|  | PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C)           \ | 
|  | C(uint32_t, arg_set_id, Column::Flag::kSetId | Column::Flag::kSorted) | 
|  | PERFETTO_TP_TABLE(PERFETTO_TP_TEST_ARGS_TABLE_DEF); | 
|  |  | 
|  | #define PERFETTO_TP_TEST_ARGS_CHILD_TABLE_DEF(NAME, PARENT, C) \ | 
|  | NAME(TestArgsChildTable, "args_child")                       \ | 
|  | PARENT(PERFETTO_TP_TEST_ARGS_TABLE_DEF, C)                   \ | 
|  | C(uint32_t, child_col) | 
|  | PERFETTO_TP_TABLE(PERFETTO_TP_TEST_ARGS_CHILD_TABLE_DEF); | 
|  |  | 
|  | TestEventTable::~TestEventTable() = default; | 
|  | TestCounterTable::~TestCounterTable() = default; | 
|  | TestSliceTable::~TestSliceTable() = default; | 
|  | TestCpuSliceTable::~TestCpuSliceTable() = default; | 
|  | TestArgsTable::~TestArgsTable() = default; | 
|  | TestArgsChildTable::~TestArgsChildTable() = default; | 
|  |  | 
|  | class TableMacrosUnittest : public ::testing::Test { | 
|  | protected: | 
|  | StringPool pool_; | 
|  |  | 
|  | TestEventTable event_{&pool_, nullptr}; | 
|  | TestCounterTable counter_{&pool_, &event_}; | 
|  | TestSliceTable slice_{&pool_, &event_}; | 
|  | TestCpuSliceTable cpu_slice_{&pool_, &slice_}; | 
|  | TestArgsTable args_{&pool_, nullptr}; | 
|  | TestArgsChildTable args_child_{&pool_, &args_}; | 
|  | }; | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, Name) { | 
|  | ASSERT_STREQ(TestEventTable::Name(), "event"); | 
|  | ASSERT_STREQ(TestSliceTable::Name(), "slice"); | 
|  | ASSERT_STREQ(TestCpuSliceTable::Name(), "cpu_slice"); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, InsertParent) { | 
|  | auto id = event_.Insert(TestEventTable::Row(100, 0)).id; | 
|  | ASSERT_EQ(id.value, 0u); | 
|  | ASSERT_EQ(event_.type().GetString(0), "event"); | 
|  | ASSERT_EQ(event_.ts()[0], 100); | 
|  | ASSERT_EQ(event_.arg_set_id()[0], 0); | 
|  |  | 
|  | id = slice_.Insert(TestSliceTable::Row(200, 123, 10, 0)).id; | 
|  | ASSERT_EQ(id.value, 1u); | 
|  |  | 
|  | ASSERT_EQ(event_.type().GetString(1), "slice"); | 
|  | ASSERT_EQ(event_.ts()[1], 200); | 
|  | ASSERT_EQ(event_.arg_set_id()[1], 123); | 
|  | ASSERT_EQ(slice_.type().GetString(0), "slice"); | 
|  | ASSERT_EQ(slice_.ts()[0], 200); | 
|  | ASSERT_EQ(slice_.arg_set_id()[0], 123); | 
|  | ASSERT_EQ(slice_.dur()[0], 10); | 
|  | ASSERT_EQ(slice_.depth()[0], 0); | 
|  |  | 
|  | id = slice_.Insert(TestSliceTable::Row(210, 456, std::nullopt, 0)).id; | 
|  | ASSERT_EQ(id.value, 2u); | 
|  |  | 
|  | ASSERT_EQ(event_.type().GetString(2), "slice"); | 
|  | ASSERT_EQ(event_.ts()[2], 210); | 
|  | ASSERT_EQ(event_.arg_set_id()[2], 456); | 
|  | ASSERT_EQ(slice_.type().GetString(1), "slice"); | 
|  | ASSERT_EQ(slice_.ts()[1], 210); | 
|  | ASSERT_EQ(slice_.arg_set_id()[1], 456); | 
|  | ASSERT_EQ(slice_.dur()[1], std::nullopt); | 
|  | ASSERT_EQ(slice_.depth()[1], 0); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, InsertChild) { | 
|  | event_.Insert(TestEventTable::Row(100, 0)); | 
|  | slice_.Insert(TestSliceTable::Row(200, 123, 10, 0)); | 
|  |  | 
|  | auto reason = pool_.InternString("R"); | 
|  | auto id = | 
|  | cpu_slice_.Insert(TestCpuSliceTable::Row(205, 456, 5, 1, 4, 1024, reason)) | 
|  | .id; | 
|  | ASSERT_EQ(id.value, 2u); | 
|  | ASSERT_EQ(event_.type().GetString(2), "cpu_slice"); | 
|  | ASSERT_EQ(event_.ts()[2], 205); | 
|  | ASSERT_EQ(event_.arg_set_id()[2], 456); | 
|  |  | 
|  | ASSERT_EQ(slice_.type().GetString(1), "cpu_slice"); | 
|  | ASSERT_EQ(slice_.ts()[1], 205); | 
|  | ASSERT_EQ(slice_.arg_set_id()[1], 456); | 
|  | ASSERT_EQ(slice_.dur()[1], 5); | 
|  | ASSERT_EQ(slice_.depth()[1], 1); | 
|  |  | 
|  | ASSERT_EQ(cpu_slice_.type().GetString(0), "cpu_slice"); | 
|  | ASSERT_EQ(cpu_slice_.ts()[0], 205); | 
|  | ASSERT_EQ(cpu_slice_.arg_set_id()[0], 456); | 
|  | ASSERT_EQ(cpu_slice_.dur()[0], 5); | 
|  | ASSERT_EQ(cpu_slice_.depth()[0], 1); | 
|  | ASSERT_EQ(cpu_slice_.cpu()[0], 4); | 
|  | ASSERT_EQ(cpu_slice_.priority()[0], 1024); | 
|  | ASSERT_EQ(cpu_slice_.end_state()[0], reason); | 
|  | ASSERT_EQ(cpu_slice_.end_state().GetString(0), "R"); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, NullableLongComparision) { | 
|  | slice_.Insert({}); | 
|  |  | 
|  | TestSliceTable::Row row; | 
|  | row.dur = 100; | 
|  | slice_.Insert(row); | 
|  |  | 
|  | row.dur = 101; | 
|  | slice_.Insert(row); | 
|  |  | 
|  | row.dur = 200; | 
|  | slice_.Insert(row); | 
|  |  | 
|  | slice_.Insert({}); | 
|  |  | 
|  | Table out = slice_.Filter({slice_.dur().is_null()}); | 
|  | const auto* dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_EQ(dur->Get(0).type, SqlValue::kNull); | 
|  | ASSERT_EQ(dur->Get(1).type, SqlValue::kNull); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().is_not_null()}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 3u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 100); | 
|  | ASSERT_EQ(dur->Get(1).long_value, 101); | 
|  | ASSERT_EQ(dur->Get(2).long_value, 200); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().lt(101)}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 100); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().eq(101)}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 101); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().gt(101)}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 200); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().ne(100)}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 101); | 
|  | ASSERT_EQ(dur->Get(1).long_value, 200); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().le(101)}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 100); | 
|  | ASSERT_EQ(dur->Get(1).long_value, 101); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().ge(101)}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 101); | 
|  | ASSERT_EQ(dur->Get(1).long_value, 200); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, NullableLongCompareWithDouble) { | 
|  | slice_.Insert({}); | 
|  |  | 
|  | TestSliceTable::Row row; | 
|  | row.dur = 100; | 
|  | slice_.Insert(row); | 
|  |  | 
|  | row.dur = std::numeric_limits<int64_t>::max(); | 
|  | slice_.Insert(row); | 
|  |  | 
|  | row.dur = std::numeric_limits<int64_t>::min(); | 
|  | slice_.Insert(row); | 
|  |  | 
|  | Table out = slice_.Filter({slice_.dur().eq_value(SqlValue::Double(100.0))}); | 
|  | const Column* dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 100); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().le_value(SqlValue::Double(99.9999))}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min()); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().ge_value(SqlValue::Double(99.9999))}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, 100); | 
|  | ASSERT_EQ(dur->Get(1).long_value, std::numeric_limits<int64_t>::max()); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().eq_value( | 
|  | SqlValue::Double(std::numeric_limits<int64_t>::min()))}); | 
|  | dur = out.GetColumnByName("dur"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min()); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, NullableLongCompareWrongType) { | 
|  | slice_.Insert({}); | 
|  |  | 
|  | TestSliceTable::Row row; | 
|  | row.dur = 100; | 
|  | slice_.Insert(row); | 
|  |  | 
|  | row.dur = 101; | 
|  | slice_.Insert(row); | 
|  |  | 
|  | row.dur = 200; | 
|  | slice_.Insert(row); | 
|  |  | 
|  | slice_.Insert({}); | 
|  |  | 
|  | Table out = slice_.Filter({slice_.dur().ne_value(SqlValue())}); | 
|  | ASSERT_EQ(out.row_count(), 0u); | 
|  |  | 
|  | out = slice_.Filter({slice_.dur().eq_value(SqlValue::String("100"))}); | 
|  | ASSERT_EQ(out.row_count(), 0u); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, NullableDoubleComparision) { | 
|  | counter_.Insert({}); | 
|  |  | 
|  | TestCounterTable::Row row; | 
|  | row.value = 100.0; | 
|  | counter_.Insert(row); | 
|  |  | 
|  | row.value = 101.0; | 
|  | counter_.Insert(row); | 
|  |  | 
|  | row.value = 200.0; | 
|  | counter_.Insert(row); | 
|  |  | 
|  | counter_.Insert({}); | 
|  |  | 
|  | Table out = counter_.Filter({counter_.value().is_null()}); | 
|  | const auto* value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_EQ(value->Get(0).type, SqlValue::kNull); | 
|  | ASSERT_EQ(value->Get(1).type, SqlValue::kNull); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().is_not_null()}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 3u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100); | 
|  | ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101); | 
|  | ASSERT_DOUBLE_EQ(value->Get(2).double_value, 200); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().lt(101)}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().eq(101)}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().gt(101)}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 200); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().ne(100)}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101); | 
|  | ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().le(101)}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100); | 
|  | ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().ge(101)}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101); | 
|  | ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, NullableDoubleCompareWithLong) { | 
|  | counter_.Insert({}); | 
|  |  | 
|  | TestCounterTable::Row row; | 
|  | row.value = 100.0; | 
|  | counter_.Insert(row); | 
|  |  | 
|  | row.value = 99.9999; | 
|  | counter_.Insert(row); | 
|  |  | 
|  | row.value = static_cast<double>(std::numeric_limits<int64_t>::min()); | 
|  | counter_.Insert(row); | 
|  |  | 
|  | Table out = counter_.Filter({counter_.value().eq_value(SqlValue::Long(100))}); | 
|  | const Column* value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100.0); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().lt_value(SqlValue::Long(100))}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, 99.9999); | 
|  | ASSERT_DOUBLE_EQ(value->Get(1).double_value, | 
|  | std::numeric_limits<int64_t>::min()); | 
|  |  | 
|  | out = counter_.Filter({counter_.value().eq_value( | 
|  | SqlValue::Long(std::numeric_limits<int64_t>::min()))}); | 
|  | value = out.GetColumnByName("value"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_DOUBLE_EQ(value->Get(0).double_value, | 
|  | std::numeric_limits<int64_t>::min()); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, StringComparision) { | 
|  | cpu_slice_.Insert({}); | 
|  |  | 
|  | TestCpuSliceTable::Row row; | 
|  | row.end_state = pool_.InternString("R"); | 
|  | cpu_slice_.Insert(row); | 
|  |  | 
|  | row.end_state = pool_.InternString("D"); | 
|  | cpu_slice_.Insert(row); | 
|  |  | 
|  | cpu_slice_.Insert({}); | 
|  |  | 
|  | Table out = cpu_slice_.Filter({cpu_slice_.end_state().is_null()}); | 
|  | const auto* end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_EQ(end_state->Get(0).type, SqlValue::kNull); | 
|  | ASSERT_EQ(end_state->Get(1).type, SqlValue::kNull); | 
|  |  | 
|  | out = cpu_slice_.Filter({cpu_slice_.end_state().is_not_null()}); | 
|  | end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "R"); | 
|  | ASSERT_STREQ(end_state->Get(1).string_value, "D"); | 
|  |  | 
|  | out = cpu_slice_.Filter({cpu_slice_.end_state().lt("R")}); | 
|  | end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "D"); | 
|  |  | 
|  | out = cpu_slice_.Filter({cpu_slice_.end_state().eq("D")}); | 
|  | end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "D"); | 
|  |  | 
|  | out = cpu_slice_.Filter({cpu_slice_.end_state().gt("D")}); | 
|  | end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "R"); | 
|  |  | 
|  | out = cpu_slice_.Filter({cpu_slice_.end_state().ne("D")}); | 
|  | end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "R"); | 
|  |  | 
|  | out = cpu_slice_.Filter({cpu_slice_.end_state().le("R")}); | 
|  | end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "R"); | 
|  | ASSERT_STREQ(end_state->Get(1).string_value, "D"); | 
|  |  | 
|  | out = cpu_slice_.Filter({cpu_slice_.end_state().ge("D")}); | 
|  | end_state = out.GetColumnByName("end_state"); | 
|  | ASSERT_EQ(out.row_count(), 2u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "R"); | 
|  | ASSERT_STREQ(end_state->Get(1).string_value, "D"); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, FilterIdThenOther) { | 
|  | TestCpuSliceTable::Row row; | 
|  | row.cpu = 1; | 
|  | row.end_state = pool_.InternString("D"); | 
|  |  | 
|  | cpu_slice_.Insert(row); | 
|  | cpu_slice_.Insert(row); | 
|  | cpu_slice_.Insert(row); | 
|  |  | 
|  | auto out = | 
|  | cpu_slice_.Filter({cpu_slice_.id().eq(0), cpu_slice_.end_state().eq("D"), | 
|  | cpu_slice_.cpu().eq(1)}); | 
|  | const auto* end_state = out.GetColumnByName("end_state"); | 
|  | const auto* cpu = out.GetColumnByName("cpu"); | 
|  |  | 
|  | ASSERT_EQ(out.row_count(), 1u); | 
|  | ASSERT_EQ(cpu->Get(0).long_value, 1u); | 
|  | ASSERT_STREQ(end_state->Get(0).string_value, "D"); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, Sort) { | 
|  | ASSERT_TRUE(event_.ts().IsSorted()); | 
|  |  | 
|  | event_.Insert(TestEventTable::Row(0 /* ts */, 100 /* arg_set_id */)); | 
|  | event_.Insert(TestEventTable::Row(1 /* ts */, 1 /* arg_set_id */)); | 
|  | event_.Insert(TestEventTable::Row(2 /* ts */, 3 /* arg_set_id */)); | 
|  |  | 
|  | Table out = event_.Sort({event_.arg_set_id().ascending()}); | 
|  | const auto* ts = out.GetColumnByName("ts"); | 
|  | const auto* arg_set_id = out.GetColumnByName("arg_set_id"); | 
|  |  | 
|  | ASSERT_FALSE(ts->IsSorted()); | 
|  | ASSERT_TRUE(arg_set_id->IsSorted()); | 
|  |  | 
|  | ASSERT_EQ(arg_set_id->Get(0).long_value, 1); | 
|  | ASSERT_EQ(arg_set_id->Get(1).long_value, 3); | 
|  | ASSERT_EQ(arg_set_id->Get(2).long_value, 100); | 
|  | } | 
|  |  | 
|  | TEST_F(TableMacrosUnittest, ChildDoesntInheritArgsSetFlag) { | 
|  | ASSERT_FALSE(args_child_.arg_set_id().IsSetId()); | 
|  | ASSERT_FALSE(TestArgsChildTable::ComputeStaticSchema() | 
|  | .columns[args_child_.arg_set_id().index_in_table()] | 
|  | .is_set_id); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace trace_processor | 
|  | }  // namespace perfetto |