1818
1919#include < cstdint>
2020#include < memory>
21+ #include < optional>
2122#include < string>
23+ #include < variant>
2224#include < vector>
2325
2426#include " src/trace_processor/containers/string_pool.h"
2830#include " src/trace_processor/core/exec/column_view.h"
2931#include " src/trace_processor/core/exec/operator.h"
3032#include " src/trace_processor/core/exec/row_batch.h"
33+ #include " src/trace_processor/core/exec/test_utils.h"
3134#include " test/gtest_and_gmock.h"
3235
3336namespace perfetto ::trace_processor::core::exec {
3437namespace {
3538
3639using ::testing::ElementsAre;
40+ using ::testing::Eq;
41+ using ::testing::Optional;
3742
3843// Bigger than an int32, so a column holding it is stored as an int64.
3944constexpr int64_t kBig = int64_t {1 } << 40 ;
@@ -62,23 +67,111 @@ class DataframeScanTest : public ::testing::Test {
6267 RowBatch batch;
6368 std::vector<int64_t > out;
6469 while (scan.GetData (batch, *state)) {
65- const ColumnView& view = batch.column (column);
66- const auto * data = static_cast <const int64_t *>(view.data ());
67- for (uint32_t i = 0 ; i < batch.size (); ++i) {
68- out.push_back (data[view.selection ().GetIndex (i)]);
69- }
70+ std::vector<int64_t > values = test::ReadColumn<int64_t >(batch, column);
71+ out.insert (out.end (), values.begin (), values.end ());
7072 }
7173 return out;
7274 }
7375
7476 StringPool pool_;
7577};
7678
79+ inline constexpr auto kAllTypes = dataframe::CreateTypedDataframeSpec(
80+ {" id" , " u32" , " i32" , " i64" , " double" , " string" },
81+ dataframe::CreateTypedColumnSpec (Id{},
82+ NonNull{},
83+ IdSorted{},
84+ NoDuplicates{}),
85+ dataframe::CreateTypedColumnSpec (Uint32{}, NonNull{}, Unsorted{}),
86+ dataframe::CreateTypedColumnSpec (Int32{}, NonNull{}, Unsorted{}),
87+ dataframe::CreateTypedColumnSpec (Int64{}, NonNull{}, Unsorted{}),
88+ dataframe::CreateTypedColumnSpec (Double{}, NonNull{}, Unsorted{}),
89+ dataframe::CreateTypedColumnSpec (String{}, NonNull{}, Unsorted{}));
90+
91+ inline constexpr auto kSparseId = dataframe::CreateTypedDataframeSpec(
92+ {" id" },
93+ dataframe::CreateTypedColumnSpec (Id{},
94+ SparseNull{},
95+ Unsorted{},
96+ NoDuplicates{}));
97+
98+ inline constexpr auto kDenseId = dataframe::CreateTypedDataframeSpec(
99+ {" id" },
100+ dataframe::CreateTypedColumnSpec (Id{},
101+ DenseNull{},
102+ Unsorted{},
103+ NoDuplicates{}));
104+
105+ TEST_F (DataframeScanTest, ReadsEveryStorageType) {
106+ StringPool::Id first = pool_.InternString (" first" );
107+ StringPool::Id second = pool_.InternString (" second" );
108+ dataframe::Dataframe df =
109+ dataframe::Dataframe::CreateFromTypedSpec (kAllTypes , &pool_);
110+ df.InsertUnchecked (kAllTypes , std::monostate{}, uint32_t {7 }, int32_t {-3 },
111+ kBig , 1.5 , first);
112+ df.InsertUnchecked (kAllTypes , std::monostate{}, uint32_t {9 }, int32_t {4 },
113+ kBig + 1 , 2.5 , second);
114+ df.Finalize ();
115+
116+ DataframeScan scan (df, {0 , 1 , 2 , 3 , 4 , 5 });
117+ std::unique_ptr<OperatorState> state = scan.MakeState ();
118+ RowBatch batch;
119+ ASSERT_TRUE (scan.GetData (batch, *state));
120+ EXPECT_TRUE (batch.column (0 ).type ().Is <Id>());
121+ EXPECT_TRUE (batch.column (1 ).type ().Is <Uint32>());
122+ EXPECT_TRUE (batch.column (2 ).type ().Is <Int32>());
123+ EXPECT_TRUE (batch.column (3 ).type ().Is <Int64>());
124+ EXPECT_TRUE (batch.column (4 ).type ().Is <Double>());
125+ EXPECT_TRUE (batch.column (5 ).type ().Is <String>());
126+ EXPECT_THAT (test::ReadColumn<uint32_t >(batch, 0 ), ElementsAre (0u , 1u ));
127+ EXPECT_THAT (test::ReadColumn<uint32_t >(batch, 1 ), ElementsAre (7u , 9u ));
128+ EXPECT_THAT (test::ReadColumn<int32_t >(batch, 2 ), ElementsAre (-3 , 4 ));
129+ EXPECT_THAT (test::ReadColumn<int64_t >(batch, 3 ), ElementsAre (kBig , kBig + 1 ));
130+ EXPECT_THAT (test::ReadColumn<double >(batch, 4 ), ElementsAre (1.5 , 2.5 ));
131+ EXPECT_THAT (test::ReadColumn<StringPool::Id>(batch, 5 ),
132+ ElementsAre (first, second));
133+ }
134+
135+ TEST_F (DataframeScanTest, PreservesNullableIdSemantics) {
136+ dataframe::Dataframe sparse =
137+ dataframe::Dataframe::CreateFromTypedSpec (kSparseId , &pool_);
138+ sparse.InsertUnchecked (kSparseId ,
139+ std::optional<std::monostate>{std::monostate{}});
140+ sparse.InsertUnchecked (kSparseId , std::optional<std::monostate>{});
141+ sparse.InsertUnchecked (kSparseId ,
142+ std::optional<std::monostate>{std::monostate{}});
143+ sparse.Finalize ();
144+
145+ DataframeScan sparse_scan (sparse, {0 });
146+ std::unique_ptr<OperatorState> sparse_state = sparse_scan.MakeState ();
147+ RowBatch batch;
148+ ASSERT_TRUE (sparse_scan.GetData (batch, *sparse_state));
149+ EXPECT_TRUE (batch.column (0 ).type ().Is <Uint32>());
150+ EXPECT_THAT (test::ReadNullableColumn<uint32_t >(batch, 0 ),
151+ ElementsAre (Optional (0u ), Eq (std::nullopt ), Optional (1u )));
152+
153+ dataframe::Dataframe dense =
154+ dataframe::Dataframe::CreateFromTypedSpec (kDenseId , &pool_);
155+ dense.InsertUnchecked (kDenseId ,
156+ std::optional<std::monostate>{std::monostate{}});
157+ dense.InsertUnchecked (kDenseId , std::optional<std::monostate>{});
158+ dense.InsertUnchecked (kDenseId ,
159+ std::optional<std::monostate>{std::monostate{}});
160+ dense.Finalize ();
161+
162+ DataframeScan dense_scan (dense, {0 });
163+ std::unique_ptr<OperatorState> dense_state = dense_scan.MakeState ();
164+ ASSERT_TRUE (dense_scan.GetData (batch, *dense_state));
165+ EXPECT_TRUE (batch.column (0 ).type ().Is <Id>());
166+ EXPECT_THAT (test::ReadNullableColumn<uint32_t >(batch, 0 ),
167+ ElementsAre (Optional (0u ), Eq (std::nullopt ), Optional (2u )));
168+ }
169+
77170// The point of the operator: the batch reads the dataframe's own storage.
78171TEST_F (DataframeScanTest, ReadsTheDataframesOwnStorage) {
79172 dataframe::Dataframe df =
80173 Build ({kBig + 10 , kBig + 20 , kBig + 30 }, {true , true , true });
81- DataframeScan scan (& df, {0 });
174+ DataframeScan scan (df, {0 });
82175
83176 std::unique_ptr<OperatorState> state = scan.MakeState ();
84177 RowBatch batch;
@@ -91,7 +184,7 @@ TEST_F(DataframeScanTest, ReadsTheDataframesOwnStorage) {
91184TEST_F (DataframeScanTest, HandsBackEveryRow) {
92185 dataframe::Dataframe df =
93186 Build ({kBig + 10 , kBig + 20 , kBig + 30 }, {true , true , true });
94- DataframeScan scan (& df, {0 });
187+ DataframeScan scan (df, {0 });
95188 EXPECT_THAT (Drain (scan, 0 ), ElementsAre (kBig + 10 , kBig + 20 , kBig + 30 ));
96189}
97190
@@ -102,7 +195,7 @@ TEST_F(DataframeScanTest, SplitsIntoBatches) {
102195 values[i] = kBig + i;
103196 }
104197 dataframe::Dataframe df = Build (values, present);
105- DataframeScan scan (& df, {0 });
198+ DataframeScan scan (df, {0 });
106199 EXPECT_EQ (Drain (scan, 0 ).size (), values.size ());
107200}
108201
@@ -111,7 +204,7 @@ TEST_F(DataframeScanTest, SplitsIntoBatches) {
111204TEST_F (DataframeScanTest, AColumnWithoutASlotPerRowIsExpanded) {
112205 dataframe::Dataframe df =
113206 Build ({kBig + 10 , 0 , kBig + 30 }, {true , false , true });
114- DataframeScan scan (& df, {0 });
207+ DataframeScan scan (df, {0 });
115208
116209 std::unique_ptr<OperatorState> state = scan.MakeState ();
117210 RowBatch batch;
@@ -142,15 +235,15 @@ TEST_F(DataframeScanTest, AColumnWithoutASlotPerRowSpansBatches) {
142235 expected.push_back (values[i]);
143236 }
144237 dataframe::Dataframe df = Build (values, present);
145- DataframeScan scan (& df, {0 });
238+ DataframeScan scan (df, {0 });
146239 EXPECT_EQ (Drain (scan, 0 ), expected);
147240}
148241
149242// Replaying has to wind the packed values back too, not just the row counter.
150243TEST_F (DataframeScanTest, AColumnWithoutASlotPerRowIsReplayable) {
151244 dataframe::Dataframe df =
152245 Build ({kBig + 10 , 0 , kBig + 30 }, {true , false , true });
153- DataframeScan scan (& df, {0 });
246+ DataframeScan scan (df, {0 });
154247
155248 std::unique_ptr<OperatorState> state = scan.MakeState ();
156249 RowBatch batch;
@@ -167,7 +260,7 @@ TEST_F(DataframeScanTest, AColumnWithoutASlotPerRowIsReplayable) {
167260
168261TEST_F (DataframeScanTest, IsReplayable) {
169262 dataframe::Dataframe df = Build ({kBig + 1 , kBig + 2 }, {true , true });
170- DataframeScan scan (& df, {0 });
263+ DataframeScan scan (df, {0 });
171264
172265 std::unique_ptr<OperatorState> state = scan.MakeState ();
173266 RowBatch batch;
0 commit comments