blob: c09096bbad1372c1c33b2715be5ecd2c96191990 [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>
rspangler@google.com49fdf182009-10-10 00:57:34 +000021#include <stdio.h>
22#include <stdlib.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070023#include <sys/stat.h>
24#include <sys/types.h>
Alex Deymo6f20dd42015-08-18 16:42:46 -070025#include <sys/xattr.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000026#include <unistd.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070027
adlr@google.comc98a7ed2009-12-04 18:54:03 +000028#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000029#include <string>
30#include <vector>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070031
Alex Deymo2b19cfb2015-03-26 00:35:07 -070032#include <base/files/file_util.h>
Alex Deymoc00c98a2015-03-17 17:38:00 -070033#include <base/format_macros.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070034#include <base/logging.h>
Alex Deymo2b19cfb2015-03-26 00:35:07 -070035#include <base/strings/string_util.h>
Alex Deymo30534502015-07-20 15:06:33 -070036#include <base/strings/stringprintf.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070037
Alex Deymo64d98782016-02-05 18:03:48 -080038#include "update_engine/common/error_code_utils.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080039#include "update_engine/common/utils.h"
40#include "update_engine/payload_consumer/file_writer.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000041
Alex Deymo161c4a12014-05-16 15:56:21 -070042using base::StringPrintf;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000043using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000044using std::string;
45using std::vector;
46
47namespace chromeos_update_engine {
48
Alex Deymo52490e72015-06-04 14:53:44 +020049void PrintTo(const Extent& extent, ::std::ostream* os) {
50 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
51}
52
Alex Deymo64d98782016-02-05 18:03:48 -080053void PrintTo(const ErrorCode& error_code, ::std::ostream* os) {
54 *os << utils::ErrorCodeToString(error_code);
55}
56
Alex Deymo10875d92014-11-10 21:52:57 -080057namespace test_utils {
58
Gilad Arnolda6742b32014-01-11 00:18:34 -080059const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
Gilad Arnold61d9d2c2013-07-22 17:54:52 -070060
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080061const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080062 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
63 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
64 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
65 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
66 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
67 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
68 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
69 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
70 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
71 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
72 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
73 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
74 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
75 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
76 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
77 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
78 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
79 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
80 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
81 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
82 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
83 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
84 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
85 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
86 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
87 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
88 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
89 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
90 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
91 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
92 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
93 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
94 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
95 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
96 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
97 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
98 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
99 0xbe, 0x9f, 0xa3, 0x5d,
100};
101
102bool IsXAttrSupported(const base::FilePath& dir_path) {
103 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
104
105 int fd = mkstemp(path);
106 if (fd == -1) {
107 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
108 free(path);
109 return false;
110 }
111
112 if (unlink(path) != 0) {
113 PLOG(ERROR) << "Error unlinking temporary file " << path;
114 close(fd);
115 free(path);
116 return false;
117 }
118
119 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
120 if (xattr_res != 0) {
121 if (errno == ENOTSUP) {
122 // Leave it to call-sites to warn about non-support.
123 } else {
124 PLOG(ERROR) << "Error setting xattr on " << path;
125 }
126 }
127 close(fd);
128 free(path);
129 return xattr_res == 0;
130}
131
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700132bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800133 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000134}
135
Alex Deymof329b932014-10-30 01:37:48 -0700136bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800137 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000138}
139
Gilad Arnold19a45f02012-07-19 12:36:10 -0700140// Binds provided |filename| to an unused loopback device, whose name is written
141// to the string pointed to by |lo_dev_name_p|. Returns true on success, false
142// otherwise (along with corresponding test failures), in which case the content
143// of |lo_dev_name_p| is unknown.
144bool BindToUnusedLoopDevice(const string& filename, string* lo_dev_name_p) {
145 CHECK(lo_dev_name_p);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800146
Gilad Arnold19a45f02012-07-19 12:36:10 -0700147 // Bind to an unused loopback device, sanity check the device name.
148 lo_dev_name_p->clear();
149 if (!(utils::ReadPipe("losetup --show -f " + filename, lo_dev_name_p) &&
Alex Vakulenko0103c362016-01-20 07:56:15 -0800150 base::StartsWith(*lo_dev_name_p, "/dev/loop",
151 base::CompareCase::SENSITIVE))) {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700152 ADD_FAILURE();
153 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000154 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000155
Gilad Arnold19a45f02012-07-19 12:36:10 -0700156 // Strip anything from the first newline char.
157 size_t newline_pos = lo_dev_name_p->find('\n');
158 if (newline_pos != string::npos)
159 lo_dev_name_p->erase(newline_pos);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000160
Gilad Arnold19a45f02012-07-19 12:36:10 -0700161 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000162}
163
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700164bool ExpectVectorsEq(const brillo::Blob& expected,
165 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800166 EXPECT_EQ(expected.size(), actual.size());
167 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000168 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700169 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800170 for (unsigned int i = 0; i < expected.size(); i++) {
171 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700172 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000173 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700174 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000175}
176
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700177void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800178 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800179 for (uint8_t& b : *buffer) {
180 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800181 input_counter++;
182 input_counter %= sizeof(kRandomString);
183 }
184}
185
Thieu Le5c7d9752010-12-15 16:09:28 -0800186void CreateEmptyExtImageAtPath(const string& path,
187 size_t size,
188 int block_size) {
189 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymoc00c98a2015-03-17 17:38:00 -0700190 " seek=%" PRIuS " bs=1 count=1 status=none",
Thieu Le5c7d9752010-12-15 16:09:28 -0800191 path.c_str(), size)));
Alex Deymo6ded6542015-03-13 15:52:46 -0700192 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
Thieu Le5c7d9752010-12-15 16:09:28 -0800193 block_size, path.c_str())));
194}
195
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000196void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700197 // create 10MiB sparse file, mounted at a unique location.
198 string mount_path;
199 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700200 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700201
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000202 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700203 " seek=10485759 bs=1 count=1 status=none",
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000204 path.c_str())));
Alex Deymo6ded6542015-03-13 15:52:46 -0700205 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
206 path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000207 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700208 mount_path.c_str())));
209 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
210 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
211 mount_path.c_str())));
212 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
213 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
214 mount_path.c_str())));
215 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
216 mount_path.c_str())));
217 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
218 mount_path.c_str())));
219 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
220 mount_path.c_str())));
221 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
222 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
223 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000224 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700225 mount_path.c_str(), mount_path.c_str())));
226 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
227 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800228 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700229 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800230 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700231 mount_path.c_str())));
232 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800233
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000234 if (out_paths) {
235 out_paths->clear();
236 out_paths->push_back("");
237 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800238 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000239 out_paths->push_back("/hello");
240 out_paths->push_back("/some_dir");
241 out_paths->push_back("/some_dir/empty_dir");
242 out_paths->push_back("/some_dir/mnt");
243 out_paths->push_back("/some_dir/test");
244 out_paths->push_back("/some_dir/fifo");
245 out_paths->push_back("/cdev");
246 out_paths->push_back("/testlink");
247 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800248 out_paths->push_back("/srchardlink0");
249 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000250 out_paths->push_back("/lost+found");
251 }
252}
253
Don Garrett58e8b1f2012-01-31 16:38:16 -0800254ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
255 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700256 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800257 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800258 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
259
Don Garrett58e8b1f2012-01-31 16:38:16 -0800260 string loop_dev;
261 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800262
263 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
264 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
265}
266
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700267base::FilePath GetBuildArtifactsPath() {
268 base::FilePath exe_path;
269 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
270 return exe_path.DirName();
271}
272
Alex Deymo10875d92014-11-10 21:52:57 -0800273} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000274} // namespace chromeos_update_engine