blob: 504724240827cc5155949390bf2ebd5c0d2df939 [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 "inspector/parser.h"
#include <blobfs/format.h>
#include <storage/buffer/array_buffer.h>
#include <fs/transaction/block_transaction.h>
#include <zxtest/zxtest.h>
namespace blobfs {
namespace {
TEST(InspectorParser, ParseSuperblock) {
uint64_t start_block = 0;
uint64_t block_length = 1;
Superblock superblock;
superblock.magic0 = kBlobfsMagic0;
superblock.magic1 = kBlobfsMagic1;
superblock.alloc_block_count = 1234;
storage::ArrayBuffer device(block_length, kBlobfsBlockSize);
auto device_sb = reinterpret_cast<Superblock*>(device.Data(start_block));
*device_sb = superblock;
Superblock out_superblock = GetSuperblock(&device);
ASSERT_EQ(superblock.magic0, out_superblock.magic0);
ASSERT_EQ(superblock.magic1, out_superblock.magic1);
ASSERT_EQ(superblock.blob_header_next, out_superblock.blob_header_next);
ASSERT_EQ(superblock.alloc_block_count, out_superblock.alloc_block_count);
}
TEST(InspectorParser, ParseBitmap) {
uint32_t start_block = 0;
uint32_t block_length = 1;
storage::ArrayBuffer device(block_length, kBlobfsBlockSize);
memset(device.Data(start_block), 0xAA, device.capacity() * device.BlockSize());
for (uint32_t i = 0; i < block_length * kBlobfsBlockSize * CHAR_BIT; ++i) {
ASSERT_EQ(i % 2 != 0, GetBitmapElement(&device, i));
}
}
TEST(InspectorParser, ParseInodeTable) {
uint32_t block_length = 2;
storage::ArrayBuffer device(block_length, kBlobfsBlockSize);
uint32_t expected_block_count = 42;
uint32_t inode_count = 0;
for (uint32_t block_offset = 0; block_offset < block_length; ++block_offset) {
auto inodes = reinterpret_cast<Inode*>(device.Data(block_offset));
for (uint32_t inode_offset = 0; inode_offset < kBlobfsInodesPerBlock; ++inode_offset) {
inodes[inode_offset].blob_size = inode_count;
inodes[inode_offset].block_count = expected_block_count;
inode_count++;
}
}
for (uint32_t i = 0; i < inode_count; ++i) {
Inode out_inode = GetInodeElement(&device, i);
ASSERT_EQ(i, out_inode.blob_size);
ASSERT_EQ(expected_block_count, out_inode.block_count);
}
}
TEST(InspectorParser, WriteBitmapElement) {
uint32_t start_block = 0;
uint32_t block_length = 1;
storage::ArrayBuffer device(block_length, kBlobfsBlockSize);
memset(device.Data(start_block), 0xFF, device.capacity() * device.BlockSize());
for (uint32_t i = 0; i < block_length * kBlobfsBlockSize * CHAR_BIT; ++i) {
ASSERT_TRUE(GetBitmapElement(&device, i));
}
// Write the |write_element| bit to false.
uint64_t write_element = 25;
bool write_value = false;
WriteBitmapElement(&device, write_value, write_element);
for (uint32_t i = 0; i < block_length * kBlobfsBlockSize * CHAR_BIT; ++i) {
bool is_set = (i == write_element) ? write_value : !write_value;
ASSERT_EQ(is_set, GetBitmapElement(&device, i));
}
// Write the bit back to true.
WriteBitmapElement(&device, true, write_element);
for (uint32_t i = 0; i < block_length * kBlobfsBlockSize * CHAR_BIT; ++i) {
ASSERT_TRUE(GetBitmapElement(&device, i));
}
}
TEST(InspectorParser, WriteSingleInodeElement) {
uint32_t block_length = 2;
storage::ArrayBuffer device(block_length, kBlobfsBlockSize);
memset(device.Data(0), 0x00, block_length * kBlobfsBlockSize);
uint32_t expected_block_count = 42;
uint32_t inode_count = block_length * kBlobfsInodesPerBlock;
// Sanity check zeroed out ok.
for (uint32_t i = 0; i < inode_count; ++i) {
Inode out_inode = GetInodeElement(&device, i);
ASSERT_EQ(0, out_inode.blob_size);
ASSERT_EQ(0, out_inode.block_count);
}
// Test writing a single inode.
Inode inode = {};
inode.blob_size = 0;
inode.block_count = expected_block_count;
WriteInodeElement(&device, inode, 0);
Inode out_inode = GetInodeElement(&device, 0);
ASSERT_EQ(inode.blob_size, out_inode.blob_size);
ASSERT_EQ(inode.block_count, out_inode.block_count);
// Make sure rest of device is not set.
for (uint64_t i = 1; i < inode_count; ++i) {
Inode out_inode = GetInodeElement(&device, i);
ASSERT_EQ(0, out_inode.blob_size);
ASSERT_EQ(0, out_inode.block_count);
}
}
TEST(InspectorParser, WriteManyInodeElements) {
uint32_t block_length = 2;
storage::ArrayBuffer device(block_length, kBlobfsBlockSize);
memset(device.Data(0), 0x00, block_length * kBlobfsBlockSize);
uint32_t expected_block_count = 42;
uint32_t inode_count = block_length * kBlobfsInodesPerBlock;
// Sanity check zeroed out ok.
for (uint32_t i = 0; i < inode_count; ++i) {
Inode out_inode = GetInodeElement(&device, i);
ASSERT_EQ(0, out_inode.blob_size);
ASSERT_EQ(0, out_inode.block_count);
}
// Test setting all the inodes.
for (uint64_t i = 0; i < inode_count; ++i) {
Inode inode = {};
inode.blob_size = i;
inode.block_count = expected_block_count;
WriteInodeElement(&device, inode, i);
}
for (uint64_t i = 0; i < inode_count; ++i) {
Inode out_inode = GetInodeElement(&device, i);
ASSERT_EQ(i, out_inode.blob_size);
ASSERT_EQ(expected_block_count, out_inode.block_count);
}
}
} // namespace
} // namespace blobfs