blob: 04f55d0704804e0d584e46eca591f7654b6c1138 [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>
Sen Jiangd37c81f2017-11-02 18:35:56 -070027#include <sys/mount.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070028#include <sys/stat.h>
Elliott Hughesce7b5692017-05-18 16:44:49 -070029#include <sys/sysmacros.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070030#include <sys/types.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 Vakulenko3f39d5c2015-10-13 09:27:13 -0700114bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800115 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000116}
117
Alex Deymof329b932014-10-30 01:37:48 -0700118bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800119 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000120}
121
Alex Deymocbc22742016-03-04 17:53:02 -0800122bool BindToUnusedLoopDevice(const string& filename,
123 bool writable,
124 string* out_lo_dev_name) {
125 CHECK(out_lo_dev_name);
126 // Get the next available loop-device.
127 int control_fd =
128 HANDLE_EINTR(open("/dev/loop-control", O_RDWR | O_LARGEFILE));
129 TEST_AND_RETURN_FALSE_ERRNO(control_fd >= 0);
130 int loop_number = ioctl(control_fd, LOOP_CTL_GET_FREE);
131 IGNORE_EINTR(close(control_fd));
132 *out_lo_dev_name = StringPrintf("/dev/loop%d", loop_number);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800133
Alex Deymocbc22742016-03-04 17:53:02 -0800134 // Double check that the loop exists and is free.
135 int loop_device_fd =
136 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
137 if (loop_device_fd == -1 && errno == ENOENT) {
138 // Workaround the case when the loop device doesn't exist.
139 TEST_AND_RETURN_FALSE_ERRNO(mknod(out_lo_dev_name->c_str(),
140 S_IFBLK | 0660,
141 makedev(LOOP_MAJOR, loop_number)) == 0);
142 loop_device_fd =
143 HANDLE_EINTR(open(out_lo_dev_name->c_str(), O_RDWR | O_LARGEFILE));
144 }
145 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
146 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
147
148 struct loop_info64 device_info;
149 if (ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info) != -1 ||
150 errno != ENXIO) {
151 PLOG(ERROR) << "Loop device " << out_lo_dev_name->c_str()
152 << " already in use";
Gilad Arnold19a45f02012-07-19 12:36:10 -0700153 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000154 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000155
Alex Deymocbc22742016-03-04 17:53:02 -0800156 // Open our data file and assign it to the loop device.
157 int data_fd = open(filename.c_str(),
158 (writable ? O_RDWR : O_RDONLY) | O_LARGEFILE | O_CLOEXEC);
159 TEST_AND_RETURN_FALSE_ERRNO(data_fd >= 0);
160 ScopedFdCloser data_fd_closer(&data_fd);
161 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_SET_FD, data_fd) == 0);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000162
Alex Deymocbc22742016-03-04 17:53:02 -0800163 memset(&device_info, 0, sizeof(device_info));
164 device_info.lo_offset = 0;
165 device_info.lo_sizelimit = 0; // 0 means whole file.
166 device_info.lo_flags = (writable ? 0 : LO_FLAGS_READ_ONLY);
167 device_info.lo_number = loop_number;
168 strncpy(reinterpret_cast<char*>(device_info.lo_file_name),
169 base::FilePath(filename).BaseName().value().c_str(),
170 LO_NAME_SIZE - 1);
171 device_info.lo_file_name[LO_NAME_SIZE - 1] = '\0';
172 TEST_AND_RETURN_FALSE_ERRNO(
173 ioctl(loop_device_fd, LOOP_SET_STATUS64, &device_info) == 0);
Sen Jiangd37c81f2017-11-02 18:35:56 -0700174 if (writable) {
175 // Make sure loop device isn't read only.
176 int ro = 0;
177 if (ioctl(loop_device_fd, BLKROSET, &ro) != 0) {
178 PLOG(WARNING) << "Failed to mark loop device writable.";
179 }
180 }
Alex Deymocbc22742016-03-04 17:53:02 -0800181 return true;
182}
183
184bool UnbindLoopDevice(const string& lo_dev_name) {
185 int loop_device_fd =
186 HANDLE_EINTR(open(lo_dev_name.c_str(), O_RDWR | O_LARGEFILE));
187 if (loop_device_fd == -1 && errno == ENOENT)
188 return true;
189 TEST_AND_RETURN_FALSE_ERRNO(loop_device_fd != -1);
190 ScopedFdCloser loop_device_fd_closer(&loop_device_fd);
191
192 struct loop_info64 device_info;
193 // Check if the device is bound before trying to unbind it.
194 int get_stat_err = ioctl(loop_device_fd, LOOP_GET_STATUS64, &device_info);
195 if (get_stat_err == -1 && errno == ENXIO)
196 return true;
197
198 TEST_AND_RETURN_FALSE_ERRNO(ioctl(loop_device_fd, LOOP_CLR_FD) == 0);
Gilad Arnold19a45f02012-07-19 12:36:10 -0700199 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000200}
201
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700202bool ExpectVectorsEq(const brillo::Blob& expected,
203 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800204 EXPECT_EQ(expected.size(), actual.size());
205 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000206 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700207 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800208 for (unsigned int i = 0; i < expected.size(); i++) {
209 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700210 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000211 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700212 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000213}
214
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700215void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800216 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800217 for (uint8_t& b : *buffer) {
218 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800219 input_counter++;
220 input_counter %= sizeof(kRandomString);
221 }
222}
223
Don Garrett58e8b1f2012-01-31 16:38:16 -0800224ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
225 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700226 unsigned long flags) { // NOLINT - long
Sen Jiang371615b2016-04-13 15:54:29 -0700227 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
Hidehiko Abe2b9d2412017-12-13 18:56:18 +0900228 *mnt_path = temp_dir_.GetPath().value();
Thieu Le5c7d9752010-12-15 16:09:28 -0800229
Don Garrett58e8b1f2012-01-31 16:38:16 -0800230 string loop_dev;
Alex Deymocbc22742016-03-04 17:53:02 -0800231 loop_binder_.reset(
232 new ScopedLoopbackDeviceBinder(file_path, true, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800233
Sen Jiang2c413572016-03-07 12:55:09 -0800234 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags, "", ""));
Thieu Le5c7d9752010-12-15 16:09:28 -0800235 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
236}
237
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700238base::FilePath GetBuildArtifactsPath() {
239 base::FilePath exe_path;
240 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
241 return exe_path.DirName();
242}
243
Sen Jiang260f03b2016-03-21 15:34:58 -0700244string GetBuildArtifactsPath(const string& relative_path) {
245 return GetBuildArtifactsPath().Append(relative_path).value();
246}
247
Alex Deymo10875d92014-11-10 21:52:57 -0800248} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000249} // namespace chromeos_update_engine