blob: a075c2d930d19f7fa71590653d5d7c610b3e107c [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
adlr@google.comc98a7ed2009-12-04 18:54:03 +000038std::string Readlink(const std::string& path) {
39 vector<char> buf(PATH_MAX + 1);
40 ssize_t r = readlink(path.c_str(), &buf[0], buf.size());
41 if (r < 0)
42 return "";
43 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
44 buf.resize(r);
45 string ret;
46 ret.insert(ret.begin(), buf.begin(), buf.end());
47 return ret;
48}
49
rspangler@google.com49fdf182009-10-10 00:57:34 +000050std::vector<char> GzipCompressData(const std::vector<char>& data) {
51 const char fname[] = "/tmp/GzipCompressDataTemp";
adlr@google.comc98a7ed2009-12-04 18:54:03 +000052 if (!WriteFileVector(fname, data)) {
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070053 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000054 return vector<char>();
55 }
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070056 EXPECT_EQ(0, system((string("cat ") + fname + "|gzip>" +
57 fname + ".gz").c_str()));
58 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
adlr@google.comc98a7ed2009-12-04 18:54:03 +000059 vector<char> ret;
60 EXPECT_TRUE(utils::ReadFile(string(fname) + ".gz", &ret));
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070061 EXPECT_EQ(0, system((string("rm ") + fname + ".gz").c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000062 return ret;
63}
64
adlr@google.comc98a7ed2009-12-04 18:54:03 +000065vector<char> GenerateSampleMbr() {
66 // This is the actual MBR from my dev machine. Partition 1 (the first)
67 // is currently marked bootable
68 char mbr[512] = {
69 0xeb, 0x48, 0x90, 0x10, 0x8e, 0xd0, 0xbc, 0x00,
70 0xb0, 0xb8, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0,
71 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9,
72 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x21, 0x06, 0x00,
73 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b,
74 0x83, 0xc6, 0x10, 0x81, 0xfe, 0xfe, 0x07, 0x75,
75 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb,
76 0x00, 0x7c, 0xb2, 0x80, 0x8a, 0x74, 0x03, 0x02,
77 0xff, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
78 0x00, 0x02, 0xfa, 0x90, 0x90, 0xf6, 0xc2, 0x80,
79 0x75, 0x02, 0xb2, 0x80, 0xea, 0x59, 0x7c, 0x00,
80 0x00, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc,
81 0x00, 0x20, 0xfb, 0xa0, 0x40, 0x7c, 0x3c, 0xff,
82 0x74, 0x02, 0x88, 0xc2, 0x52, 0xbe, 0x7f, 0x7d,
83 0xe8, 0x34, 0x01, 0xf6, 0xc2, 0x80, 0x74, 0x54,
84 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x5a,
85 0x52, 0x72, 0x49, 0x81, 0xfb, 0x55, 0xaa, 0x75,
86 0x43, 0xa0, 0x41, 0x7c, 0x84, 0xc0, 0x75, 0x05,
87 0x83, 0xe1, 0x01, 0x74, 0x37, 0x66, 0x8b, 0x4c,
88 0x10, 0xbe, 0x05, 0x7c, 0xc6, 0x44, 0xff, 0x01,
89 0x66, 0x8b, 0x1e, 0x44, 0x7c, 0xc7, 0x04, 0x10,
90 0x00, 0xc7, 0x44, 0x02, 0x01, 0x00, 0x66, 0x89,
91 0x5c, 0x08, 0xc7, 0x44, 0x06, 0x00, 0x70, 0x66,
92 0x31, 0xc0, 0x89, 0x44, 0x04, 0x66, 0x89, 0x44,
93 0x0c, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x05, 0xbb,
94 0x00, 0x70, 0xeb, 0x7d, 0xb4, 0x08, 0xcd, 0x13,
95 0x73, 0x0a, 0xf6, 0xc2, 0x80, 0x0f, 0x84, 0xea,
96 0x00, 0xe9, 0x8d, 0x00, 0xbe, 0x05, 0x7c, 0xc6,
97 0x44, 0xff, 0x00, 0x66, 0x31, 0xc0, 0x88, 0xf0,
98 0x40, 0x66, 0x89, 0x44, 0x04, 0x31, 0xd2, 0x88,
99 0xca, 0xc1, 0xe2, 0x02, 0x88, 0xe8, 0x88, 0xf4,
100 0x40, 0x89, 0x44, 0x08, 0x31, 0xc0, 0x88, 0xd0,
101 0xc0, 0xe8, 0x02, 0x66, 0x89, 0x04, 0x66, 0xa1,
102 0x44, 0x7c, 0x66, 0x31, 0xd2, 0x66, 0xf7, 0x34,
103 0x88, 0x54, 0x0a, 0x66, 0x31, 0xd2, 0x66, 0xf7,
104 0x74, 0x04, 0x88, 0x54, 0x0b, 0x89, 0x44, 0x0c,
105 0x3b, 0x44, 0x08, 0x7d, 0x3c, 0x8a, 0x54, 0x0d,
106 0xc0, 0xe2, 0x06, 0x8a, 0x4c, 0x0a, 0xfe, 0xc1,
107 0x08, 0xd1, 0x8a, 0x6c, 0x0c, 0x5a, 0x8a, 0x74,
108 0x0b, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, 0xdb,
109 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x72, 0x2a, 0x8c,
110 0xc3, 0x8e, 0x06, 0x48, 0x7c, 0x60, 0x1e, 0xb9,
111 0x00, 0x01, 0x8e, 0xdb, 0x31, 0xf6, 0x31, 0xff,
112 0xfc, 0xf3, 0xa5, 0x1f, 0x61, 0xff, 0x26, 0x42,
113 0x7c, 0xbe, 0x85, 0x7d, 0xe8, 0x40, 0x00, 0xeb,
114 0x0e, 0xbe, 0x8a, 0x7d, 0xe8, 0x38, 0x00, 0xeb,
115 0x06, 0xbe, 0x94, 0x7d, 0xe8, 0x30, 0x00, 0xbe,
116 0x99, 0x7d, 0xe8, 0x2a, 0x00, 0xeb, 0xfe, 0x47,
117 0x52, 0x55, 0x42, 0x20, 0x00, 0x47, 0x65, 0x6f,
118 0x6d, 0x00, 0x48, 0x61, 0x72, 0x64, 0x20, 0x44,
119 0x69, 0x73, 0x6b, 0x00, 0x52, 0x65, 0x61, 0x64,
120 0x00, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00,
121 0xbb, 0x01, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac,
122 0x3c, 0x00, 0x75, 0xf4, 0xc3, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x50, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x80, 0x01,
125 0x01, 0x00, 0x83, 0xfe, 0xff, 0xff, 0x3f, 0x00,
126 0x00, 0x00, 0x09, 0x7f, 0x32, 0x06, 0x00, 0xfe,
127 0xff, 0xff, 0x05, 0xfe, 0xff, 0xff, 0x48, 0x7f,
128 0x32, 0x06, 0x79, 0x59, 0x2d, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x55, 0xaa
133 };
134 vector<char> ret;
135 ret.insert(ret.begin(), mbr, mbr + sizeof(mbr));
136 return ret;
137}
138
139std::string GetUnusedLoopDevice() {
140 // get a loop device we can use for the install device
141 FILE* find_dev_cmd = popen("losetup -f", "r");
142 CHECK(find_dev_cmd);
143
144 string ret;
145 char dev[100] = {0};
146 size_t r;
147 while ((r = fread(dev, 1, sizeof(dev - 1), find_dev_cmd)) > 0) {
148 EXPECT_LT(r, sizeof(dev));
149 ret.insert(ret.end(), dev, dev + r);
150 }
151 EXPECT_EQ(r, 0);
152 EXPECT_TRUE(feof(find_dev_cmd));
153 fclose(find_dev_cmd);
154
155 // strip trailing \n on dev
156 if (*ret.rbegin() == '\n')
157 ret.resize(ret.size() - 1);
158
159 return ret;
160}
161
Andrew de los Reyes80061062010-02-04 14:25:00 -0800162bool ExpectVectorsEq(const vector<char>& expected, const vector<char>& actual) {
163 EXPECT_EQ(expected.size(), actual.size());
164 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000165 return false;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800166 for (unsigned int i = 0; i < expected.size(); i++) {
167 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000168 }
169 return true;
170}
171
Andrew de los Reyes80061062010-02-04 14:25:00 -0800172void FillWithData(vector<char>* buffer) {
173 size_t input_counter = 0;
174 for (vector<char>::iterator it = buffer->begin(); it != buffer->end(); ++it) {
175 *it = kRandomString[input_counter];
176 input_counter++;
177 input_counter %= sizeof(kRandomString);
178 }
179}
180
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000181void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
182 // create 10MiB sparse file
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000183 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
184 " seek=10485759 bs=1 count=1",
185 path.c_str())));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700186 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b 4096 -F %s", path.c_str())));
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800187 EXPECT_EQ(0, System(StringPrintf("mkdir -p %s", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000188 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800189 kMountPath)));
190 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", kMountPath)));
191 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello", kMountPath)));
192 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", kMountPath)));
193 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir", kMountPath)));
194 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt", kMountPath)));
195 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test", kMountPath)));
196 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo", kMountPath)));
197 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", kMountPath)));
198 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000199 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800200 kMountPath, kMountPath)));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700201 EXPECT_EQ(0, System(StringPrintf("umount -d %s", kMountPath)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000202
203 if (out_paths) {
204 out_paths->clear();
205 out_paths->push_back("");
206 out_paths->push_back("/hi");
207 out_paths->push_back("/hello");
208 out_paths->push_back("/some_dir");
209 out_paths->push_back("/some_dir/empty_dir");
210 out_paths->push_back("/some_dir/mnt");
211 out_paths->push_back("/some_dir/test");
212 out_paths->push_back("/some_dir/fifo");
213 out_paths->push_back("/cdev");
214 out_paths->push_back("/testlink");
215 out_paths->push_back("/sym");
216 out_paths->push_back("/lost+found");
217 }
218}
219
220void VerifyAllPaths(const string& parent, set<string> expected_paths) {
221 FilesystemIterator iter(parent, set<string>());
222 ino_t test_ino = 0;
223 ino_t testlink_ino = 0;
224 while (!iter.IsEnd()) {
225 string path = iter.GetFullPath();
226 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
227 EXPECT_EQ(1, expected_paths.erase(path));
228 if (utils::StringHasSuffix(path, "/hi") ||
229 utils::StringHasSuffix(path, "/hello") ||
230 utils::StringHasSuffix(path, "/test") ||
231 utils::StringHasSuffix(path, "/testlink")) {
232 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
233 if (utils::StringHasSuffix(path, "/test"))
234 test_ino = iter.GetStat().st_ino;
235 else if (utils::StringHasSuffix(path, "/testlink"))
236 testlink_ino = iter.GetStat().st_ino;
237 } else if (utils::StringHasSuffix(path, "/some_dir") ||
238 utils::StringHasSuffix(path, "/empty_dir") ||
239 utils::StringHasSuffix(path, "/mnt") ||
240 utils::StringHasSuffix(path, "/lost+found") ||
241 parent == path) {
242 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
243 } else if (utils::StringHasSuffix(path, "/fifo")) {
244 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
245 } else if (utils::StringHasSuffix(path, "/cdev")) {
246 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
247 } else if (utils::StringHasSuffix(path, "/sym")) {
248 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
249 } else {
250 LOG(INFO) << "got non hardcoded path: " << path;
251 }
252 iter.Increment();
253 }
254 EXPECT_EQ(testlink_ino, test_ino);
255 EXPECT_NE(0, test_ino);
256 EXPECT_FALSE(iter.IsErr());
257 EXPECT_TRUE(expected_paths.empty());
258 if (!expected_paths.empty()) {
259 for (set<string>::const_iterator it = expected_paths.begin();
260 it != expected_paths.end(); ++it) {
261 LOG(INFO) << "extra path: " << *it;
262 }
263 }
264}
265
rspangler@google.com49fdf182009-10-10 00:57:34 +0000266} // namespace chromeos_update_engine