ext2_filesystem_unittest.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //
  2. // Copyright (C) 2015 The Android Open Source Project
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "update_engine/payload_generator/ext2_filesystem.h"
  17. #include <unistd.h>
  18. #include <map>
  19. #include <set>
  20. #include <string>
  21. #include <vector>
  22. #include <base/format_macros.h>
  23. #include <base/logging.h>
  24. #include <base/strings/string_number_conversions.h>
  25. #include <base/strings/string_util.h>
  26. #include <base/strings/stringprintf.h>
  27. #include <gtest/gtest.h>
  28. #include "update_engine/common/test_utils.h"
  29. #include "update_engine/common/utils.h"
  30. #include "update_engine/payload_generator/extent_utils.h"
  31. using chromeos_update_engine::test_utils::GetBuildArtifactsPath;
  32. using std::map;
  33. using std::set;
  34. using std::string;
  35. using std::unique_ptr;
  36. using std::vector;
  37. namespace chromeos_update_engine {
  38. namespace {
  39. uint64_t kDefaultFilesystemSize = 4 * 1024 * 1024;
  40. size_t kDefaultFilesystemBlockCount = 1024;
  41. size_t kDefaultFilesystemBlockSize = 4096;
  42. // Checks that all the blocks in |extents| are in the range [0, total_blocks).
  43. void ExpectBlocksInRange(const vector<Extent>& extents, uint64_t total_blocks) {
  44. for (const Extent& extent : extents) {
  45. EXPECT_LE(0U, extent.start_block());
  46. EXPECT_LE(extent.start_block() + extent.num_blocks(), total_blocks);
  47. }
  48. }
  49. } // namespace
  50. class Ext2FilesystemTest : public ::testing::Test {};
  51. TEST_F(Ext2FilesystemTest, InvalidFilesystem) {
  52. test_utils::ScopedTempFile fs_filename_{"Ext2FilesystemTest-XXXXXX"};
  53. ASSERT_EQ(0, truncate(fs_filename_.path().c_str(), kDefaultFilesystemSize));
  54. unique_ptr<Ext2Filesystem> fs =
  55. Ext2Filesystem::CreateFromFile(fs_filename_.path());
  56. ASSERT_EQ(nullptr, fs.get());
  57. fs = Ext2Filesystem::CreateFromFile("/path/to/invalid/file");
  58. ASSERT_EQ(nullptr, fs.get());
  59. }
  60. TEST_F(Ext2FilesystemTest, EmptyFilesystem) {
  61. unique_ptr<Ext2Filesystem> fs = Ext2Filesystem::CreateFromFile(
  62. GetBuildArtifactsPath("gen/disk_ext2_4k_empty.img"));
  63. ASSERT_NE(nullptr, fs.get());
  64. EXPECT_EQ(kDefaultFilesystemBlockCount, fs->GetBlockCount());
  65. EXPECT_EQ(kDefaultFilesystemBlockSize, fs->GetBlockSize());
  66. vector<FilesystemInterface::File> files;
  67. EXPECT_TRUE(fs->GetFiles(&files));
  68. map<string, FilesystemInterface::File> map_files;
  69. for (const auto& file : files) {
  70. EXPECT_EQ(map_files.end(), map_files.find(file.name))
  71. << "File " << file.name << " repeated in the list.";
  72. map_files[file.name] = file;
  73. ExpectBlocksInRange(file.extents, fs->GetBlockCount());
  74. }
  75. EXPECT_EQ(2U, map_files["/"].file_stat.st_ino);
  76. EXPECT_FALSE(map_files["<free-space>"].extents.empty());
  77. }
  78. // This test parses the sample images generated during build time with the
  79. // "generate_image.sh" script. The expected conditions of each file in these
  80. // images is encoded in the file name, as defined in the mentioned script.
  81. TEST_F(Ext2FilesystemTest, ParseGeneratedImages) {
  82. const vector<string> kGeneratedImages = {"disk_ext2_1k.img",
  83. "disk_ext2_4k.img"};
  84. base::FilePath build_path = GetBuildArtifactsPath().Append("gen");
  85. for (const string& fs_name : kGeneratedImages) {
  86. LOG(INFO) << "Testing " << fs_name;
  87. unique_ptr<Ext2Filesystem> fs =
  88. Ext2Filesystem::CreateFromFile(build_path.Append(fs_name).value());
  89. ASSERT_NE(nullptr, fs.get());
  90. vector<FilesystemInterface::File> files;
  91. map<string, FilesystemInterface::File> map_files;
  92. set<string> filenames;
  93. EXPECT_TRUE(fs->GetFiles(&files));
  94. for (const auto& file : files) {
  95. // Check no repeated files. We should parse hard-links with two different
  96. // names.
  97. EXPECT_EQ(map_files.end(), map_files.find(file.name))
  98. << "File " << file.name << " repeated in the list.";
  99. map_files[file.name] = file;
  100. filenames.insert(file.name);
  101. ExpectBlocksInRange(file.extents, fs->GetBlockCount());
  102. }
  103. // Check that all the files are parsed, and the /removed file should not
  104. // be included in the list.
  105. set<string> kExpectedFiles = {
  106. "/",
  107. "/cdev",
  108. "/dir1",
  109. "/dir1/file",
  110. "/dir1/dir2",
  111. "/dir1/dir2/file",
  112. "/dir1/dir2/dir1",
  113. "/empty-file",
  114. "/fifo",
  115. "/link-hard-regular-16k",
  116. "/link-long_symlink",
  117. "/link-short_symlink",
  118. "/lost+found",
  119. "/regular-small",
  120. "/regular-16k",
  121. "/regular-32k-zeros",
  122. "/regular-with_net_cap",
  123. "/sparse_empty-10k",
  124. "/sparse_empty-2blocks",
  125. "/sparse-10000blocks",
  126. "/sparse-16k-last_block",
  127. "/sparse-16k-first_block",
  128. "/sparse-16k-holes",
  129. "<inode-blocks>",
  130. "<free-space>",
  131. "<group-descriptors>",
  132. };
  133. EXPECT_EQ(kExpectedFiles, filenames);
  134. FilesystemInterface::File file;
  135. // Small symlinks don't actually have data blocks.
  136. EXPECT_TRUE(map_files["/link-short_symlink"].extents.empty());
  137. EXPECT_EQ(1U,
  138. utils::BlocksInExtents(map_files["/link-long_symlink"].extents));
  139. // Hard-links report the same list of blocks.
  140. EXPECT_EQ(map_files["/link-hard-regular-16k"].extents,
  141. map_files["/regular-16k"].extents);
  142. EXPECT_FALSE(map_files["/regular-16k"].extents.empty());
  143. // The number of blocks in these files doesn't depend on the
  144. // block size.
  145. EXPECT_TRUE(map_files["/empty-file"].extents.empty());
  146. EXPECT_EQ(1U, utils::BlocksInExtents(map_files["/regular-small"].extents));
  147. EXPECT_EQ(
  148. 1U, utils::BlocksInExtents(map_files["/regular-with_net_cap"].extents));
  149. EXPECT_TRUE(map_files["/sparse_empty-10k"].extents.empty());
  150. EXPECT_TRUE(map_files["/sparse_empty-2blocks"].extents.empty());
  151. EXPECT_EQ(
  152. 1U,
  153. utils::BlocksInExtents(map_files["/sparse-16k-last_block"].extents));
  154. EXPECT_EQ(
  155. 1U,
  156. utils::BlocksInExtents(map_files["/sparse-16k-first_block"].extents));
  157. EXPECT_EQ(2U,
  158. utils::BlocksInExtents(map_files["/sparse-16k-holes"].extents));
  159. }
  160. }
  161. TEST_F(Ext2FilesystemTest, LoadSettingsFailsTest) {
  162. unique_ptr<Ext2Filesystem> fs = Ext2Filesystem::CreateFromFile(
  163. GetBuildArtifactsPath("gen/disk_ext2_1k.img"));
  164. ASSERT_NE(nullptr, fs.get());
  165. brillo::KeyValueStore store;
  166. // disk_ext2_1k.img doesn't have the /etc/update_engine.conf file.
  167. EXPECT_FALSE(fs->LoadSettings(&store));
  168. }
  169. TEST_F(Ext2FilesystemTest, LoadSettingsWorksTest) {
  170. unique_ptr<Ext2Filesystem> fs = Ext2Filesystem::CreateFromFile(
  171. GetBuildArtifactsPath("gen/disk_ext2_unittest.img"));
  172. ASSERT_NE(nullptr, fs.get());
  173. brillo::KeyValueStore store;
  174. EXPECT_TRUE(fs->LoadSettings(&store));
  175. string minor_version;
  176. EXPECT_TRUE(store.GetString("PAYLOAD_MINOR_VERSION", &minor_version));
  177. EXPECT_EQ("1234", minor_version);
  178. }
  179. } // namespace chromeos_update_engine