blob: 036b729631f1ecfe88327d7d7a9ae29d8f8a72bd [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
adlr@google.comc98a7ed2009-12-04 18:54:03 +000017#include "update_engine/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
rspangler@google.com49fdf182009-10-10 00:57:34 +000038#include "update_engine/file_writer.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000039#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000040
Alex Deymo161c4a12014-05-16 15:56:21 -070041using base::StringPrintf;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000042using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000043using std::string;
44using std::vector;
45
46namespace chromeos_update_engine {
47
Alex Deymo52490e72015-06-04 14:53:44 +020048void PrintTo(const Extent& extent, ::std::ostream* os) {
49 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
50}
51
Alex Deymo10875d92014-11-10 21:52:57 -080052namespace test_utils {
53
Gilad Arnolda6742b32014-01-11 00:18:34 -080054const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
Gilad Arnold61d9d2c2013-07-22 17:54:52 -070055
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080056const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080057 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
58 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
59 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
60 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
61 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
62 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
63 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
64 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
65 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
66 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
67 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
68 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
69 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
70 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
71 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
72 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
73 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
74 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
75 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
76 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
77 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
78 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
79 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
80 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
81 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
82 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
83 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
84 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
85 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
86 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
87 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
88 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
89 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
90 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
91 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
92 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
93 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
94 0xbe, 0x9f, 0xa3, 0x5d,
95};
96
97bool IsXAttrSupported(const base::FilePath& dir_path) {
98 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
99
100 int fd = mkstemp(path);
101 if (fd == -1) {
102 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
103 free(path);
104 return false;
105 }
106
107 if (unlink(path) != 0) {
108 PLOG(ERROR) << "Error unlinking temporary file " << path;
109 close(fd);
110 free(path);
111 return false;
112 }
113
114 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
115 if (xattr_res != 0) {
116 if (errno == ENOTSUP) {
117 // Leave it to call-sites to warn about non-support.
118 } else {
119 PLOG(ERROR) << "Error setting xattr on " << path;
120 }
121 }
122 close(fd);
123 free(path);
124 return xattr_res == 0;
125}
126
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700127bool WriteFileVector(const string& path, const brillo::Blob& data) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800128 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000129}
130
Alex Deymof329b932014-10-30 01:37:48 -0700131bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800132 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000133}
134
Gilad Arnold19a45f02012-07-19 12:36:10 -0700135// Binds provided |filename| to an unused loopback device, whose name is written
136// to the string pointed to by |lo_dev_name_p|. Returns true on success, false
137// otherwise (along with corresponding test failures), in which case the content
138// of |lo_dev_name_p| is unknown.
139bool BindToUnusedLoopDevice(const string& filename, string* lo_dev_name_p) {
140 CHECK(lo_dev_name_p);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800141
Gilad Arnold19a45f02012-07-19 12:36:10 -0700142 // Bind to an unused loopback device, sanity check the device name.
143 lo_dev_name_p->clear();
144 if (!(utils::ReadPipe("losetup --show -f " + filename, lo_dev_name_p) &&
Alex Vakulenko6a9d3492015-06-15 12:53:22 -0700145 base::StartsWithASCII(*lo_dev_name_p, "/dev/loop", true))) {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700146 ADD_FAILURE();
147 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000148 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000149
Gilad Arnold19a45f02012-07-19 12:36:10 -0700150 // Strip anything from the first newline char.
151 size_t newline_pos = lo_dev_name_p->find('\n');
152 if (newline_pos != string::npos)
153 lo_dev_name_p->erase(newline_pos);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000154
Gilad Arnold19a45f02012-07-19 12:36:10 -0700155 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000156}
157
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700158bool ExpectVectorsEq(const brillo::Blob& expected,
159 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800160 EXPECT_EQ(expected.size(), actual.size());
161 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000162 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700163 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800164 for (unsigned int i = 0; i < expected.size(); i++) {
165 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700166 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000167 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700168 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000169}
170
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700171void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800172 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800173 for (uint8_t& b : *buffer) {
174 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800175 input_counter++;
176 input_counter %= sizeof(kRandomString);
177 }
178}
179
Thieu Le5c7d9752010-12-15 16:09:28 -0800180void CreateEmptyExtImageAtPath(const string& path,
181 size_t size,
182 int block_size) {
183 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymoc00c98a2015-03-17 17:38:00 -0700184 " seek=%" PRIuS " bs=1 count=1 status=none",
Thieu Le5c7d9752010-12-15 16:09:28 -0800185 path.c_str(), size)));
Alex Deymo6ded6542015-03-13 15:52:46 -0700186 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
Thieu Le5c7d9752010-12-15 16:09:28 -0800187 block_size, path.c_str())));
188}
189
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000190void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700191 // create 10MiB sparse file, mounted at a unique location.
192 string mount_path;
193 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700194 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700195
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000196 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700197 " seek=10485759 bs=1 count=1 status=none",
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000198 path.c_str())));
Alex Deymo6ded6542015-03-13 15:52:46 -0700199 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
200 path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000201 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700202 mount_path.c_str())));
203 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
204 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
205 mount_path.c_str())));
206 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
207 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
208 mount_path.c_str())));
209 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
210 mount_path.c_str())));
211 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
212 mount_path.c_str())));
213 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
214 mount_path.c_str())));
215 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
216 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
217 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000218 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700219 mount_path.c_str(), mount_path.c_str())));
220 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
221 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800222 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700223 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800224 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700225 mount_path.c_str())));
226 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800227
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000228 if (out_paths) {
229 out_paths->clear();
230 out_paths->push_back("");
231 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800232 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000233 out_paths->push_back("/hello");
234 out_paths->push_back("/some_dir");
235 out_paths->push_back("/some_dir/empty_dir");
236 out_paths->push_back("/some_dir/mnt");
237 out_paths->push_back("/some_dir/test");
238 out_paths->push_back("/some_dir/fifo");
239 out_paths->push_back("/cdev");
240 out_paths->push_back("/testlink");
241 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800242 out_paths->push_back("/srchardlink0");
243 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000244 out_paths->push_back("/lost+found");
245 }
246}
247
Don Garrett58e8b1f2012-01-31 16:38:16 -0800248ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
249 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700250 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800251 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800252 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
253
Don Garrett58e8b1f2012-01-31 16:38:16 -0800254 string loop_dev;
255 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800256
257 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
258 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
Alex Deymo10875d92014-11-10 21:52:57 -0800267} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000268} // namespace chromeos_update_engine