blob: 73f29c6e6b3c3388debee12eed95bee0cbd70716 [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
Gilad Arnoldcf175a02014-07-10 16:48:47 -07005#ifndef UPDATE_ENGINE_TEST_UTILS_H_
6#define 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
Ben Chan02f7c1d2014-10-18 15:18:02 -070012#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000013#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000014#include <string>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000015#include <vector>
Thieu Le5c7d9752010-12-15 16:09:28 -080016
Alex Deymo53556ec2014-03-17 10:05:57 -070017#include <base/callback.h>
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070018#include <glib-object.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000019#include <gtest/gtest.h>
Thieu Le5c7d9752010-12-15 16:09:28 -080020
adlr@google.comc98a7ed2009-12-04 18:54:03 +000021#include "update_engine/action.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070022#include "update_engine/subprocess.h"
Andrew de los Reyesf9185172010-05-03 11:07:05 -070023#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000024
25// These are some handy functions for unittests.
26
27namespace chromeos_update_engine {
28
rspangler@google.com49fdf182009-10-10 00:57:34 +000029// Writes the data passed to path. The file at path will be overwritten if it
30// exists. Returns true on success, false otherwise.
adlr@google.comc98a7ed2009-12-04 18:54:03 +000031bool WriteFileVector(const std::string& path, const std::vector<char>& data);
32bool WriteFileString(const std::string& path, const std::string& data);
rspangler@google.com49fdf182009-10-10 00:57:34 +000033
Gilad Arnold19a45f02012-07-19 12:36:10 -070034bool BindToUnusedLoopDevice(const std::string &filename,
35 std::string* lo_dev_name_ptr);
adlr@google.comc98a7ed2009-12-04 18:54:03 +000036
37// Returns true iff a == b
38bool ExpectVectorsEq(const std::vector<char>& a, const std::vector<char>& b);
39
40inline int System(const std::string& cmd) {
41 return system(cmd.c_str());
42}
43
Gilad Arnold2c2b8842013-07-16 06:44:37 -070044inline int Symlink(const std::string& oldpath, const std::string& newpath) {
45 return symlink(oldpath.c_str(), newpath.c_str());
46}
47
48inline int Chmod(const std::string& path, mode_t mode) {
49 return chmod(path.c_str(), mode);
50}
51
52inline int Mkdir(const std::string& path, mode_t mode) {
53 return mkdir(path.c_str(), mode);
54}
55
Gilad Arnold30dedd82013-07-03 06:19:09 -070056inline int Chdir(const std::string& path) {
57 return chdir(path.c_str());
58}
59
Andrew de los Reyes80061062010-02-04 14:25:00 -080060void FillWithData(std::vector<char>* buffer);
61
Alex Vakulenkod2779df2014-06-16 13:19:00 -070062namespace { // NOLINT(build/namespaces) - anon. NS in header file.
adlr@google.comc98a7ed2009-12-04 18:54:03 +000063// 300 byte pseudo-random string. Not null terminated.
64// This does not gzip compress well.
65const unsigned char kRandomString[] = {
66 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
67 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
68 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
69 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
70 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
71 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
72 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
73 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
74 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
75 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
76 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
77 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
78 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
79 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
80 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
81 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
82 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
83 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
84 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
85 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
86 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
87 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
88 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
89 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
90 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
91 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
92 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
93 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
94 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
95 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
96 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
97 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
98 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
99 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
100 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
101 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
102 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
103 0xbe, 0x9f, 0xa3, 0x5d
104};
105
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700106} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000107
Thieu Le5c7d9752010-12-15 16:09:28 -0800108// Creates an empty ext image.
109void CreateEmptyExtImageAtPath(const std::string& path,
110 size_t size,
111 int block_size);
112
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000113// Creates an ext image with some files in it. The paths creates are
114// returned in out_paths.
115void CreateExtImageAtPath(const std::string& path,
116 std::vector<std::string>* out_paths);
117
118// Verifies that for each path in paths, it exists in the filesystem under
119// parent. Also, verifies that no additional paths are present under parent.
120// Also tests properties of various files created by CreateExtImageAtPath().
121// Intentionally copies expected_paths.
122void VerifyAllPaths(const std::string& parent,
123 std::set<std::string> expected_paths);
124
Don Garrett58e8b1f2012-01-31 16:38:16 -0800125class ScopedLoopbackDeviceBinder {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700126 public:
Don Garrett58e8b1f2012-01-31 16:38:16 -0800127 ScopedLoopbackDeviceBinder(const std::string& file, std::string* dev) {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700128 is_bound_ = BindToUnusedLoopDevice(file, &dev_);
129 EXPECT_TRUE(is_bound_);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800130
Gilad Arnold19a45f02012-07-19 12:36:10 -0700131 if (is_bound_ && dev)
Don Garrett58e8b1f2012-01-31 16:38:16 -0800132 *dev = dev_;
133 }
134
135 ~ScopedLoopbackDeviceBinder() {
Gilad Arnold19a45f02012-07-19 12:36:10 -0700136 if (!is_bound_)
137 return;
138
Darin Petkovcf562482010-12-03 10:31:00 -0800139 for (int retry = 0; retry < 5; retry++) {
140 std::vector<std::string> args;
141 args.push_back("/sbin/losetup");
142 args.push_back("-d");
143 args.push_back(dev_);
144 int return_code = 0;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700145 EXPECT_TRUE(Subprocess::SynchronousExec(args, &return_code, nullptr));
Darin Petkovcf562482010-12-03 10:31:00 -0800146 if (return_code == 0) {
147 return;
148 }
149 sleep(1);
150 }
151 ADD_FAILURE();
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700152 }
Don Garrett58e8b1f2012-01-31 16:38:16 -0800153
Gilad Arnold19a45f02012-07-19 12:36:10 -0700154 const std::string &dev() {
155 EXPECT_TRUE(is_bound_);
156 return dev_;
157 }
Don Garrett58e8b1f2012-01-31 16:38:16 -0800158
Gilad Arnoldc33faeb2012-07-24 15:11:11 -0700159 bool is_bound() const { return is_bound_; }
160
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700161 private:
Don Garrett58e8b1f2012-01-31 16:38:16 -0800162 std::string dev_;
Gilad Arnold19a45f02012-07-19 12:36:10 -0700163 bool is_bound_;
Don Garrett58e8b1f2012-01-31 16:38:16 -0800164 DISALLOW_COPY_AND_ASSIGN(ScopedLoopbackDeviceBinder);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700165};
166
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700167class ScopedTempFile {
168 public:
169 ScopedTempFile() {
170 EXPECT_TRUE(utils::MakeTempFile("/tmp/update_engine_test_temp_file.XXXXXX",
171 &path_,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700172 nullptr));
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700173 unlinker_.reset(new ScopedPathUnlinker(path_));
174 }
175 const std::string& GetPath() { return path_; }
176 private:
177 std::string path_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700178 std::unique_ptr<ScopedPathUnlinker> unlinker_;
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700179};
180
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000181// Useful actions for test
182
183class NoneType;
184
185template<typename T>
186class ObjectFeederAction;
187
188template<typename T>
Ben Chanf9cb98c2014-09-21 18:31:30 -0700189class ActionTraits<ObjectFeederAction<T>> {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000190 public:
191 typedef T OutputObjectType;
192 typedef NoneType InputObjectType;
193};
194
195// This is a simple Action class for testing. It feeds an object into
196// another action.
197template<typename T>
Ben Chanf9cb98c2014-09-21 18:31:30 -0700198class ObjectFeederAction : public Action<ObjectFeederAction<T>> {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000199 public:
200 typedef NoneType InputObjectType;
201 typedef T OutputObjectType;
202 void PerformAction() {
203 LOG(INFO) << "feeder running!";
204 CHECK(this->processor_);
205 if (this->HasOutputPipe()) {
206 this->SetOutputObject(out_obj_);
207 }
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700208 this->processor_->ActionComplete(this, ErrorCode::kSuccess);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000209 }
210 static std::string StaticType() { return "ObjectFeederAction"; }
211 std::string Type() const { return StaticType(); }
212 void set_obj(const T& out_obj) {
213 out_obj_ = out_obj;
214 }
215 private:
216 T out_obj_;
217};
218
219template<typename T>
220class ObjectCollectorAction;
221
222template<typename T>
Ben Chanf9cb98c2014-09-21 18:31:30 -0700223class ActionTraits<ObjectCollectorAction<T>> {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000224 public:
225 typedef NoneType OutputObjectType;
226 typedef T InputObjectType;
227};
228
229// This is a simple Action class for testing. It receives an object from
230// another action.
231template<typename T>
Ben Chanf9cb98c2014-09-21 18:31:30 -0700232class ObjectCollectorAction : public Action<ObjectCollectorAction<T>> {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000233 public:
234 typedef T InputObjectType;
235 typedef NoneType OutputObjectType;
236 void PerformAction() {
237 LOG(INFO) << "collector running!";
238 ASSERT_TRUE(this->processor_);
239 if (this->HasInputObject()) {
240 object_ = this->GetInputObject();
241 }
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700242 this->processor_->ActionComplete(this, ErrorCode::kSuccess);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000243 }
244 static std::string StaticType() { return "ObjectCollectorAction"; }
245 std::string Type() const { return StaticType(); }
246 const T& object() const { return object_; }
247 private:
248 T object_;
249};
250
Thieu Le5c7d9752010-12-15 16:09:28 -0800251class ScopedLoopMounter {
252 public:
253 explicit ScopedLoopMounter(const std::string& file_path,
254 std::string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700255 unsigned long flags); // NOLINT(runtime/int)
Thieu Le5c7d9752010-12-15 16:09:28 -0800256
257 private:
258 // These objects must be destructed in the following order:
259 // ScopedFilesystemUnmounter (the file system must be unmounted first)
Don Garrett58e8b1f2012-01-31 16:38:16 -0800260 // ScopedLoopbackDeviceBinder (then the loop device can be deleted)
Thieu Le5c7d9752010-12-15 16:09:28 -0800261 // ScopedDirRemover (then the mount point can be deleted)
Ben Chan02f7c1d2014-10-18 15:18:02 -0700262 std::unique_ptr<ScopedDirRemover> dir_remover_;
263 std::unique_ptr<ScopedLoopbackDeviceBinder> loop_binder_;
264 std::unique_ptr<ScopedFilesystemUnmounter> unmounter_;
Thieu Le5c7d9752010-12-15 16:09:28 -0800265};
266
Alex Deymo53556ec2014-03-17 10:05:57 -0700267// Runs the default GLib main loop for at most |timeout_msec| or until the
268// function |terminate| returns true, whichever happens first. The function
269// |terminate| is called before every GLib main loop iteration and its value is
270// checked.
271void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate);
272
Alex Deymo7b948f02014-03-10 17:01:10 -0700273// Runs the default GLib main loop at most |iterations| times. This
274// dispatches all the events that are already waiting in the main loop and
275// those that get scheduled as a result of these events being attended.
276// Returns the number of iterations the main loop was ran. If there are more
277// than |iterations| events to attend, then this function returns |iterations|
278// and the remaining events are not dispatched.
279int RunGMainLoopMaxIterations(int iterations);
280
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700281// Allocates, initializes and returns a string GValue object.
282GValue* GValueNewString(const char* str);
283
284// Frees a GValue object and its allocated resources.
285void GValueFree(gpointer arg);
286
rspangler@google.com49fdf182009-10-10 00:57:34 +0000287} // namespace chromeos_update_engine
288
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700289#endif // UPDATE_ENGINE_TEST_UTILS_H_