20 #include <gtest/gtest.h>
59 EXPECT_TRUE(status.
ok());
61 EXPECT_TRUE(status.ok());
66 EXPECT_TRUE(status.ok());
68 EXPECT_TRUE(status.ok());
79 *
reinterpret_cast<int32_t*
>(tuple_mem) = val;
98 while (!iter.
AtEnd()) {
100 int32_t val = *
reinterpret_cast<int32_t*
>(
build_expr_ctxs_[0]->GetValue(row));
103 if (all_unique) EXPECT_TRUE(results[val] == NULL);
113 EXPECT_TRUE(probe_row != build_row);
118 EXPECT_EQ(build_val, probe_val);
129 for (
int i = 0; i < num_data; ++i) {
134 iter = table->
Find(ht_ctx, hash);
136 if (data[i].expected_build_rows.size() == 0) {
137 EXPECT_TRUE(iter.
AtEnd());
140 map<TupleRow*, bool> matched;
141 while (!iter.
AtEnd()) {
142 EXPECT_EQ(matched.find(iter.
GetRow()), matched.end());
143 matched[iter.
GetRow()] =
true;
148 EXPECT_TRUE(matched[data[i].expected_build_rows[j]]);
151 EXPECT_EQ(data[i].expected_build_rows.size(), 1);
152 EXPECT_EQ(data[i].expected_build_rows[0]->GetTuple(0),
169 EXPECT_EQ(*val_row1, 1);
172 EXPECT_EQ(*val_row2, 2);
175 EXPECT_EQ(*val_row3, 3);
178 EXPECT_EQ(*val_row4, 4);
196 for (
int i = 0; i < 10; ++i) {
207 EXPECT_TRUE(success);
208 for (
int i = 0; i < 5; ++i) {
210 bool inserted = hash_table.
Insert(&ht_ctx, build_rows[i]->GetTuple(0), hash);
211 EXPECT_TRUE(inserted);
213 EXPECT_EQ(hash_table.
size(), 5);
216 FullScan(&hash_table, &ht_ctx, 0, 5,
true, scan_rows, build_rows);
217 ProbeTest(&hash_table, &ht_ctx, probe_rows, 10,
false);
222 EXPECT_EQ(hash_table.
size(), 5);
223 memset(scan_rows, 0,
sizeof(scan_rows));
224 FullScan(&hash_table, &ht_ctx, 0, 5,
true, scan_rows, build_rows);
225 ProbeTest(&hash_table, &ht_ctx, probe_rows, 10,
false);
230 EXPECT_EQ(hash_table.
size(), 5);
231 memset(scan_rows, 0,
sizeof(scan_rows));
232 FullScan(&hash_table, &ht_ctx, 0, 5,
true, scan_rows, build_rows);
233 ProbeTest(&hash_table, &ht_ctx, probe_rows, 10,
false);
238 EXPECT_EQ(hash_table.
size(), 5);
239 memset(scan_rows, 0,
sizeof(scan_rows));
240 FullScan(&hash_table, &ht_ctx, 0, 5,
true, scan_rows, build_rows);
241 ProbeTest(&hash_table, &ht_ctx, probe_rows, 10,
false);
247 void ScanTest(
bool quadratic,
int initial_size,
int rows_to_insert,
248 int additional_rows) {
249 int total_rows = rows_to_insert + additional_rows;
255 vector<TupleRow*> build_rows;
259 for (
int val = 1; val <= rows_to_insert; ++val) {
261 EXPECT_TRUE(success) <<
" failed to resize: " << val;
263 for (
int i = 0; i < val; ++i) {
267 build_rows.push_back(row);
273 for (
int val = rows_to_insert; val < rows_to_insert + additional_rows; ++val) {
278 ProbeTest(&hash_table, &ht_ctx, probe_rows, total_rows,
true);
284 ProbeTest(&hash_table, &ht_ctx, probe_rows, total_rows,
true);
289 ProbeTest(&hash_table, &ht_ctx, probe_rows, total_rows,
true);
291 delete [] probe_rows;
300 int expected_size = 0;
305 HashTable hash_table(&pool, quadratic, num_to_add);
310 int build_row_val = 0;
312 for (
int i = 0; i < 20; ++i) {
318 EXPECT_TRUE(success) <<
" failed to resize: " << num_to_add;
319 for (
int j = 0; j < num_to_add; ++build_row_val, ++j) {
323 if (!inserted)
goto done_inserting;
325 expected_size += num_to_add;
330 EXPECT_EQ(hash_table.
size(), 4194300);
332 for (
int i = 0; i < expected_size * 5; i += 100000) {
336 if (i < hash_table.
size()) {
337 EXPECT_TRUE(!iter.
AtEnd()) <<
" i: " << i;
340 EXPECT_TRUE(iter.
AtEnd()) <<
" i: " << i;
356 HashTable hash_table(&pool, quadratic, table_size);
364 for (
int build_row_val = 0; build_row_val < table_size; ++build_row_val) {
369 EXPECT_TRUE(inserted);
370 EXPECT_EQ(hash_table.
EmptyBuckets(), table_size - build_row_val - 1);
374 iter = hash_table.
Find(&ht_ctx, hash);
375 EXPECT_FALSE(iter.
AtEnd());
384 iter = hash_table.
Find(&ht_ctx, hash);
385 EXPECT_TRUE(iter.
AtEnd());
394 SetupTest(
false, 1024);
395 SetupTest(
false, 65536);
400 SetupTest(
true, 1024);
401 SetupTest(
true, 65536);
406 BasicTest(
false, 1024);
407 BasicTest(
false, 65536);
412 BasicTest(
true, 1024);
413 BasicTest(
true, 65536);
418 ScanTest(
false, 1, 10, 5);
419 ScanTest(
false, 1024, 1000, 5);
420 ScanTest(
false, 1024, 1000, 500);
424 ScanTest(
true, 1, 10, 5);
425 ScanTest(
true, 1024, 1000, 5);
426 ScanTest(
true, 1024, 1000, 500);
430 GrowTableTest(
false);
438 InsertFullTest(
false, 1);
439 InsertFullTest(
false, 4);
440 InsertFullTest(
false, 64);
441 InsertFullTest(
false, 1024);
442 InsertFullTest(
false, 65536);
446 InsertFullTest(
true, 1);
447 InsertFullTest(
true, 4);
448 InsertFullTest(
true, 64);
449 InsertFullTest(
true, 1024);
450 InsertFullTest(
true, 65536);
455 int main(
int argc,
char** argv) {
456 ::testing::InitGoogleTest(&argc, argv);
458 return RUN_ALL_TESTS();
vector< ExprContext * > build_expr_ctxs_
stl-like iterator interface.
void SetupTest(bool quadratic, int table_size)
bool AtEnd() const
Returns true if this iterator is at the end, i.e. GetRow() cannot be called.
void ValidateMatch(TupleRow *probe_row, TupleRow *build_row)
TEST_F(InstructionCounterTest, Count)
Tuple * GetTuple(int tuple_idx)
void BasicTest(bool quadratic, int table_size)
void InsertFullTest(bool quadratic, int table_size)
void FullScan(HashTable *table, HashTableCtx *ht_ctx, int min, int max, bool all_unique, TupleRow **results, TupleRow **expected)
static Status Open(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for opening multiple expr trees.
void ScanTest(bool quadratic, int initial_size, int rows_to_insert, int additional_rows)
A tuple with 0 materialised slots is represented as NULL.
const StringSearch UrlParser::hash_search & hash
vector< TupleRow * > expected_build_rows
Iterator Begin(HashTableCtx *ht_ctx)
bool CheckAndResize(uint64_t buckets_to_fill, HashTableCtx *ht_ctx)
int64_t EmptyBuckets() const
Returns the number of empty buckets.
static Tuple * Create(int size, MemPool *pool)
initialize individual tuple with data residing in mem pool
void ProbeTest(HashTable *table, HashTableCtx *ht_ctx, ProbeTestData *data, int num_data, bool scan)
static void Close(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for closing multiple expr trees.
void GrowTableTest(bool quadratic)
vector< ExprContext * > probe_expr_ctxs_
void IR_ALWAYS_INLINE Next()
Iterates to the next element. It should be called only if !AtEnd().
This is the superclass of all expr evaluation nodes.
bool ResizeBuckets(int64_t num_buckets, HashTableCtx *ht_ctx)
Resize the hash table to 'num_buckets'. Returns false on OOM.
This class is thread-safe.
uint64_t Test(T *ht, const ProbeTuple *input, uint64_t num_tuples)
void SetTuple(int tuple_idx, Tuple *tuple)
static int64_t NextPowerOfTwo(int64_t v)
int64_t num_buckets() const
Returns the number of buckets.
int main(int argc, char **argv)
TupleRow * CreateTupleRow(int32_t val)
Reference to a single slot of a tuple.
Iterator IR_ALWAYS_INLINE Find(HashTableCtx *ht_ctx, uint32_t hash)
static void Init()
Initialize CpuInfo.
static Status Prepare(const std::vector< ExprContext * > &ctxs, RuntimeState *state, const RowDescriptor &row_desc, MemTracker *tracker)
void ResizeTable(HashTable *table, int64_t new_size, HashTableCtx *ht_ctx)
void Close()
Call to cleanup any resources. Must be called once.
bool IR_ALWAYS_INLINE EvalAndHashBuild(TupleRow *row, uint32_t *hash)
TupleRow * GetRow() const
bool IR_ALWAYS_INLINE Insert(HashTableCtx *ht_ctx, const BufferedTupleStream::RowIdx &idx, TupleRow *row, uint32_t hash)
int64_t size() const
Returns number of elements inserted in the hash table.
uint8_t * Allocate(int size)
bool IR_ALWAYS_INLINE EvalAndHashProbe(TupleRow *row, uint32_t *hash)