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