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