blob: 34ce77a48e232539bc2de8161b36c2c7aa46d5c6 [file] [log] [blame]
// Copyright 2019 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 "src/lib/storage/vfs/cpp/journal/header_view.h"
#include <gtest/gtest.h>
#include "src/lib/storage/vfs/cpp/journal/format.h"
namespace fs {
namespace {
constexpr size_t kBlockSize = kJournalBlockSize;
constexpr uint64_t kPayloadBlocks = 10;
constexpr uint64_t kSequenceNumber = 20;
TEST(JournalHeaderView, JournalHeaderView) {
uint8_t block[kBlockSize] = {};
JournalHeaderView header(cpp20::span<uint8_t>(block, kBlockSize));
}
TEST(JournalHeaderView, Initialize) {
uint8_t block[kBlockSize] = {};
cpp20::span<uint8_t> span(block, kBlockSize);
JournalHeaderView header(span, kPayloadBlocks, kSequenceNumber);
ASSERT_EQ(kPayloadBlocks, header.PayloadBlocks());
ASSERT_EQ(kSequenceNumber, header.SequenceNumber());
for (uint32_t i = 0; i < kPayloadBlocks; i++) {
ASSERT_EQ(header.TargetBlock(i), 0ul);
ASSERT_FALSE(header.EscapedBlock(i));
}
}
TEST(JournalHeaderView, LoadValidHeader) {
uint8_t block[kBlockSize] = {};
cpp20::span<uint8_t> span(block, kBlockSize);
JournalHeaderView header(span, kPayloadBlocks, kSequenceNumber);
auto loaded = fs::JournalHeaderView::Create(span, kSequenceNumber).value();
ASSERT_EQ(loaded.PayloadBlocks(), header.PayloadBlocks());
ASSERT_EQ(loaded.SequenceNumber(), header.SequenceNumber());
ASSERT_EQ(loaded.ObjectType(), JournalObjectType::kHeader);
}
TEST(JournalHeaderView, LoadValidRevocation) {
uint8_t block[kBlockSize] = {};
cpp20::span<uint8_t> span(block, kBlockSize);
JournalHeaderView header(span, kPayloadBlocks, kSequenceNumber);
auto prefix = reinterpret_cast<JournalPrefix*>(block);
prefix->flags = kJournalPrefixFlagRevocation;
auto loaded = fs::JournalHeaderView::Create(span, kSequenceNumber).value();
ASSERT_EQ(loaded.PayloadBlocks(), header.PayloadBlocks());
ASSERT_EQ(loaded.SequenceNumber(), header.SequenceNumber());
ASSERT_EQ(loaded.ObjectType(), JournalObjectType::kRevocation);
}
TEST(JournalHeaderView, LoadBadMagicNumber) {
uint8_t block[kBlockSize] = {};
cpp20::span<uint8_t> span(block, kBlockSize);
auto loaded = fs::JournalHeaderView::Create(span, kSequenceNumber);
ASSERT_EQ(ZX_ERR_BAD_STATE, loaded.error());
}
TEST(JournalHeaderView, LoadSmallBuffer) {
uint8_t block[kBlockSize - 1] = {};
cpp20::span<uint8_t> span(block, sizeof(block));
auto loaded = fs::JournalHeaderView::Create(span, kSequenceNumber);
ASSERT_EQ(ZX_ERR_BUFFER_TOO_SMALL, loaded.error());
}
TEST(JournalHeaderView, SetTargetBlock) {
uint8_t block[kBlockSize] = {};
cpp20::span<uint8_t> span(block, kBlockSize);
JournalHeaderView header(span, kPayloadBlocks, kSequenceNumber);
for (uint32_t i = 0; i < kPayloadBlocks; i++) {
header.SetTargetBlock(i, i + 1);
}
auto loaded = fs::JournalHeaderView::Create(span, kSequenceNumber).value();
for (uint32_t i = 0; i < kPayloadBlocks; i++) {
ASSERT_EQ(i + 1, header.TargetBlock(i));
ASSERT_EQ(i + 1, loaded.TargetBlock(i));
}
}
TEST(JournalHeaderView, TargetBlockPtr) {
uint8_t block[kBlockSize] = {};
auto header_block = reinterpret_cast<const JournalHeaderBlock*>(block);
cpp20::span<uint8_t> span(block, kBlockSize);
uint32_t target_block = 3;
JournalHeaderView header(span, kPayloadBlocks, kSequenceNumber);
header.SetTargetBlock(target_block, target_block);
auto ptr = header.TargetBlockPtr(target_block);
ASSERT_NE(ptr, nullptr);
ASSERT_EQ(ptr, &header_block->target_blocks[target_block]);
ASSERT_EQ(*ptr, header_block->target_blocks[target_block]);
}
TEST(JournalHeaderView, SetEscapedBlock) {
uint8_t block[kBlockSize] = {};
auto header_block = reinterpret_cast<const JournalHeaderBlock*>(block);
cpp20::span<uint8_t> span(block, kBlockSize);
JournalHeaderView header(span, kPayloadBlocks, kSequenceNumber);
for (uint32_t i = 0; i < kPayloadBlocks; i++) {
header.SetEscapedBlock(i, (i % 2) == 0);
}
auto loaded = fs::JournalHeaderView::Create(span, kSequenceNumber).value();
for (uint32_t i = 0; i < kPayloadBlocks; i++) {
ASSERT_EQ((i % 2) == 0, header.EscapedBlock(i));
ASSERT_EQ((i % 2) == 0, loaded.EscapedBlock(i));
ASSERT_EQ((i % 2) == 0,
(header_block->target_flags[i] & kJournalBlockDescriptorFlagEscapedBlock) ==
kJournalBlockDescriptorFlagEscapedBlock);
}
}
TEST(JournalHeaderView, PayloadBlocks) {
uint8_t block[kBlockSize] = {};
cpp20::span<uint8_t> span(block, kBlockSize);
uint32_t payload_blocks = 5;
JournalHeaderView header(span, payload_blocks, kSequenceNumber);
ASSERT_EQ(payload_blocks, header.PayloadBlocks());
}
TEST(JournalHeaderView, PayloadBlocksPtr) {
uint8_t block[kBlockSize] = {};
auto header_block = reinterpret_cast<const JournalHeaderBlock*>(block);
cpp20::span<uint8_t> span(block, kBlockSize);
JournalHeaderView header(span, kPayloadBlocks, kSequenceNumber);
auto ptr = header.PayloadBlocksPtr();
ASSERT_NE(ptr, nullptr);
ASSERT_EQ(ptr, &header_block->payload_blocks);
ASSERT_EQ(*ptr, header_block->payload_blocks);
}
TEST(JournalHeaderView, SequenceNumber) {
uint8_t block[kBlockSize] = {};
cpp20::span<uint8_t> span(block, kBlockSize);
uint32_t sequence_number = 33;
JournalHeaderView header(span, kPayloadBlocks, sequence_number);
ASSERT_EQ(sequence_number, header.SequenceNumber());
}
} // namespace
} // namespace fs