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