Fabien Sanglard | 0f29f54 | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 1 | #include "gmock/gmock.h" |
| 2 | #include "gtest/gtest.h" |
| 3 | |
| 4 | #include "ZipAlign.h" |
| 5 | |
weisu | eae4531 | 2021-12-13 17:56:12 +0000 | [diff] [blame] | 6 | #include <filesystem> |
Fabien Sanglard | 0f29f54 | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 7 | #include <stdio.h> |
Fabien Sanglard | 6dfc6fb | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 8 | #include <string> |
| 9 | |
| 10 | #include <android-base/file.h> |
Fabien Sanglard | 0f29f54 | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 11 | |
| 12 | using namespace android; |
Fabien Sanglard | df73d1b | 2021-09-14 14:18:31 -0700 | [diff] [blame] | 13 | using namespace base; |
Fabien Sanglard | 0f29f54 | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 14 | |
Fabien Sanglard | 8163cfa | 2022-10-10 22:19:47 +0000 | [diff] [blame] | 15 | // This load the whole file to memory so be careful! |
| 16 | static bool sameContent(const std::string& path1, const std::string& path2) { |
| 17 | std::string f1; |
| 18 | if (!ReadFileToString(path1, &f1)) { |
| 19 | printf("Unable to read '%s' content: %m\n", path1.c_str()); |
| 20 | return false; |
| 21 | } |
| 22 | |
| 23 | std::string f2; |
| 24 | if (!ReadFileToString(path2, &f2)) { |
| 25 | printf("Unable to read '%s' content %m\n", path1.c_str()); |
| 26 | return false; |
| 27 | } |
| 28 | |
| 29 | if (f1.size() != f2.size()) { |
| 30 | printf("File '%s' and '%s' are not the same\n", path1.c_str(), path2.c_str()); |
| 31 | return false; |
| 32 | } |
| 33 | |
| 34 | return f1.compare(f2) == 0; |
| 35 | } |
| 36 | |
Fabien Sanglard | 6dfc6fb | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 37 | static std::string GetTestPath(const std::string& filename) { |
| 38 | static std::string test_data_dir = android::base::GetExecutableDirectory() + "/tests/data/"; |
| 39 | return test_data_dir + filename; |
| 40 | } |
| 41 | |
weisu | eae4531 | 2021-12-13 17:56:12 +0000 | [diff] [blame] | 42 | static std::string GetTempPath(const std::string& filename) { |
| 43 | std::filesystem::path temp_path = std::filesystem::path(testing::TempDir()); |
| 44 | temp_path += filename; |
| 45 | return temp_path.string(); |
| 46 | } |
| 47 | |
Fabien Sanglard | 0f29f54 | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 48 | TEST(Align, Unaligned) { |
Fabien Sanglard | 6dfc6fb | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 49 | const std::string src = GetTestPath("unaligned.zip"); |
weisu | eae4531 | 2021-12-13 17:56:12 +0000 | [diff] [blame] | 50 | const std::string dst = GetTempPath("unaligned_out.zip"); |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 51 | int pageSize = 4096; |
Fabien Sanglard | 6dfc6fb | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 52 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 53 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, false, pageSize); |
Fabien Sanglard | 4b4b495 | 2020-11-05 18:36:56 -0800 | [diff] [blame] | 54 | ASSERT_EQ(0, processed); |
| 55 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 56 | int verified = verify(dst.c_str(), 4, true, false, pageSize); |
Fabien Sanglard | 4b4b495 | 2020-11-05 18:36:56 -0800 | [diff] [blame] | 57 | ASSERT_EQ(0, verified); |
Fabien Sanglard | 0f29f54 | 2020-10-22 17:58:12 -0700 | [diff] [blame] | 58 | } |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 59 | |
Fabien Sanglard | df73d1b | 2021-09-14 14:18:31 -0700 | [diff] [blame] | 60 | TEST(Align, DoubleAligment) { |
| 61 | const std::string src = GetTestPath("unaligned.zip"); |
weisu | eae4531 | 2021-12-13 17:56:12 +0000 | [diff] [blame] | 62 | const std::string tmp = GetTempPath("da_aligned.zip"); |
| 63 | const std::string dst = GetTempPath("da_d_aligner.zip"); |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 64 | int pageSize = 4096; |
Fabien Sanglard | df73d1b | 2021-09-14 14:18:31 -0700 | [diff] [blame] | 65 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 66 | int processed = process(src.c_str(), tmp.c_str(), 4, true, false, false, pageSize); |
Fabien Sanglard | df73d1b | 2021-09-14 14:18:31 -0700 | [diff] [blame] | 67 | ASSERT_EQ(0, processed); |
| 68 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 69 | int verified = verify(tmp.c_str(), 4, true, false, pageSize); |
Fabien Sanglard | df73d1b | 2021-09-14 14:18:31 -0700 | [diff] [blame] | 70 | ASSERT_EQ(0, verified); |
| 71 | |
| 72 | // Align the result of the previous run. Essentially double aligning. |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 73 | processed = process(tmp.c_str(), dst.c_str(), 4, true, false, false, pageSize); |
Fabien Sanglard | df73d1b | 2021-09-14 14:18:31 -0700 | [diff] [blame] | 74 | ASSERT_EQ(0, processed); |
| 75 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 76 | verified = verify(dst.c_str(), 4, true, false, pageSize); |
Fabien Sanglard | df73d1b | 2021-09-14 14:18:31 -0700 | [diff] [blame] | 77 | ASSERT_EQ(0, verified); |
| 78 | |
| 79 | // Nothing should have changed between tmp and dst. |
| 80 | std::string tmp_content; |
| 81 | ASSERT_EQ(true, ReadFileToString(tmp, &tmp_content)); |
| 82 | |
| 83 | std::string dst_content; |
| 84 | ASSERT_EQ(true, ReadFileToString(dst, &dst_content)); |
| 85 | |
| 86 | ASSERT_EQ(tmp_content, dst_content); |
| 87 | } |
| 88 | |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 89 | // Align a zip featuring a hole at the beginning. The |
| 90 | // hole in the archive is a delete entry in the Central |
| 91 | // Directory. |
| 92 | TEST(Align, Holes) { |
| 93 | const std::string src = GetTestPath("holes.zip"); |
weisu | eae4531 | 2021-12-13 17:56:12 +0000 | [diff] [blame] | 94 | const std::string dst = GetTempPath("holes_out.zip"); |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 95 | int pageSize = 4096; |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 96 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 97 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize); |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 98 | ASSERT_EQ(0, processed); |
| 99 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 100 | int verified = verify(dst.c_str(), 4, false, true, pageSize); |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 101 | ASSERT_EQ(0, verified); |
| 102 | } |
| 103 | |
| 104 | // Align a zip where LFH order and CD entries differ. |
| 105 | TEST(Align, DifferenteOrders) { |
| 106 | const std::string src = GetTestPath("diffOrders.zip"); |
weisu | eae4531 | 2021-12-13 17:56:12 +0000 | [diff] [blame] | 107 | const std::string dst = GetTempPath("diffOrders_out.zip"); |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 108 | int pageSize = 4096; |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 109 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 110 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize); |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 111 | ASSERT_EQ(0, processed); |
| 112 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 113 | int verified = verify(dst.c_str(), 4, false, true, pageSize); |
Fabien Sanglard | a720635 | 2020-10-20 15:47:10 -0700 | [diff] [blame] | 114 | ASSERT_EQ(0, verified); |
| 115 | } |
Fabien Sanglard | 8163cfa | 2022-10-10 22:19:47 +0000 | [diff] [blame] | 116 | |
| 117 | TEST(Align, DirectoryEntryDoNotRequireAlignment) { |
| 118 | const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip"); |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 119 | int pageSize = 4096; |
| 120 | int verified = verify(src.c_str(), 4, false, true, pageSize); |
Fabien Sanglard | 8163cfa | 2022-10-10 22:19:47 +0000 | [diff] [blame] | 121 | ASSERT_EQ(0, verified); |
| 122 | } |
| 123 | |
| 124 | TEST(Align, DirectoryEntry) { |
| 125 | const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip"); |
| 126 | const std::string dst = GetTempPath("archiveWithOneDirectoryEntry_out.zip"); |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 127 | int pageSize = 4096; |
Fabien Sanglard | 8163cfa | 2022-10-10 22:19:47 +0000 | [diff] [blame] | 128 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 129 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize); |
Fabien Sanglard | 8163cfa | 2022-10-10 22:19:47 +0000 | [diff] [blame] | 130 | ASSERT_EQ(0, processed); |
| 131 | ASSERT_EQ(true, sameContent(src, dst)); |
| 132 | |
Kalesh Singh | 55405b6 | 2023-08-17 09:44:45 -0700 | [diff] [blame^] | 133 | int verified = verify(dst.c_str(), 4, false, true, pageSize); |
| 134 | ASSERT_EQ(0, verified); |
| 135 | } |
| 136 | |
| 137 | class UncompressedSharedLibsTest : public ::testing::Test { |
| 138 | protected: |
| 139 | static void SetUpTestSuite() { |
| 140 | src = GetTestPath("apkWithUncompressedSharedLibs.zip"); |
| 141 | dst = GetTempPath("apkWithUncompressedSharedLibs_out.zip"); |
| 142 | } |
| 143 | |
| 144 | static std::string src; |
| 145 | static std::string dst; |
| 146 | }; |
| 147 | |
| 148 | std::string UncompressedSharedLibsTest::src; |
| 149 | std::string UncompressedSharedLibsTest::dst; |
| 150 | |
| 151 | TEST_F(UncompressedSharedLibsTest, Unaligned) { |
| 152 | int pageSize = 4096; |
| 153 | |
| 154 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, false, pageSize); |
| 155 | ASSERT_EQ(0, processed); |
| 156 | |
| 157 | int verified = verify(dst.c_str(), 4, true, true, pageSize); |
| 158 | ASSERT_NE(0, verified); // .so's not page-aligned |
| 159 | } |
| 160 | |
| 161 | TEST_F(UncompressedSharedLibsTest, AlignedPageSize4kB) { |
| 162 | int pageSize = 4096; |
| 163 | |
| 164 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize); |
| 165 | ASSERT_EQ(0, processed); |
| 166 | |
| 167 | int verified = verify(dst.c_str(), 4, true, true, pageSize); |
| 168 | ASSERT_EQ(0, verified); |
| 169 | } |
| 170 | |
| 171 | TEST_F(UncompressedSharedLibsTest, AlignedPageSize16kB) { |
| 172 | int pageSize = 16384; |
| 173 | |
| 174 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize); |
| 175 | ASSERT_EQ(0, processed); |
| 176 | |
| 177 | int verified = verify(dst.c_str(), 4, true, true, pageSize); |
| 178 | ASSERT_EQ(0, verified); |
| 179 | } |
| 180 | |
| 181 | TEST_F(UncompressedSharedLibsTest, AlignedPageSize64kB) { |
| 182 | int pageSize = 65536; |
| 183 | |
| 184 | int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize); |
| 185 | ASSERT_EQ(0, processed); |
| 186 | |
| 187 | int verified = verify(dst.c_str(), 4, true, true, pageSize); |
Fabien Sanglard | 8163cfa | 2022-10-10 22:19:47 +0000 | [diff] [blame] | 188 | ASSERT_EQ(0, verified); |
| 189 | } |