Repository: vespa-engine/vespa
File: searchlib/src/tests/common/bitvector/bitvector_test.cpp (C++)

Code before:

std::unique_ptr<nbostream>
write_test_bv_to_nbostream(const BitVector &bv, uint32_t guard_bits, size_t alignment)
{
    auto out = std::make_unique<nbostream>();
    Aligner aligner(alignment);
    uint64_t size = bv.size();
    uint64_t cached_hits = bv.countTrueBits();
    uint64_t file_bytes = aligner.align(bv.num_bytes_plain(size + guard_bits));
    *out << size << cached_hits << file_bytes;
    out->write(bv.getStart(), std::min(bv.getFileBytes(), file_bytes));
    if (guard_bits == BitVector::num_guard_bits) {
        EXPECT_EQ(file_bytes, bv.getFileBytes());
    } else {
        EXPECT_NE(file_bytes, bv.getFileBytes());
    }
    if (file_bytes > bv.getFileBytes()) {
        EXPECT_TRUE(guard_bits > BitVector::num_guard_bits);
        std::vector<char> zerofill(file_bytes - bv.getFileBytes());
        out->write(zerofill.data(), zerofill.size());
    }
    return out;
}

void
write_test_bv_to_file(const BitVector& bv, const std::string& file_name)
{
    std::filesystem::path bvpath(file_name);
    std::ofstream bvfile(bvpath, std::ios::binary);
    auto legacy_entry_size = BitVector::legacy_num_bytes_with_single_guard_bit(bv.size());
    bvfile.write(static_cast<const char *>(bv.getStart()), legacy_entry_size);
    bvfile.close();
    ASSERT_TRUE(bvfile.good());
    std::filesystem::resize_file(bvpath, 1024u);
}

class BitVectorTest : public ::testing::Test {
protected:
    static std::unique_ptr<const BitVector> _file_bv;
    static constexpr uint32_t file_alignment = 0x100;

    BitVectorTest();
    ~BitVectorTest() override;
    static void SetUpTestSuite();
    static void TearDownTestSuite();
};

std::unique_ptr<const BitVector> BitVectorTest::_file_bv;

BitVectorTest::BitVectorTest()
    : ::testing::Test()

Review comment (suggestion):
Consider adding a comment on why we resize the file to this specific length since it is constant whereas `legacy_entry_size` is (presumably) not

Code after:
    *out << size << cached_hits << file_bytes;
    out->write(bv.getStart(), std::min(bv.getFileBytes(), file_bytes));
    if (guard_bits == BitVector::num_guard_bits) {
        EXPECT_EQ(file_bytes, bv.getFileBytes());
    } else {
        EXPECT_NE(file_bytes, bv.getFileBytes());
    }
    if (file_bytes > bv.getFileBytes()) {
        EXPECT_TRUE(guard_bits > BitVector::num_guard_bits);
        std::vector<char> zerofill(file_bytes - bv.getFileBytes());
        out->write(zerofill.data(), zerofill.size());
    }
    return out;
}

void
write_test_bv_to_file(const BitVector& bv, const std::string& file_name)
{
    std::filesystem::path bvpath(file_name);
    std::ofstream bvfile(bvpath, std::ios::binary);
    auto legacy_entry_size = BitVector::legacy_num_bytes_with_single_guard_bit(bv.size());
    bvfile.write(static_cast<const char *>(bv.getStart()), legacy_entry_size);
    bvfile.close();
    ASSERT_TRUE(bvfile.good());
    // Resize file to beyond what is needed ( 1 guard bit => 256 bytes, 2 guard bits => 512 bytes).
    std::filesystem::resize_file(bvpath, 1024u);
}

class BitVectorTest : public ::testing::Test {
protected:
    static std::unique_ptr<const BitVector> _file_bv;
    static constexpr uint32_t bitvector_alignment_bits = BitVector::getAlignment() * 8;

    BitVectorTest();
    ~BitVectorTest() override;
    static void SetUpTestSuite();
    static void TearDownTestSuite();
    static std::unique_ptr<const BitVector> make_test_bv();
};

std::unique_ptr<const BitVector> BitVectorTest::_file_bv;

BitVectorTest::BitVectorTest()
    : ::testing::Test()
{
}

BitVectorTest::~BitVectorTest() = default;

void
BitVectorTest::SetUpTestSuite()