blob: beda7986d7649a254c4980444454cefbabcbc43a [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"
166 " seek=%zu bs=1 count=1",
167 path.c_str(), size)));
168 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b %d -F %s",
169 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"
179 " seek=10485759 bs=1 count=1",
180 path.c_str())));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700181 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b 4096 -F %s", path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000182 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700183 mount_path.c_str())));
184 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
185 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
186 mount_path.c_str())));
187 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
188 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
189 mount_path.c_str())));
190 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
191 mount_path.c_str())));
192 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
193 mount_path.c_str())));
194 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
195 mount_path.c_str())));
196 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
197 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
198 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000199 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700200 mount_path.c_str(), mount_path.c_str())));
201 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
202 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800203 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700204 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800205 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700206 mount_path.c_str())));
207 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800208
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000209 if (out_paths) {
210 out_paths->clear();
211 out_paths->push_back("");
212 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800213 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000214 out_paths->push_back("/hello");
215 out_paths->push_back("/some_dir");
216 out_paths->push_back("/some_dir/empty_dir");
217 out_paths->push_back("/some_dir/mnt");
218 out_paths->push_back("/some_dir/test");
219 out_paths->push_back("/some_dir/fifo");
220 out_paths->push_back("/cdev");
221 out_paths->push_back("/testlink");
222 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800223 out_paths->push_back("/srchardlink0");
224 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000225 out_paths->push_back("/lost+found");
226 }
227}
228
229void VerifyAllPaths(const string& parent, set<string> expected_paths) {
230 FilesystemIterator iter(parent, set<string>());
231 ino_t test_ino = 0;
232 ino_t testlink_ino = 0;
233 while (!iter.IsEnd()) {
234 string path = iter.GetFullPath();
235 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
236 EXPECT_EQ(1, expected_paths.erase(path));
Alex Deymo10875d92014-11-10 21:52:57 -0800237 if (EndsWith(path, "/hi", true) ||
238 EndsWith(path, "/hello", true) ||
239 EndsWith(path, "/test", true) ||
240 EndsWith(path, "/testlink", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000241 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800242 if (EndsWith(path, "/test", true))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000243 test_ino = iter.GetStat().st_ino;
Alex Deymo10875d92014-11-10 21:52:57 -0800244 else if (EndsWith(path, "/testlink", true))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000245 testlink_ino = iter.GetStat().st_ino;
Alex Deymo10875d92014-11-10 21:52:57 -0800246 } else if (EndsWith(path, "/some_dir", true) ||
247 EndsWith(path, "/empty_dir", true) ||
248 EndsWith(path, "/mnt", true) ||
249 EndsWith(path, "/lost+found", true) ||
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000250 parent == path) {
251 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800252 } else if (EndsWith(path, "/fifo", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000253 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800254 } else if (EndsWith(path, "/cdev", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000255 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
Alex Deymo10875d92014-11-10 21:52:57 -0800256 } else if (EndsWith(path, "/sym", true)) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000257 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
258 } else {
259 LOG(INFO) << "got non hardcoded path: " << path;
260 }
261 iter.Increment();
262 }
263 EXPECT_EQ(testlink_ino, test_ino);
264 EXPECT_NE(0, test_ino);
265 EXPECT_FALSE(iter.IsErr());
266 EXPECT_TRUE(expected_paths.empty());
267 if (!expected_paths.empty()) {
Alex Deymo020600d2014-11-05 21:05:55 -0800268 for (const string& path : expected_paths) {
269 LOG(INFO) << "extra path: " << path;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000270 }
271 }
272}
273
Don Garrett58e8b1f2012-01-31 16:38:16 -0800274ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
275 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700276 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800277 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800278 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
279
Don Garrett58e8b1f2012-01-31 16:38:16 -0800280 string loop_dev;
281 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800282
283 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
284 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
285}
286
Alex Deymo10875d92014-11-10 21:52:57 -0800287namespace {
288class ScopedDirCloser {
289 public:
290 explicit ScopedDirCloser(DIR** dir) : dir_(dir) {}
291 ~ScopedDirCloser() {
292 if (dir_ && *dir_) {
293 int r = closedir(*dir_);
294 TEST_AND_RETURN_ERRNO(r == 0);
295 *dir_ = nullptr;
296 dir_ = nullptr;
297 }
298 }
299 private:
300 DIR** dir_;
301};
302} // namespace
303
304bool RecursiveUnlinkDir(const string& path) {
305 struct stat stbuf;
306 int r = lstat(path.c_str(), &stbuf);
307 TEST_AND_RETURN_FALSE_ERRNO((r == 0) || (errno == ENOENT));
308 if ((r < 0) && (errno == ENOENT))
309 // path request is missing. that's fine.
310 return true;
311 if (!S_ISDIR(stbuf.st_mode)) {
312 TEST_AND_RETURN_FALSE_ERRNO((unlink(path.c_str()) == 0) ||
313 (errno == ENOENT));
314 // success or path disappeared before we could unlink.
315 return true;
316 }
317 {
318 // We have a dir, unlink all children, then delete dir
319 DIR *dir = opendir(path.c_str());
320 TEST_AND_RETURN_FALSE_ERRNO(dir);
321 ScopedDirCloser dir_closer(&dir);
322 struct dirent dir_entry;
323 struct dirent *dir_entry_p;
324 int err = 0;
325 while ((err = readdir_r(dir, &dir_entry, &dir_entry_p)) == 0) {
326 if (dir_entry_p == nullptr) {
327 // end of stream reached
328 break;
329 }
330 // Skip . and ..
331 if (!strcmp(dir_entry_p->d_name, ".") ||
332 !strcmp(dir_entry_p->d_name, ".."))
333 continue;
334 TEST_AND_RETURN_FALSE(RecursiveUnlinkDir(path + "/" +
335 dir_entry_p->d_name));
336 }
337 TEST_AND_RETURN_FALSE(err == 0);
338 }
339 // unlink dir
340 TEST_AND_RETURN_FALSE_ERRNO((rmdir(path.c_str()) == 0) || (errno == ENOENT));
341 return true;
342}
343
Alex Deymo53556ec2014-03-17 10:05:57 -0700344static gboolean RunGMainLoopOnTimeout(gpointer user_data) {
345 bool* timeout = static_cast<bool*>(user_data);
346 *timeout = true;
347 return FALSE; // Remove timeout source
348}
349
350void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700351 GMainLoop* loop = g_main_loop_new(nullptr, FALSE);
Alex Deymo53556ec2014-03-17 10:05:57 -0700352 GMainContext* context = g_main_context_default();
353
354 bool timeout = false;
355 guint source_id = g_timeout_add(
356 timeout_msec, RunGMainLoopOnTimeout, &timeout);
357
358 while (!timeout && (terminate.is_null() || !terminate.Run()))
359 g_main_context_iteration(context, TRUE);
360
361 g_source_remove(source_id);
362 g_main_loop_unref(loop);
363}
364
Alex Deymo7b948f02014-03-10 17:01:10 -0700365int RunGMainLoopMaxIterations(int iterations) {
366 int result;
367 GMainContext* context = g_main_context_default();
368 for (result = 0;
369 result < iterations && g_main_context_iteration(context, FALSE);
370 result++) {}
371 return result;
372}
373
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700374GValue* GValueNewString(const char* str) {
Alex Deymo5665d0c2014-05-28 17:45:43 -0700375 GValue* gval = g_new0(GValue, 1);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700376 g_value_init(gval, G_TYPE_STRING);
377 g_value_set_string(gval, str);
378 return gval;
379}
380
381void GValueFree(gpointer arg) {
382 auto gval = reinterpret_cast<GValue*>(arg);
383 g_value_unset(gval);
Alex Deymo5665d0c2014-05-28 17:45:43 -0700384 g_free(gval);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700385}
386
Alex Deymo10875d92014-11-10 21:52:57 -0800387} // namespace test_utils
rspangler@google.com49fdf182009-10-10 00:57:34 +0000388} // namespace chromeos_update_engine