blob: b7d145833b3bd2e70e53be7afb10e0bc9d051b24 [file] [log] [blame]
Adam Lesinski622f3042015-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 Hughes53039d62015-12-04 22:00:26 -080020#include <android-base/test_utils.h>
Adam Lesinski622f3042015-10-05 18:16:18 -070021#include <gtest/gtest.h>
22#include <memory>
Christopher Ferrisfcc081f2015-11-04 17:54:32 -080023#include <vector>
Adam Lesinski622f3042015-10-05 18:16:18 -070024
25struct zipwriter : public ::testing::Test {
26 TemporaryFile* temp_file_;
27 int fd_;
28 FILE* file_;
29
30 void SetUp() override {
31 temp_file_ = new TemporaryFile();
32 fd_ = temp_file_->fd;
33 file_ = fdopen(fd_, "w");
34 ASSERT_NE(file_, nullptr);
35 }
36
37 void TearDown() override {
38 fclose(file_);
39 delete temp_file_;
40 }
41};
42
43TEST_F(zipwriter, WriteUncompressedZipWithOneFile) {
44 ZipWriter writer(file_);
45
46 const char* expected = "hello";
47
Adam Lesinskic322b432015-10-06 15:23:46 -070048 ASSERT_EQ(0, writer.StartEntry("file.txt", 0));
49 ASSERT_EQ(0, writer.WriteBytes("he", 2));
50 ASSERT_EQ(0, writer.WriteBytes("llo", 3));
51 ASSERT_EQ(0, writer.FinishEntry());
52 ASSERT_EQ(0, writer.Finish());
Adam Lesinski622f3042015-10-05 18:16:18 -070053
Adam Lesinskic322b432015-10-06 15:23:46 -070054 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
Adam Lesinski622f3042015-10-05 18:16:18 -070055
56 ZipArchiveHandle handle;
Adam Lesinskic322b432015-10-06 15:23:46 -070057 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
Adam Lesinski622f3042015-10-05 18:16:18 -070058
59 ZipEntry data;
Adam Lesinskic322b432015-10-06 15:23:46 -070060 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
61 EXPECT_EQ(strlen(expected), data.compressed_length);
62 EXPECT_EQ(strlen(expected), data.uncompressed_length);
63 EXPECT_EQ(kCompressStored, data.method);
Adam Lesinski622f3042015-10-05 18:16:18 -070064
65 char buffer[6];
Adam Lesinskic322b432015-10-06 15:23:46 -070066 EXPECT_EQ(0,
67 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(&buffer), sizeof(buffer)));
Adam Lesinski622f3042015-10-05 18:16:18 -070068 buffer[5] = 0;
69
70 EXPECT_STREQ(expected, buffer);
71
72 CloseArchive(handle);
73}
74
75TEST_F(zipwriter, WriteUncompressedZipWithMultipleFiles) {
76 ZipWriter writer(file_);
77
Adam Lesinskic322b432015-10-06 15:23:46 -070078 ASSERT_EQ(0, writer.StartEntry("file.txt", 0));
79 ASSERT_EQ(0, writer.WriteBytes("he", 2));
80 ASSERT_EQ(0, writer.FinishEntry());
Adam Lesinski622f3042015-10-05 18:16:18 -070081
Adam Lesinskic322b432015-10-06 15:23:46 -070082 ASSERT_EQ(0, writer.StartEntry("file/file.txt", 0));
83 ASSERT_EQ(0, writer.WriteBytes("llo", 3));
84 ASSERT_EQ(0, writer.FinishEntry());
Adam Lesinski622f3042015-10-05 18:16:18 -070085
Adam Lesinskic322b432015-10-06 15:23:46 -070086 ASSERT_EQ(0, writer.StartEntry("file/file2.txt", 0));
87 ASSERT_EQ(0, writer.FinishEntry());
Adam Lesinski622f3042015-10-05 18:16:18 -070088
Adam Lesinskic322b432015-10-06 15:23:46 -070089 ASSERT_EQ(0, writer.Finish());
Adam Lesinski622f3042015-10-05 18:16:18 -070090
Adam Lesinskic322b432015-10-06 15:23:46 -070091 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
Adam Lesinski622f3042015-10-05 18:16:18 -070092
93 ZipArchiveHandle handle;
Adam Lesinskic322b432015-10-06 15:23:46 -070094 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
Adam Lesinski622f3042015-10-05 18:16:18 -070095
96 char buffer[4];
97 ZipEntry data;
98
Adam Lesinskic322b432015-10-06 15:23:46 -070099 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
100 EXPECT_EQ(kCompressStored, data.method);
101 EXPECT_EQ(2u, data.compressed_length);
102 EXPECT_EQ(2u, data.uncompressed_length);
103 ASSERT_EQ(0,
104 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
Adam Lesinski622f3042015-10-05 18:16:18 -0700105 buffer[2] = 0;
106 EXPECT_STREQ("he", buffer);
107
Adam Lesinskic322b432015-10-06 15:23:46 -0700108 ASSERT_EQ(0, FindEntry(handle, ZipString("file/file.txt"), &data));
109 EXPECT_EQ(kCompressStored, data.method);
110 EXPECT_EQ(3u, data.compressed_length);
111 EXPECT_EQ(3u, data.uncompressed_length);
112 ASSERT_EQ(0,
113 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
Adam Lesinski622f3042015-10-05 18:16:18 -0700114 buffer[3] = 0;
115 EXPECT_STREQ("llo", buffer);
116
Adam Lesinskic322b432015-10-06 15:23:46 -0700117 ASSERT_EQ(0, FindEntry(handle, ZipString("file/file2.txt"), &data));
118 EXPECT_EQ(kCompressStored, data.method);
119 EXPECT_EQ(0u, data.compressed_length);
120 EXPECT_EQ(0u, data.uncompressed_length);
Adam Lesinski622f3042015-10-05 18:16:18 -0700121
122 CloseArchive(handle);
123}
124
125TEST_F(zipwriter, WriteUncompressedZipWithAlignedFile) {
126 ZipWriter writer(file_);
127
Adam Lesinskic322b432015-10-06 15:23:46 -0700128 ASSERT_EQ(0, writer.StartEntry("align.txt", ZipWriter::kAlign32));
129 ASSERT_EQ(0, writer.WriteBytes("he", 2));
130 ASSERT_EQ(0, writer.FinishEntry());
131 ASSERT_EQ(0, writer.Finish());
Adam Lesinski622f3042015-10-05 18:16:18 -0700132
Adam Lesinskic322b432015-10-06 15:23:46 -0700133 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
Adam Lesinski622f3042015-10-05 18:16:18 -0700134
135 ZipArchiveHandle handle;
Adam Lesinskic322b432015-10-06 15:23:46 -0700136 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
Adam Lesinski622f3042015-10-05 18:16:18 -0700137
138 ZipEntry data;
Adam Lesinskic322b432015-10-06 15:23:46 -0700139 ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
140 EXPECT_EQ(0, data.offset & 0x03);
141
142 CloseArchive(handle);
143}
144
145TEST_F(zipwriter, WriteCompressedZipWithOneFile) {
146 ZipWriter writer(file_);
147
148 ASSERT_EQ(0, writer.StartEntry("file.txt", ZipWriter::kCompress));
149 ASSERT_EQ(0, writer.WriteBytes("helo", 4));
150 ASSERT_EQ(0, writer.FinishEntry());
151 ASSERT_EQ(0, writer.Finish());
152
153 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
154
155 ZipArchiveHandle handle;
156 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
157
158 ZipEntry data;
159 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
160 EXPECT_EQ(kCompressDeflated, data.method);
161 EXPECT_EQ(4u, data.uncompressed_length);
162
163 char buffer[5];
164 ASSERT_EQ(0,
165 ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
166 buffer[4] = 0;
167
168 EXPECT_STREQ("helo", buffer);
169
170 CloseArchive(handle);
Adam Lesinski622f3042015-10-05 18:16:18 -0700171}
Christopher Ferrisfcc081f2015-11-04 17:54:32 -0800172
173TEST_F(zipwriter, WriteCompressedZipFlushFull) {
174 // This exact data will cause the Finish() to require multiple calls
175 // to deflate() because the ZipWriter buffer isn't big enough to hold
176 // the entire compressed data buffer.
177 constexpr size_t kBufSize = 10000000;
178 std::vector<uint8_t> buffer(kBufSize);
179 size_t prev = 1;
180 for (size_t i = 0; i < kBufSize; i++) {
181 buffer[i] = i + prev;
182 prev = i;
183 }
184
185 ZipWriter writer(file_);
186 ASSERT_EQ(0, writer.StartEntry("file.txt", ZipWriter::kCompress));
187 ASSERT_EQ(0, writer.WriteBytes(buffer.data(), buffer.size()));
188 ASSERT_EQ(0, writer.FinishEntry());
189 ASSERT_EQ(0, writer.Finish());
190
191 ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
192
193 ZipArchiveHandle handle;
194 ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
195
196 ZipEntry data;
197 ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
198 EXPECT_EQ(kCompressDeflated, data.method);
199 EXPECT_EQ(kBufSize, data.uncompressed_length);
200
201 std::vector<uint8_t> decompress(kBufSize);
202 memset(decompress.data(), 0, kBufSize);
203 ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(), decompress.size()));
204 EXPECT_EQ(0, memcmp(decompress.data(), buffer.data(), kBufSize))
205 << "Input buffer and output buffer are different.";
206
207 CloseArchive(handle);
208}