blob: 712df648f3d79e814388cc3b88dbdff04dfaf076 [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// 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#include "update_engine/test_utils.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07006
Alex Deymo10875d92014-11-10 21:52:57 -08007#include <attr/xattr.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>
Alex Deymo161c4a12014-05-16 15:56:21 -070011#include <sys/stat.h>
12#include <sys/types.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000013#include <unistd.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070014
adlr@google.comc98a7ed2009-12-04 18:54:03 +000015#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000016#include <string>
17#include <vector>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070018
Alex Deymo161c4a12014-05-16 15:56:21 -070019#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070020#include <base/strings/string_util.h>
21#include <base/strings/stringprintf.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070022
rspangler@google.com49fdf182009-10-10 00:57:34 +000023#include "update_engine/file_writer.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070024#include "update_engine/payload_generator/filesystem_iterator.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000025#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000026
Alex Deymo161c4a12014-05-16 15:56:21 -070027using base::StringPrintf;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000028using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000029using std::string;
30using std::vector;
31
32namespace chromeos_update_engine {
33
Alex Deymo52490e72015-06-04 14:53:44 +020034void PrintTo(const Extent& extent, ::std::ostream* os) {
35 *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
36}
37
Alex Deymo10875d92014-11-10 21:52:57 -080038namespace test_utils {
39
Gilad Arnolda6742b32014-01-11 00:18:34 -080040const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
Gilad Arnold61d9d2c2013-07-22 17:54:52 -070041
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080042const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080043 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
44 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
45 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
46 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
47 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
48 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
49 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
50 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
51 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
52 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
53 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
54 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
55 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
56 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
57 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
58 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
59 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
60 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
61 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
62 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
63 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
64 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
65 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
66 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
67 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
68 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
69 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
70 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
71 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
72 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
73 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
74 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
75 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
76 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
77 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
78 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
79 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
80 0xbe, 0x9f, 0xa3, 0x5d,
81};
82
83bool IsXAttrSupported(const base::FilePath& dir_path) {
84 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
85
86 int fd = mkstemp(path);
87 if (fd == -1) {
88 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
89 free(path);
90 return false;
91 }
92
93 if (unlink(path) != 0) {
94 PLOG(ERROR) << "Error unlinking temporary file " << path;
95 close(fd);
96 free(path);
97 return false;
98 }
99
100 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
101 if (xattr_res != 0) {
102 if (errno == ENOTSUP) {
103 // Leave it to call-sites to warn about non-support.
104 } else {
105 PLOG(ERROR) << "Error setting xattr on " << path;
106 }
107 }
108 close(fd);
109 free(path);
110 return xattr_res == 0;
111}
112
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800113bool WriteFileVector(const string& path, const chromeos::Blob& data) {
114 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000115}
116
Alex Deymof329b932014-10-30 01:37:48 -0700117bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800118 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000119}
120
Gilad Arnold19a45f02012-07-19 12:36:10 -0700121// Binds provided |filename| to an unused loopback device, whose name is written
122// to the string pointed to by |lo_dev_name_p|. Returns true on success, false
123// otherwise (along with corresponding test failures), in which case the content
124// of |lo_dev_name_p| is unknown.
125bool BindToUnusedLoopDevice(const string& filename, string* lo_dev_name_p) {
126 CHECK(lo_dev_name_p);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800127
Gilad Arnold19a45f02012-07-19 12:36:10 -0700128 // Bind to an unused loopback device, sanity check the device name.
129 lo_dev_name_p->clear();
130 if (!(utils::ReadPipe("losetup --show -f " + filename, lo_dev_name_p) &&
131 StartsWithASCII(*lo_dev_name_p, "/dev/loop", true))) {
132 ADD_FAILURE();
133 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000134 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000135
Gilad Arnold19a45f02012-07-19 12:36:10 -0700136 // Strip anything from the first newline char.
137 size_t newline_pos = lo_dev_name_p->find('\n');
138 if (newline_pos != string::npos)
139 lo_dev_name_p->erase(newline_pos);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000140
Gilad Arnold19a45f02012-07-19 12:36:10 -0700141 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000142}
143
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800144bool ExpectVectorsEq(const chromeos::Blob& expected,
145 const chromeos::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800146 EXPECT_EQ(expected.size(), actual.size());
147 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000148 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700149 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800150 for (unsigned int i = 0; i < expected.size(); i++) {
151 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700152 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000153 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700154 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000155}
156
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800157void FillWithData(chromeos::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800158 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800159 for (uint8_t& b : *buffer) {
160 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800161 input_counter++;
162 input_counter %= sizeof(kRandomString);
163 }
164}
165
Thieu Le5c7d9752010-12-15 16:09:28 -0800166void CreateEmptyExtImageAtPath(const string& path,
167 size_t size,
168 int block_size) {
169 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700170 " seek=%zu bs=1 count=1 status=none",
Thieu Le5c7d9752010-12-15 16:09:28 -0800171 path.c_str(), size)));
Alex Deymo6ded6542015-03-13 15:52:46 -0700172 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
Thieu Le5c7d9752010-12-15 16:09:28 -0800173 block_size, path.c_str())));
174}
175
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000176void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700177 // create 10MiB sparse file, mounted at a unique location.
178 string mount_path;
179 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700180 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700181
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000182 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700183 " seek=10485759 bs=1 count=1 status=none",
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000184 path.c_str())));
Alex Deymo6ded6542015-03-13 15:52:46 -0700185 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
186 path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000187 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700188 mount_path.c_str())));
189 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
190 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
191 mount_path.c_str())));
192 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
193 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
194 mount_path.c_str())));
195 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
196 mount_path.c_str())));
197 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
198 mount_path.c_str())));
199 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
200 mount_path.c_str())));
201 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
202 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
203 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000204 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700205 mount_path.c_str(), mount_path.c_str())));
206 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
207 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800208 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700209 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800210 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700211 mount_path.c_str())));
212 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800213
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000214 if (out_paths) {
215 out_paths->clear();
216 out_paths->push_back("");
217 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800218 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000219 out_paths->push_back("/hello");
220 out_paths->push_back("/some_dir");
221 out_paths->push_back("/some_dir/empty_dir");
222 out_paths->push_back("/some_dir/mnt");
223 out_paths->push_back("/some_dir/test");
224 out_paths->push_back("/some_dir/fifo");
225 out_paths->push_back("/cdev");
226 out_paths->push_back("/testlink");
227 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800228 out_paths->push_back("/srchardlink0");
229 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000230 out_paths->push_back("/lost+found");
231 }
232}
233
234void VerifyAllPaths(const string& parent, set<string> expected_paths) {
235 FilesystemIterator iter(parent, set<string>());
236 ino_t test_ino = 0;
237 ino_t testlink_ino = 0;
238 while (!iter.IsEnd()) {
239 string path = iter.GetFullPath();
240 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
241 EXPECT_EQ(1, expected_paths.erase(path));
Alex Deymo10875d92014-11-10 21:52:57 -0800242 if (EndsWith(path, "/hi", true) ||
243 EndsWith(path, "/hello", true) ||
244 EndsWith(path, "/test", true) ||
245 EndsWith(path, "/testlink", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000246 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800247 if (EndsWith(path, "/test", true))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000248 test_ino = iter.GetStat().st_ino;
Alex Deymo10875d92014-11-10 21:52:57 -0800249 else if (EndsWith(path, "/testlink", true))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000250 testlink_ino = iter.GetStat().st_ino;
Alex Deymo10875d92014-11-10 21:52:57 -0800251 } else if (EndsWith(path, "/some_dir", true) ||
252 EndsWith(path, "/empty_dir", true) ||
253 EndsWith(path, "/mnt", true) ||
254 EndsWith(path, "/lost+found", true) ||
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000255 parent == path) {
256 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800257 } else if (EndsWith(path, "/fifo", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000258 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800259 } else if (EndsWith(path, "/cdev", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000260 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800261 } else if (EndsWith(path, "/sym", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000262 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
263 } else {
264 LOG(INFO) << "got non hardcoded path: " << path;
265 }
266 iter.Increment();
267 }
268 EXPECT_EQ(testlink_ino, test_ino);
269 EXPECT_NE(0, test_ino);
270 EXPECT_FALSE(iter.IsErr());
271 EXPECT_TRUE(expected_paths.empty());
272 if (!expected_paths.empty()) {
Alex Deymo020600d2014-11-05 21:05:55 -0800273 for (const string& path : expected_paths) {
274 LOG(INFO) << "extra path: " << path;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000275 }
276 }
277}
278
Don Garrett58e8b1f2012-01-31 16:38:16 -0800279ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
280 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700281 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800282 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800283 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
284
Don Garrett58e8b1f2012-01-31 16:38:16 -0800285 string loop_dev;
286 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800287
288 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
289 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
290}
291
Alex Deymo10875d92014-11-10 21:52:57 -0800292namespace {
293class ScopedDirCloser {
294 public:
295 explicit ScopedDirCloser(DIR** dir) : dir_(dir) {}
296 ~ScopedDirCloser() {
297 if (dir_ && *dir_) {
298 int r = closedir(*dir_);
299 TEST_AND_RETURN_ERRNO(r == 0);
300 *dir_ = nullptr;
301 dir_ = nullptr;
302 }
303 }
304 private:
305 DIR** dir_;
306};
307} // namespace
308
309bool RecursiveUnlinkDir(const string& path) {
310 struct stat stbuf;
311 int r = lstat(path.c_str(), &stbuf);
312 TEST_AND_RETURN_FALSE_ERRNO((r == 0) || (errno == ENOENT));
313 if ((r < 0) && (errno == ENOENT))
314 // path request is missing. that's fine.
315 return true;
316 if (!S_ISDIR(stbuf.st_mode)) {
317 TEST_AND_RETURN_FALSE_ERRNO((unlink(path.c_str()) == 0) ||
318 (errno == ENOENT));
319 // success or path disappeared before we could unlink.
320 return true;
321 }
322 {
323 // We have a dir, unlink all children, then delete dir
324 DIR *dir = opendir(path.c_str());
325 TEST_AND_RETURN_FALSE_ERRNO(dir);
326 ScopedDirCloser dir_closer(&dir);
327 struct dirent dir_entry;
328 struct dirent *dir_entry_p;
329 int err = 0;
330 while ((err = readdir_r(dir, &dir_entry, &dir_entry_p)) == 0) {
331 if (dir_entry_p == nullptr) {
332 // end of stream reached
333 break;
334 }
335 // Skip . and ..
336 if (!strcmp(dir_entry_p->d_name, ".") ||
337 !strcmp(dir_entry_p->d_name, ".."))
338 continue;
339 TEST_AND_RETURN_FALSE(RecursiveUnlinkDir(path + "/" +
340 dir_entry_p->d_name));
341 }
342 TEST_AND_RETURN_FALSE(err == 0);
343 }
344 // unlink dir
345 TEST_AND_RETURN_FALSE_ERRNO((rmdir(path.c_str()) == 0) || (errno == ENOENT));
346 return true;
347}
348
Alex Deymo53556ec2014-03-17 10:05:57 -0700349static gboolean RunGMainLoopOnTimeout(gpointer user_data) {
350 bool* timeout = static_cast<bool*>(user_data);
351 *timeout = true;
352 return FALSE; // Remove timeout source
353}
354
355void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700356 GMainLoop* loop = g_main_loop_new(nullptr, FALSE);
Alex Deymo53556ec2014-03-17 10:05:57 -0700357 GMainContext* context = g_main_context_default();
358
359 bool timeout = false;
360 guint source_id = g_timeout_add(
361 timeout_msec, RunGMainLoopOnTimeout, &timeout);
362
363 while (!timeout && (terminate.is_null() || !terminate.Run()))
364 g_main_context_iteration(context, TRUE);
365
366 g_source_remove(source_id);
367 g_main_loop_unref(loop);
368}
369
Alex Deymo7b948f02014-03-10 17:01:10 -0700370int RunGMainLoopMaxIterations(int iterations) {
371 int result;
372 GMainContext* context = g_main_context_default();
373 for (result = 0;
374 result < iterations && g_main_context_iteration(context, FALSE);
375 result++) {}
376 return result;
377}
378
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700379GValue* GValueNewString(const char* str) {
Alex Deymo5665d0c2014-05-28 17:45:43 -0700380 GValue* gval = g_new0(GValue, 1);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700381 g_value_init(gval, G_TYPE_STRING);
382 g_value_set_string(gval, str);
383 return gval;
384}
385
386void GValueFree(gpointer arg) {
387 auto gval = reinterpret_cast<GValue*>(arg);
388 g_value_unset(gval);
Alex Deymo5665d0c2014-05-28 17:45:43 -0700389 g_free(gval);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700390}
391
Alex Deymo10875d92014-11-10 21:52:57 -0800392} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000393} // namespace chromeos_update_engine