blob: fb22c80dc52b7f8c977e3378d3a2512f218efc55 [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>
Elliott Hughesce7b5692017-05-18 16:44:49 -070028#include <sys/sysmacros.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070029#include <sys/types.h>
Alex Deymo6f20dd42015-08-18 16:42:46 -070030#include <sys/xattr.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000031#include <unistd.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070032
adlr@google.comc98a7ed2009-12-04 18:54:03 +000033#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000034#include <string>
35#include <vector>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070036
Alex Deymo2b19cfb2015-03-26 00:35:07 -070037#include <base/files/file_util.h>
Alex Deymoc00c98a2015-03-17 17:38:00 -070038#include <base/format_macros.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070039#include <base/logging.h>
Alex Deymo2b19cfb2015-03-26 00:35:07 -070040#include <base/strings/string_util.h>
Alex Deymo30534502015-07-20 15:06:33 -070041#include <base/strings/stringprintf.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070042
Alex Deymo64d98782016-02-05 18:03:48 -080043#include "update_engine/common/error_code_utils.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080044#include "update_engine/common/utils.h"
45#include "update_engine/payload_consumer/file_writer.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000046
Alex Deymo161c4a12014-05-16 15:56:21 -070047using base::StringPrintf;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000048using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000049using std::string;
50using std::vector;
51
52namespace chromeos_update_engine {
53
Alex Deymo52490e72015-06-04 14:53:44 +020054void PrintTo(const Extent& extent, ::std::ostream* os) {
55 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
56}
57
Alex Deymo64d98782016-02-05 18:03:48 -080058void PrintTo(const ErrorCode& error_code, ::std::ostream* os) {
59 *os << utils::ErrorCodeToString(error_code);
60}
61
Alex Deymo10875d92014-11-10 21:52:57 -080062namespace test_utils {
63
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080064const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080065 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
66 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
67 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
68 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
69 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
70 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
71 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
72 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
73 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
74 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
75 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
76 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
77 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
78 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
79 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
80 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
81 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
82 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
83 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
84 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
85 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
86 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
87 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
88 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
89 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
90 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
91 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
92 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
93 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
94 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
95 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
96 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
97 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
98 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
99 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
100 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
101 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
102 0xbe, 0x9f, 0xa3, 0x5d,
103};
104
Alex Deymod15c5462016-03-09 18:11:12 -0800105string Readlink(const string& path) {
106 vector<char> buf(PATH_MAX + 1);
107 ssize_t r = readlink(path.c_str(), buf.data(), buf.size());
108 if (r < 0)
109 return "";
110 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
111 return string(buf.begin(), buf.begin() + r);
112}
113
Alex Deymo10875d92014-11-10 21:52:57 -0800114bool IsXAttrSupported(const base::FilePath& dir_path) {
115 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
116
117 int fd = mkstemp(path);
118 if (fd == -1) {
119 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
120 free(path);
121 return false;
122 }
123
124 if (unlink(path) != 0) {
125 PLOG(ERROR) << "Error unlinking temporary file " << path;
126 close(fd);
127 free(path);
128 return false;
129 }
130
131 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
132 if (xattr_res != 0) {
133 if (errno == ENOTSUP) {
134 // Leave it to call-sites to warn about non-support.
135 } else {
136 PLOG(ERROR) << "Error setting xattr on " << path;
137 }
138 }
139 close(fd);
140 free(path);
141 return xattr_res == 0;
142}
143
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700144bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800145 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000146}
147
Alex Deymof329b932014-10-30 01:37:48 -0700148bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800149 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000150}
151
Alex Deymocbc22742016-03-04 17:53:02 -0800152bool BindToUnusedLoopDevice(const string& filename,
153 bool writable,
154 string* out_lo_dev_name) {
155 CHECK(out_lo_dev_name);
156 // Get the next available loop-device.
157 int control_fd =
158 HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
159 TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
160 int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
161 IGNORE_EINTR(close(control_fd));
162 *out_lo_dev_name = StringPrintf("/dev/loop%d", loop_number);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800163
Alex Deymocbc22742016-03-04 17:53:02 -0800164 // Double check that the loop exists and is free.
165 int loop_device_fd =
166 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
167 if (loop_device_fd == -1 && errno == ENOENT) {
168 // Workaround the case when the loop device doesn't exist.
169 TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
170 S_IFBLK | 0660,
171 makedev(LOOP_MAJOR, loop_number)) == 0);
172 loop_device_fd =
173 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
174 }
175 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
176 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
177
178 struct loop_info64 device_info;
179 if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
180 errno != ENXIO) {
181 PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
182 << " already in use";
Gilad Arnold19a45f02012-07-19 12:36:10 -0700183 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000184 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000185
Alex Deymocbc22742016-03-04 17:53:02 -0800186 // Open our data file and assign it to the loop device.
187 int data_fd = open(filename.c_str(),
188 (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
189 TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
190 ScopedFdCloser data_fd_closer(&data_fd);
191 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000192
Alex Deymocbc22742016-03-04 17:53:02 -0800193 memset(&device_info, 0, sizeof(device_info));
194 device_info.lo_offset = 0;
195 device_info.lo_sizelimit = 0; // 0 means whole file.
196 device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
197 device_info.lo_number = loop_number;
198 strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
199 base::FilePath(filename).BaseName().value().c_str(),
200 LO_NAME_SIZE - 1);
201 device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
202 TEST_AND_RETURN_FALSE_ERRNO(
203 ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
204 return true;
205}
206
207bool UnbindLoopDevice(const string& lo_dev_name) {
208 int loop_device_fd =
209 HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
210 if (loop_device_fd == -1 && errno == ENOENT)
211 return true;
212 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
213 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
214
215 struct loop_info64 device_info;
216 // Check if the device is bound before trying to unbind it.
217 int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
218 if (get_stat_err == -1 && errno == ENXIO)
219 return true;
220
221 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
Gilad Arnold19a45f02012-07-19 12:36:10 -0700222 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000223}
224
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700225bool ExpectVectorsEq(const brillo::Blob& expected,
226 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800227 EXPECT_EQ(expected.size(), actual.size());
228 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000229 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700230 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800231 for (unsigned int i = 0; i < expected.size(); i++) {
232 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700233 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000234 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700235 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000236}
237
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700238void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800239 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800240 for (uint8_t& b : *buffer) {
241 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800242 input_counter++;
243 input_counter %= sizeof(kRandomString);
244 }
245}
246
Don Garrett58e8b1f2012-01-31 16:38:16 -0800247ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
248 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700249 unsigned long flags) { // NOLINT - long
Sen Jiang371615b2016-04-13 15:54:29 -0700250 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
251 *mnt_path = temp_dir_.path().value();
Thieu Le5c7d9752010-12-15 16:09:28 -0800252
Don Garrett58e8b1f2012-01-31 16:38:16 -0800253 string loop_dev;
Alex Deymocbc22742016-03-04 17:53:02 -0800254 loop_binder_.reset(
255 new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800256
Sen Jiang2c413572016-03-07 12:55:09 -0800257 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", ""));
Thieu Le5c7d9752010-12-15 16:09:28 -0800258 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
259}
260
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700261base::FilePath GetBuildArtifactsPath() {
262 base::FilePath exe_path;
263 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
264 return exe_path.DirName();
265}
266
Sen Jiang260f03b2016-03-21 15:34:58 -0700267string GetBuildArtifactsPath(const string& relative_path) {
268 return GetBuildArtifactsPath().Append(relative_path).value();
269}
270
Alex Deymo10875d92014-11-10 21:52:57 -0800271} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000272} // namespace chromeos_update_engine