blob: f8952ce659a6a02af4d85b2643c4a01748f10af6 [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>
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -070020#include <fcntl.h>
Narayan Kamath00a258c2013-12-13 16:06:19 +000021#include <getopt.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000022#include <stdio.h>
Narayan Kamath00a258c2013-12-13 16:06:19 +000023#include <unistd.h>
24#include <vector>
25
Narayan Kamathf899bd52015-04-17 11:53:14 +010026#include <base/file.h>
Narayan Kamath7462f022013-11-21 13:05:04 +000027#include <gtest/gtest.h>
28
Narayan Kamath58aaf462013-12-10 16:47:14 +000029static std::string test_data_dir;
Narayan Kamath7462f022013-11-21 13:05:04 +000030
Neil Fullerb1a113f2014-07-25 14:43:04 +010031static const std::string kMissingZip = "missing.zip";
Narayan Kamath58aaf462013-12-10 16:47:14 +000032static const std::string kValidZip = "valid.zip";
33
34static const uint8_t kATxtContents[] = {
35 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
36 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
37 '\n'
38};
39
40static const uint8_t kBTxtContents[] = {
41 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
42 '\n'
43};
44
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +010045static const uint16_t kATxtNameLength = 5;
46static const uint16_t kBTxtNameLength = 5;
47static const uint16_t kNonexistentTxtNameLength = 15;
48static const uint16_t kEmptyTxtNameLength = 9;
49
50static const uint8_t kATxtName[kATxtNameLength] = {
51 'a', '.', 't', 'x', 't'
52};
53
54static const uint8_t kBTxtName[kBTxtNameLength] = {
55 'b', '.', 't', 'x', 't'
56};
57
58static const uint8_t kNonexistentTxtName[kNonexistentTxtNameLength] = {
59 'n', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 't', 'x' ,'t'
60};
61
62static const uint8_t kEmptyTxtName[kEmptyTxtNameLength] = {
63 'e', 'm', 'p', 't', 'y', '.', 't', 'x', 't'
64};
65
Narayan Kamath58aaf462013-12-10 16:47:14 +000066static int32_t OpenArchiveWrapper(const std::string& name,
67 ZipArchiveHandle* handle) {
68 const std::string abs_path = test_data_dir + "/" + name;
69 return OpenArchive(abs_path.c_str(), handle);
70}
71
72static void AssertNameEquals(const std::string& name_str,
73 const ZipEntryName& name) {
74 ASSERT_EQ(name_str.size(), name.name_length);
75 ASSERT_EQ(0, memcmp(name_str.c_str(), name.name, name.name_length));
76}
77
78TEST(ziparchive, Open) {
79 ZipArchiveHandle handle;
80 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
81
82 CloseArchive(handle);
83}
84
Neil Fullerb1a113f2014-07-25 14:43:04 +010085TEST(ziparchive, OpenMissing) {
86 ZipArchiveHandle handle;
87 ASSERT_NE(0, OpenArchiveWrapper(kMissingZip, &handle));
88
89 // Confirm the file descriptor is not going to be mistaken for a valid one.
90 ASSERT_EQ(-1, GetFileDescriptor(handle));
91}
92
Dmitriy Ivanov40b52b22014-07-15 19:33:00 -070093TEST(ziparchive, OpenAssumeFdOwnership) {
94 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY);
95 ASSERT_NE(-1, fd);
96 ZipArchiveHandle handle;
97 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle));
98 CloseArchive(handle);
99 ASSERT_EQ(-1, lseek(fd, 0, SEEK_SET));
100 ASSERT_EQ(EBADF, errno);
101}
102
103TEST(ziparchive, OpenDoNotAssumeFdOwnership) {
104 int fd = open((test_data_dir + "/" + kValidZip).c_str(), O_RDONLY);
105 ASSERT_NE(-1, fd);
106 ZipArchiveHandle handle;
107 ASSERT_EQ(0, OpenArchiveFd(fd, "OpenWithAssumeFdOwnership", &handle, false));
108 CloseArchive(handle);
109 ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
110 close(fd);
111}
112
Narayan Kamath58aaf462013-12-10 16:47:14 +0000113TEST(ziparchive, Iteration) {
114 ZipArchiveHandle handle;
115 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
116
117 void* iteration_cookie;
118 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL));
Narayan Kamath7462f022013-11-21 13:05:04 +0000119
120 ZipEntry data;
121 ZipEntryName name;
Narayan Kamath58aaf462013-12-10 16:47:14 +0000122
123 // b/c.txt
124 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
125 AssertNameEquals("b/c.txt", name);
126
127 // b/d.txt
128 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
129 AssertNameEquals("b/d.txt", name);
130
131 // a.txt
132 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
133 AssertNameEquals("a.txt", name);
134
135 // b.txt
136 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
137 AssertNameEquals("b.txt", name);
138
139 // b/
140 ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
141 AssertNameEquals("b/", name);
142
143 // End of iteration.
144 ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
145
146 CloseArchive(handle);
147}
148
149TEST(ziparchive, FindEntry) {
150 ZipArchiveHandle handle;
151 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
152
153 ZipEntry data;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100154 ZipEntryName name;
155 name.name = kATxtName;
156 name.name_length = kATxtNameLength;
157 ASSERT_EQ(0, FindEntry(handle, name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000158
159 // Known facts about a.txt, from zipinfo -v.
160 ASSERT_EQ(63, data.offset);
161 ASSERT_EQ(kCompressDeflated, data.method);
162 ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
163 ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
164 ASSERT_EQ(0x950821c5, data.crc32);
165
166 // An entry that doesn't exist. Should be a negative return code.
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100167 ZipEntryName absent_name;
168 absent_name.name = kNonexistentTxtName;
169 absent_name.name_length = kNonexistentTxtNameLength;
170 ASSERT_LT(FindEntry(handle, absent_name, &data), 0);
Narayan Kamath58aaf462013-12-10 16:47:14 +0000171
172 CloseArchive(handle);
173}
174
Mykola Kondratenko50afc152014-09-08 12:46:37 +0200175TEST(ziparchive, TestInvalidDeclaredLength) {
176 ZipArchiveHandle handle;
177 ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle));
178
179 void* iteration_cookie;
180 ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL));
181
182 ZipEntryName name;
183 ZipEntry data;
184
185 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
186 ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
187
188 CloseArchive(handle);
189}
190
Narayan Kamath58aaf462013-12-10 16:47:14 +0000191TEST(ziparchive, ExtractToMemory) {
192 ZipArchiveHandle handle;
193 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
194
195 // An entry that's deflated.
196 ZipEntry data;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100197 ZipEntryName a_name;
198 a_name.name = kATxtName;
199 a_name.name_length = kATxtNameLength;
200 ASSERT_EQ(0, FindEntry(handle, a_name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000201 const uint32_t a_size = data.uncompressed_length;
202 ASSERT_EQ(a_size, sizeof(kATxtContents));
203 uint8_t* buffer = new uint8_t[a_size];
204 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, a_size));
205 ASSERT_EQ(0, memcmp(buffer, kATxtContents, a_size));
206 delete[] buffer;
207
208 // An entry that's stored.
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100209 ZipEntryName b_name;
210 b_name.name = kBTxtName;
211 b_name.name_length = kBTxtNameLength;
212 ASSERT_EQ(0, FindEntry(handle, b_name, &data));
Narayan Kamath58aaf462013-12-10 16:47:14 +0000213 const uint32_t b_size = data.uncompressed_length;
214 ASSERT_EQ(b_size, sizeof(kBTxtContents));
215 buffer = new uint8_t[b_size];
216 ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, b_size));
217 ASSERT_EQ(0, memcmp(buffer, kBTxtContents, b_size));
218 delete[] buffer;
219
220 CloseArchive(handle);
221}
222
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100223static const uint32_t kEmptyEntriesZip[] = {
Narayan Kamath48953a12014-01-24 12:32:39 +0000224 0x04034b50, 0x0000000a, 0x63600000, 0x00004438, 0x00000000, 0x00000000,
225 0x00090000, 0x6d65001c, 0x2e797470, 0x55747874, 0x03000954, 0x52e25c13,
226 0x52e25c24, 0x000b7875, 0x42890401, 0x88040000, 0x50000013, 0x1e02014b,
227 0x00000a03, 0x60000000, 0x00443863, 0x00000000, 0x00000000, 0x09000000,
228 0x00001800, 0x00000000, 0xa0000000, 0x00000081, 0x706d6500, 0x742e7974,
229 0x54557478, 0x13030005, 0x7552e25c, 0x01000b78, 0x00428904, 0x13880400,
230 0x4b500000, 0x00000605, 0x00010000, 0x004f0001, 0x00430000, 0x00000000 };
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100231
Narayan Kamathf899bd52015-04-17 11:53:14 +0100232// This is a zip file containing a single entry (ab.txt) that contains
233// 90072 repetitions of the string "ab\n" and has an uncompressed length
234// of 270216 bytes.
235static const uint16_t kAbZip[] = {
236 0x4b50, 0x0403, 0x0014, 0x0000, 0x0008, 0x51d2, 0x4698, 0xc4b0,
237 0x2cda, 0x011b, 0x0000, 0x1f88, 0x0004, 0x0006, 0x001c, 0x6261,
238 0x742e, 0x7478, 0x5455, 0x0009, 0x7c03, 0x3a09, 0x7c55, 0x3a09,
239 0x7555, 0x0b78, 0x0100, 0x8904, 0x0042, 0x0400, 0x1388, 0x0000,
240 0xc2ed, 0x0d31, 0x0000, 0x030c, 0x7fa0, 0x3b2e, 0x22ff, 0xa2aa,
241 0x841f, 0x45fc, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
242 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
243 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
244 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
245 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
246 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
247 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
248 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
249 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
250 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
251 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
252 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
253 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
254 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
255 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
256 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555,
257 0x5555, 0x5555, 0x5555, 0x5555, 0xdd55, 0x502c, 0x014b, 0x1e02,
258 0x1403, 0x0000, 0x0800, 0xd200, 0x9851, 0xb046, 0xdac4, 0x1b2c,
259 0x0001, 0x8800, 0x041f, 0x0600, 0x1800, 0x0000, 0x0000, 0x0100,
260 0x0000, 0xa000, 0x0081, 0x0000, 0x6100, 0x2e62, 0x7874, 0x5574,
261 0x0554, 0x0300, 0x097c, 0x553a, 0x7875, 0x000b, 0x0401, 0x4289,
262 0x0000, 0x8804, 0x0013, 0x5000, 0x054b, 0x0006, 0x0000, 0x0100,
263 0x0100, 0x4c00, 0x0000, 0x5b00, 0x0001, 0x0000, 0x0000
264};
265
266static const uint8_t kAbTxtName[] = { 'a', 'b', '.', 't', 'x', 't' };
267static const uint16_t kAbTxtNameLength = sizeof(kAbTxtName);
268static const size_t kAbUncompressedSize = 270216;
269
Narayan Kamath926973e2014-06-09 14:18:14 +0100270static int make_temporary_file(const char* file_name_pattern) {
271 char full_path[1024];
272 // Account for differences between the host and the target.
273 //
274 // TODO: Maybe reuse bionic/tests/TemporaryFile.h.
275 snprintf(full_path, sizeof(full_path), "/data/local/tmp/%s", file_name_pattern);
276 int fd = mkstemp(full_path);
277 if (fd == -1) {
278 snprintf(full_path, sizeof(full_path), "/tmp/%s", file_name_pattern);
279 fd = mkstemp(full_path);
280 }
281
282 return fd;
283}
284
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100285TEST(ziparchive, EmptyEntries) {
286 char temp_file_pattern[] = "empty_entries_test_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100287 int fd = make_temporary_file(temp_file_pattern);
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100288 ASSERT_NE(-1, fd);
289 const ssize_t file_size = sizeof(kEmptyEntriesZip);
290 ASSERT_EQ(file_size, TEMP_FAILURE_RETRY(write(fd, kEmptyEntriesZip, file_size)));
Narayan Kamath48953a12014-01-24 12:32:39 +0000291
292 ZipArchiveHandle handle;
293 ASSERT_EQ(0, OpenArchiveFd(fd, "EmptyEntriesTest", &handle));
294
295 ZipEntry entry;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100296 ZipEntryName empty_name;
297 empty_name.name = kEmptyTxtName;
298 empty_name.name_length = kEmptyTxtNameLength;
299 ASSERT_EQ(0, FindEntry(handle, empty_name, &entry));
Narayan Kamath48953a12014-01-24 12:32:39 +0000300 ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
301 uint8_t buffer[1];
302 ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
303
304 char output_file_pattern[] = "empty_entries_output_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100305 int output_fd = make_temporary_file(output_file_pattern);
Narayan Kamath48953a12014-01-24 12:32:39 +0000306 ASSERT_NE(-1, output_fd);
307 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, output_fd));
308
309 struct stat stat_buf;
310 ASSERT_EQ(0, fstat(output_fd, &stat_buf));
311 ASSERT_EQ(0, stat_buf.st_size);
312
313 close(fd);
314 close(output_fd);
315}
316
Narayan Kamathf899bd52015-04-17 11:53:14 +0100317TEST(ziparchive, EntryLargerThan32K) {
318 char temp_file_pattern[] = "entry_larger_than_32k_test_XXXXXX";
319 int fd = make_temporary_file(temp_file_pattern);
320 ASSERT_NE(-1, fd);
321 ASSERT_TRUE(android::base::WriteFully(fd, reinterpret_cast<const uint8_t*>(kAbZip),
322 sizeof(kAbZip) - 1));
323 ZipArchiveHandle handle;
324 ASSERT_EQ(0, OpenArchiveFd(fd, "EntryLargerThan32KTest", &handle));
325
326 ZipEntry entry;
327 ZipEntryName ab_name;
328 ab_name.name = kAbTxtName;
329 ab_name.name_length = kAbTxtNameLength;
330 ASSERT_EQ(0, FindEntry(handle, ab_name, &entry));
331 ASSERT_EQ(kAbUncompressedSize, entry.uncompressed_length);
332
333 // Extract the entry to memory.
334 std::vector<uint8_t> buffer(kAbUncompressedSize);
335 ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], buffer.size()));
336
337 // Extract the entry to a file.
338 char output_file_pattern[] = "entry_larger_than_32k_test_output_XXXXXX";
339 int output_fd = make_temporary_file(output_file_pattern);
340 ASSERT_NE(-1, output_fd);
341 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, output_fd));
342
343 // Make sure the extracted file size is as expected.
344 struct stat stat_buf;
345 ASSERT_EQ(0, fstat(output_fd, &stat_buf));
346 ASSERT_EQ(kAbUncompressedSize, static_cast<size_t>(stat_buf.st_size));
347
348 // Read the file back to a buffer and make sure the contents are
349 // the same as the memory buffer we extracted directly to.
350 std::vector<uint8_t> file_contents(kAbUncompressedSize);
351 ASSERT_EQ(0, lseek64(output_fd, 0, SEEK_SET));
352 ASSERT_TRUE(android::base::ReadFully(output_fd, &file_contents[0], file_contents.size()));
353 ASSERT_EQ(file_contents, buffer);
354
355 for (int i = 0; i < 90072; ++i) {
356 const uint8_t* line = &file_contents[0] + (3 * i);
357 ASSERT_EQ('a', line[0]);
358 ASSERT_EQ('b', line[1]);
359 ASSERT_EQ('\n', line[2]);
360 }
361
362 close(fd);
363 close(output_fd);
364}
365
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100366TEST(ziparchive, TrailerAfterEOCD) {
367 char temp_file_pattern[] = "trailer_after_eocd_test_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100368 int fd = make_temporary_file(temp_file_pattern);
Narayan Kamath4f6b4992014-06-03 13:59:23 +0100369 ASSERT_NE(-1, fd);
370
371 // Create a file with 8 bytes of random garbage.
372 static const uint8_t trailer[] = { 'A' ,'n', 'd', 'r', 'o', 'i', 'd', 'z' };
373 const ssize_t file_size = sizeof(kEmptyEntriesZip);
374 const ssize_t trailer_size = sizeof(trailer);
375 ASSERT_EQ(file_size, TEMP_FAILURE_RETRY(write(fd, kEmptyEntriesZip, file_size)));
376 ASSERT_EQ(trailer_size, TEMP_FAILURE_RETRY(write(fd, trailer, trailer_size)));
377
378 ZipArchiveHandle handle;
379 ASSERT_GT(0, OpenArchiveFd(fd, "EmptyEntriesTest", &handle));
380}
381
Narayan Kamath00a258c2013-12-13 16:06:19 +0000382TEST(ziparchive, ExtractToFile) {
Narayan Kamath48953a12014-01-24 12:32:39 +0000383 char kTempFilePattern[] = "zip_archive_input_XXXXXX";
Narayan Kamath926973e2014-06-09 14:18:14 +0100384 int fd = make_temporary_file(kTempFilePattern);
Narayan Kamath00a258c2013-12-13 16:06:19 +0000385 ASSERT_NE(-1, fd);
386 const uint8_t data[8] = { '1', '2', '3', '4', '5', '6', '7', '8' };
387 const ssize_t data_size = sizeof(data);
388
389 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(write(fd, data, data_size)));
390
391 ZipArchiveHandle handle;
392 ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
393
394 ZipEntry entry;
Piotr Jastrzebskiecccc5a2014-08-11 16:35:11 +0100395 ZipEntryName name;
396 name.name = kATxtName;
397 name.name_length = kATxtNameLength;
398 ASSERT_EQ(0, FindEntry(handle, name, &entry));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000399 ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, fd));
400
401
402 // Assert that the first 8 bytes of the file haven't been clobbered.
403 uint8_t read_buffer[data_size];
404 ASSERT_EQ(0, lseek64(fd, 0, SEEK_SET));
405 ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(read(fd, read_buffer, data_size)));
406 ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
407
408 // Assert that the remainder of the file contains the incompressed data.
409 std::vector<uint8_t> uncompressed_data(entry.uncompressed_length);
410 ASSERT_EQ(static_cast<ssize_t>(entry.uncompressed_length),
411 TEMP_FAILURE_RETRY(
412 read(fd, &uncompressed_data[0], entry.uncompressed_length)));
413 ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents,
414 sizeof(kATxtContents)));
415
416 // Assert that the total length of the file is sane
Ying Wangcf86e2f2014-05-15 20:06:40 -0700417 ASSERT_EQ(data_size + static_cast<ssize_t>(sizeof(kATxtContents)),
418 lseek64(fd, 0, SEEK_END));
Narayan Kamath00a258c2013-12-13 16:06:19 +0000419
420 close(fd);
421}
422
Narayan Kamath58aaf462013-12-10 16:47:14 +0000423int main(int argc, char** argv) {
424 ::testing::InitGoogleTest(&argc, argv);
425
426 static struct option options[] = {
427 { "test_data_dir", required_argument, NULL, 't' },
428 { NULL, 0, NULL, 0 }
429 };
430
431 while (true) {
432 int option_index;
433 const int c = getopt_long_only(argc, argv, "", options, &option_index);
434 if (c == -1) {
435 break;
436 }
437
438 if (c == 't') {
439 test_data_dir = optarg;
440 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000441 }
442
Narayan Kamath58aaf462013-12-10 16:47:14 +0000443 if (test_data_dir.size() == 0) {
444 printf("Test data flag (--test_data_dir) required\n\n");
445 return -1;
446 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000447
Narayan Kamath58aaf462013-12-10 16:47:14 +0000448 if (test_data_dir[0] != '/') {
449 printf("Test data must be an absolute path, was %s\n\n",
450 test_data_dir.c_str());
451 return -2;
452 }
Narayan Kamath7462f022013-11-21 13:05:04 +0000453
Narayan Kamath58aaf462013-12-10 16:47:14 +0000454 return RUN_ALL_TESTS();
Narayan Kamath7462f022013-11-21 13:05:04 +0000455}