blob: 28add2e49086a6844d39ab667289189244aa6860 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <zxtest/zxtest.h>
#include "src/devices/block/drivers/block-verity/geometry.h"
namespace {
TEST(GeometryTest, IntegrityShapeFor4kSHA256) {
block_verity::IntegrityShape i = block_verity::IntegrityShapeFor(4096, 32, 8192);
// The optimal shape is 1 superblock, 65 integrity blocks, and 8126 data blocks.
// 8126 / 128 = 63.48 or so.
// We need 64 direct hash blocks, and one indirect hash block, which contains
// hashes of the direct hash blocks (which themselves contain hashes of the
// data blocks).
ASSERT_EQ(i.integrity_block_count, 65);
ASSERT_EQ(i.tree_depth, 2);
}
TEST(GeometryTest, IntegrityShapeForAssertsIfHashNotMultipleOfBlockSize) {
ASSERT_DEATH([] { block_verity::IntegrityShapeFor(4096, 33, 8192); },
"IntegrityShapeFor should assert if block_size modulo hash_size is not 0");
}
TEST(GeometryTest, BestSplitFor) {
block_verity::BlockAllocation a = block_verity::BestSplitFor(4096, 32, 3);
ASSERT_EQ(a.superblock_count, 1);
ASSERT_EQ(a.padded_integrity_block_count, 1);
ASSERT_EQ(a.data_block_count, 1);
ASSERT_EQ(a.superblock_count + a.padded_integrity_block_count + a.data_block_count, 3);
// Verify that we smoothly allocate additional blocks, and that we always
// allocate all blocks, from the smallest possible partition (3 blocks) up to
// ~32MiB on 4k blocks with SHA256 hash function.
block_verity::BlockAllocation prev = a;
for (uint64_t block_count = 4; block_count <= 8192; block_count++) {
block_verity::BlockAllocation ba = block_verity::BestSplitFor(4096, 32, block_count);
ASSERT_EQ(ba.superblock_count + ba.padded_integrity_block_count + ba.data_block_count,
block_count);
ASSERT_EQ(ba.superblock_count, 1);
bool changed_integrity = (ba.padded_integrity_block_count != prev.padded_integrity_block_count);
bool changed_data = (ba.data_block_count != prev.data_block_count);
ASSERT_TRUE(changed_integrity != changed_data);
if (changed_integrity) {
ASSERT_EQ(ba.padded_integrity_block_count, prev.padded_integrity_block_count + 1);
}
if (changed_data) {
ASSERT_EQ(ba.data_block_count, prev.data_block_count + 1);
}
prev = ba;
}
}
TEST(GeometryTest, BestSplitForAssertsIfTooSmall) {
ASSERT_DEATH([] { block_verity::BestSplitFor(4096, 32, 2); },
"BestSplitFor should assert if total_blocks is less than 3");
}
} // namespace