| // 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 "fshost-boot-args.h" |
| |
| #include <fidl/fuchsia.boot/cpp/wire.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/async/dispatcher.h> |
| #include <lib/fidl-async/cpp/bind.h> |
| #include <lib/fidl/llcpp/string_view.h> |
| #include <lib/fidl/llcpp/vector_view.h> |
| #include <zircon/assert.h> |
| |
| #include <map> |
| #include <memory> |
| |
| #include <gtest/gtest.h> |
| #include <mock-boot-arguments/server.h> |
| |
| #include "src/storage/fshost/block-device.h" |
| #include "src/storage/fshost/config.h" |
| |
| namespace fshost { |
| namespace { |
| |
| namespace startup = fuchsia_fs_startup; |
| |
| // Create a subclass to access the test-only constructor on FshostBootArgs. |
| class FshostBootArgsForTest : public FshostBootArgs { |
| public: |
| explicit FshostBootArgsForTest(fidl::WireSyncClient<fuchsia_boot::Arguments> boot_args) |
| : FshostBootArgs(std::move(boot_args)) {} |
| }; |
| |
| class FshostBootArgsTest : public testing::Test { |
| public: |
| FshostBootArgsTest() : loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {} |
| |
| void CreateFshostBootArgs(std::map<std::string, std::string> config) { |
| boot_args_server_ = mock_boot_arguments::Server{std::move(config)}; |
| fidl::WireSyncClient<fuchsia_boot::Arguments> client; |
| boot_args_server_.CreateClient(loop_.dispatcher(), &client); |
| |
| ASSERT_EQ(loop_.StartThread(), ZX_OK); |
| boot_args_ = std::make_shared<FshostBootArgsForTest>(std::move(client)); |
| } |
| |
| FshostBootArgsForTest& boot_args() { return *boot_args_; } |
| std::shared_ptr<FshostBootArgs> boot_args_shared() { return boot_args_; } |
| |
| private: |
| async::Loop loop_; |
| mock_boot_arguments::Server boot_args_server_; |
| std::shared_ptr<FshostBootArgsForTest> boot_args_; |
| }; |
| |
| TEST_F(FshostBootArgsTest, GetDefaultBools) { |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs({})); |
| |
| EXPECT_EQ(false, boot_args().netboot()); |
| EXPECT_EQ(false, boot_args().check_filesystems()); |
| } |
| |
| TEST_F(FshostBootArgsTest, GetNonDefaultBools) { |
| std::map<std::string, std::string> config = { |
| {"netsvc.netboot", ""}, |
| {"zircon.system.disable-automount", ""}, |
| {"zircon.system.filesystem-check", ""}, |
| }; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(config)); |
| |
| EXPECT_EQ(true, boot_args().netboot()); |
| EXPECT_EQ(true, boot_args().check_filesystems()); |
| } |
| |
| TEST_F(FshostBootArgsTest, GetBlobfsCompressionAlgorithm) { |
| std::map<std::string, std::string> config = { |
| {"blobfs.write-compression-algorithm", "ZSTD_CHUNKED"}}; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(config)); |
| |
| EXPECT_EQ("ZSTD_CHUNKED", boot_args().blobfs_write_compression_algorithm()); |
| } |
| |
| TEST_F(FshostBootArgsTest, GetBlobfsCompressionAlgorithm_Unspecified) { |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs({})); |
| |
| EXPECT_EQ(std::nullopt, boot_args().blobfs_write_compression_algorithm()); |
| } |
| |
| TEST_F(FshostBootArgsTest, GetBlockVeritySeal) { |
| std::map<std::string, std::string> config = { |
| {"factory_verity_seal", "ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7"}}; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(config)); |
| |
| EXPECT_EQ("ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7", |
| boot_args().block_verity_seal()); |
| } |
| |
| TEST_F(FshostBootArgsTest, GetBlobfsEvictionPolicy) { |
| std::map<std::string, std::string> config = {{"blobfs.cache-eviction-policy", "NEVER_EVICT"}}; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(config)); |
| |
| EXPECT_EQ("NEVER_EVICT", boot_args().blobfs_eviction_policy()); |
| } |
| |
| TEST_F(FshostBootArgsTest, GetBlobfsEvictionPolicy_Unspecified) { |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs({})); |
| |
| EXPECT_EQ(std::nullopt, boot_args().blobfs_eviction_policy()); |
| } |
| |
| TEST_F(FshostBootArgsTest, BlobfsStartOptionsDefaults) { |
| std::map<std::string, std::string> boot_config = {}; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(boot_config)); |
| |
| auto fshost_config = DefaultConfig(); |
| |
| startup::wire::StartOptions options = GetBlobfsStartOptions(&fshost_config, boot_args_shared()); |
| ASSERT_EQ(options.write_compression_algorithm, startup::wire::CompressionAlgorithm::kZstdChunked); |
| ASSERT_EQ(options.cache_eviction_policy_override, startup::wire::EvictionPolicyOverride::kNone); |
| ASSERT_FALSE(options.sandbox_decompression); |
| } |
| |
| TEST_F(FshostBootArgsTest, BlobfsStartOptionsUncompressedNoEvictNoSandbox) { |
| std::map<std::string, std::string> boot_config = { |
| {"blobfs.write-compression-algorithm", "UNCOMPRESSED"}, |
| {"blobfs.cache-eviction-policy", "NEVER_EVICT"}}; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(boot_config)); |
| |
| auto fshost_config = DefaultConfig(); |
| |
| startup::wire::StartOptions options = GetBlobfsStartOptions(&fshost_config, boot_args_shared()); |
| ASSERT_EQ(options.write_compression_algorithm, |
| startup::wire::CompressionAlgorithm::kUncompressed); |
| ASSERT_EQ(options.cache_eviction_policy_override, |
| startup::wire::EvictionPolicyOverride::kNeverEvict); |
| ASSERT_FALSE(options.sandbox_decompression); |
| } |
| |
| TEST_F(FshostBootArgsTest, BlobfsStartOptionsChunkedEvictSandbox) { |
| std::map<std::string, std::string> boot_config = { |
| {"blobfs.write-compression-algorithm", "ZSTD_CHUNKED"}, |
| {"blobfs.cache-eviction-policy", "EVICT_IMMEDIATELY"}}; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(boot_config)); |
| |
| auto fshost_config = EmptyConfig(); |
| fshost_config.sandbox_decompression() = true; |
| |
| startup::wire::StartOptions options = GetBlobfsStartOptions(&fshost_config, boot_args_shared()); |
| ASSERT_EQ(options.write_compression_algorithm, startup::wire::CompressionAlgorithm::kZstdChunked); |
| ASSERT_EQ(options.cache_eviction_policy_override, |
| startup::wire::EvictionPolicyOverride::kEvictImmediately); |
| ASSERT_TRUE(options.sandbox_decompression); |
| } |
| |
| TEST_F(FshostBootArgsTest, BlobfsStartOptionsGarbage) { |
| std::map<std::string, std::string> boot_config = { |
| {"blobfs.write-compression-algorithm", "NOT_AN_ALGORITHM"}, |
| {"blobfs.cache-eviction-policy", "NOT_A_POLICY"}}; |
| ASSERT_NO_FATAL_FAILURE(CreateFshostBootArgs(boot_config)); |
| |
| // The fshost config implementation should pick up on this as "set" even if there is a value we |
| // don't care about. This is the equivalent of putting "sandbox-decompression=GARBAGE_VALUE" in |
| // the fshost config file. |
| auto fshost_config = EmptyConfig(); |
| fshost_config.sandbox_decompression() = true; |
| |
| startup::wire::StartOptions options = GetBlobfsStartOptions(&fshost_config, boot_args_shared()); |
| ASSERT_EQ(options.write_compression_algorithm, startup::wire::CompressionAlgorithm::kZstdChunked); |
| ASSERT_EQ(options.cache_eviction_policy_override, startup::wire::EvictionPolicyOverride::kNone); |
| ASSERT_TRUE(options.sandbox_decompression); |
| } |
| |
| } // namespace |
| } // namespace fshost |