This test continues adding tuples to the hash table and exercises the resize code paths.
| 461 | // This test continues adding tuples to the hash table and exercises the resize code |
| 462 | // paths. |
| 463 | void GrowTableTest(bool quadratic) { |
| 464 | uint64_t num_to_add = 4; |
| 465 | int expected_size = 0; |
| 466 | |
| 467 | // Need enough memory for two hash table bucket directories during resize. |
| 468 | const int64_t mem_limit_mb = 128 + 64; |
| 469 | HashTable* hash_table; |
| 470 | ASSERT_TRUE( |
| 471 | CreateHashTable(quadratic, num_to_add, &hash_table, 1024 * 1024, mem_limit_mb)); |
| 472 | scoped_ptr<HashTableCtx> ht_ctx; |
| 473 | Status status = HashTableCtx::Create(&pool_, runtime_state_, build_exprs_, |
| 474 | probe_exprs_, false /* !stores_nulls_ */, |
| 475 | vector<bool>(build_exprs_.size(), false), 1, 0, 1, &mem_pool_, &mem_pool_, |
| 476 | &mem_pool_, &ht_ctx); |
| 477 | EXPECT_OK(status); |
| 478 | |
| 479 | // Inserts num_to_add + (num_to_add^2) + (num_to_add^4) + ... + (num_to_add^20) |
| 480 | // entries. When num_to_add == 4, then the total number of inserts is 4194300. |
| 481 | int build_row_val = 0; |
| 482 | for (int i = 0; i < 20; ++i) { |
| 483 | bool success; |
| 484 | EXPECT_OK(hash_table->CheckAndResize(num_to_add, ht_ctx.get(), &success)); |
| 485 | EXPECT_TRUE(success) << " failed to resize: " << num_to_add << "\n" |
| 486 | << tracker_.LogUsage(MemTracker::UNLIMITED_DEPTH) << "\n" |
| 487 | << clients_.back()->DebugString(); |
| 488 | for (int j = 0; j < num_to_add; ++build_row_val, ++j) { |
| 489 | TupleRow* row = CreateTupleRow(build_row_val); |
| 490 | if (!ht_ctx->EvalAndHashBuild(row)) continue; |
| 491 | BufferedTupleStream::FlatRowPtr dummy_flat_row = nullptr; |
| 492 | EXPECT_TRUE(hash_table->stores_tuples_); |
| 493 | bool inserted = hash_table->Insert(ht_ctx.get(), dummy_flat_row, row, &status); |
| 494 | ASSERT_OK(status); |
| 495 | if (!inserted) goto done_inserting; |
| 496 | } |
| 497 | expected_size += num_to_add; |
| 498 | num_to_add *= 2; |
| 499 | } |
| 500 | done_inserting: |
| 501 | EXPECT_EQ(hash_table->size(), 4194300); |
| 502 | |
| 503 | // The next allocation should put us over the limit, since we'll need 128MB for |
| 504 | // the old buckets and 256MB for the new buckets. |
| 505 | bool success; |
| 506 | EXPECT_OK(hash_table->CheckAndResize(num_to_add * 2, ht_ctx.get(), &success)); |
| 507 | EXPECT_FALSE(success); |
| 508 | |
| 509 | // Validate that we can find the entries before we went over the limit |
| 510 | for (int i = 0; i < expected_size * 5; i += 100000) { |
| 511 | TupleRow* probe_row = CreateTupleRow(i); |
| 512 | if (!ht_ctx->EvalAndHashProbe(probe_row)) continue; |
| 513 | HashTable::Iterator iter = hash_table->FindProbeRow(ht_ctx.get()); |
| 514 | if (i < hash_table->size()) { |
| 515 | EXPECT_TRUE(!iter.AtEnd()) << " i: " << i; |
| 516 | ValidateMatch(probe_row, iter.GetRow()); |
| 517 | } else { |
| 518 | EXPECT_TRUE(iter.AtEnd()) << " i: " << i; |
| 519 | } |
| 520 | } |
nothing calls this directly
no test coverage detected