blob: 6d3c5bd37bb0c2b22b412020d98391de434879d6 [file] [log] [blame]
Gilad Arnoldc33faeb2012-07-24 15:11:11 -07001// 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#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_TEST_UTILS_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_TEST_UTILS_H__
rspangler@google.com49fdf182009-10-10 00:57:34 +00007
Gilad Arnold2c2b8842013-07-16 06:44:37 -07008#include <sys/stat.h>
9#include <sys/types.h>
10#include <unistd.h>
11
adlr@google.comc98a7ed2009-12-04 18:54:03 +000012#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000013#include <string>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000014#include <vector>
Thieu Le5c7d9752010-12-15 16:09:28 -080015
Chris Masoned903c3b2011-05-12 15:35:46 -070016#include <base/memory/scoped_ptr.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000017#include <gtest/gtest.h>
Thieu Le5c7d9752010-12-15 16:09:28 -080018
adlr@google.comc98a7ed2009-12-04 18:54:03 +000019#include "update_engine/action.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070020#include "update_engine/subprocess.h"
Andrew de los Reyesf9185172010-05-03 11:07:05 -070021#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000022
23// These are some handy functions for unittests.
24
25namespace chromeos_update_engine {
26
rspangler@google.com49fdf182009-10-10 00:57:34 +000027// Writes the data passed to path. The file at path will be overwritten if it
28// exists. Returns true on success, false otherwise.
adlr@google.comc98a7ed2009-12-04 18:54:03 +000029bool WriteFileVector(const std::string& path, const std::vector<char>& data);
30bool WriteFileString(const std::string& path, const std::string& data);
rspangler@google.com49fdf182009-10-10 00:57:34 +000031
adlr@google.comc98a7ed2009-12-04 18:54:03 +000032// Reads a symlink from disk. Returns empty string on failure.
33std::string Readlink(const std::string& path);
34
rspangler@google.com49fdf182009-10-10 00:57:34 +000035// Gzip compresses the data passed using the gzip command line program.
36// Returns compressed data back.
37std::vector<char> GzipCompressData(const std::vector<char>& data);
38
adlr@google.comc98a7ed2009-12-04 18:54:03 +000039// Gives back a 512-bytes length array that contains an MBR with
40// the first partition is marked bootable.
41std::vector<char> GenerateSampleMbr();
42
Gilad Arnold19a45f02012-07-19 12:36:10 -070043bool BindToUnusedLoopDevice(const std::string &filename,
44 std::string* lo_dev_name_ptr);
adlr@google.comc98a7ed2009-12-04 18:54:03 +000045
46// Returns true iff a == b
47bool ExpectVectorsEq(const std::vector<char>& a, const std::vector<char>& b);
48
49inline int System(const std::string& cmd) {
50 return system(cmd.c_str());
51}
52
Gilad Arnold2c2b8842013-07-16 06:44:37 -070053inline int Symlink(const std::string& oldpath, const std::string& newpath) {
54 return symlink(oldpath.c_str(), newpath.c_str());
55}
56
57inline int Chmod(const std::string& path, mode_t mode) {
58 return chmod(path.c_str(), mode);
59}
60
61inline int Mkdir(const std::string& path, mode_t mode) {
62 return mkdir(path.c_str(), mode);
63}
64
Gilad Arnold30dedd82013-07-03 06:19:09 -070065inline int Chdir(const std::string& path) {
66 return chdir(path.c_str());
67}
68
Andrew de los Reyes80061062010-02-04 14:25:00 -080069void FillWithData(std::vector<char>* buffer);
70
adlr@google.comc98a7ed2009-12-04 18:54:03 +000071namespace {
72// 300 byte pseudo-random string. Not null terminated.
73// This does not gzip compress well.
74const unsigned char kRandomString[] = {
75 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
76 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
77 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
78 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
79 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
80 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
81 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
82 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
83 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
84 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
85 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
86 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
87 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
88 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
89 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
90 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
91 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
92 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
93 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
94 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
95 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
96 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
97 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
98 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
99 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
100 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
101 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
102 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
103 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
104 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
105 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
106 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
107 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
108 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
109 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
110 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
111 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
112 0xbe, 0x9f, 0xa3, 0x5d
113};
114
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800115const char* const kMountPath = "/tmp/UpdateEngineTests_mnt";
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000116} // namespace {}
117
Thieu Le5c7d9752010-12-15 16:09:28 -0800118// Creates an empty ext image.
119void CreateEmptyExtImageAtPath(const std::string& path,
120 size_t size,
121 int block_size);
122
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000123// Creates an ext image with some files in it. The paths creates are
124// returned in out_paths.
125void CreateExtImageAtPath(const std::string& path,
126 std::vector<std::string>* out_paths);
127
128// Verifies that for each path in paths, it exists in the filesystem under
129// parent. Also, verifies that no additional paths are present under parent.
130// Also tests properties of various files created by CreateExtImageAtPath().
131// Intentionally copies expected_paths.
132void VerifyAllPaths(const std::string& parent,
133 std::set<std::string> expected_paths);
134
Don Garrett58e8b1f2012-01-31 16:38:16 -0800135class ScopedLoopbackDeviceBinder {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700136 public:
Don Garrett58e8b1f2012-01-31 16:38:16 -0800137 ScopedLoopbackDeviceBinder(const std::string& file, std::string* dev) {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700138 is_bound_ = BindToUnusedLoopDevice(file, &dev_);
139 EXPECT_TRUE(is_bound_);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800140
Gilad Arnold19a45f02012-07-19 12:36:10 -0700141 if (is_bound_ && dev)
Don Garrett58e8b1f2012-01-31 16:38:16 -0800142 *dev = dev_;
143 }
144
145 ~ScopedLoopbackDeviceBinder() {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700146 if (!is_bound_)
147 return;
148
Darin Petkovcf562482010-12-03 10:31:00 -0800149 for (int retry = 0; retry < 5; retry++) {
150 std::vector<std::string> args;
151 args.push_back("/sbin/losetup");
152 args.push_back("-d");
153 args.push_back(dev_);
154 int return_code = 0;
Darin Petkov85d02b72011-05-17 13:25:51 -0700155 EXPECT_TRUE(Subprocess::SynchronousExec(args, &return_code, NULL));
Darin Petkovcf562482010-12-03 10:31:00 -0800156 if (return_code == 0) {
157 return;
158 }
159 sleep(1);
160 }
161 ADD_FAILURE();
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700162 }
Don Garrett58e8b1f2012-01-31 16:38:16 -0800163
Gilad Arnold19a45f02012-07-19 12:36:10 -0700164 const std::string &dev() {
165 EXPECT_TRUE(is_bound_);
166 return dev_;
167 }
Don Garrett58e8b1f2012-01-31 16:38:16 -0800168
Gilad Arnoldc33faeb2012-07-24 15:11:11 -0700169 bool is_bound() const { return is_bound_; }
170
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700171 private:
Don Garrett58e8b1f2012-01-31 16:38:16 -0800172 std::string dev_;
Gilad Arnold19a45f02012-07-19 12:36:10 -0700173 bool is_bound_;
Don Garrett58e8b1f2012-01-31 16:38:16 -0800174 DISALLOW_COPY_AND_ASSIGN(ScopedLoopbackDeviceBinder);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700175};
176
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700177class ScopedTempFile {
178 public:
179 ScopedTempFile() {
180 EXPECT_TRUE(utils::MakeTempFile("/tmp/update_engine_test_temp_file.XXXXXX",
181 &path_,
182 NULL));
183 unlinker_.reset(new ScopedPathUnlinker(path_));
184 }
185 const std::string& GetPath() { return path_; }
186 private:
187 std::string path_;
188 scoped_ptr<ScopedPathUnlinker> unlinker_;
189};
190
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000191// Useful actions for test
192
193class NoneType;
194
195template<typename T>
196class ObjectFeederAction;
197
198template<typename T>
199class ActionTraits<ObjectFeederAction<T> > {
200 public:
201 typedef T OutputObjectType;
202 typedef NoneType InputObjectType;
203};
204
205// This is a simple Action class for testing. It feeds an object into
206// another action.
207template<typename T>
Yunlian Jianga178e5e2013-04-05 14:41:56 -0700208class ObjectFeederAction : public Action<ObjectFeederAction<T> > {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000209 public:
210 typedef NoneType InputObjectType;
211 typedef T OutputObjectType;
212 void PerformAction() {
213 LOG(INFO) << "feeder running!";
214 CHECK(this->processor_);
215 if (this->HasOutputPipe()) {
216 this->SetOutputObject(out_obj_);
217 }
David Zeuthena99981f2013-04-29 13:42:47 -0700218 this->processor_->ActionComplete(this, kErrorCodeSuccess);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000219 }
220 static std::string StaticType() { return "ObjectFeederAction"; }
221 std::string Type() const { return StaticType(); }
222 void set_obj(const T& out_obj) {
223 out_obj_ = out_obj;
224 }
225 private:
226 T out_obj_;
227};
228
229template<typename T>
230class ObjectCollectorAction;
231
232template<typename T>
233class ActionTraits<ObjectCollectorAction<T> > {
234 public:
235 typedef NoneType OutputObjectType;
236 typedef T InputObjectType;
237};
238
239// This is a simple Action class for testing. It receives an object from
240// another action.
241template<typename T>
Yunlian Jianga178e5e2013-04-05 14:41:56 -0700242class ObjectCollectorAction : public Action<ObjectCollectorAction<T> > {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000243 public:
244 typedef T InputObjectType;
245 typedef NoneType OutputObjectType;
246 void PerformAction() {
247 LOG(INFO) << "collector running!";
248 ASSERT_TRUE(this->processor_);
249 if (this->HasInputObject()) {
250 object_ = this->GetInputObject();
251 }
David Zeuthena99981f2013-04-29 13:42:47 -0700252 this->processor_->ActionComplete(this, kErrorCodeSuccess);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000253 }
254 static std::string StaticType() { return "ObjectCollectorAction"; }
255 std::string Type() const { return StaticType(); }
256 const T& object() const { return object_; }
257 private:
258 T object_;
259};
260
Thieu Le5c7d9752010-12-15 16:09:28 -0800261class ScopedLoopMounter {
262 public:
263 explicit ScopedLoopMounter(const std::string& file_path,
264 std::string* mnt_path,
265 unsigned long flags);
266
267 private:
268 // These objects must be destructed in the following order:
269 // ScopedFilesystemUnmounter (the file system must be unmounted first)
Don Garrett58e8b1f2012-01-31 16:38:16 -0800270 // ScopedLoopbackDeviceBinder (then the loop device can be deleted)
Thieu Le5c7d9752010-12-15 16:09:28 -0800271 // ScopedDirRemover (then the mount point can be deleted)
272 scoped_ptr<ScopedDirRemover> dir_remover_;
Don Garrett58e8b1f2012-01-31 16:38:16 -0800273 scoped_ptr<ScopedLoopbackDeviceBinder> loop_binder_;
Thieu Le5c7d9752010-12-15 16:09:28 -0800274 scoped_ptr<ScopedFilesystemUnmounter> unmounter_;
275};
276
rspangler@google.com49fdf182009-10-10 00:57:34 +0000277} // namespace chromeos_update_engine
278
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700279#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_TEST_UTILS_H__