blob: 2b72af1b5042c84243aeba8fa92ae27eb24935f9 [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
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000115} // namespace {}
116
Thieu Le5c7d9752010-12-15 16:09:28 -0800117// Creates an empty ext image.
118void CreateEmptyExtImageAtPath(const std::string& path,
119 size_t size,
120 int block_size);
121
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000122// Creates an ext image with some files in it. The paths creates are
123// returned in out_paths.
124void CreateExtImageAtPath(const std::string& path,
125 std::vector<std::string>* out_paths);
126
127// Verifies that for each path in paths, it exists in the filesystem under
128// parent. Also, verifies that no additional paths are present under parent.
129// Also tests properties of various files created by CreateExtImageAtPath().
130// Intentionally copies expected_paths.
131void VerifyAllPaths(const std::string& parent,
132 std::set<std::string> expected_paths);
133
Don Garrett58e8b1f2012-01-31 16:38:16 -0800134class ScopedLoopbackDeviceBinder {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700135 public:
Don Garrett58e8b1f2012-01-31 16:38:16 -0800136 ScopedLoopbackDeviceBinder(const std::string& file, std::string* dev) {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700137 is_bound_ = BindToUnusedLoopDevice(file, &dev_);
138 EXPECT_TRUE(is_bound_);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800139
Gilad Arnold19a45f02012-07-19 12:36:10 -0700140 if (is_bound_ && dev)
Don Garrett58e8b1f2012-01-31 16:38:16 -0800141 *dev = dev_;
142 }
143
144 ~ScopedLoopbackDeviceBinder() {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700145 if (!is_bound_)
146 return;
147
Darin Petkovcf562482010-12-03 10:31:00 -0800148 for (int retry = 0; retry < 5; retry++) {
149 std::vector<std::string> args;
150 args.push_back("/sbin/losetup");
151 args.push_back("-d");
152 args.push_back(dev_);
153 int return_code = 0;
Darin Petkov85d02b72011-05-17 13:25:51 -0700154 EXPECT_TRUE(Subprocess::SynchronousExec(args, &return_code, NULL));
Darin Petkovcf562482010-12-03 10:31:00 -0800155 if (return_code == 0) {
156 return;
157 }
158 sleep(1);
159 }
160 ADD_FAILURE();
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700161 }
Don Garrett58e8b1f2012-01-31 16:38:16 -0800162
Gilad Arnold19a45f02012-07-19 12:36:10 -0700163 const std::string &dev() {
164 EXPECT_TRUE(is_bound_);
165 return dev_;
166 }
Don Garrett58e8b1f2012-01-31 16:38:16 -0800167
Gilad Arnoldc33faeb2012-07-24 15:11:11 -0700168 bool is_bound() const { return is_bound_; }
169
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700170 private:
Don Garrett58e8b1f2012-01-31 16:38:16 -0800171 std::string dev_;
Gilad Arnold19a45f02012-07-19 12:36:10 -0700172 bool is_bound_;
Don Garrett58e8b1f2012-01-31 16:38:16 -0800173 DISALLOW_COPY_AND_ASSIGN(ScopedLoopbackDeviceBinder);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700174};
175
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700176class ScopedTempFile {
177 public:
178 ScopedTempFile() {
179 EXPECT_TRUE(utils::MakeTempFile("/tmp/update_engine_test_temp_file.XXXXXX",
180 &path_,
181 NULL));
182 unlinker_.reset(new ScopedPathUnlinker(path_));
183 }
184 const std::string& GetPath() { return path_; }
185 private:
186 std::string path_;
187 scoped_ptr<ScopedPathUnlinker> unlinker_;
188};
189
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000190// Useful actions for test
191
192class NoneType;
193
194template<typename T>
195class ObjectFeederAction;
196
197template<typename T>
198class ActionTraits<ObjectFeederAction<T> > {
199 public:
200 typedef T OutputObjectType;
201 typedef NoneType InputObjectType;
202};
203
204// This is a simple Action class for testing. It feeds an object into
205// another action.
206template<typename T>
Yunlian Jianga178e5e2013-04-05 14:41:56 -0700207class ObjectFeederAction : public Action<ObjectFeederAction<T> > {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000208 public:
209 typedef NoneType InputObjectType;
210 typedef T OutputObjectType;
211 void PerformAction() {
212 LOG(INFO) << "feeder running!";
213 CHECK(this->processor_);
214 if (this->HasOutputPipe()) {
215 this->SetOutputObject(out_obj_);
216 }
David Zeuthena99981f2013-04-29 13:42:47 -0700217 this->processor_->ActionComplete(this, kErrorCodeSuccess);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000218 }
219 static std::string StaticType() { return "ObjectFeederAction"; }
220 std::string Type() const { return StaticType(); }
221 void set_obj(const T& out_obj) {
222 out_obj_ = out_obj;
223 }
224 private:
225 T out_obj_;
226};
227
228template<typename T>
229class ObjectCollectorAction;
230
231template<typename T>
232class ActionTraits<ObjectCollectorAction<T> > {
233 public:
234 typedef NoneType OutputObjectType;
235 typedef T InputObjectType;
236};
237
238// This is a simple Action class for testing. It receives an object from
239// another action.
240template<typename T>
Yunlian Jianga178e5e2013-04-05 14:41:56 -0700241class ObjectCollectorAction : public Action<ObjectCollectorAction<T> > {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000242 public:
243 typedef T InputObjectType;
244 typedef NoneType OutputObjectType;
245 void PerformAction() {
246 LOG(INFO) << "collector running!";
247 ASSERT_TRUE(this->processor_);
248 if (this->HasInputObject()) {
249 object_ = this->GetInputObject();
250 }
David Zeuthena99981f2013-04-29 13:42:47 -0700251 this->processor_->ActionComplete(this, kErrorCodeSuccess);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000252 }
253 static std::string StaticType() { return "ObjectCollectorAction"; }
254 std::string Type() const { return StaticType(); }
255 const T& object() const { return object_; }
256 private:
257 T object_;
258};
259
Thieu Le5c7d9752010-12-15 16:09:28 -0800260class ScopedLoopMounter {
261 public:
262 explicit ScopedLoopMounter(const std::string& file_path,
263 std::string* mnt_path,
264 unsigned long flags);
265
266 private:
267 // These objects must be destructed in the following order:
268 // ScopedFilesystemUnmounter (the file system must be unmounted first)
Don Garrett58e8b1f2012-01-31 16:38:16 -0800269 // ScopedLoopbackDeviceBinder (then the loop device can be deleted)
Thieu Le5c7d9752010-12-15 16:09:28 -0800270 // ScopedDirRemover (then the mount point can be deleted)
271 scoped_ptr<ScopedDirRemover> dir_remover_;
Don Garrett58e8b1f2012-01-31 16:38:16 -0800272 scoped_ptr<ScopedLoopbackDeviceBinder> loop_binder_;
Thieu Le5c7d9752010-12-15 16:09:28 -0800273 scoped_ptr<ScopedFilesystemUnmounter> unmounter_;
274};
275
rspangler@google.com49fdf182009-10-10 00:57:34 +0000276} // namespace chromeos_update_engine
277
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700278#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_TEST_UTILS_H__