blob: 4d1e20df078dfa5b1d38d1397876a7f9dffc2db8 [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 Deymo39910dc2015-11-09 17:04:30 -080038#include "update_engine/common/utils.h"
39#include "update_engine/payload_consumer/file_writer.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 Vakulenko0103c362016-01-20 07:56:15 -0800145 base::StartsWith(*lo_dev_name_p, "/dev/loop",
146 base::CompareCase::SENSITIVE))) {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700147 ADD_FAILURE();
148 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000149 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000150
Gilad Arnold19a45f02012-07-19 12:36:10 -0700151 // Strip anything from the first newline char.
152 size_t newline_pos = lo_dev_name_p->find('\n');
153 if (newline_pos != string::npos)
154 lo_dev_name_p->erase(newline_pos);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000155
Gilad Arnold19a45f02012-07-19 12:36:10 -0700156 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000157}
158
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700159bool ExpectVectorsEq(const brillo::Blob& expected,
160 const brillo::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800161 EXPECT_EQ(expected.size(), actual.size());
162 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000163 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700164 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800165 for (unsigned int i = 0; i < expected.size(); i++) {
166 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700167 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000168 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700169 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000170}
171
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700172void FillWithData(brillo::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800173 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800174 for (uint8_t& b : *buffer) {
175 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800176 input_counter++;
177 input_counter %= sizeof(kRandomString);
178 }
179}
180
Thieu Le5c7d9752010-12-15 16:09:28 -0800181void CreateEmptyExtImageAtPath(const string& path,
182 size_t size,
183 int block_size) {
184 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymoc00c98a2015-03-17 17:38:00 -0700185 " seek=%" PRIuS " bs=1 count=1 status=none",
Thieu Le5c7d9752010-12-15 16:09:28 -0800186 path.c_str(), size)));
Alex Deymo6ded6542015-03-13 15:52:46 -0700187 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
Thieu Le5c7d9752010-12-15 16:09:28 -0800188 block_size, path.c_str())));
189}
190
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000191void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700192 // create 10MiB sparse file, mounted at a unique location.
193 string mount_path;
194 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700195 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700196
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000197 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700198 " seek=10485759 bs=1 count=1 status=none",
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000199 path.c_str())));
Alex Deymo6ded6542015-03-13 15:52:46 -0700200 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
201 path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000202 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700203 mount_path.c_str())));
204 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
205 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
206 mount_path.c_str())));
207 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
208 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
209 mount_path.c_str())));
210 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
211 mount_path.c_str())));
212 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
213 mount_path.c_str())));
214 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
215 mount_path.c_str())));
216 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
217 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
218 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000219 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700220 mount_path.c_str(), mount_path.c_str())));
221 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
222 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800223 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700224 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800225 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700226 mount_path.c_str())));
227 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800228
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000229 if (out_paths) {
230 out_paths->clear();
231 out_paths->push_back("");
232 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800233 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000234 out_paths->push_back("/hello");
235 out_paths->push_back("/some_dir");
236 out_paths->push_back("/some_dir/empty_dir");
237 out_paths->push_back("/some_dir/mnt");
238 out_paths->push_back("/some_dir/test");
239 out_paths->push_back("/some_dir/fifo");
240 out_paths->push_back("/cdev");
241 out_paths->push_back("/testlink");
242 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800243 out_paths->push_back("/srchardlink0");
244 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000245 out_paths->push_back("/lost+found");
246 }
247}
248
Don Garrett58e8b1f2012-01-31 16:38:16 -0800249ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
250 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700251 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800252 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800253 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
254
Don Garrett58e8b1f2012-01-31 16:38:16 -0800255 string loop_dev;
256 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800257
258 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
259 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
260}
261
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700262base::FilePath GetBuildArtifactsPath() {
263 base::FilePath exe_path;
264 base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
265 return exe_path.DirName();
266}
267
Alex Deymo10875d92014-11-10 21:52:57 -0800268} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000269} // namespace chromeos_update_engine