blob: 6a86025456ddb9af2915e36fb30d4f128bc328f0 [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// 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"
rspangler@google.com49fdf182009-10-10 00:57:34 +00006#include <sys/stat.h>
7#include <sys/types.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +00008#include <errno.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +00009#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000012#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000013#include <string>
14#include <vector>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000015#include "base/string_util.h"
16#include "chromeos/obsolete_logging.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000017
18#include "update_engine/file_writer.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000019#include "update_engine/filesystem_iterator.h"
20#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000021
adlr@google.comc98a7ed2009-12-04 18:54:03 +000022using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000023using std::string;
24using std::vector;
25
26namespace chromeos_update_engine {
27
adlr@google.comc98a7ed2009-12-04 18:54:03 +000028bool WriteFileVector(const std::string& path, const std::vector<char>& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080029 return utils::WriteFile(path.c_str(), &data[0], data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +000030}
31
32bool WriteFileString(const std::string& path, const std::string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080033 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +000034}
35
36off_t FileSize(const string& path) {
37 struct stat stbuf;
38 int rc = stat(path.c_str(), &stbuf);
adlr@google.comc98a7ed2009-12-04 18:54:03 +000039 CHECK_EQ(rc, 0);
rspangler@google.com49fdf182009-10-10 00:57:34 +000040 if (rc < 0)
41 return rc;
42 return stbuf.st_size;
43}
44
adlr@google.comc98a7ed2009-12-04 18:54:03 +000045std::string Readlink(const std::string& path) {
46 vector<char> buf(PATH_MAX + 1);
47 ssize_t r = readlink(path.c_str(), &buf[0], buf.size());
48 if (r < 0)
49 return "";
50 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
51 buf.resize(r);
52 string ret;
53 ret.insert(ret.begin(), buf.begin(), buf.end());
54 return ret;
55}
56
rspangler@google.com49fdf182009-10-10 00:57:34 +000057std::vector<char> GzipCompressData(const std::vector<char>& data) {
58 const char fname[] = "/tmp/GzipCompressDataTemp";
adlr@google.comc98a7ed2009-12-04 18:54:03 +000059 if (!WriteFileVector(fname, data)) {
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070060 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000061 return vector<char>();
62 }
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070063 EXPECT_EQ(0, system((string("cat ") + fname + "|gzip>" +
64 fname + ".gz").c_str()));
65 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
adlr@google.comc98a7ed2009-12-04 18:54:03 +000066 vector<char> ret;
67 EXPECT_TRUE(utils::ReadFile(string(fname) + ".gz", &ret));
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070068 EXPECT_EQ(0, system((string("rm ") + fname + ".gz").c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000069 return ret;
70}
71
adlr@google.comc98a7ed2009-12-04 18:54:03 +000072vector<char> GenerateSampleMbr() {
73 // This is the actual MBR from my dev machine. Partition 1 (the first)
74 // is currently marked bootable
75 char mbr[512] = {
76 0xeb, 0x48, 0x90, 0x10, 0x8e, 0xd0, 0xbc, 0x00,
77 0xb0, 0xb8, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0,
78 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9,
79 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x21, 0x06, 0x00,
80 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b,
81 0x83, 0xc6, 0x10, 0x81, 0xfe, 0xfe, 0x07, 0x75,
82 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb,
83 0x00, 0x7c, 0xb2, 0x80, 0x8a, 0x74, 0x03, 0x02,
84 0xff, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
85 0x00, 0x02, 0xfa, 0x90, 0x90, 0xf6, 0xc2, 0x80,
86 0x75, 0x02, 0xb2, 0x80, 0xea, 0x59, 0x7c, 0x00,
87 0x00, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc,
88 0x00, 0x20, 0xfb, 0xa0, 0x40, 0x7c, 0x3c, 0xff,
89 0x74, 0x02, 0x88, 0xc2, 0x52, 0xbe, 0x7f, 0x7d,
90 0xe8, 0x34, 0x01, 0xf6, 0xc2, 0x80, 0x74, 0x54,
91 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x5a,
92 0x52, 0x72, 0x49, 0x81, 0xfb, 0x55, 0xaa, 0x75,
93 0x43, 0xa0, 0x41, 0x7c, 0x84, 0xc0, 0x75, 0x05,
94 0x83, 0xe1, 0x01, 0x74, 0x37, 0x66, 0x8b, 0x4c,
95 0x10, 0xbe, 0x05, 0x7c, 0xc6, 0x44, 0xff, 0x01,
96 0x66, 0x8b, 0x1e, 0x44, 0x7c, 0xc7, 0x04, 0x10,
97 0x00, 0xc7, 0x44, 0x02, 0x01, 0x00, 0x66, 0x89,
98 0x5c, 0x08, 0xc7, 0x44, 0x06, 0x00, 0x70, 0x66,
99 0x31, 0xc0, 0x89, 0x44, 0x04, 0x66, 0x89, 0x44,
100 0x0c, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x05, 0xbb,
101 0x00, 0x70, 0xeb, 0x7d, 0xb4, 0x08, 0xcd, 0x13,
102 0x73, 0x0a, 0xf6, 0xc2, 0x80, 0x0f, 0x84, 0xea,
103 0x00, 0xe9, 0x8d, 0x00, 0xbe, 0x05, 0x7c, 0xc6,
104 0x44, 0xff, 0x00, 0x66, 0x31, 0xc0, 0x88, 0xf0,
105 0x40, 0x66, 0x89, 0x44, 0x04, 0x31, 0xd2, 0x88,
106 0xca, 0xc1, 0xe2, 0x02, 0x88, 0xe8, 0x88, 0xf4,
107 0x40, 0x89, 0x44, 0x08, 0x31, 0xc0, 0x88, 0xd0,
108 0xc0, 0xe8, 0x02, 0x66, 0x89, 0x04, 0x66, 0xa1,
109 0x44, 0x7c, 0x66, 0x31, 0xd2, 0x66, 0xf7, 0x34,
110 0x88, 0x54, 0x0a, 0x66, 0x31, 0xd2, 0x66, 0xf7,
111 0x74, 0x04, 0x88, 0x54, 0x0b, 0x89, 0x44, 0x0c,
112 0x3b, 0x44, 0x08, 0x7d, 0x3c, 0x8a, 0x54, 0x0d,
113 0xc0, 0xe2, 0x06, 0x8a, 0x4c, 0x0a, 0xfe, 0xc1,
114 0x08, 0xd1, 0x8a, 0x6c, 0x0c, 0x5a, 0x8a, 0x74,
115 0x0b, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, 0xdb,
116 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x72, 0x2a, 0x8c,
117 0xc3, 0x8e, 0x06, 0x48, 0x7c, 0x60, 0x1e, 0xb9,
118 0x00, 0x01, 0x8e, 0xdb, 0x31, 0xf6, 0x31, 0xff,
119 0xfc, 0xf3, 0xa5, 0x1f, 0x61, 0xff, 0x26, 0x42,
120 0x7c, 0xbe, 0x85, 0x7d, 0xe8, 0x40, 0x00, 0xeb,
121 0x0e, 0xbe, 0x8a, 0x7d, 0xe8, 0x38, 0x00, 0xeb,
122 0x06, 0xbe, 0x94, 0x7d, 0xe8, 0x30, 0x00, 0xbe,
123 0x99, 0x7d, 0xe8, 0x2a, 0x00, 0xeb, 0xfe, 0x47,
124 0x52, 0x55, 0x42, 0x20, 0x00, 0x47, 0x65, 0x6f,
125 0x6d, 0x00, 0x48, 0x61, 0x72, 0x64, 0x20, 0x44,
126 0x69, 0x73, 0x6b, 0x00, 0x52, 0x65, 0x61, 0x64,
127 0x00, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00,
128 0xbb, 0x01, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac,
129 0x3c, 0x00, 0x75, 0xf4, 0xc3, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x50, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x80, 0x01,
132 0x01, 0x00, 0x83, 0xfe, 0xff, 0xff, 0x3f, 0x00,
133 0x00, 0x00, 0x09, 0x7f, 0x32, 0x06, 0x00, 0xfe,
134 0xff, 0xff, 0x05, 0xfe, 0xff, 0xff, 0x48, 0x7f,
135 0x32, 0x06, 0x79, 0x59, 0x2d, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
140 };
141 vector<char> ret;
142 ret.insert(ret.begin(), mbr, mbr + sizeof(mbr));
143 return ret;
144}
145
146std::string GetUnusedLoopDevice() {
147 // get a loop device we can use for the install device
148 FILE* find_dev_cmd = popen("losetup -f", "r");
149 CHECK(find_dev_cmd);
150
151 string ret;
152 char dev[100] = {0};
153 size_t r;
154 while ((r = fread(dev, 1, sizeof(dev - 1), find_dev_cmd)) > 0) {
155 EXPECT_LT(r, sizeof(dev));
156 ret.insert(ret.end(), dev, dev + r);
157 }
158 EXPECT_EQ(r, 0);
159 EXPECT_TRUE(feof(find_dev_cmd));
160 fclose(find_dev_cmd);
161
162 // strip trailing \n on dev
163 if (*ret.rbegin() == '\n')
164 ret.resize(ret.size() - 1);
165
166 return ret;
167}
168
Andrew de los Reyes80061062010-02-04 14:25:00 -0800169bool ExpectVectorsEq(const vector<char>& expected, const vector<char>& actual) {
170 EXPECT_EQ(expected.size(), actual.size());
171 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000172 return false;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800173 for (unsigned int i = 0; i < expected.size(); i++) {
174 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000175 }
176 return true;
177}
178
Andrew de los Reyes80061062010-02-04 14:25:00 -0800179void FillWithData(vector<char>* buffer) {
180 size_t input_counter = 0;
181 for (vector<char>::iterator it = buffer->begin(); it != buffer->end(); ++it) {
182 *it = kRandomString[input_counter];
183 input_counter++;
184 input_counter %= sizeof(kRandomString);
185 }
186}
187
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000188void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
189 // create 10MiB sparse file
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000190 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
191 " seek=10485759 bs=1 count=1",
192 path.c_str())));
193 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -F %s", path.c_str())));
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800194 EXPECT_EQ(0, System(StringPrintf("mkdir -p %s", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000195 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800196 kMountPath)));
197 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", kMountPath)));
198 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello", kMountPath)));
199 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", kMountPath)));
200 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir", kMountPath)));
201 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt", kMountPath)));
202 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test", kMountPath)));
203 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo", kMountPath)));
204 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", kMountPath)));
205 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000206 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800207 kMountPath, kMountPath)));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700208 EXPECT_EQ(0, System(StringPrintf("umount -d %s", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000209
210 if (out_paths) {
211 out_paths->clear();
212 out_paths->push_back("");
213 out_paths->push_back("/hi");
214 out_paths->push_back("/hello");
215 out_paths->push_back("/some_dir");
216 out_paths->push_back("/some_dir/empty_dir");
217 out_paths->push_back("/some_dir/mnt");
218 out_paths->push_back("/some_dir/test");
219 out_paths->push_back("/some_dir/fifo");
220 out_paths->push_back("/cdev");
221 out_paths->push_back("/testlink");
222 out_paths->push_back("/sym");
223 out_paths->push_back("/lost+found");
224 }
225}
226
227void VerifyAllPaths(const string& parent, set<string> expected_paths) {
228 FilesystemIterator iter(parent, set<string>());
229 ino_t test_ino = 0;
230 ino_t testlink_ino = 0;
231 while (!iter.IsEnd()) {
232 string path = iter.GetFullPath();
233 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
234 EXPECT_EQ(1, expected_paths.erase(path));
235 if (utils::StringHasSuffix(path, "/hi") ||
236 utils::StringHasSuffix(path, "/hello") ||
237 utils::StringHasSuffix(path, "/test") ||
238 utils::StringHasSuffix(path, "/testlink")) {
239 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
240 if (utils::StringHasSuffix(path, "/test"))
241 test_ino = iter.GetStat().st_ino;
242 else if (utils::StringHasSuffix(path, "/testlink"))
243 testlink_ino = iter.GetStat().st_ino;
244 } else if (utils::StringHasSuffix(path, "/some_dir") ||
245 utils::StringHasSuffix(path, "/empty_dir") ||
246 utils::StringHasSuffix(path, "/mnt") ||
247 utils::StringHasSuffix(path, "/lost+found") ||
248 parent == path) {
249 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
250 } else if (utils::StringHasSuffix(path, "/fifo")) {
251 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
252 } else if (utils::StringHasSuffix(path, "/cdev")) {
253 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
254 } else if (utils::StringHasSuffix(path, "/sym")) {
255 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
256 } else {
257 LOG(INFO) << "got non hardcoded path: " << path;
258 }
259 iter.Increment();
260 }
261 EXPECT_EQ(testlink_ino, test_ino);
262 EXPECT_NE(0, test_ino);
263 EXPECT_FALSE(iter.IsErr());
264 EXPECT_TRUE(expected_paths.empty());
265 if (!expected_paths.empty()) {
266 for (set<string>::const_iterator it = expected_paths.begin();
267 it != expected_paths.end(); ++it) {
268 LOG(INFO) << "extra path: " << *it;
269 }
270 }
271}
272
rspangler@google.com49fdf182009-10-10 00:57:34 +0000273} // namespace chromeos_update_engine