123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- //
- // Copyright (C) 2015 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/ext2_filesystem.h"
- #include <unistd.h>
- #include <map>
- #include <set>
- #include <string>
- #include <vector>
- #include <base/format_macros.h>
- #include <base/logging.h>
- #include <base/strings/string_number_conversions.h>
- #include <base/strings/string_util.h>
- #include <base/strings/stringprintf.h>
- #include <gtest/gtest.h>
- #include "update_engine/common/test_utils.h"
- #include "update_engine/common/utils.h"
- #include "update_engine/payload_generator/extent_utils.h"
- using chromeos_update_engine::test_utils::GetBuildArtifactsPath;
- using std::map;
- using std::set;
- using std::string;
- using std::unique_ptr;
- using std::vector;
- namespace chromeos_update_engine {
- namespace {
- uint64_t kDefaultFilesystemSize = 4 * 1024 * 1024;
- size_t kDefaultFilesystemBlockCount = 1024;
- size_t kDefaultFilesystemBlockSize = 4096;
- // Checks that all the blocks in |extents| are in the range [0, total_blocks).
- void ExpectBlocksInRange(const vector<Extent>& extents, uint64_t total_blocks) {
- for (const Extent& extent : extents) {
- EXPECT_LE(0U, extent.start_block());
- EXPECT_LE(extent.start_block() + extent.num_blocks(), total_blocks);
- }
- }
- } // namespace
- class Ext2FilesystemTest : public ::testing::Test {};
- TEST_F(Ext2FilesystemTest, InvalidFilesystem) {
- test_utils::ScopedTempFile fs_filename_{"Ext2FilesystemTest-XXXXXX"};
- ASSERT_EQ(0, truncate(fs_filename_.path().c_str(), kDefaultFilesystemSize));
- unique_ptr<Ext2Filesystem> fs =
- Ext2Filesystem::CreateFromFile(fs_filename_.path());
- ASSERT_EQ(nullptr, fs.get());
- fs = Ext2Filesystem::CreateFromFile("/path/to/invalid/file");
- ASSERT_EQ(nullptr, fs.get());
- }
- TEST_F(Ext2FilesystemTest, EmptyFilesystem) {
- unique_ptr<Ext2Filesystem> fs = Ext2Filesystem::CreateFromFile(
- GetBuildArtifactsPath("gen/disk_ext2_4k_empty.img"));
- ASSERT_NE(nullptr, fs.get());
- EXPECT_EQ(kDefaultFilesystemBlockCount, fs->GetBlockCount());
- EXPECT_EQ(kDefaultFilesystemBlockSize, fs->GetBlockSize());
- vector<FilesystemInterface::File> files;
- EXPECT_TRUE(fs->GetFiles(&files));
- map<string, FilesystemInterface::File> map_files;
- for (const auto& file : files) {
- EXPECT_EQ(map_files.end(), map_files.find(file.name))
- << "File " << file.name << " repeated in the list.";
- map_files[file.name] = file;
- ExpectBlocksInRange(file.extents, fs->GetBlockCount());
- }
- EXPECT_EQ(2U, map_files["/"].file_stat.st_ino);
- EXPECT_FALSE(map_files["<free-space>"].extents.empty());
- }
- // 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(Ext2FilesystemTest, ParseGeneratedImages) {
- const vector<string> kGeneratedImages = {"disk_ext2_1k.img",
- "disk_ext2_4k.img"};
- base::FilePath build_path = GetBuildArtifactsPath().Append("gen");
- for (const string& fs_name : kGeneratedImages) {
- LOG(INFO) << "Testing " << fs_name;
- unique_ptr<Ext2Filesystem> fs =
- Ext2Filesystem::CreateFromFile(build_path.Append(fs_name).value());
- ASSERT_NE(nullptr, fs.get());
- vector<FilesystemInterface::File> files;
- map<string, FilesystemInterface::File> map_files;
- set<string> filenames;
- EXPECT_TRUE(fs->GetFiles(&files));
- for (const auto& file : files) {
- // Check no repeated files. We should parse hard-links with two different
- // names.
- EXPECT_EQ(map_files.end(), map_files.find(file.name))
- << "File " << file.name << " repeated in the list.";
- map_files[file.name] = file;
- filenames.insert(file.name);
- ExpectBlocksInRange(file.extents, fs->GetBlockCount());
- }
- // Check that all the files are parsed, and the /removed file should not
- // be included in the list.
- set<string> kExpectedFiles = {
- "/",
- "/cdev",
- "/dir1",
- "/dir1/file",
- "/dir1/dir2",
- "/dir1/dir2/file",
- "/dir1/dir2/dir1",
- "/empty-file",
- "/fifo",
- "/link-hard-regular-16k",
- "/link-long_symlink",
- "/link-short_symlink",
- "/lost+found",
- "/regular-small",
- "/regular-16k",
- "/regular-32k-zeros",
- "/regular-with_net_cap",
- "/sparse_empty-10k",
- "/sparse_empty-2blocks",
- "/sparse-10000blocks",
- "/sparse-16k-last_block",
- "/sparse-16k-first_block",
- "/sparse-16k-holes",
- "<inode-blocks>",
- "<free-space>",
- "<group-descriptors>",
- };
- EXPECT_EQ(kExpectedFiles, filenames);
- FilesystemInterface::File file;
- // Small symlinks don't actually have data blocks.
- EXPECT_TRUE(map_files["/link-short_symlink"].extents.empty());
- EXPECT_EQ(1U,
- utils::BlocksInExtents(map_files["/link-long_symlink"].extents));
- // Hard-links report the same list of blocks.
- EXPECT_EQ(map_files["/link-hard-regular-16k"].extents,
- map_files["/regular-16k"].extents);
- EXPECT_FALSE(map_files["/regular-16k"].extents.empty());
- // The number of blocks in these files doesn't depend on the
- // block size.
- EXPECT_TRUE(map_files["/empty-file"].extents.empty());
- EXPECT_EQ(1U, utils::BlocksInExtents(map_files["/regular-small"].extents));
- EXPECT_EQ(
- 1U, utils::BlocksInExtents(map_files["/regular-with_net_cap"].extents));
- EXPECT_TRUE(map_files["/sparse_empty-10k"].extents.empty());
- EXPECT_TRUE(map_files["/sparse_empty-2blocks"].extents.empty());
- EXPECT_EQ(
- 1U,
- utils::BlocksInExtents(map_files["/sparse-16k-last_block"].extents));
- EXPECT_EQ(
- 1U,
- utils::BlocksInExtents(map_files["/sparse-16k-first_block"].extents));
- EXPECT_EQ(2U,
- utils::BlocksInExtents(map_files["/sparse-16k-holes"].extents));
- }
- }
- TEST_F(Ext2FilesystemTest, LoadSettingsFailsTest) {
- unique_ptr<Ext2Filesystem> fs = Ext2Filesystem::CreateFromFile(
- GetBuildArtifactsPath("gen/disk_ext2_1k.img"));
- ASSERT_NE(nullptr, fs.get());
- brillo::KeyValueStore store;
- // disk_ext2_1k.img doesn't have the /etc/update_engine.conf file.
- EXPECT_FALSE(fs->LoadSettings(&store));
- }
- TEST_F(Ext2FilesystemTest, LoadSettingsWorksTest) {
- unique_ptr<Ext2Filesystem> fs = Ext2Filesystem::CreateFromFile(
- GetBuildArtifactsPath("gen/disk_ext2_unittest.img"));
- ASSERT_NE(nullptr, fs.get());
- brillo::KeyValueStore store;
- EXPECT_TRUE(fs->LoadSettings(&store));
- string minor_version;
- EXPECT_TRUE(store.GetString("PAYLOAD_MINOR_VERSION", &minor_version));
- EXPECT_EQ("1234", minor_version);
- }
- } // namespace chromeos_update_engine
|