blob: 7e77519a6b45471f0af7b676d00fb54c7ef10025 [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
rspangler@google.com49fdf182009-10-10 00:57:34 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
adlr@google.comc98a7ed2009-12-04 18:54:03 +00005#include "update_engine/test_utils.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07006
rspangler@google.com49fdf182009-10-10 00:57:34 +00007#include <sys/stat.h>
8#include <sys/types.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +00009#include <errno.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000010#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070013
adlr@google.comc98a7ed2009-12-04 18:54:03 +000014#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000015#include <string>
16#include <vector>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070017
adlr@google.comc98a7ed2009-12-04 18:54:03 +000018#include "base/string_util.h"
Mike Frysinger8155d082012-04-06 15:23:18 -040019#include <base/stringprintf.h>
Chris Masone790e62e2010-08-12 10:41:18 -070020#include "base/logging.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000021#include "update_engine/file_writer.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000022#include "update_engine/filesystem_iterator.h"
23#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000024
adlr@google.comc98a7ed2009-12-04 18:54:03 +000025using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000026using std::string;
27using std::vector;
28
29namespace chromeos_update_engine {
30
adlr@google.comc98a7ed2009-12-04 18:54:03 +000031bool WriteFileVector(const std::string& path, const std::vector<char>& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080032 return utils::WriteFile(path.c_str(), &data[0], data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +000033}
34
35bool WriteFileString(const std::string& path, const std::string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080036 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +000037}
38
adlr@google.comc98a7ed2009-12-04 18:54:03 +000039std::string Readlink(const std::string& path) {
40 vector<char> buf(PATH_MAX + 1);
41 ssize_t r = readlink(path.c_str(), &buf[0], buf.size());
42 if (r < 0)
43 return "";
44 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
45 buf.resize(r);
46 string ret;
47 ret.insert(ret.begin(), buf.begin(), buf.end());
48 return ret;
49}
50
rspangler@google.com49fdf182009-10-10 00:57:34 +000051std::vector<char> GzipCompressData(const std::vector<char>& data) {
52 const char fname[] = "/tmp/GzipCompressDataTemp";
adlr@google.comc98a7ed2009-12-04 18:54:03 +000053 if (!WriteFileVector(fname, data)) {
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070054 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000055 return vector<char>();
56 }
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070057 EXPECT_EQ(0, system((string("cat ") + fname + "|gzip>" +
58 fname + ".gz").c_str()));
59 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
adlr@google.comc98a7ed2009-12-04 18:54:03 +000060 vector<char> ret;
61 EXPECT_TRUE(utils::ReadFile(string(fname) + ".gz", &ret));
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070062 EXPECT_EQ(0, system((string("rm ") + fname + ".gz").c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000063 return ret;
64}
65
adlr@google.comc98a7ed2009-12-04 18:54:03 +000066vector<char> GenerateSampleMbr() {
67 // This is the actual MBR from my dev machine. Partition 1 (the first)
68 // is currently marked bootable
69 char mbr[512] = {
70 0xeb, 0x48, 0x90, 0x10, 0x8e, 0xd0, 0xbc, 0x00,
71 0xb0, 0xb8, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0,
72 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9,
73 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x21, 0x06, 0x00,
74 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b,
75 0x83, 0xc6, 0x10, 0x81, 0xfe, 0xfe, 0x07, 0x75,
76 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb,
77 0x00, 0x7c, 0xb2, 0x80, 0x8a, 0x74, 0x03, 0x02,
78 0xff, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
79 0x00, 0x02, 0xfa, 0x90, 0x90, 0xf6, 0xc2, 0x80,
80 0x75, 0x02, 0xb2, 0x80, 0xea, 0x59, 0x7c, 0x00,
81 0x00, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc,
82 0x00, 0x20, 0xfb, 0xa0, 0x40, 0x7c, 0x3c, 0xff,
83 0x74, 0x02, 0x88, 0xc2, 0x52, 0xbe, 0x7f, 0x7d,
84 0xe8, 0x34, 0x01, 0xf6, 0xc2, 0x80, 0x74, 0x54,
85 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x5a,
86 0x52, 0x72, 0x49, 0x81, 0xfb, 0x55, 0xaa, 0x75,
87 0x43, 0xa0, 0x41, 0x7c, 0x84, 0xc0, 0x75, 0x05,
88 0x83, 0xe1, 0x01, 0x74, 0x37, 0x66, 0x8b, 0x4c,
89 0x10, 0xbe, 0x05, 0x7c, 0xc6, 0x44, 0xff, 0x01,
90 0x66, 0x8b, 0x1e, 0x44, 0x7c, 0xc7, 0x04, 0x10,
91 0x00, 0xc7, 0x44, 0x02, 0x01, 0x00, 0x66, 0x89,
92 0x5c, 0x08, 0xc7, 0x44, 0x06, 0x00, 0x70, 0x66,
93 0x31, 0xc0, 0x89, 0x44, 0x04, 0x66, 0x89, 0x44,
94 0x0c, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x05, 0xbb,
95 0x00, 0x70, 0xeb, 0x7d, 0xb4, 0x08, 0xcd, 0x13,
96 0x73, 0x0a, 0xf6, 0xc2, 0x80, 0x0f, 0x84, 0xea,
97 0x00, 0xe9, 0x8d, 0x00, 0xbe, 0x05, 0x7c, 0xc6,
98 0x44, 0xff, 0x00, 0x66, 0x31, 0xc0, 0x88, 0xf0,
99 0x40, 0x66, 0x89, 0x44, 0x04, 0x31, 0xd2, 0x88,
100 0xca, 0xc1, 0xe2, 0x02, 0x88, 0xe8, 0x88, 0xf4,
101 0x40, 0x89, 0x44, 0x08, 0x31, 0xc0, 0x88, 0xd0,
102 0xc0, 0xe8, 0x02, 0x66, 0x89, 0x04, 0x66, 0xa1,
103 0x44, 0x7c, 0x66, 0x31, 0xd2, 0x66, 0xf7, 0x34,
104 0x88, 0x54, 0x0a, 0x66, 0x31, 0xd2, 0x66, 0xf7,
105 0x74, 0x04, 0x88, 0x54, 0x0b, 0x89, 0x44, 0x0c,
106 0x3b, 0x44, 0x08, 0x7d, 0x3c, 0x8a, 0x54, 0x0d,
107 0xc0, 0xe2, 0x06, 0x8a, 0x4c, 0x0a, 0xfe, 0xc1,
108 0x08, 0xd1, 0x8a, 0x6c, 0x0c, 0x5a, 0x8a, 0x74,
109 0x0b, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, 0xdb,
110 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x72, 0x2a, 0x8c,
111 0xc3, 0x8e, 0x06, 0x48, 0x7c, 0x60, 0x1e, 0xb9,
112 0x00, 0x01, 0x8e, 0xdb, 0x31, 0xf6, 0x31, 0xff,
113 0xfc, 0xf3, 0xa5, 0x1f, 0x61, 0xff, 0x26, 0x42,
114 0x7c, 0xbe, 0x85, 0x7d, 0xe8, 0x40, 0x00, 0xeb,
115 0x0e, 0xbe, 0x8a, 0x7d, 0xe8, 0x38, 0x00, 0xeb,
116 0x06, 0xbe, 0x94, 0x7d, 0xe8, 0x30, 0x00, 0xbe,
117 0x99, 0x7d, 0xe8, 0x2a, 0x00, 0xeb, 0xfe, 0x47,
118 0x52, 0x55, 0x42, 0x20, 0x00, 0x47, 0x65, 0x6f,
119 0x6d, 0x00, 0x48, 0x61, 0x72, 0x64, 0x20, 0x44,
120 0x69, 0x73, 0x6b, 0x00, 0x52, 0x65, 0x61, 0x64,
121 0x00, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00,
122 0xbb, 0x01, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac,
123 0x3c, 0x00, 0x75, 0xf4, 0xc3, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x50, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x80, 0x01,
126 0x01, 0x00, 0x83, 0xfe, 0xff, 0xff, 0x3f, 0x00,
127 0x00, 0x00, 0x09, 0x7f, 0x32, 0x06, 0x00, 0xfe,
128 0xff, 0xff, 0x05, 0xfe, 0xff, 0xff, 0x48, 0x7f,
129 0x32, 0x06, 0x79, 0x59, 0x2d, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
134 };
135 vector<char> ret;
136 ret.insert(ret.begin(), mbr, mbr + sizeof(mbr));
137 return ret;
138}
139
Don Garrett58e8b1f2012-01-31 16:38:16 -0800140string BindToUnusedLoopDevice(const string &filename) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000141 // get a loop device we can use for the install device
Don Garrett58e8b1f2012-01-31 16:38:16 -0800142 string cmd = "losetup --show -f " + filename;
143
144 FILE* find_dev_cmd = popen(cmd.c_str(), "r");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000145 CHECK(find_dev_cmd);
146
147 string ret;
148 char dev[100] = {0};
149 size_t r;
150 while ((r = fread(dev, 1, sizeof(dev - 1), find_dev_cmd)) > 0) {
151 EXPECT_LT(r, sizeof(dev));
152 ret.insert(ret.end(), dev, dev + r);
153 }
154 EXPECT_EQ(r, 0);
155 EXPECT_TRUE(feof(find_dev_cmd));
156 fclose(find_dev_cmd);
157
158 // strip trailing \n on dev
159 if (*ret.rbegin() == '\n')
160 ret.resize(ret.size() - 1);
161
Don Garrett58e8b1f2012-01-31 16:38:16 -0800162 // Ensure that the device starts with "/dev/loop"
163 EXPECT_TRUE(StartsWithASCII(ret, "/dev/loop", true));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000164 return ret;
165}
166
Andrew de los Reyes80061062010-02-04 14:25:00 -0800167bool ExpectVectorsEq(const vector<char>& expected, const vector<char>& actual) {
168 EXPECT_EQ(expected.size(), actual.size());
169 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000170 return false;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800171 for (unsigned int i = 0; i < expected.size(); i++) {
172 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000173 }
174 return true;
175}
176
Andrew de los Reyes80061062010-02-04 14:25:00 -0800177void FillWithData(vector<char>* buffer) {
178 size_t input_counter = 0;
179 for (vector<char>::iterator it = buffer->begin(); it != buffer->end(); ++it) {
180 *it = kRandomString[input_counter];
181 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"
190 " seek=%zu bs=1 count=1",
191 path.c_str(), size)));
192 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b %d -F %s",
193 block_size, path.c_str())));
194}
195
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000196void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
197 // create 10MiB sparse file
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000198 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
199 " seek=10485759 bs=1 count=1",
200 path.c_str())));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700201 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b 4096 -F %s", path.c_str())));
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800202 EXPECT_EQ(0, System(StringPrintf("mkdir -p %s", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000203 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800204 kMountPath)));
205 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", kMountPath)));
206 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello", kMountPath)));
207 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", kMountPath)));
208 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir", kMountPath)));
209 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt", kMountPath)));
210 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test", kMountPath)));
211 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo", kMountPath)));
212 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", kMountPath)));
213 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000214 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800215 kMountPath, kMountPath)));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800216 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0", kMountPath)));
217 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
218 kMountPath, kMountPath)));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800219 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
220 kMountPath)));
David James7f42b822012-02-16 15:44:16 -0800221 EXPECT_EQ(0, System(StringPrintf("umount %s", kMountPath)));
Thieu Le5c7d9752010-12-15 16:09:28 -0800222
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000223 if (out_paths) {
224 out_paths->clear();
225 out_paths->push_back("");
226 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800227 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000228 out_paths->push_back("/hello");
229 out_paths->push_back("/some_dir");
230 out_paths->push_back("/some_dir/empty_dir");
231 out_paths->push_back("/some_dir/mnt");
232 out_paths->push_back("/some_dir/test");
233 out_paths->push_back("/some_dir/fifo");
234 out_paths->push_back("/cdev");
235 out_paths->push_back("/testlink");
236 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800237 out_paths->push_back("/srchardlink0");
238 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000239 out_paths->push_back("/lost+found");
240 }
241}
242
243void VerifyAllPaths(const string& parent, set<string> expected_paths) {
244 FilesystemIterator iter(parent, set<string>());
245 ino_t test_ino = 0;
246 ino_t testlink_ino = 0;
247 while (!iter.IsEnd()) {
248 string path = iter.GetFullPath();
249 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
250 EXPECT_EQ(1, expected_paths.erase(path));
251 if (utils::StringHasSuffix(path, "/hi") ||
252 utils::StringHasSuffix(path, "/hello") ||
253 utils::StringHasSuffix(path, "/test") ||
254 utils::StringHasSuffix(path, "/testlink")) {
255 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
256 if (utils::StringHasSuffix(path, "/test"))
257 test_ino = iter.GetStat().st_ino;
258 else if (utils::StringHasSuffix(path, "/testlink"))
259 testlink_ino = iter.GetStat().st_ino;
260 } else if (utils::StringHasSuffix(path, "/some_dir") ||
261 utils::StringHasSuffix(path, "/empty_dir") ||
262 utils::StringHasSuffix(path, "/mnt") ||
263 utils::StringHasSuffix(path, "/lost+found") ||
264 parent == path) {
265 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
266 } else if (utils::StringHasSuffix(path, "/fifo")) {
267 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
268 } else if (utils::StringHasSuffix(path, "/cdev")) {
269 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
270 } else if (utils::StringHasSuffix(path, "/sym")) {
271 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
272 } else {
273 LOG(INFO) << "got non hardcoded path: " << path;
274 }
275 iter.Increment();
276 }
277 EXPECT_EQ(testlink_ino, test_ino);
278 EXPECT_NE(0, test_ino);
279 EXPECT_FALSE(iter.IsErr());
280 EXPECT_TRUE(expected_paths.empty());
281 if (!expected_paths.empty()) {
282 for (set<string>::const_iterator it = expected_paths.begin();
283 it != expected_paths.end(); ++it) {
284 LOG(INFO) << "extra path: " << *it;
285 }
286 }
287}
288
Don Garrett58e8b1f2012-01-31 16:38:16 -0800289ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
290 string* mnt_path,
Thieu Le5c7d9752010-12-15 16:09:28 -0800291 unsigned long flags) {
292 EXPECT_TRUE(utils::MakeTempDirectory("/tmp/mnt.XXXXXX", mnt_path));
293 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
294
Don Garrett58e8b1f2012-01-31 16:38:16 -0800295 string loop_dev;
296 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800297
298 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
299 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
300}
301
rspangler@google.com49fdf182009-10-10 00:57:34 +0000302} // namespace chromeos_update_engine