blob: 8988c0030b3b041896a122531b7017615c4b6a98 [file] [log] [blame]
/*
* Copyright (C) 2023 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 <numeric>
#include "src/trace_processor/db/numeric_storage.h"
#include "src/trace_processor/db/null_overlay.h"
#include "src/trace_processor/db/storage_overlay.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace trace_processor {
namespace column {
namespace {
TEST(NumericStorageUnittest, StableSortTrivial) {
std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
std::vector<uint32_t> out = {0, 1, 2, 3, 4, 5, 6, 7, 8};
NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
RowMap rm(0, 9);
storage.StableSort(out.data(), 9);
std::vector<uint32_t> stable_out{0, 3, 6, 1, 4, 7, 2, 5, 8};
ASSERT_EQ(out, stable_out);
}
TEST(NumericStorageUnittest, StableSort) {
std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
std::vector<uint32_t> out = {1, 7, 4, 0, 6, 3, 2, 5, 8};
NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
RowMap rm(0, 9);
storage.StableSort(out.data(), 9);
std::vector<uint32_t> stable_out{0, 6, 3, 1, 7, 4, 2, 5, 8};
ASSERT_EQ(out, stable_out);
}
TEST(NumericStorageUnittest, CompareSlow) {
uint32_t size = 10;
std::vector<uint32_t> data_vec(size);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), size, ColumnType::kUint32);
BitVector::Builder builder(size);
storage.CompareSlow(FilterOp::kGe, SqlValue::Long(5), 0, size, builder);
BitVector bv = std::move(builder).Build();
ASSERT_EQ(bv.CountSetBits(), 5u);
ASSERT_EQ(bv.IndexOfNthSet(0), 5u);
}
TEST(NumericStorageUnittest, CompareSlowLarge) {
uint32_t size = 1025;
std::vector<uint32_t> data_vec(size);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), size, ColumnType::kUint32);
BitVector::Builder builder(size);
storage.CompareSlow(FilterOp::kGe, SqlValue::Long(5), 0, size, builder);
BitVector bv = std::move(builder).Build();
ASSERT_EQ(bv.CountSetBits(), 1020u);
ASSERT_EQ(bv.IndexOfNthSet(0), 5u);
}
TEST(NumericStorageUnittest, CompareFast) {
std::vector<uint32_t> data_vec(128);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), 128, ColumnType::kUint32);
BitVector::Builder builder(128);
storage.CompareFast(FilterOp::kGe, SqlValue::Long(100), 0, 128, builder);
BitVector bv = std::move(builder).Build();
ASSERT_EQ(bv.CountSetBits(), 28u);
ASSERT_EQ(bv.IndexOfNthSet(0), 100u);
}
TEST(NumericStorageUnittest, CompareSorted) {
std::vector<uint32_t> data_vec(128);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), 128, ColumnType::kUint32);
RowMap rm(0, 128);
storage.CompareSorted(FilterOp::kGe, SqlValue::Long(100), rm);
ASSERT_EQ(rm.size(), 28u);
ASSERT_EQ(rm.Get(0), 100u);
}
TEST(NumericStorageUnittest, CompareSortedIndexesGreaterEqual) {
std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
RowMap rm(0, 10);
storage.CompareSortedIndexes(FilterOp::kGe, SqlValue::Long(60),
sorted_order.data(), rm);
ASSERT_EQ(rm.size(), 4u);
ASSERT_EQ(rm.Get(0), 3u);
ASSERT_EQ(rm.Get(1), 6u);
ASSERT_EQ(rm.Get(2), 5u);
ASSERT_EQ(rm.Get(3), 4u);
}
TEST(NumericStorageUnittest, CompareSortedIndexesLess) {
std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
RowMap rm(0, 10);
storage.CompareSortedIndexes(FilterOp::kLt, SqlValue::Long(60),
sorted_order.data(), rm);
ASSERT_EQ(rm.size(), 6u);
ASSERT_EQ(rm.Get(0), 7u);
}
TEST(NumericStorageUnittest, CompareSortedIndexesEqual) {
std::vector<uint32_t> data_vec{30, 40, 50, 60, 90, 80, 70, 0, 10, 20};
std::vector<uint32_t> sorted_order{7, 8, 9, 0, 1, 2, 3, 6, 5, 4};
NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
RowMap rm(0, 10);
storage.CompareSortedIndexes(FilterOp::kEq, SqlValue::Long(60),
sorted_order.data(), rm);
ASSERT_EQ(rm.size(), 1u);
ASSERT_EQ(rm.Get(0), 3u);
}
TEST(StorageOverlayUnittests, FilterIsNull) {
std::vector<uint32_t> data_vec(1025);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), 1025, ColumnType::kUint32);
StorageOverlay overlay(&storage);
RowMap rm(0, 1025);
overlay.Filter(FilterOp::kIsNull, SqlValue::Long(0), rm);
ASSERT_EQ(rm.size(), 0u);
}
TEST(StorageOverlayUnittests, FilterIsNotNull) {
std::vector<uint32_t> data_vec(1025);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), 1025, ColumnType::kUint32);
StorageOverlay overlay(&storage);
RowMap rm(0, 1025);
overlay.Filter(FilterOp::kIsNotNull, SqlValue::Long(0), rm);
ASSERT_EQ(rm.size(), 1025u);
}
TEST(StorageOverlayUnittests, Filter) {
std::vector<uint32_t> data_vec(1025);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), 1025, ColumnType::kUint32);
StorageOverlay overlay(&storage);
RowMap rm(0, 1025);
overlay.Filter(FilterOp::kGe, SqlValue::Long(200), rm);
ASSERT_EQ(rm.size(), 825u);
ASSERT_EQ(rm.Get(0), 200u);
}
TEST(StorageOverlayUnittests, Sort) {
std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
std::vector<uint32_t> out = {1, 7, 4, 0, 6, 3, 2, 5, 8};
NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
StorageOverlay overlay(&storage);
overlay.StableSort(out.data(), 9);
std::vector<uint32_t> stable_out{0, 6, 3, 1, 7, 4, 2, 5, 8};
ASSERT_EQ(out, stable_out);
}
TEST(NullOverlayUnittest, FilterIsNull) {
std::vector<uint32_t> data_vec(10);
std::iota(data_vec.begin(), data_vec.end(), 0);
BitVector bv = BitVector::Range(0, 20, [](uint32_t t) { return t % 2 == 0; });
NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
NullOverlay overlay(std::move(storage_overlay), &bv);
RowMap rm(0, 10);
overlay.Filter(FilterOp::kIsNull, SqlValue::Long(5), rm);
ASSERT_EQ(rm.size(), 5u);
ASSERT_EQ(rm.Get(0), 1u);
}
TEST(NullOverlayUnittest, FilterIsNotNull) {
std::vector<uint32_t> data_vec(10);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), 10, ColumnType::kUint32);
BitVector bv = BitVector::Range(0, 20, [](uint32_t t) { return t % 2 == 0; });
std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
NullOverlay overlay(std::move(storage_overlay), &bv);
RowMap rm(0, 10);
overlay.Filter(FilterOp::kIsNotNull, SqlValue::Long(5), rm);
ASSERT_EQ(rm.size(), 5u);
ASSERT_EQ(rm.Get(0), 0u);
}
TEST(NullOverlayUnittest, Filter) {
uint32_t bv_size = 20;
uint32_t data_size = 10;
// Prepare storage
std::vector<uint32_t> data_vec(data_size);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), data_size, ColumnType::kUint32);
// Prepare NullOverlay
BitVector bv =
BitVector::Range(0, bv_size, [](uint32_t t) { return t % 2 == 0; });
std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
NullOverlay overlay(std::move(storage_overlay), &bv);
RowMap rm(0, bv_size);
overlay.Filter(FilterOp::kGe, SqlValue::Long(5), rm);
ASSERT_EQ(rm.size(), 5u);
ASSERT_EQ(rm.Get(0), 10u);
}
TEST(NullOverlayUnittest, FilterLarge) {
uint32_t bv_size = 1000;
uint32_t data_size = 100;
// Prepare storage
std::vector<uint32_t> data_vec(data_size);
std::iota(data_vec.begin(), data_vec.end(), 0);
NumericStorage storage(data_vec.data(), data_size, ColumnType::kUint32);
// Prepare NullOverlay
BitVector bv =
BitVector::Range(800, bv_size, [](uint32_t t) { return t % 2 == 0; });
std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
NullOverlay overlay(std::move(storage_overlay), &bv);
RowMap rm(0, bv_size);
overlay.Filter(FilterOp::kGe, SqlValue::Long(50), rm);
ASSERT_EQ(rm.size(), 50u);
ASSERT_EQ(rm.Get(0), 900u);
}
TEST(NullOverlayUnittest, Sort) {
// Prepare storage
std::vector<uint32_t> data_vec{0, 1, 2, 0, 1, 2, 0, 1, 2};
std::vector<uint32_t> out(18);
std::iota(out.begin(), out.end(), 0);
NumericStorage storage(data_vec.data(), 9, ColumnType::kUint32);
// Prepare NullOverlay
BitVector bv = BitVector::Range(0, 18, [](uint32_t t) { return t % 2 == 0; });
std::unique_ptr<ColumnOverlay> storage_overlay(new StorageOverlay(&storage));
NullOverlay overlay(std::move(storage_overlay), &bv);
overlay.StableSort(out.data(), 18);
std::vector<uint32_t> stable_out{1, 3, 5, 7, 9, 11, 13, 15, 17,
0, 6, 12, 2, 8, 14, 4, 10, 16};
ASSERT_EQ(out, stable_out);
}
} // namespace
} // namespace column
} // namespace trace_processor
} // namespace perfetto