blob: 16a574d99ff367d319c733611bbf7f42497e454a [file] [log] [blame]
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -07001/*
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
17#include "ziparchive/zip_archive.h"
18#include "ziparchive/zip_writer.h"
19
Elliott Hughes4f713192015-12-04 22:00:26 -080020#include <android-base/test_utils.h>
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070021#include <gtest/gtest.h>
Christopher Ferris5e9f3d42016-01-19 10:33:03 -080022#include <time.h>
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070023#include <memory>
Christopher Ferrisa2a32b02015-11-04 17:54:32 -080024#include <vector>
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070025
26struct zipwriter : public ::testing::Test {
27 TemporaryFile* temp_file_;
28 int fd_;
29 FILE* file_;
30
31 void SetUp() override {
32 temp_file_ = new TemporaryFile();
33 fd_ = temp_file_->fd;
34 file_ = fdopen(fd_, "w");
35 ASSERT_NE(file_, nullptr);
36 }
37
38 void TearDown() override {
39 fclose(file_);
40 delete temp_file_;
41 }
42};
43
44TEST_F(zipwriter, WriteUncompressedZipWithOneFile) {
45 ZipWriter writer(file_);
46
47 const char* expected = "hello";
48
Adam Lesinski591fd392015-10-06 15:23:46 -070049 ASSERT_EQ(0, writer.StartEntry("file.txt", 0));
50 ASSERT_EQ(0, writer.WriteBytes("he", 2));
51 ASSERT_EQ(0, writer.WriteBytes("llo", 3));
52 ASSERT_EQ(0, writer.FinishEntry());
53 ASSERT_EQ(0, writer.Finish());
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070054
Adam Lesinski591fd392015-10-06 15:23:46 -070055 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070056
57 ZipArchiveHandle handle;
Adam Lesinski591fd392015-10-06 15:23:46 -070058 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070059
60 ZipEntry data;
Adam Lesinski591fd392015-10-06 15:23:46 -070061 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
62 EXPECT_EQ(strlen(expected), data.compressed_length);
63 EXPECT_EQ(strlen(expected), data.uncompressed_length);
64 EXPECT_EQ(kCompressStored, data.method);
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070065
66 char buffer[6];
Adam Lesinski591fd392015-10-06 15:23:46 -070067 EXPECT_EQ(0,
68 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(&buffer), sizeof(buffer)));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070069 buffer[5] = 0;
70
71 EXPECT_STREQ(expected, buffer);
72
73 CloseArchive(handle);
74}
75
76TEST_F(zipwriter, WriteUncompressedZipWithMultipleFiles) {
77 ZipWriter writer(file_);
78
Adam Lesinski591fd392015-10-06 15:23:46 -070079 ASSERT_EQ(0, writer.StartEntry("file.txt", 0));
80 ASSERT_EQ(0, writer.WriteBytes("he", 2));
81 ASSERT_EQ(0, writer.FinishEntry());
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070082
Adam Lesinski591fd392015-10-06 15:23:46 -070083 ASSERT_EQ(0, writer.StartEntry("file/file.txt", 0));
84 ASSERT_EQ(0, writer.WriteBytes("llo", 3));
85 ASSERT_EQ(0, writer.FinishEntry());
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070086
Adam Lesinski591fd392015-10-06 15:23:46 -070087 ASSERT_EQ(0, writer.StartEntry("file/file2.txt", 0));
88 ASSERT_EQ(0, writer.FinishEntry());
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070089
Adam Lesinski591fd392015-10-06 15:23:46 -070090 ASSERT_EQ(0, writer.Finish());
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070091
Adam Lesinski591fd392015-10-06 15:23:46 -070092 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070093
94 ZipArchiveHandle handle;
Adam Lesinski591fd392015-10-06 15:23:46 -070095 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -070096
97 char buffer[4];
98 ZipEntry data;
99
Adam Lesinski591fd392015-10-06 15:23:46 -0700100 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
101 EXPECT_EQ(kCompressStored, data.method);
102 EXPECT_EQ(2u, data.compressed_length);
103 EXPECT_EQ(2u, data.uncompressed_length);
104 ASSERT_EQ(0,
105 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700106 buffer[2] = 0;
107 EXPECT_STREQ("he", buffer);
108
Adam Lesinski591fd392015-10-06 15:23:46 -0700109 ASSERT_EQ(0, FindEntry(handle, ZipString("file/file.txt"), &data));
110 EXPECT_EQ(kCompressStored, data.method);
111 EXPECT_EQ(3u, data.compressed_length);
112 EXPECT_EQ(3u, data.uncompressed_length);
113 ASSERT_EQ(0,
114 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700115 buffer[3] = 0;
116 EXPECT_STREQ("llo", buffer);
117
Adam Lesinski591fd392015-10-06 15:23:46 -0700118 ASSERT_EQ(0, FindEntry(handle, ZipString("file/file2.txt"), &data));
119 EXPECT_EQ(kCompressStored, data.method);
120 EXPECT_EQ(0u, data.compressed_length);
121 EXPECT_EQ(0u, data.uncompressed_length);
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700122
123 CloseArchive(handle);
124}
125
Christopher Ferris5e9f3d42016-01-19 10:33:03 -0800126TEST_F(zipwriter, WriteUncompressedZipFileWithAlignedFlag) {
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700127 ZipWriter writer(file_);
128
Adam Lesinski591fd392015-10-06 15:23:46 -0700129 ASSERT_EQ(0, writer.StartEntry("align.txt", ZipWriter::kAlign32));
130 ASSERT_EQ(0, writer.WriteBytes("he", 2));
131 ASSERT_EQ(0, writer.FinishEntry());
132 ASSERT_EQ(0, writer.Finish());
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700133
Adam Lesinski591fd392015-10-06 15:23:46 -0700134 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700135
136 ZipArchiveHandle handle;
Adam Lesinski591fd392015-10-06 15:23:46 -0700137 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700138
139 ZipEntry data;
Adam Lesinski591fd392015-10-06 15:23:46 -0700140 ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
141 EXPECT_EQ(0, data.offset & 0x03);
142
143 CloseArchive(handle);
144}
145
Christopher Ferris5e9f3d42016-01-19 10:33:03 -0800146void ConvertZipTimeToTm(uint32_t& zip_time, struct tm* tm) {
147 memset(tm, 0, sizeof(struct tm));
148 tm->tm_hour = (zip_time >> 11) & 0x1f;
149 tm->tm_min = (zip_time >> 5) & 0x3f;
150 tm->tm_sec = (zip_time & 0x1f) << 1;
151
152 tm->tm_year = ((zip_time >> 25) & 0x7f) + 80;
153 tm->tm_mon = ((zip_time >> 21) & 0xf) - 1;
154 tm->tm_mday = (zip_time >> 16) & 0x1f;
155}
156
Yabin Cui8e6f7222016-02-08 16:26:33 -0800157static struct tm MakeTm() {
158 struct tm tm;
159 memset(&tm, 0, sizeof(struct tm));
160 tm.tm_year = 2001 - 1900;
161 tm.tm_mon = 1;
162 tm.tm_mday = 12;
163 tm.tm_hour = 18;
164 tm.tm_min = 30;
165 tm.tm_sec = 20;
166 return tm;
167}
168
Christopher Ferris5e9f3d42016-01-19 10:33:03 -0800169TEST_F(zipwriter, WriteUncompressedZipFileWithAlignedFlagAndTime) {
170 ZipWriter writer(file_);
171
Yabin Cui8e6f7222016-02-08 16:26:33 -0800172 struct tm tm = MakeTm();
Christopher Ferris5e9f3d42016-01-19 10:33:03 -0800173 time_t time = mktime(&tm);
174 ASSERT_EQ(0, writer.StartEntryWithTime("align.txt", ZipWriter::kAlign32, time));
175 ASSERT_EQ(0, writer.WriteBytes("he", 2));
176 ASSERT_EQ(0, writer.FinishEntry());
177 ASSERT_EQ(0, writer.Finish());
178
179 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
180
181 ZipArchiveHandle handle;
182 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
183
184 ZipEntry data;
185 ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
186 EXPECT_EQ(0, data.offset & 0x03);
187
188 struct tm mod;
189 ConvertZipTimeToTm(data.mod_time, &mod);
190 EXPECT_EQ(tm.tm_sec, mod.tm_sec);
191 EXPECT_EQ(tm.tm_min, mod.tm_min);
192 EXPECT_EQ(tm.tm_hour, mod.tm_hour);
193 EXPECT_EQ(tm.tm_mday, mod.tm_mday);
194 EXPECT_EQ(tm.tm_mon, mod.tm_mon);
195 EXPECT_EQ(tm.tm_year, mod.tm_year);
196
197 CloseArchive(handle);
198}
199
200TEST_F(zipwriter, WriteUncompressedZipFileWithAlignedValue) {
201 ZipWriter writer(file_);
202
203 ASSERT_EQ(0, writer.StartAlignedEntry("align.txt", 0, 4096));
204 ASSERT_EQ(0, writer.WriteBytes("he", 2));
205 ASSERT_EQ(0, writer.FinishEntry());
206 ASSERT_EQ(0, writer.Finish());
207
208 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
209
210 ZipArchiveHandle handle;
211 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
212
213 ZipEntry data;
214 ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
215 EXPECT_EQ(0, data.offset & 0xfff);
216
217 CloseArchive(handle);
218}
219
220TEST_F(zipwriter, WriteUncompressedZipFileWithAlignedValueAndTime) {
221 ZipWriter writer(file_);
222
Yabin Cui8e6f7222016-02-08 16:26:33 -0800223 struct tm tm = MakeTm();
Christopher Ferris5e9f3d42016-01-19 10:33:03 -0800224 time_t time = mktime(&tm);
225 ASSERT_EQ(0, writer.StartAlignedEntryWithTime("align.txt", 0, time, 4096));
226 ASSERT_EQ(0, writer.WriteBytes("he", 2));
227 ASSERT_EQ(0, writer.FinishEntry());
228 ASSERT_EQ(0, writer.Finish());
229
230 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
231
232 ZipArchiveHandle handle;
233 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
234
235 ZipEntry data;
236 ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
237 EXPECT_EQ(0, data.offset & 0xfff);
238
239 struct tm mod;
240 ConvertZipTimeToTm(data.mod_time, &mod);
241 EXPECT_EQ(tm.tm_sec, mod.tm_sec);
242 EXPECT_EQ(tm.tm_min, mod.tm_min);
243 EXPECT_EQ(tm.tm_hour, mod.tm_hour);
244 EXPECT_EQ(tm.tm_mday, mod.tm_mday);
245 EXPECT_EQ(tm.tm_mon, mod.tm_mon);
246 EXPECT_EQ(tm.tm_year, mod.tm_year);
247
248 CloseArchive(handle);
249}
250
Adam Lesinski591fd392015-10-06 15:23:46 -0700251TEST_F(zipwriter, WriteCompressedZipWithOneFile) {
252 ZipWriter writer(file_);
253
254 ASSERT_EQ(0, writer.StartEntry("file.txt", ZipWriter::kCompress));
255 ASSERT_EQ(0, writer.WriteBytes("helo", 4));
256 ASSERT_EQ(0, writer.FinishEntry());
257 ASSERT_EQ(0, writer.Finish());
258
259 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
260
261 ZipArchiveHandle handle;
262 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
263
264 ZipEntry data;
265 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
266 EXPECT_EQ(kCompressDeflated, data.method);
267 EXPECT_EQ(4u, data.uncompressed_length);
268
269 char buffer[5];
270 ASSERT_EQ(0,
271 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
272 buffer[4] = 0;
273
274 EXPECT_STREQ("helo", buffer);
275
276 CloseArchive(handle);
Adam Lesinskiad4ad8c2015-10-05 18:16:18 -0700277}
Christopher Ferrisa2a32b02015-11-04 17:54:32 -0800278
279TEST_F(zipwriter, WriteCompressedZipFlushFull) {
280 // This exact data will cause the Finish() to require multiple calls
281 // to deflate() because the ZipWriter buffer isn't big enough to hold
282 // the entire compressed data buffer.
283 constexpr size_t kBufSize = 10000000;
284 std::vector<uint8_t> buffer(kBufSize);
285 size_t prev = 1;
286 for (size_t i = 0; i < kBufSize; i++) {
287 buffer[i] = i + prev;
288 prev = i;
289 }
290
291 ZipWriter writer(file_);
292 ASSERT_EQ(0, writer.StartEntry("file.txt", ZipWriter::kCompress));
293 ASSERT_EQ(0, writer.WriteBytes(buffer.data(), buffer.size()));
294 ASSERT_EQ(0, writer.FinishEntry());
295 ASSERT_EQ(0, writer.Finish());
296
297 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
298
299 ZipArchiveHandle handle;
300 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
301
302 ZipEntry data;
303 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
304 EXPECT_EQ(kCompressDeflated, data.method);
305 EXPECT_EQ(kBufSize, data.uncompressed_length);
306
307 std::vector<uint8_t> decompress(kBufSize);
308 memset(decompress.data(), 0, kBufSize);
309 ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(), decompress.size()));
310 EXPECT_EQ(0, memcmp(decompress.data(), buffer.data(), kBufSize))
311 << "Input buffer and output buffer are different.";
312
313 CloseArchive(handle);
314}
Christopher Ferris5e9f3d42016-01-19 10:33:03 -0800315
316TEST_F(zipwriter, CheckStartEntryErrors) {
317 ZipWriter writer(file_);
318
319 ASSERT_EQ(-5, writer.StartAlignedEntry("align.txt", ZipWriter::kAlign32, 4096));
320 ASSERT_EQ(-6, writer.StartAlignedEntry("align.txt", 0, 3));
321}