blob: 13ce6f9d94ecb276a673dd963154d19d1075b72e [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
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080063const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080064 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
65 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
66 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
67 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
68 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
69 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
70 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
71 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
72 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
73 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
74 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
75 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
76 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
77 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
78 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
79 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
80 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
81 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
82 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
83 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
84 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
85 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
86 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
87 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
88 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
89 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
90 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
91 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
92 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
93 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
94 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
95 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
96 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
97 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
98 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
99 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
100 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
101 0xbe, 0x9f, 0xa3, 0x5d,
102};
103
Alex Deymod15c5462016-03-09 18:11:12 -0800104string Readlink(const string& path) {
105 vector<char> buf(PATH_MAX + 1);
106 ssize_t r = readlink(path.c_str(), buf.data(), buf.size());
107 if (r < 0)
108 return "";
109 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
110 return string(buf.begin(), buf.begin() + r);
111}
112
Alex Deymo10875d92014-11-10 21:52:57 -0800113bool IsXAttrSupported(const base::FilePath& dir_path) {
114 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
115
116 int fd = mkstemp(path);
117 if (fd == -1) {
118 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
119 free(path);
120 return false;
121 }
122
123 if (unlink(path) != 0) {
124 PLOG(ERROR) << "Error unlinking temporary file " << path;
125 close(fd);
126 free(path);
127 return false;
128 }
129
130 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
131 if (xattr_res != 0) {
132 if (errno == ENOTSUP) {
133 // Leave it to call-sites to warn about non-support.
134 } else {
135 PLOG(ERROR) << "Error setting xattr on " << path;
136 }
137 }
138 close(fd);
139 free(path);
140 return xattr_res == 0;
141}
142
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700143bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800144 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000145}
146
Alex Deymof329b932014-10-30 01:37:48 -0700147bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800148 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000149}
150
Alex Deymocbc22742016-03-04 17:53:02 -0800151bool BindToUnusedLoopDevice(const string& filename,
152 bool writable,
153 string* out_lo_dev_name) {
154 CHECK(out_lo_dev_name);
155 // Get the next available loop-device.
156 int control_fd =
157 HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
158 TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
159 int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
160 IGNORE_EINTR(close(control_fd));
161 *out_lo_dev_name = StringPrintf("/dev/loop%d", loop_number);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800162
Alex Deymocbc22742016-03-04 17:53:02 -0800163 // Double check that the loop exists and is free.
164 int loop_device_fd =
165 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
166 if (loop_device_fd == -1 && errno == ENOENT) {
167 // Workaround the case when the loop device doesn't exist.
168 TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
169 S_IFBLK | 0660,
170 makedev(LOOP_MAJOR, loop_number)) == 0);
171 loop_device_fd =
172 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
173 }
174 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
175 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
176
177 struct loop_info64 device_info;
178 if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
179 errno != ENXIO) {
180 PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
181 << " already in use";
Gilad Arnold19a45f02012-07-19 12:36:10 -0700182 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000183 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000184
Alex Deymocbc22742016-03-04 17:53:02 -0800185 // Open our data file and assign it to the loop device.
186 int data_fd = open(filename.c_str(),
187 (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
188 TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
189 ScopedFdCloser data_fd_closer(&data_fd);
190 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000191
Alex Deymocbc22742016-03-04 17:53:02 -0800192 memset(&device_info, 0, sizeof(device_info));
193 device_info.lo_offset = 0;
194 device_info.lo_sizelimit = 0; // 0 means whole file.
195 device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
196 device_info.lo_number = loop_number;
197 strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
198 base::FilePath(filename).BaseName().value().c_str(),
199 LO_NAME_SIZE - 1);
200 device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
201 TEST_AND_RETURN_FALSE_ERRNO(
202 ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
203 return true;
204}
205
206bool UnbindLoopDevice(const string& lo_dev_name) {
207 int loop_device_fd =
208 HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
209 if (loop_device_fd == -1 && errno == ENOENT)
210 return true;
211 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
212 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
213
214 struct loop_info64 device_info;
215 // Check if the device is bound before trying to unbind it.
216 int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
217 if (get_stat_err == -1 && errno == ENXIO)
218 return true;
219
220 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
Gilad Arnold19a45f02012-07-19 12:36:10 -0700221 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000222}
223
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700224bool ExpectVectorsEq(const brillo::Blob& expected,
225 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800226 EXPECT_EQ(expected.size(), actual.size());
227 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000228 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700229 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800230 for (unsigned int i = 0; i < expected.size(); i++) {
231 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700232 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000233 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700234 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000235}
236
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700237void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800238 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800239 for (uint8_t& b : *buffer) {
240 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800241 input_counter++;
242 input_counter %= sizeof(kRandomString);
243 }
244}
245
Don Garrett58e8b1f2012-01-31 16:38:16 -0800246ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
247 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700248 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800249 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800250 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
251
Don Garrett58e8b1f2012-01-31 16:38:16 -0800252 string loop_dev;
Alex Deymocbc22742016-03-04 17:53:02 -0800253 loop_binder_.reset(
254 new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800255
Sen Jiang2c413572016-03-07 12:55:09 -0800256 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", ""));
Thieu Le5c7d9752010-12-15 16:09:28 -0800257 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
258}
259
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700260base::FilePath GetBuildArtifactsPath() {
261 base::FilePath exe_path;
262 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
263 return exe_path.DirName();
264}
265
Sen Jiang260f03b2016-03-21 15:34:58 -0700266string GetBuildArtifactsPath(const string& relative_path) {
267 return GetBuildArtifactsPath().Append(relative_path).value();
268}
269
Alex Deymo10875d92014-11-10 21:52:57 -0800270} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000271} // namespace chromeos_update_engine