blob: 129d3dede6ce3f1ae0116486205602c2375f8af9 [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 <zircon/assert.h>
#include <zircon/device/block.h>
#include <zircon/hw/gpt.h>
#include <zxtest/zxtest.h>
#include "block-device-interface.h"
namespace {
class MockBlockDevice : public devmgr::BlockDeviceInterface {
public:
disk_format_t GetFormat() override = 0;
void SetFormat(disk_format_t format) override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
bool Netbooting() override { return false; }
zx_status_t GetInfo(fuchsia_hardware_block_BlockInfo* out_info) override {
fuchsia_hardware_block_BlockInfo info = {};
info.flags = 0;
info.block_size = 512;
info.block_count = 1024;
*out_info = info;
return ZX_OK;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
zx_status_t AttachDriver(const fbl::StringPiece& driver) override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
zx_status_t UnsealZxcrypt() override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
zx_status_t IsUnsealedZxcrypt(bool* is_unsealed_zxcrypt) override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
zx_status_t FormatZxcrypt() override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
bool ShouldCheckFilesystems() override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
zx_status_t CheckFilesystem() override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
zx_status_t FormatFilesystem() override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
zx_status_t MountFilesystem() override {
ZX_PANIC("Test should not invoke function %s\n", __FUNCTION__);
}
};
// Tests adding a device which has no GUID and an unknown format.
TEST(AddDeviceTestCase, AddUnknownDevice) {
class UnknownDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_UNKNOWN;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
return ZX_ERR_NOT_SUPPORTED;
}
};
UnknownDevice device;
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, device.Add());
}
// Tests adding a device with an unknown GUID and unknown format.
TEST(AddDeviceTestCase, AddUnknownPartition) {
class UnknownDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_UNKNOWN;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
const uint8_t expected[GPT_GUID_LEN] = GUID_EMPTY_VALUE;
memcpy(out_guid->value, expected, sizeof(expected));
return ZX_OK;
}
};
UnknownDevice device;
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, device.Add());
}
// Tests adding a device with a GPT format.
TEST(AddDeviceTestCase, AddGPTDevice) {
class GptDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_GPT;
}
zx_status_t AttachDriver(const fbl::StringPiece& driver) final {
EXPECT_STR_EQ(devmgr::kGPTDriverPath, driver.data());
attached = true;
return ZX_OK;
}
bool attached = false;
};
GptDevice device;
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_TRUE(device.attached);
}
// Tests adding a device with an FVM format.
TEST(AddDeviceTestCase, AddFVMDevice) {
class FvmDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_FVM;
}
zx_status_t AttachDriver(const fbl::StringPiece& driver) final {
EXPECT_STR_EQ(devmgr::kFVMDriverPath, driver.data());
attached = true;
return ZX_OK;
}
bool attached = false;
};
FvmDevice device;
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_TRUE(device.attached);
}
// Tests adding a device with an MBR format.
TEST(AddDeviceTestCase, AddMBRDevice) {
class MbrDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_MBR;
}
zx_status_t AttachDriver(const fbl::StringPiece& driver) final {
EXPECT_STR_EQ(devmgr::kMBRDriverPath, driver.data());
attached = true;
return ZX_OK;
}
bool attached = false;
};
MbrDevice device;
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_TRUE(device.attached);
}
// Tests adding blobfs which does not not have a type GUID.
TEST(AddDeviceTestCase, AddNoGUIDBlobDevice) {
class BlobDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_BLOBFS;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
return ZX_ERR_NOT_SUPPORTED;
}
};
BlobDevice device;
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, device.Add());
}
// Tests adding blobfs with a valid type GUID, but invalid metadata.
TEST(AddDeviceTestCase, AddInvalidBlobDevice) {
class BlobDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_BLOBFS;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
const uint8_t expected[GPT_GUID_LEN] = GUID_BLOB_VALUE;
memcpy(out_guid->value, expected, sizeof(expected));
return ZX_OK;
}
zx_status_t CheckFilesystem() final {
checked = true;
return ZX_ERR_BAD_STATE;
}
zx_status_t FormatFilesystem() final {
formatted = true;
return ZX_OK;
}
zx_status_t MountFilesystem() final {
mounted = true;
return ZX_OK;
}
bool checked = false;
bool formatted = false;
bool mounted = false;
};
BlobDevice device;
EXPECT_EQ(ZX_ERR_BAD_STATE, device.Add());
EXPECT_TRUE(device.checked);
EXPECT_FALSE(device.formatted);
EXPECT_FALSE(device.mounted);
}
// Tests adding blobfs with a valid type GUID and valid metadata.
TEST(AddDeviceTestCase, AddValidBlobDevice) {
class BlobDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_BLOBFS;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
const uint8_t expected[GPT_GUID_LEN] = GUID_BLOB_VALUE;
memcpy(out_guid->value, expected, sizeof(expected));
return ZX_OK;
}
zx_status_t CheckFilesystem() final {
checked = true;
return ZX_OK;
}
zx_status_t FormatFilesystem() final {
formatted = true;
return ZX_OK;
}
zx_status_t MountFilesystem() final {
mounted = true;
return ZX_OK;
}
bool checked = false;
bool formatted = false;
bool mounted = false;
};
BlobDevice device;
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_TRUE(device.checked);
EXPECT_FALSE(device.formatted);
EXPECT_TRUE(device.mounted);
}
// Tests adding minfs with a valid type GUID and invalid metadata. Observe that
// the filesystem reformats itself.
TEST(AddDeviceTestCase, AddInvalidMinfsDevice) {
class MinfsDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_MINFS;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
const uint8_t expected[GPT_GUID_LEN] = GUID_DATA_VALUE;
memcpy(out_guid->value, expected, sizeof(expected));
return ZX_OK;
}
zx_status_t CheckFilesystem() final {
checked = true;
return ZX_ERR_BAD_STATE;
}
zx_status_t FormatFilesystem() final {
formatted = true;
return ZX_OK;
}
zx_status_t MountFilesystem() final {
mounted = true;
return ZX_OK;
}
bool checked = false;
bool formatted = false;
bool mounted = false;
};
MinfsDevice device;
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_TRUE(device.checked);
EXPECT_TRUE(device.formatted);
EXPECT_TRUE(device.mounted);
}
// Tests adding minfs with a valid type GUID and invalid format. Observe that
// the filesystem reformats itself.
TEST(AddDeviceTestCase, AddUnknownFormatMinfsDevice) {
class MinfsDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return format;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
const uint8_t expected[GPT_GUID_LEN] = GUID_DATA_VALUE;
memcpy(out_guid->value, expected, sizeof(expected));
return ZX_OK;
}
zx_status_t FormatFilesystem() final {
formatted = true;
return ZX_OK;
}
zx_status_t CheckFilesystem() final {
return ZX_OK;
}
zx_status_t MountFilesystem() final {
EXPECT_TRUE(formatted);
mounted = true;
return ZX_OK;
}
zx_status_t IsUnsealedZxcrypt(bool* is_unsealed_zxcrypt) final {
*is_unsealed_zxcrypt = true;
return ZX_OK;
}
void SetFormat(disk_format_t f) final {
format = f;
}
disk_format_t format = DISK_FORMAT_UNKNOWN;
bool formatted = false;
bool mounted = false;
};
MinfsDevice device;
EXPECT_FALSE(device.formatted);
EXPECT_FALSE(device.mounted);
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_TRUE(device.formatted);
EXPECT_TRUE(device.mounted);
}
// Tests adding zxcrypt with a valid type GUID and invalid format. Observe that
// the partition reformats itself.
TEST(AddDeviceTestCase, AddUnknownFormatZxcryptDevice) {
class ZxcryptDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return format;
}
zx_status_t GetTypeGUID(fuchsia_hardware_block_partition_GUID* out_guid) final {
const uint8_t expected[GPT_GUID_LEN] = GUID_DATA_VALUE;
memcpy(out_guid->value, expected, sizeof(expected));
return ZX_OK;
}
zx_status_t FormatZxcrypt() final {
formatted_zxcrypt = true;
return ZX_OK;
}
zx_status_t FormatFilesystem() final {
formatted_filesystem = true;
return ZX_OK;
}
zx_status_t CheckFilesystem() final {
return ZX_OK;
}
zx_status_t UnsealZxcrypt() final {
return ZX_OK;
}
zx_status_t IsUnsealedZxcrypt(bool* is_unsealed_zxcrypt) final {
*is_unsealed_zxcrypt = false;
return ZX_OK;
}
void SetFormat(disk_format_t f) final {
format = f;
}
zx_status_t AttachDriver(const fbl::StringPiece& driver) final {
EXPECT_STR_EQ(devmgr::kZxcryptDriverPath, driver.data());
return ZX_OK;
}
disk_format_t format = DISK_FORMAT_UNKNOWN;
bool formatted_zxcrypt = false;
bool formatted_filesystem = false;
};
ZxcryptDevice device;
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_TRUE(device.formatted_zxcrypt);
EXPECT_FALSE(device.formatted_filesystem);
}
// Tests adding a boot partition device with unknown format can be added with
// the correct driver.
TEST(AddDeviceTestCase, AddUnknownFormatBootPartitionDevice) {
class BootPartDevice : public MockBlockDevice {
public:
disk_format_t GetFormat() final {
return DISK_FORMAT_UNKNOWN;
}
zx_status_t GetInfo(fuchsia_hardware_block_BlockInfo* out_info) override {
fuchsia_hardware_block_BlockInfo info = {};
info.flags = BLOCK_FLAG_BOOTPART;
info.block_size = 512;
info.block_count = 1024;
*out_info = info;
return ZX_OK;
}
zx_status_t AttachDriver(const fbl::StringPiece& driver) final {
EXPECT_STR_EQ(devmgr::kBootpartDriverPath, driver.data());
return ZX_OK;
}
zx_status_t IsUnsealedZxcrypt(bool* is_unsealed_zxcrypt) final {
*is_unsealed_zxcrypt = false;
checked_unsealed_zxcrypt = true;
return ZX_OK;
}
bool checked_unsealed_zxcrypt = false;
};
BootPartDevice device;
EXPECT_EQ(ZX_OK, device.Add());
EXPECT_FALSE(device.checked_unsealed_zxcrypt);
}
} // namespace