blob: e2361a52878e24d46f8945e166360453c25ddbc2 [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 Deymo10875d92014-11-10 21:52:57 -080034namespace test_utils {
35
Gilad Arnolda6742b32014-01-11 00:18:34 -080036const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
Gilad Arnold61d9d2c2013-07-22 17:54:52 -070037
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080038const uint8_t kRandomString[] = {
Alex Deymo10875d92014-11-10 21:52:57 -080039 0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
40 0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
41 0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
42 0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
43 0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
44 0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
45 0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
46 0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
47 0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
48 0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
49 0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
50 0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
51 0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
52 0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
53 0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
54 0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
55 0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
56 0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
57 0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
58 0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
59 0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
60 0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
61 0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
62 0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
63 0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
64 0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
65 0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
66 0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
67 0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
68 0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
69 0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
70 0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
71 0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
72 0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
73 0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
74 0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
75 0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
76 0xbe, 0x9f, 0xa3, 0x5d,
77};
78
79bool IsXAttrSupported(const base::FilePath& dir_path) {
80 char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
81
82 int fd = mkstemp(path);
83 if (fd == -1) {
84 PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
85 free(path);
86 return false;
87 }
88
89 if (unlink(path) != 0) {
90 PLOG(ERROR) << "Error unlinking temporary file " << path;
91 close(fd);
92 free(path);
93 return false;
94 }
95
96 int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
97 if (xattr_res != 0) {
98 if (errno == ENOTSUP) {
99 // Leave it to call-sites to warn about non-support.
100 } else {
101 PLOG(ERROR) << "Error setting xattr on " << path;
102 }
103 }
104 close(fd);
105 free(path);
106 return xattr_res == 0;
107}
108
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800109bool WriteFileVector(const string& path, const chromeos::Blob& data) {
110 return utils::WriteFile(path.c_str(), data.data(), data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000111}
112
Alex Deymof329b932014-10-30 01:37:48 -0700113bool WriteFileString(const string& path, const string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -0800114 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000115}
116
Gilad Arnold19a45f02012-07-19 12:36:10 -0700117// Binds provided |filename| to an unused loopback device, whose name is written
118// to the string pointed to by |lo_dev_name_p|. Returns true on success, false
119// otherwise (along with corresponding test failures), in which case the content
120// of |lo_dev_name_p| is unknown.
121bool BindToUnusedLoopDevice(const string& filename, string* lo_dev_name_p) {
122 CHECK(lo_dev_name_p);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800123
Gilad Arnold19a45f02012-07-19 12:36:10 -0700124 // Bind to an unused loopback device, sanity check the device name.
125 lo_dev_name_p->clear();
126 if (!(utils::ReadPipe("losetup --show -f " + filename, lo_dev_name_p) &&
127 StartsWithASCII(*lo_dev_name_p, "/dev/loop", true))) {
128 ADD_FAILURE();
129 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000130 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000131
Gilad Arnold19a45f02012-07-19 12:36:10 -0700132 // Strip anything from the first newline char.
133 size_t newline_pos = lo_dev_name_p->find('\n');
134 if (newline_pos != string::npos)
135 lo_dev_name_p->erase(newline_pos);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000136
Gilad Arnold19a45f02012-07-19 12:36:10 -0700137 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000138}
139
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800140bool ExpectVectorsEq(const chromeos::Blob& expected,
141 const chromeos::Blob& actual) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800142 EXPECT_EQ(expected.size(), actual.size());
143 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000144 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700145 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800146 for (unsigned int i = 0; i < expected.size(); i++) {
147 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700148 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000149 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700150 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000151}
152
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800153void FillWithData(chromeos::Blob* buffer) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800154 size_t input_counter = 0;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800155 for (uint8_t& b : *buffer) {
156 b = kRandomString[input_counter];
Andrew de los Reyes80061062010-02-04 14:25:00 -0800157 input_counter++;
158 input_counter %= sizeof(kRandomString);
159 }
160}
161
Thieu Le5c7d9752010-12-15 16:09:28 -0800162void CreateEmptyExtImageAtPath(const string& path,
163 size_t size,
164 int block_size) {
165 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700166 " seek=%zu bs=1 count=1 status=none",
Thieu Le5c7d9752010-12-15 16:09:28 -0800167 path.c_str(), size)));
Alex Deymo6ded6542015-03-13 15:52:46 -0700168 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
Thieu Le5c7d9752010-12-15 16:09:28 -0800169 block_size, path.c_str())));
170}
171
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000172void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700173 // create 10MiB sparse file, mounted at a unique location.
174 string mount_path;
175 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700176 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700177
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000178 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
Alex Deymo1f93d032015-03-10 18:58:32 -0700179 " seek=10485759 bs=1 count=1 status=none",
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000180 path.c_str())));
Alex Deymo6ded6542015-03-13 15:52:46 -0700181 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
182 path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000183 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700184 mount_path.c_str())));
185 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
186 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
187 mount_path.c_str())));
188 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
189 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
190 mount_path.c_str())));
191 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
192 mount_path.c_str())));
193 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
194 mount_path.c_str())));
195 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
196 mount_path.c_str())));
197 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
198 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
199 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000200 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700201 mount_path.c_str(), mount_path.c_str())));
202 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
203 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800204 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700205 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800206 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700207 mount_path.c_str())));
208 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800209
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000210 if (out_paths) {
211 out_paths->clear();
212 out_paths->push_back("");
213 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800214 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000215 out_paths->push_back("/hello");
216 out_paths->push_back("/some_dir");
217 out_paths->push_back("/some_dir/empty_dir");
218 out_paths->push_back("/some_dir/mnt");
219 out_paths->push_back("/some_dir/test");
220 out_paths->push_back("/some_dir/fifo");
221 out_paths->push_back("/cdev");
222 out_paths->push_back("/testlink");
223 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800224 out_paths->push_back("/srchardlink0");
225 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000226 out_paths->push_back("/lost+found");
227 }
228}
229
230void VerifyAllPaths(const string& parent, set<string> expected_paths) {
231 FilesystemIterator iter(parent, set<string>());
232 ino_t test_ino = 0;
233 ino_t testlink_ino = 0;
234 while (!iter.IsEnd()) {
235 string path = iter.GetFullPath();
236 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
237 EXPECT_EQ(1, expected_paths.erase(path));
Alex Deymo10875d92014-11-10 21:52:57 -0800238 if (EndsWith(path, "/hi", true) ||
239 EndsWith(path, "/hello", true) ||
240 EndsWith(path, "/test", true) ||
241 EndsWith(path, "/testlink", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000242 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800243 if (EndsWith(path, "/test", true))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000244 test_ino = iter.GetStat().st_ino;
Alex Deymo10875d92014-11-10 21:52:57 -0800245 else if (EndsWith(path, "/testlink", true))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000246 testlink_ino = iter.GetStat().st_ino;
Alex Deymo10875d92014-11-10 21:52:57 -0800247 } else if (EndsWith(path, "/some_dir", true) ||
248 EndsWith(path, "/empty_dir", true) ||
249 EndsWith(path, "/mnt", true) ||
250 EndsWith(path, "/lost+found", true) ||
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000251 parent == path) {
252 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800253 } else if (EndsWith(path, "/fifo", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000254 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800255 } else if (EndsWith(path, "/cdev", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000256 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800257 } else if (EndsWith(path, "/sym", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000258 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
259 } else {
260 LOG(INFO) << "got non hardcoded path: " << path;
261 }
262 iter.Increment();
263 }
264 EXPECT_EQ(testlink_ino, test_ino);
265 EXPECT_NE(0, test_ino);
266 EXPECT_FALSE(iter.IsErr());
267 EXPECT_TRUE(expected_paths.empty());
268 if (!expected_paths.empty()) {
Alex Deymo020600d2014-11-05 21:05:55 -0800269 for (const string& path : expected_paths) {
270 LOG(INFO) << "extra path: " << path;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000271 }
272 }
273}
274
Don Garrett58e8b1f2012-01-31 16:38:16 -0800275ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
276 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700277 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800278 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800279 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
280
Don Garrett58e8b1f2012-01-31 16:38:16 -0800281 string loop_dev;
282 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800283
284 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
285 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
286}
287
Alex Deymo10875d92014-11-10 21:52:57 -0800288namespace {
289class ScopedDirCloser {
290 public:
291 explicit ScopedDirCloser(DIR** dir) : dir_(dir) {}
292 ~ScopedDirCloser() {
293 if (dir_ && *dir_) {
294 int r = closedir(*dir_);
295 TEST_AND_RETURN_ERRNO(r == 0);
296 *dir_ = nullptr;
297 dir_ = nullptr;
298 }
299 }
300 private:
301 DIR** dir_;
302};
303} // namespace
304
305bool RecursiveUnlinkDir(const string& path) {
306 struct stat stbuf;
307 int r = lstat(path.c_str(), &stbuf);
308 TEST_AND_RETURN_FALSE_ERRNO((r == 0) || (errno == ENOENT));
309 if ((r < 0) && (errno == ENOENT))
310 // path request is missing. that's fine.
311 return true;
312 if (!S_ISDIR(stbuf.st_mode)) {
313 TEST_AND_RETURN_FALSE_ERRNO((unlink(path.c_str()) == 0) ||
314 (errno == ENOENT));
315 // success or path disappeared before we could unlink.
316 return true;
317 }
318 {
319 // We have a dir, unlink all children, then delete dir
320 DIR *dir = opendir(path.c_str());
321 TEST_AND_RETURN_FALSE_ERRNO(dir);
322 ScopedDirCloser dir_closer(&dir);
323 struct dirent dir_entry;
324 struct dirent *dir_entry_p;
325 int err = 0;
326 while ((err = readdir_r(dir, &dir_entry, &dir_entry_p)) == 0) {
327 if (dir_entry_p == nullptr) {
328 // end of stream reached
329 break;
330 }
331 // Skip . and ..
332 if (!strcmp(dir_entry_p->d_name, ".") ||
333 !strcmp(dir_entry_p->d_name, ".."))
334 continue;
335 TEST_AND_RETURN_FALSE(RecursiveUnlinkDir(path + "/" +
336 dir_entry_p->d_name));
337 }
338 TEST_AND_RETURN_FALSE(err == 0);
339 }
340 // unlink dir
341 TEST_AND_RETURN_FALSE_ERRNO((rmdir(path.c_str()) == 0) || (errno == ENOENT));
342 return true;
343}
344
Alex Deymo53556ec2014-03-17 10:05:57 -0700345static gboolean RunGMainLoopOnTimeout(gpointer user_data) {
346 bool* timeout = static_cast<bool*>(user_data);
347 *timeout = true;
348 return FALSE; // Remove timeout source
349}
350
351void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700352 GMainLoop* loop = g_main_loop_new(nullptr, FALSE);
Alex Deymo53556ec2014-03-17 10:05:57 -0700353 GMainContext* context = g_main_context_default();
354
355 bool timeout = false;
356 guint source_id = g_timeout_add(
357 timeout_msec, RunGMainLoopOnTimeout, &timeout);
358
359 while (!timeout && (terminate.is_null() || !terminate.Run()))
360 g_main_context_iteration(context, TRUE);
361
362 g_source_remove(source_id);
363 g_main_loop_unref(loop);
364}
365
Alex Deymo7b948f02014-03-10 17:01:10 -0700366int RunGMainLoopMaxIterations(int iterations) {
367 int result;
368 GMainContext* context = g_main_context_default();
369 for (result = 0;
370 result < iterations && g_main_context_iteration(context, FALSE);
371 result++) {}
372 return result;
373}
374
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700375GValue* GValueNewString(const char* str) {
Alex Deymo5665d0c2014-05-28 17:45:43 -0700376 GValue* gval = g_new0(GValue, 1);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700377 g_value_init(gval, G_TYPE_STRING);
378 g_value_set_string(gval, str);
379 return gval;
380}
381
382void GValueFree(gpointer arg) {
383 auto gval = reinterpret_cast<GValue*>(arg);
384 g_value_unset(gval);
Alex Deymo5665d0c2014-05-28 17:45:43 -0700385 g_free(gval);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700386}
387
Alex Deymo10875d92014-11-10 21:52:57 -0800388} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000389} // namespace chromeos_update_engine