blob: 022be5b6f040254010e7a4064508afd5d86d8035 [file] [log] [blame]
Narayan Kamath7462f022013-11-21 13:05:04 +00001/*
2 * Copyright (C) 2013 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
Narayan Kamath00a258c2013-12-13 16:06:19 +000019#include <errno.h>
20#include <getopt.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000021#include <stdio.h>
Narayan Kamath00a258c2013-12-13 16:06:19 +000022#include <unistd.h>
23#include <vector>
24
Narayan Kamath7462f022013-11-21 13:05:04 +000025#include <gtest/gtest.h>
26
Narayan Kamath58aaf462013-12-10 16:47:14 +000027static std::string test_data_dir;
Narayan Kamath7462f022013-11-21 13:05:04 +000028
Narayan Kamath58aaf462013-12-10 16:47:14 +000029static const std::string kValidZip = "valid.zip";
30
31static const uint8_t kATxtContents[] = {
32 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
33 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
34 '\n'
35};
36
37static const uint8_t kBTxtContents[] = {
38 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
39 '\n'
40};
41
42static int32_t OpenArchiveWrapper(const std::string& name,
43 ZipArchiveHandle* handle) {
44 const std::string abs_path = test_data_dir + "/" + name;
45 return OpenArchive(abs_path.c_str(), handle);
46}
47
48static void AssertNameEquals(const std::string& name_str,
49 const ZipEntryName& name) {
50 ASSERT_EQ(name_str.size(), name.name_length);
51 ASSERT_EQ(0, memcmp(name_str.c_str(), name.name, name.name_length));
52}
53
54TEST(ziparchive, Open) {
55 ZipArchiveHandle handle;
56 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
57
58 CloseArchive(handle);
59}
60
61TEST(ziparchive, Iteration) {
62 ZipArchiveHandle handle;
63 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
64
65 void* iteration_cookie;
66 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL));
Narayan Kamath7462f022013-11-21 13:05:04 +000067
68 ZipEntry data;
69 ZipEntryName name;
Narayan Kamath58aaf462013-12-10 16:47:14 +000070
71 // b/c.txt
72 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
73 AssertNameEquals("b/c.txt", name);
74
75 // b/d.txt
76 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
77 AssertNameEquals("b/d.txt", name);
78
79 // a.txt
80 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
81 AssertNameEquals("a.txt", name);
82
83 // b.txt
84 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
85 AssertNameEquals("b.txt", name);
86
87 // b/
88 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
89 AssertNameEquals("b/", name);
90
91 // End of iteration.
92 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
93
94 CloseArchive(handle);
95}
96
97TEST(ziparchive, FindEntry) {
98 ZipArchiveHandle handle;
99 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
100
101 ZipEntry data;
102 ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
103
104 // Known facts about a.txt, from zipinfo -v.
105 ASSERT_EQ(63, data.offset);
106 ASSERT_EQ(kCompressDeflated, data.method);
107 ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
108 ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
109 ASSERT_EQ(0x950821c5, data.crc32);
110
111 // An entry that doesn't exist. Should be a negative return code.
112 ASSERT_LT(FindEntry(handle, "nonexistent.txt", &data), 0);
113
114 CloseArchive(handle);
115}
116
117TEST(ziparchive, ExtractToMemory) {
118 ZipArchiveHandle handle;
119 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
120
121 // An entry that's deflated.
122 ZipEntry data;
123 ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
124 const uint32_t a_size = data.uncompressed_length;
125 ASSERT_EQ(a_size, sizeof(kATxtContents));
126 uint8_t* buffer = new uint8_t[a_size];
127 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, a_size));
128 ASSERT_EQ(0, memcmp(buffer, kATxtContents, a_size));
129 delete[] buffer;
130
131 // An entry that's stored.
132 ASSERT_EQ(0, FindEntry(handle, "b.txt", &data));
133 const uint32_t b_size = data.uncompressed_length;
134 ASSERT_EQ(b_size, sizeof(kBTxtContents));
135 buffer = new uint8_t[b_size];
136 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, b_size));
137 ASSERT_EQ(0, memcmp(buffer, kBTxtContents, b_size));
138 delete[] buffer;
139
140 CloseArchive(handle);
141}
142
Narayan Kamath00a258c2013-12-13 16:06:19 +0000143TEST(ziparchive, ExtractToFile) {
144 char kTempFilePattern[] = "zip_archive_test_XXXXXX";
145 int fd = mkstemp(kTempFilePattern);
146 ASSERT_NE(-1, fd);
147 const uint8_t data[8] = { '1', '2', '3', '4', '5', '6', '7', '8' };
148 const ssize_t data_size = sizeof(data);
149
150 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(write(fd, data, data_size)));
151
152 ZipArchiveHandle handle;
153 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
154
155 ZipEntry entry;
156 ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
157 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, fd));
158
159
160 // Assert that the first 8 bytes of the file haven't been clobbered.
161 uint8_t read_buffer[data_size];
162 ASSERT_EQ(0, lseek64(fd, 0, SEEK_SET));
163 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(read(fd, read_buffer, data_size)));
164 ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
165
166 // Assert that the remainder of the file contains the incompressed data.
167 std::vector<uint8_t> uncompressed_data(entry.uncompressed_length);
168 ASSERT_EQ(static_cast<ssize_t>(entry.uncompressed_length),
169 TEMP_FAILURE_RETRY(
170 read(fd, &uncompressed_data[0], entry.uncompressed_length)));
171 ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents,
172 sizeof(kATxtContents)));
173
174 // Assert that the total length of the file is sane
175 ASSERT_EQ(data_size + sizeof(kATxtContents), lseek64(fd, 0, SEEK_END));
176
177 close(fd);
178}
179
Narayan Kamath58aaf462013-12-10 16:47:14 +0000180int main(int argc, char** argv) {
181 ::testing::InitGoogleTest(&argc, argv);
182
183 static struct option options[] = {
184 { "test_data_dir", required_argument, NULL, 't' },
185 { NULL, 0, NULL, 0 }
186 };
187
188 while (true) {
189 int option_index;
190 const int c = getopt_long_only(argc, argv, "", options, &option_index);
191 if (c == -1) {
192 break;
193 }
194
195 if (c == 't') {
196 test_data_dir = optarg;
197 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000198 }
199
Narayan Kamath58aaf462013-12-10 16:47:14 +0000200 if (test_data_dir.size() == 0) {
201 printf("Test data flag (--test_data_dir) required\n\n");
202 return -1;
203 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000204
Narayan Kamath58aaf462013-12-10 16:47:14 +0000205 if (test_data_dir[0] != '/') {
206 printf("Test data must be an absolute path, was %s\n\n",
207 test_data_dir.c_str());
208 return -2;
209 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000210
Narayan Kamath58aaf462013-12-10 16:47:14 +0000211 return RUN_ALL_TESTS();
Narayan Kamath7462f022013-11-21 13:05:04 +0000212}
213