blob: 3aba6dcf891e8c56c08292696d9fbc043293c60d [file]
// Copyright 2023 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.
#ifndef SRC_FIRMWARE_LIB_STORAGE_TEST_TEST_UTILS_H_
#define SRC_FIRMWARE_LIB_STORAGE_TEST_TEST_UTILS_H_
#include <lib/storage/storage.h>
#include <memory>
#include <vector>
// A helper class that creates a buffer meeting `FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT`.
class AlignedBuffer {
public:
explicit AlignedBuffer(size_t size)
: buffer_(size + FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT - 1) {}
uint8_t* get() {
uintptr_t addr = reinterpret_cast<uintptr_t>(buffer_.data());
uintptr_t gap = (addr + FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT - 1) /
FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT *
FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT -
addr;
return buffer_.data() + gap;
}
size_t size() const { return buffer_.size() - (FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT - 1); }
private:
std::vector<uint8_t> buffer_;
};
// A helper class to constructs a FuchsiaFirmwareStorage backed in-memory buffer.
// Usage:
//
// TestFuchsiaFirmwareStorage test_storage(<storage_size>, <block_size>);
// FuchsiaFIrmwareStorage storage = test_storage.GetFuchsiaFirmwareStorage();
// ...
class TestFuchsiaFirmwareStorage {
public:
TestFuchsiaFirmwareStorage(size_t size, size_t block_size)
: scratch_buffer_(block_size), fill_buffer_(2 * block_size), block_size_(block_size) {
// Initialize buffer data;
for (size_t i = 0; i < size; i++) {
buffer_.push_back(static_cast<uint8_t>(i));
}
}
FuchsiaFirmwareStorage GetFuchsiaFirmwareStorage() {
return FuchsiaFirmwareStorage{
.block_size = block_size_,
.total_blocks = buffer_.size() / block_size_,
.scratch_buffer = scratch_buffer_.get(),
.scratch_buffer_size_bytes = scratch_buffer_.size(),
.fill_buffer = fill_buffer_.get(),
.fill_buffer_size_bytes = fill_buffer_.size(),
.ctx = this,
.read = Read,
.write = Write,
};
}
std::vector<uint8_t>& buffer() { return buffer_; }
private:
static bool Read(void* ctx, size_t block_offset, size_t blocks_count, void* dst) {
TestFuchsiaFirmwareStorage* ptr = static_cast<TestFuchsiaFirmwareStorage*>(ctx);
size_t offset = block_offset * ptr->block_size_, size = blocks_count * ptr->block_size_;
if ((reinterpret_cast<uintptr_t>(dst) % FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT) ||
offset + size > ptr->buffer_.size()) {
return false;
}
memcpy(dst, ptr->buffer_.data() + offset, size);
return true;
}
static bool Write(void* ctx, size_t block_offset, size_t blocks_count, const void* src) {
TestFuchsiaFirmwareStorage* ptr = static_cast<TestFuchsiaFirmwareStorage*>(ctx);
size_t offset = block_offset * ptr->block_size_, size = blocks_count * ptr->block_size_;
if ((reinterpret_cast<uintptr_t>(src) % FUCHSIA_FIRMWARE_STORAGE_BUFFER_ALIGNMENT) ||
offset + size > ptr->buffer_.size()) {
return false;
}
memcpy(ptr->buffer_.data() + offset, src, size);
return true;
}
AlignedBuffer scratch_buffer_;
AlignedBuffer fill_buffer_;
std::vector<uint8_t> buffer_;
size_t block_size_;
};
#endif // SRC_FIRMWARE_LIB_STORAGE_TEST_TEST_UTILS_H_