blob: 4ab16634f6a451e79e7928b311fa7420b8597a7e [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2012 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//
rspangler@google.com49fdf182009-10-10 00:57:34 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/common/test_utils.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070018
Alex Deymo6b9e38e2015-06-05 00:26:37 +020019#include <dirent.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000020#include <errno.h>
Alex Deymocbc22742016-03-04 17:53:02 -080021#include <fcntl.h>
22#include <linux/loop.h>
23#include <linux/major.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000024#include <stdio.h>
25#include <stdlib.h>
Alex Deymocbc22742016-03-04 17:53:02 -080026#include <sys/ioctl.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070027#include <sys/stat.h>
28#include <sys/types.h>
Alex Deymo6f20dd42015-08-18 16:42:46 -070029#include <sys/xattr.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000030#include <unistd.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070031
adlr@google.comc98a7ed2009-12-04 18:54:03 +000032#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000033#include <string>
34#include <vector>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070035
Alex Deymo2b19cfb2015-03-26 00:35:07 -070036#include <base/files/file_util.h>
Alex Deymoc00c98a2015-03-17 17:38:00 -070037#include <base/format_macros.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070038#include <base/logging.h>
Alex Deymo2b19cfb2015-03-26 00:35:07 -070039#include <base/strings/string_util.h>
Alex Deymo30534502015-07-20 15:06:33 -070040#include <base/strings/stringprintf.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070041
Alex Deymo64d98782016-02-05 18:03:48 -080042#include "update_engine/common/error_code_utils.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080043#include "update_engine/common/utils.h"
44#include "update_engine/payload_consumer/file_writer.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000045
Alex Deymo161c4a12014-05-16 15:56:21 -070046using base::StringPrintf;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000047using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000048using std::string;
49using std::vector;
50
51namespace chromeos_update_engine {
52
Alex Deymo52490e72015-06-04 14:53:44 +020053void PrintTo(const Extent& extent, ::std::ostream* os) {
54 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
55}
56
Alex Deymo64d98782016-02-05 18:03:48 -080057void PrintTo(const ErrorCode& error_code, ::std::ostream* os) {
58 *os << utils::ErrorCodeToString(error_code);
59}
60
Alex Deymo10875d92014-11-10 21:52:57 -080061namespace test_utils {
62
Gilad Arnolda6742b32014-01-11 00:18:34 -080063const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
Gilad Arnold61d9d2c2013-07-22 17:54:52 -070064
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080065const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080066 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
67 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
68 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
69 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
70 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
71 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
72 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
73 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
74 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
75 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
76 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
77 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
78 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
79 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
80 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
81 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
82 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
83 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
84 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
85 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
86 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
87 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
88 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
89 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
90 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
91 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
92 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
93 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
94 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
95 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
96 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
97 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
98 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
99 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
100 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
101 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
102 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
103 0xbe, 0x9f, 0xa3, 0x5d,
104};
105
Alex Deymod15c5462016-03-09 18:11:12 -0800106string Readlink(const string& path) {
107 vector<char> buf(PATH_MAX + 1);
108 ssize_t r = readlink(path.c_str(), buf.data(), buf.size());
109 if (r < 0)
110 return "";
111 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
112 return string(buf.begin(), buf.begin() + r);
113}
114
Alex Deymo10875d92014-11-10 21:52:57 -0800115bool IsXAttrSupported(const base::FilePath& dir_path) {
116 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
117
118 int fd = mkstemp(path);
119 if (fd == -1) {
120 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
121 free(path);
122 return false;
123 }
124
125 if (unlink(path) != 0) {
126 PLOG(ERROR) << "Error unlinking temporary file " << path;
127 close(fd);
128 free(path);
129 return false;
130 }
131
132 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
133 if (xattr_res != 0) {
134 if (errno == ENOTSUP) {
135 // Leave it to call-sites to warn about non-support.
136 } else {
137 PLOG(ERROR) << "Error setting xattr on " << path;
138 }
139 }
140 close(fd);
141 free(path);
142 return xattr_res == 0;
143}
144
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700145bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800146 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000147}
148
Alex Deymof329b932014-10-30 01:37:48 -0700149bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800150 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000151}
152
Alex Deymocbc22742016-03-04 17:53:02 -0800153bool BindToUnusedLoopDevice(const string& filename,
154 bool writable,
155 string* out_lo_dev_name) {
156 CHECK(out_lo_dev_name);
157 // Get the next available loop-device.
158 int control_fd =
159 HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
160 TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
161 int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
162 IGNORE_EINTR(close(control_fd));
163 *out_lo_dev_name = StringPrintf("/dev/loop%d", loop_number);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800164
Alex Deymocbc22742016-03-04 17:53:02 -0800165 // Double check that the loop exists and is free.
166 int loop_device_fd =
167 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
168 if (loop_device_fd == -1 && errno == ENOENT) {
169 // Workaround the case when the loop device doesn't exist.
170 TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
171 S_IFBLK | 0660,
172 makedev(LOOP_MAJOR, loop_number)) == 0);
173 loop_device_fd =
174 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
175 }
176 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
177 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
178
179 struct loop_info64 device_info;
180 if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
181 errno != ENXIO) {
182 PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
183 << " already in use";
Gilad Arnold19a45f02012-07-19 12:36:10 -0700184 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000185 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000186
Alex Deymocbc22742016-03-04 17:53:02 -0800187 // Open our data file and assign it to the loop device.
188 int data_fd = open(filename.c_str(),
189 (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
190 TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
191 ScopedFdCloser data_fd_closer(&data_fd);
192 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000193
Alex Deymocbc22742016-03-04 17:53:02 -0800194 memset(&device_info, 0, sizeof(device_info));
195 device_info.lo_offset = 0;
196 device_info.lo_sizelimit = 0; // 0 means whole file.
197 device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
198 device_info.lo_number = loop_number;
199 strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
200 base::FilePath(filename).BaseName().value().c_str(),
201 LO_NAME_SIZE - 1);
202 device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
203 TEST_AND_RETURN_FALSE_ERRNO(
204 ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
205 return true;
206}
207
208bool UnbindLoopDevice(const string& lo_dev_name) {
209 int loop_device_fd =
210 HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
211 if (loop_device_fd == -1 && errno == ENOENT)
212 return true;
213 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
214 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
215
216 struct loop_info64 device_info;
217 // Check if the device is bound before trying to unbind it.
218 int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
219 if (get_stat_err == -1 && errno == ENXIO)
220 return true;
221
222 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
Gilad Arnold19a45f02012-07-19 12:36:10 -0700223 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000224}
225
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700226bool ExpectVectorsEq(const brillo::Blob& expected,
227 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800228 EXPECT_EQ(expected.size(), actual.size());
229 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000230 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700231 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800232 for (unsigned int i = 0; i < expected.size(); i++) {
233 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700234 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000235 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700236 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000237}
238
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700239void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800240 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800241 for (uint8_t& b : *buffer) {
242 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800243 input_counter++;
244 input_counter %= sizeof(kRandomString);
245 }
246}
247
Thieu Le5c7d9752010-12-15 16:09:28 -0800248void CreateEmptyExtImageAtPath(const string& path,
249 size_t size,
250 int block_size) {
251 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymoc00c98a2015-03-17 17:38:00 -0700252 " seek=%" PRIuS " bs=1 count=1 status=none",
Thieu Le5c7d9752010-12-15 16:09:28 -0800253 path.c_str(), size)));
Alex Deymo6ded6542015-03-13 15:52:46 -0700254 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
Thieu Le5c7d9752010-12-15 16:09:28 -0800255 block_size, path.c_str())));
256}
257
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000258void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700259 // create 10MiB sparse file, mounted at a unique location.
260 string mount_path;
261 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700262 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700263
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000264 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700265 " seek=10485759 bs=1 count=1 status=none",
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000266 path.c_str())));
Alex Deymo6ded6542015-03-13 15:52:46 -0700267 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
268 path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000269 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700270 mount_path.c_str())));
271 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
272 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
273 mount_path.c_str())));
274 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
275 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
276 mount_path.c_str())));
277 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
278 mount_path.c_str())));
279 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
280 mount_path.c_str())));
281 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
282 mount_path.c_str())));
283 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
284 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
285 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000286 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700287 mount_path.c_str(), mount_path.c_str())));
288 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
289 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800290 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700291 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800292 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700293 mount_path.c_str())));
294 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800295
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000296 if (out_paths) {
297 out_paths->clear();
298 out_paths->push_back("");
299 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800300 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000301 out_paths->push_back("/hello");
302 out_paths->push_back("/some_dir");
303 out_paths->push_back("/some_dir/empty_dir");
304 out_paths->push_back("/some_dir/mnt");
305 out_paths->push_back("/some_dir/test");
306 out_paths->push_back("/some_dir/fifo");
307 out_paths->push_back("/cdev");
308 out_paths->push_back("/testlink");
309 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800310 out_paths->push_back("/srchardlink0");
311 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000312 out_paths->push_back("/lost+found");
313 }
314}
315
Don Garrett58e8b1f2012-01-31 16:38:16 -0800316ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
317 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700318 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800319 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800320 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
321
Don Garrett58e8b1f2012-01-31 16:38:16 -0800322 string loop_dev;
Alex Deymocbc22742016-03-04 17:53:02 -0800323 loop_binder_.reset(
324 new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800325
Sen Jiang2c413572016-03-07 12:55:09 -0800326 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", ""));
Thieu Le5c7d9752010-12-15 16:09:28 -0800327 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
328}
329
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700330base::FilePath GetBuildArtifactsPath() {
331 base::FilePath exe_path;
332 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
333 return exe_path.DirName();
334}
335
Alex Deymo10875d92014-11-10 21:52:57 -0800336} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000337} // namespace chromeos_update_engine