blob: 14e5416905d246e8a36b35c03d41fb39bcf4d49a [file] [log] [blame]
Tom Marshall981118e2017-10-25 20:27:08 +02001/*
2 * Copyright 2016 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 <errno.h>
18#include <sys/stat.h>
19#include <unistd.h>
20
21#include <string>
22
23#include <android-base/file.h>
24#include <android-base/test_utils.h>
25#include <gtest/gtest.h>
26#include <otautil/ZipUtil.h>
27#include <ziparchive/zip_archive.h>
28
29#include "common/test_constants.h"
30
31TEST(ZipUtilTest, invalid_args) {
32 std::string zip_path = from_testdata_base("ziptest_valid.zip");
33 ZipArchiveHandle handle;
34 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
35
36 // zip_path must be a relative path.
37 ASSERT_FALSE(ExtractPackageRecursive(handle, "/a/b", "/tmp", nullptr, nullptr));
38
39 // dest_path must be an absolute path.
40 ASSERT_FALSE(ExtractPackageRecursive(handle, "a/b", "tmp", nullptr, nullptr));
41 ASSERT_FALSE(ExtractPackageRecursive(handle, "a/b", "", nullptr, nullptr));
42
43 CloseArchive(handle);
44}
45
46TEST(ZipUtilTest, extract_all) {
47 std::string zip_path = from_testdata_base("ziptest_valid.zip");
48 ZipArchiveHandle handle;
49 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
50
51 // Extract the whole package into a temp directory.
52 TemporaryDir td;
53 ExtractPackageRecursive(handle, "", td.path, nullptr, nullptr);
54
55 // Make sure all the files are extracted correctly.
56 std::string path(td.path);
57 ASSERT_EQ(0, access((path + "/a.txt").c_str(), F_OK));
58 ASSERT_EQ(0, access((path + "/b.txt").c_str(), F_OK));
59 ASSERT_EQ(0, access((path + "/b/c.txt").c_str(), F_OK));
60 ASSERT_EQ(0, access((path + "/b/d.txt").c_str(), F_OK));
61
62 // The content of the file is the same as expected.
63 std::string content1;
64 ASSERT_TRUE(android::base::ReadFileToString(path + "/a.txt", &content1));
65 ASSERT_EQ(kATxtContents, content1);
66
67 std::string content2;
68 ASSERT_TRUE(android::base::ReadFileToString(path + "/b/d.txt", &content2));
69 ASSERT_EQ(kDTxtContents, content2);
70
71 // Clean up the temp files under td.
72 ASSERT_EQ(0, unlink((path + "/a.txt").c_str()));
73 ASSERT_EQ(0, unlink((path + "/b.txt").c_str()));
74 ASSERT_EQ(0, unlink((path + "/b/c.txt").c_str()));
75 ASSERT_EQ(0, unlink((path + "/b/d.txt").c_str()));
76 ASSERT_EQ(0, rmdir((path + "/b").c_str()));
77
78 CloseArchive(handle);
79}
80
81TEST(ZipUtilTest, extract_prefix_with_slash) {
82 std::string zip_path = from_testdata_base("ziptest_valid.zip");
83 ZipArchiveHandle handle;
84 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
85
86 // Extract all the entries starting with "b/".
87 TemporaryDir td;
88 ExtractPackageRecursive(handle, "b/", td.path, nullptr, nullptr);
89
90 // Make sure all the files with "b/" prefix are extracted correctly.
91 std::string path(td.path);
92 ASSERT_EQ(0, access((path + "/c.txt").c_str(), F_OK));
93 ASSERT_EQ(0, access((path + "/d.txt").c_str(), F_OK));
94
95 // And the rest are not extracted.
96 ASSERT_EQ(-1, access((path + "/a.txt").c_str(), F_OK));
97 ASSERT_EQ(ENOENT, errno);
98 ASSERT_EQ(-1, access((path + "/b.txt").c_str(), F_OK));
99 ASSERT_EQ(ENOENT, errno);
100
101 // The content of the file is the same as expected.
102 std::string content1;
103 ASSERT_TRUE(android::base::ReadFileToString(path + "/c.txt", &content1));
104 ASSERT_EQ(kCTxtContents, content1);
105
106 std::string content2;
107 ASSERT_TRUE(android::base::ReadFileToString(path + "/d.txt", &content2));
108 ASSERT_EQ(kDTxtContents, content2);
109
110 // Clean up the temp files under td.
111 ASSERT_EQ(0, unlink((path + "/c.txt").c_str()));
112 ASSERT_EQ(0, unlink((path + "/d.txt").c_str()));
113
114 CloseArchive(handle);
115}
116
117TEST(ZipUtilTest, extract_prefix_without_slash) {
118 std::string zip_path = from_testdata_base("ziptest_valid.zip");
119 ZipArchiveHandle handle;
120 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
121
122 // Extract all the file entries starting with "b/".
123 TemporaryDir td;
124 ExtractPackageRecursive(handle, "b", td.path, nullptr, nullptr);
125
126 // Make sure all the files with "b/" prefix are extracted correctly.
127 std::string path(td.path);
128 ASSERT_EQ(0, access((path + "/c.txt").c_str(), F_OK));
129 ASSERT_EQ(0, access((path + "/d.txt").c_str(), F_OK));
130
131 // And the rest are not extracted.
132 ASSERT_EQ(-1, access((path + "/a.txt").c_str(), F_OK));
133 ASSERT_EQ(ENOENT, errno);
134 ASSERT_EQ(-1, access((path + "/b.txt").c_str(), F_OK));
135 ASSERT_EQ(ENOENT, errno);
136
137 // The content of the file is the same as expected.
138 std::string content1;
139 ASSERT_TRUE(android::base::ReadFileToString(path + "/c.txt", &content1));
140 ASSERT_EQ(kCTxtContents, content1);
141
142 std::string content2;
143 ASSERT_TRUE(android::base::ReadFileToString(path + "/d.txt", &content2));
144 ASSERT_EQ(kDTxtContents, content2);
145
146 // Clean up the temp files under td.
147 ASSERT_EQ(0, unlink((path + "/c.txt").c_str()));
148 ASSERT_EQ(0, unlink((path + "/d.txt").c_str()));
149
150 CloseArchive(handle);
151}
152
153TEST(ZipUtilTest, set_timestamp) {
154 std::string zip_path = from_testdata_base("ziptest_valid.zip");
155 ZipArchiveHandle handle;
156 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
157
158 // Set the timestamp to 8/1/2008.
159 constexpr struct utimbuf timestamp = { 1217592000, 1217592000 };
160
161 // Extract all the entries starting with "b/".
162 TemporaryDir td;
163 ExtractPackageRecursive(handle, "b", td.path, &timestamp, nullptr);
164
165 // Make sure all the files with "b/" prefix are extracted correctly.
166 std::string path(td.path);
167 std::string file_c = path + "/c.txt";
168 std::string file_d = path + "/d.txt";
169 ASSERT_EQ(0, access(file_c.c_str(), F_OK));
170 ASSERT_EQ(0, access(file_d.c_str(), F_OK));
171
172 // Verify the timestamp.
173 timespec time;
174 time.tv_sec = 1217592000;
175 time.tv_nsec = 0;
176
177 struct stat sb;
178 ASSERT_EQ(0, stat(file_c.c_str(), &sb)) << strerror(errno);
179 ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_atime));
180 ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_mtime));
181
182 ASSERT_EQ(0, stat(file_d.c_str(), &sb)) << strerror(errno);
183 ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_atime));
184 ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_mtime));
185
186 // Clean up the temp files under td.
187 ASSERT_EQ(0, unlink(file_c.c_str()));
188 ASSERT_EQ(0, unlink(file_d.c_str()));
189
190 CloseArchive(handle);
191}