1 #include "gmock/gmock.h"
2 #include "gtest/gtest.h"
3
4 #include "ZipAlign.h"
5
6 #include <filesystem>
7 #include <stdio.h>
8 #include <string>
9
10 #include <android-base/file.h>
11
12 using namespace android;
13 using namespace base;
14
15 // This load the whole file to memory so be careful!
sameContent(const std::string & path1,const std::string & path2)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
GetTestPath(const std::string & filename)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
GetTempPath(const std::string & filename)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
TEST(Align,Unaligned)48 TEST(Align, Unaligned) {
49 const std::string src = GetTestPath("unaligned.zip");
50 const std::string dst = GetTempPath("unaligned_out.zip");
51 int pageSize = 4096;
52
53 int processed = process(src.c_str(), dst.c_str(), 4, true, false, false, pageSize);
54 ASSERT_EQ(0, processed);
55
56 int verified = verify(dst.c_str(), 4, true, false, pageSize);
57 ASSERT_EQ(0, verified);
58 }
59
TEST(Align,DoubleAligment)60 TEST(Align, DoubleAligment) {
61 const std::string src = GetTestPath("unaligned.zip");
62 const std::string tmp = GetTempPath("da_aligned.zip");
63 const std::string dst = GetTempPath("da_d_aligner.zip");
64 int pageSize = 4096;
65
66 int processed = process(src.c_str(), tmp.c_str(), 4, true, false, false, pageSize);
67 ASSERT_EQ(0, processed);
68
69 int verified = verify(tmp.c_str(), 4, true, false, pageSize);
70 ASSERT_EQ(0, verified);
71
72 // Align the result of the previous run. Essentially double aligning.
73 processed = process(tmp.c_str(), dst.c_str(), 4, true, false, false, pageSize);
74 ASSERT_EQ(0, processed);
75
76 verified = verify(dst.c_str(), 4, true, false, pageSize);
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
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.
TEST(Align,Holes)92 TEST(Align, Holes) {
93 const std::string src = GetTestPath("holes.zip");
94 const std::string dst = GetTempPath("holes_out.zip");
95 int pageSize = 4096;
96
97 int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
98 ASSERT_EQ(0, processed);
99
100 int verified = verify(dst.c_str(), 4, false, true, pageSize);
101 ASSERT_EQ(0, verified);
102 }
103
104 // Align a zip where LFH order and CD entries differ.
TEST(Align,DifferenteOrders)105 TEST(Align, DifferenteOrders) {
106 const std::string src = GetTestPath("diffOrders.zip");
107 const std::string dst = GetTempPath("diffOrders_out.zip");
108 int pageSize = 4096;
109
110 int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
111 ASSERT_EQ(0, processed);
112
113 int verified = verify(dst.c_str(), 4, false, true, pageSize);
114 ASSERT_EQ(0, verified);
115 }
116
TEST(Align,DirectoryEntryDoNotRequireAlignment)117 TEST(Align, DirectoryEntryDoNotRequireAlignment) {
118 const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
119 int pageSize = 4096;
120 int verified = verify(src.c_str(), 4, false, true, pageSize);
121 ASSERT_EQ(0, verified);
122 }
123
TEST(Align,DirectoryEntry)124 TEST(Align, DirectoryEntry) {
125 const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
126 const std::string dst = GetTempPath("archiveWithOneDirectoryEntry_out.zip");
127 int pageSize = 4096;
128
129 int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
130 ASSERT_EQ(0, processed);
131 ASSERT_EQ(true, sameContent(src, dst));
132
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:
SetUpTestSuite()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
TEST_F(UncompressedSharedLibsTest,Unaligned)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
TEST_F(UncompressedSharedLibsTest,AlignedPageSize4kB)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
TEST_F(UncompressedSharedLibsTest,AlignedPageSize16kB)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
TEST_F(UncompressedSharedLibsTest,AlignedPageSize64kB)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);
188 ASSERT_EQ(0, verified);
189 }
190