// Copyright 2018 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 #include #include #include #include #include #include #include #include #include #include namespace fs_test_utils { namespace { zx_status_t GetBlockDeviceInfo(const fbl::String& block_device_path, block_info_t* blk_info) { fbl::unique_fd fd(open(block_device_path.c_str(), O_RDONLY)); ssize_t result = ioctl_block_get_info(fd.get(), blk_info); if (result < 0) { return static_cast(result); } return ZX_OK; } bool IsValidBlockDeviceOnlyTrue() { BEGIN_TEST; FixtureOptions options; fbl::String err_str; options.block_device_path = "some_block_device"; ASSERT_TRUE(options.IsValid(&err_str), err_str.c_str()); ASSERT_TRUE(err_str.empty()); END_TEST; } bool IsValidUseRamdiskTrue() { BEGIN_TEST; FixtureOptions options; fbl::String err_str; options.use_ramdisk = true; options.ramdisk_block_size = 512; options.ramdisk_block_count = 1; ASSERT_TRUE(options.IsValid(&err_str), err_str.c_str()); ASSERT_TRUE(err_str.empty()); END_TEST; } bool IsValidUseFvmTrue() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_BLOBFS); fbl::String err_str; options.use_fvm = true; options.fvm_slice_size = kFvmBlockSize; ASSERT_TRUE(options.IsValid(&err_str), err_str.c_str()); ASSERT_TRUE(err_str.empty()); END_TEST; } bool IsValidEmptyIsFalse() { BEGIN_TEST; FixtureOptions options; fbl::String err_str; ASSERT_FALSE(options.IsValid(&err_str)); ASSERT_FALSE(err_str.empty()); END_TEST; } bool IsValidDefaultIsTrue() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_BLOBFS); fbl::String err_str; ASSERT_TRUE(options.IsValid(&err_str)); ASSERT_TRUE(err_str.empty()); END_TEST; } bool IsValidBlockAndRamdiskSetIsFalse() { BEGIN_TEST; FixtureOptions options; fbl::String err_str; options.block_device_path = "some_block_device"; options.use_ramdisk = true; ASSERT_FALSE(options.IsValid(&err_str)); ASSERT_FALSE(err_str.empty()); END_TEST; } bool IsValidRamdiskBlockCountIsZeroFalse() { BEGIN_TEST; FixtureOptions options; fbl::String err_str; options.use_ramdisk = true; options.ramdisk_block_count = 0; options.ramdisk_block_size = 512; ASSERT_FALSE(options.IsValid(&err_str)); ASSERT_FALSE(err_str.empty()); END_TEST; } bool IsValidRamdiskBlockSizeIsZeroFalse() { BEGIN_TEST; FixtureOptions options; fbl::String err_str; options.use_ramdisk = true; options.ramdisk_block_count = 10; options.ramdisk_block_size = 0; ASSERT_FALSE(options.IsValid(&err_str)); ASSERT_FALSE(err_str.empty()); END_TEST; } bool IsValidFvmSlizeSizeIsZeroFalse() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_BLOBFS); fbl::String err_str; options.use_fvm = true; options.fvm_slice_size = 0; ASSERT_FALSE(options.IsValid(&err_str)); ASSERT_FALSE(err_str.empty()); END_TEST; } bool IsValidFvmSlizeSizeIsNotMultipleOfFvmBlockSizeFalse() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_BLOBFS); fbl::String err_str; options.use_fvm = true; options.fvm_slice_size = kFvmBlockSize + 3; ASSERT_FALSE(options.IsValid(&err_str)); ASSERT_FALSE(err_str.empty()); END_TEST; } bool IsValidNoBlockDeviceFalse() { BEGIN_TEST; FixtureOptions options; fbl::String err_str; options.block_device_path = ""; ASSERT_FALSE(options.IsValid(&err_str)); ASSERT_FALSE(err_str.empty()); END_TEST; } BEGIN_TEST_CASE(FixtureOptionsTests); RUN_TEST(IsValidBlockDeviceOnlyTrue); RUN_TEST(IsValidUseRamdiskTrue); RUN_TEST(IsValidUseFvmTrue); RUN_TEST(IsValidDefaultIsTrue); RUN_TEST(IsValidEmptyIsFalse); RUN_TEST(IsValidNoBlockDeviceFalse); RUN_TEST(IsValidBlockAndRamdiskSetIsFalse); RUN_TEST(IsValidRamdiskBlockCountIsZeroFalse); RUN_TEST(IsValidRamdiskBlockSizeIsZeroFalse); RUN_TEST(IsValidFvmSlizeSizeIsZeroFalse); RUN_TEST(IsValidFvmSlizeSizeIsNotMultipleOfFvmBlockSizeFalse); END_TEST_CASE(FixtureOptionsTests); bool RamdiskSetupAndCleanup() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_BLOBFS); Fixture fixture(options); fixture.SetUpTestCase(); ASSERT_TRUE(!fixture.block_device_path().empty()); block_info_t ramdisk_info; ASSERT_EQ(GetBlockDeviceInfo(fixture.block_device_path(), &ramdisk_info), ZX_OK); ASSERT_EQ(ramdisk_info.block_count, options.ramdisk_block_count); ASSERT_EQ(ramdisk_info.block_size, options.ramdisk_block_size); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); fbl::unique_fd ramdisk_fd(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_FALSE(ramdisk_fd); END_TEST; } bool DiskIsFormattedCorrectlyNoFvm() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); ASSERT_EQ(fixture.SetUp(), ZX_OK); // Check device format. fbl::unique_fd blk_fd(open(fixture.GetFsBlockDevice().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); disk_format_t actual = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual, DISK_FORMAT_MINFS); ASSERT_EQ(fixture.TearDown(), ZX_OK); // Verify nothing is mounted anymore. ASSERT_EQ(umount(fixture.fs_path().c_str()), ZX_ERR_NOT_FOUND); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool DiskAndFvmAreFormattedCorrectly() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.use_fvm = true; Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); ASSERT_EQ(fixture.SetUp(), ZX_OK); // Check device format. fbl::unique_fd blk_fd(open(fixture.GetFsBlockDevice().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); disk_format_t actual = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual, DISK_FORMAT_MINFS); fbl::unique_fd fvm_blk_fd(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(fvm_blk_fd); disk_format_t fvm_actual = detect_disk_format(fvm_blk_fd.get()); ASSERT_EQ(fvm_actual, DISK_FORMAT_FVM); ASSERT_EQ(fixture.TearDown(), ZX_OK); // Verify nothing is mounted anymore. ASSERT_EQ(umount(fixture.fs_path().c_str()), ZX_ERR_NOT_FOUND); ASSERT_TRUE(fvm_blk_fd); fvm_actual = detect_disk_format(fvm_blk_fd.get()); ASSERT_EQ(fvm_actual, DISK_FORMAT_UNKNOWN); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool UseBlockDeviceIsOk() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.use_ramdisk = false; // Create a Ramdisk which will be passed as the 'block_device'. char block_device[kPathSize]; ASSERT_EQ(create_ramdisk(options.ramdisk_block_size, options.ramdisk_block_count, block_device), ZX_OK); options.block_device_path = block_device; auto clean_up = fbl::MakeAutoCall([&options]() { destroy_ramdisk(options.block_device_path.c_str()); }); mkfs_options_t mkfs_options = default_mkfs_options; ASSERT_EQ(mkfs(options.block_device_path.c_str(), DISK_FORMAT_BLOBFS, launch_stdio_sync, &mkfs_options), ZX_OK); Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); EXPECT_TRUE(options.block_device_path == fixture.block_device_path()); EXPECT_TRUE(options.block_device_path == fixture.GetFsBlockDevice()); fbl::unique_fd blk_fd(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); disk_format_t actual_format = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_BLOBFS); ASSERT_EQ(fixture.SetUp(), ZX_OK); blk_fd.reset(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); actual_format = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_MINFS); ASSERT_EQ(fixture.TearDown(), ZX_OK); blk_fd.reset(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); actual_format = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_MINFS); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool UseBlockDeviceWithFvmIsOk() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.use_ramdisk = false; options.use_fvm = true; // Create a Ramdisk which will be passed as the 'block_device'. char block_device[kPathSize]; ASSERT_EQ(create_ramdisk(options.ramdisk_block_size, options.ramdisk_block_count, block_device), ZX_OK); options.block_device_path = block_device; auto clean_up = fbl::MakeAutoCall([&options]() { destroy_ramdisk(options.block_device_path.c_str()); }); mkfs_options_t mkfs_options = default_mkfs_options; ASSERT_EQ(mkfs(options.block_device_path.c_str(), DISK_FORMAT_BLOBFS, launch_stdio_sync, &mkfs_options), ZX_OK); Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); EXPECT_TRUE(options.block_device_path == fixture.block_device_path()); EXPECT_TRUE(fixture.GetFsBlockDevice().empty()); fbl::unique_fd blk_fd(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); disk_format_t actual_format = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_BLOBFS); ASSERT_EQ(fixture.SetUp(), ZX_OK); blk_fd.reset(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); actual_format = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_FVM); blk_fd.reset(open(fixture.GetFsBlockDevice().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); actual_format = detect_disk_format(blk_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_MINFS); ASSERT_EQ(fixture.TearDown(), ZX_OK); blk_fd.reset(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(blk_fd); actual_format = detect_disk_format(blk_fd.get()); // Destroying the FVM should leave this in unknown format. ASSERT_EQ(actual_format, DISK_FORMAT_UNKNOWN); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool SkipFormatIsOk() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.use_ramdisk = false; options.fs_format = false; // Create a Ramdisk which will be passed as the 'block_device'. char block_device[kPathSize]; ASSERT_EQ(create_ramdisk(options.ramdisk_block_size, options.ramdisk_block_count, block_device), ZX_OK); options.block_device_path = block_device; auto clean_up = fbl::MakeAutoCall([&options]() { destroy_ramdisk(options.block_device_path.c_str()); }); mkfs_options_t mkfs_options = default_mkfs_options; ASSERT_EQ(mkfs(options.block_device_path.c_str(), DISK_FORMAT_BLOBFS, launch_stdio_sync, &mkfs_options), ZX_OK); Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); EXPECT_TRUE(options.block_device_path == fixture.block_device_path()); EXPECT_TRUE(options.block_device_path == fixture.GetFsBlockDevice()); fbl::unique_fd block_fd(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(block_fd); disk_format_t actual_format = detect_disk_format(block_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_BLOBFS); ASSERT_EQ(fixture.SetUp(), ZX_OK); block_fd.reset(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(block_fd); actual_format = detect_disk_format(block_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_BLOBFS); ASSERT_EQ(fixture.TearDown(), ZX_OK); block_fd.reset(open(fixture.block_device_path().c_str(), O_RDONLY)); ASSERT_TRUE(block_fd); actual_format = detect_disk_format(block_fd.get()); ASSERT_EQ(actual_format, DISK_FORMAT_BLOBFS); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool SkipMountIsOk() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.fs_mount = false; Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); ASSERT_EQ(fixture.SetUp(), ZX_OK); // Verify nothing is mounted anymore. ASSERT_EQ(umount(fixture.fs_path().c_str()), ZX_ERR_NOT_FOUND); ASSERT_EQ(fixture.TearDown(), ZX_OK); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool MountIsOk() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.fs_mount = false; Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); ASSERT_EQ(fixture.SetUp(), ZX_OK); ASSERT_EQ(umount(fixture.fs_path().c_str()), ZX_ERR_NOT_FOUND); ASSERT_EQ(fixture.Mount(), ZX_OK); ASSERT_EQ(umount(fixture.fs_path().c_str()), ZX_OK); // Since we need to try to umount to verify if the device is mounted, // the fixture still sees the device as mounted, so it will try to umount // and fail with not found, which is ok. ASSERT_EQ(fixture.TearDown(), ZX_ERR_NOT_FOUND); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool UmountIsOk() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.fs_mount = true; Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); ASSERT_EQ(fixture.SetUp(), ZX_OK); ASSERT_EQ(fixture.Umount(), ZX_OK); // Verify nothing is mounted anymore. ASSERT_EQ(umount(fixture.fs_path().c_str()), ZX_ERR_NOT_FOUND); ASSERT_EQ(fixture.TearDown(), ZX_OK); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } bool RemountIsOk() { BEGIN_TEST; FixtureOptions options = FixtureOptions::Default(DISK_FORMAT_MINFS); options.fs_mount = true; Fixture fixture(options); ASSERT_EQ(fixture.SetUpTestCase(), ZX_OK); ASSERT_EQ(fixture.SetUp(), ZX_OK); ASSERT_EQ(fixture.Remount(), ZX_OK); ASSERT_EQ(umount(fixture.fs_path().c_str()), ZX_OK); // Teardown will return this error because we manually umount the underlying ASSERT_EQ(fixture.TearDown(), ZX_ERR_NOT_FOUND); ASSERT_EQ(fixture.TearDownTestCase(), ZX_OK); END_TEST; } BEGIN_TEST_CASE(FixtureTest); RUN_TEST(RamdiskSetupAndCleanup); RUN_TEST(DiskIsFormattedCorrectlyNoFvm); RUN_TEST(DiskAndFvmAreFormattedCorrectly); RUN_TEST(UseBlockDeviceIsOk); RUN_TEST(UseBlockDeviceWithFvmIsOk); RUN_TEST(SkipFormatIsOk); RUN_TEST(SkipMountIsOk); RUN_TEST(MountIsOk); RUN_TEST(UmountIsOk); RUN_TEST(RemountIsOk); END_TEST_CASE(FixtureTest); } // namespace } // namespace fs_test_utils