// // Copyright (C) 2021 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "update_engine/payload_generator/erofs_filesystem.h" #include #include #include #include #include #include #include #include #include #include "payload_generator/delta_diff_generator.h" #include "update_engine/common/test_utils.h" #include "update_engine/common/utils.h" #include "update_engine/payload_generator/extent_utils.h" using std::string; using std::unique_ptr; using std::vector; namespace { class ErofsFilesystemTest : public ::testing::Test {}; } // namespace namespace chromeos_update_engine { using test_utils::GetBuildArtifactsPath; TEST_F(ErofsFilesystemTest, InvalidFilesystem) { ScopedTempFile fs_filename_{"ErofsFilesystemTest-XXXXXX"}; ASSERT_EQ(0, truncate(fs_filename_.path().c_str(), kBlockSize)); unique_ptr fs = ErofsFilesystem::CreateFromFile(fs_filename_.path()); ASSERT_EQ(nullptr, fs.get()); fs = ErofsFilesystem::CreateFromFile("/path/to/invalid/file"); ASSERT_EQ(nullptr, fs.get()); } TEST_F(ErofsFilesystemTest, EmptyFilesystem) { unique_ptr fs = ErofsFilesystem::CreateFromFile( GetBuildArtifactsPath("gen/erofs_empty.img")); ASSERT_NE(nullptr, fs); ASSERT_EQ(kBlockSize, fs->GetBlockSize()); vector files; ASSERT_TRUE(fs->GetFiles(&files)); ASSERT_EQ(files.size(), 0UL); } // This test parses the sample images generated during build time with the // "generate_image.sh" script. The expected conditions of each file in these // images is encoded in the file name, as defined in the mentioned script. TEST_F(ErofsFilesystemTest, ParseGeneratedImages) { const auto build_path = GetBuildArtifactsPath("gen/erofs.img"); auto fs = ErofsFilesystem::CreateFromFile(build_path); ASSERT_NE(fs, nullptr); ASSERT_EQ(kBlockSize, fs->GetBlockSize()); vector files; ASSERT_TRUE(fs->GetFiles(&files)); std::sort(files.begin(), files.end(), [](const auto& a, const auto& b) { return a.name < b.name; }); vector filenames; filenames.resize(files.size()); std::transform( files.begin(), files.end(), filenames.begin(), [](const auto& file) { return file.name; }); const std::vector expected_filenames = { "/delta_generator", "/dir1/dir2/dir123/chunks_of_zero", // Empty files are ignored // "/dir1/dir2/dir123/empty", "/dir1/dir2/file0", "/dir1/dir2/file1", "/dir1/dir2/file2", "/dir1/dir2/file4", "/dir1/file0", "/dir1/file2", "/file1", // Files < 4K are stored inline, and therefore ignored, as they are often // stored not on block boundary. // "/generate_test_erofs_images.sh" }; ASSERT_EQ(filenames, expected_filenames); const auto delta_generator = files[0]; ASSERT_GT(delta_generator.compressed_file_info.blocks.size(), 0UL); size_t compressed_size = 0; size_t uncompressed_size = 0; for (const auto& block : delta_generator.compressed_file_info.blocks) { compressed_size += block.compressed_length; uncompressed_size += block.uncompressed_length; } ASSERT_GE(uncompressed_size, static_cast(delta_generator.file_stat.st_size)) << "Uncompressed data should be at least as big as original file, plus " "possible trailing data."; const auto total_blocks = utils::BlocksInExtents(delta_generator.extents); ASSERT_EQ(compressed_size, total_blocks * kBlockSize); } } // namespace chromeos_update_engine