blob: 0005f03f019bac6ba023f726dbfde7300d19ed5d [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
rspangler@google.com49fdf182009-10-10 00:57:34 +00007#include <sys/stat.h>
8#include <sys/types.h>
adlr@google.comc98a7ed2009-12-04 18:54:03 +00009#include <errno.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000010#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070013
adlr@google.comc98a7ed2009-12-04 18:54:03 +000014#include <set>
rspangler@google.com49fdf182009-10-10 00:57:34 +000015#include <string>
16#include <vector>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070017
Alex Vakulenko75039d72014-03-25 12:36:28 -070018#include <base/strings/string_util.h>
19#include <base/strings/stringprintf.h>
Chris Masone790e62e2010-08-12 10:41:18 -070020#include "base/logging.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000021#include "update_engine/file_writer.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000022#include "update_engine/filesystem_iterator.h"
23#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000024
adlr@google.comc98a7ed2009-12-04 18:54:03 +000025using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000026using std::string;
27using std::vector;
Alex Vakulenko75039d72014-03-25 12:36:28 -070028using base::StringPrintf;
rspangler@google.com49fdf182009-10-10 00:57:34 +000029
30namespace chromeos_update_engine {
31
Gilad Arnolda6742b32014-01-11 00:18:34 -080032const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
Gilad Arnold61d9d2c2013-07-22 17:54:52 -070033
adlr@google.comc98a7ed2009-12-04 18:54:03 +000034bool WriteFileVector(const std::string& path, const std::vector<char>& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080035 return utils::WriteFile(path.c_str(), &data[0], data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +000036}
37
38bool WriteFileString(const std::string& path, const std::string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080039 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +000040}
41
adlr@google.comc98a7ed2009-12-04 18:54:03 +000042std::string Readlink(const std::string& path) {
43 vector<char> buf(PATH_MAX + 1);
44 ssize_t r = readlink(path.c_str(), &buf[0], buf.size());
45 if (r < 0)
46 return "";
47 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
48 buf.resize(r);
49 string ret;
50 ret.insert(ret.begin(), buf.begin(), buf.end());
51 return ret;
52}
53
rspangler@google.com49fdf182009-10-10 00:57:34 +000054std::vector<char> GzipCompressData(const std::vector<char>& data) {
55 const char fname[] = "/tmp/GzipCompressDataTemp";
adlr@google.comc98a7ed2009-12-04 18:54:03 +000056 if (!WriteFileVector(fname, data)) {
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070057 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000058 return vector<char>();
59 }
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070060 EXPECT_EQ(0, system((string("cat ") + fname + "|gzip>" +
61 fname + ".gz").c_str()));
62 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
adlr@google.comc98a7ed2009-12-04 18:54:03 +000063 vector<char> ret;
64 EXPECT_TRUE(utils::ReadFile(string(fname) + ".gz", &ret));
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070065 EXPECT_EQ(0, system((string("rm ") + fname + ".gz").c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000066 return ret;
67}
68
adlr@google.comc98a7ed2009-12-04 18:54:03 +000069vector<char> GenerateSampleMbr() {
70 // This is the actual MBR from my dev machine. Partition 1 (the first)
71 // is currently marked bootable
Han Shen2643cb72012-06-26 14:45:33 -070072 unsigned char mbr[512] = {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000073 0xeb, 0x48, 0x90, 0x10, 0x8e, 0xd0, 0xbc, 0x00,
74 0xb0, 0xb8, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0,
75 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9,
76 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x21, 0x06, 0x00,
77 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b,
78 0x83, 0xc6, 0x10, 0x81, 0xfe, 0xfe, 0x07, 0x75,
79 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb,
80 0x00, 0x7c, 0xb2, 0x80, 0x8a, 0x74, 0x03, 0x02,
81 0xff, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
82 0x00, 0x02, 0xfa, 0x90, 0x90, 0xf6, 0xc2, 0x80,
83 0x75, 0x02, 0xb2, 0x80, 0xea, 0x59, 0x7c, 0x00,
84 0x00, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc,
85 0x00, 0x20, 0xfb, 0xa0, 0x40, 0x7c, 0x3c, 0xff,
86 0x74, 0x02, 0x88, 0xc2, 0x52, 0xbe, 0x7f, 0x7d,
87 0xe8, 0x34, 0x01, 0xf6, 0xc2, 0x80, 0x74, 0x54,
88 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x5a,
89 0x52, 0x72, 0x49, 0x81, 0xfb, 0x55, 0xaa, 0x75,
90 0x43, 0xa0, 0x41, 0x7c, 0x84, 0xc0, 0x75, 0x05,
91 0x83, 0xe1, 0x01, 0x74, 0x37, 0x66, 0x8b, 0x4c,
92 0x10, 0xbe, 0x05, 0x7c, 0xc6, 0x44, 0xff, 0x01,
93 0x66, 0x8b, 0x1e, 0x44, 0x7c, 0xc7, 0x04, 0x10,
94 0x00, 0xc7, 0x44, 0x02, 0x01, 0x00, 0x66, 0x89,
95 0x5c, 0x08, 0xc7, 0x44, 0x06, 0x00, 0x70, 0x66,
96 0x31, 0xc0, 0x89, 0x44, 0x04, 0x66, 0x89, 0x44,
97 0x0c, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x05, 0xbb,
98 0x00, 0x70, 0xeb, 0x7d, 0xb4, 0x08, 0xcd, 0x13,
99 0x73, 0x0a, 0xf6, 0xc2, 0x80, 0x0f, 0x84, 0xea,
100 0x00, 0xe9, 0x8d, 0x00, 0xbe, 0x05, 0x7c, 0xc6,
101 0x44, 0xff, 0x00, 0x66, 0x31, 0xc0, 0x88, 0xf0,
102 0x40, 0x66, 0x89, 0x44, 0x04, 0x31, 0xd2, 0x88,
103 0xca, 0xc1, 0xe2, 0x02, 0x88, 0xe8, 0x88, 0xf4,
104 0x40, 0x89, 0x44, 0x08, 0x31, 0xc0, 0x88, 0xd0,
105 0xc0, 0xe8, 0x02, 0x66, 0x89, 0x04, 0x66, 0xa1,
106 0x44, 0x7c, 0x66, 0x31, 0xd2, 0x66, 0xf7, 0x34,
107 0x88, 0x54, 0x0a, 0x66, 0x31, 0xd2, 0x66, 0xf7,
108 0x74, 0x04, 0x88, 0x54, 0x0b, 0x89, 0x44, 0x0c,
109 0x3b, 0x44, 0x08, 0x7d, 0x3c, 0x8a, 0x54, 0x0d,
110 0xc0, 0xe2, 0x06, 0x8a, 0x4c, 0x0a, 0xfe, 0xc1,
111 0x08, 0xd1, 0x8a, 0x6c, 0x0c, 0x5a, 0x8a, 0x74,
112 0x0b, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, 0xdb,
113 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x72, 0x2a, 0x8c,
114 0xc3, 0x8e, 0x06, 0x48, 0x7c, 0x60, 0x1e, 0xb9,
115 0x00, 0x01, 0x8e, 0xdb, 0x31, 0xf6, 0x31, 0xff,
116 0xfc, 0xf3, 0xa5, 0x1f, 0x61, 0xff, 0x26, 0x42,
117 0x7c, 0xbe, 0x85, 0x7d, 0xe8, 0x40, 0x00, 0xeb,
118 0x0e, 0xbe, 0x8a, 0x7d, 0xe8, 0x38, 0x00, 0xeb,
119 0x06, 0xbe, 0x94, 0x7d, 0xe8, 0x30, 0x00, 0xbe,
120 0x99, 0x7d, 0xe8, 0x2a, 0x00, 0xeb, 0xfe, 0x47,
121 0x52, 0x55, 0x42, 0x20, 0x00, 0x47, 0x65, 0x6f,
122 0x6d, 0x00, 0x48, 0x61, 0x72, 0x64, 0x20, 0x44,
123 0x69, 0x73, 0x6b, 0x00, 0x52, 0x65, 0x61, 0x64,
124 0x00, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00,
125 0xbb, 0x01, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac,
126 0x3c, 0x00, 0x75, 0xf4, 0xc3, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x50, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x80, 0x01,
129 0x01, 0x00, 0x83, 0xfe, 0xff, 0xff, 0x3f, 0x00,
130 0x00, 0x00, 0x09, 0x7f, 0x32, 0x06, 0x00, 0xfe,
131 0xff, 0xff, 0x05, 0xfe, 0xff, 0xff, 0x48, 0x7f,
132 0x32, 0x06, 0x79, 0x59, 0x2d, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
137 };
138 vector<char> ret;
Han Shen2643cb72012-06-26 14:45:33 -0700139 ret.insert(ret.begin(), reinterpret_cast<char *>(mbr),
140 reinterpret_cast<char *>(mbr + sizeof(mbr)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000141 return ret;
142}
143
Gilad Arnold19a45f02012-07-19 12:36:10 -0700144// Binds provided |filename| to an unused loopback device, whose name is written
145// to the string pointed to by |lo_dev_name_p|. Returns true on success, false
146// otherwise (along with corresponding test failures), in which case the content
147// of |lo_dev_name_p| is unknown.
148bool BindToUnusedLoopDevice(const string& filename, string* lo_dev_name_p) {
149 CHECK(lo_dev_name_p);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800150
Gilad Arnold19a45f02012-07-19 12:36:10 -0700151 // Bind to an unused loopback device, sanity check the device name.
152 lo_dev_name_p->clear();
153 if (!(utils::ReadPipe("losetup --show -f " + filename, lo_dev_name_p) &&
154 StartsWithASCII(*lo_dev_name_p, "/dev/loop", true))) {
155 ADD_FAILURE();
156 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000157 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000158
Gilad Arnold19a45f02012-07-19 12:36:10 -0700159 // Strip anything from the first newline char.
160 size_t newline_pos = lo_dev_name_p->find('\n');
161 if (newline_pos != string::npos)
162 lo_dev_name_p->erase(newline_pos);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000163
Gilad Arnold19a45f02012-07-19 12:36:10 -0700164 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000165}
166
Andrew de los Reyes80061062010-02-04 14:25:00 -0800167bool ExpectVectorsEq(const vector<char>& expected, const vector<char>& actual) {
168 EXPECT_EQ(expected.size(), actual.size());
169 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000170 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700171 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800172 for (unsigned int i = 0; i < expected.size(); i++) {
173 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700174 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000175 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700176 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000177}
178
Andrew de los Reyes80061062010-02-04 14:25:00 -0800179void FillWithData(vector<char>* buffer) {
180 size_t input_counter = 0;
181 for (vector<char>::iterator it = buffer->begin(); it != buffer->end(); ++it) {
182 *it = kRandomString[input_counter];
183 input_counter++;
184 input_counter %= sizeof(kRandomString);
185 }
186}
187
Thieu Le5c7d9752010-12-15 16:09:28 -0800188void CreateEmptyExtImageAtPath(const string& path,
189 size_t size,
190 int block_size) {
191 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
192 " seek=%zu bs=1 count=1",
193 path.c_str(), size)));
194 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b %d -F %s",
195 block_size, path.c_str())));
196}
197
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000198void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700199 // create 10MiB sparse file, mounted at a unique location.
200 string mount_path;
201 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700202 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700203
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000204 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
205 " seek=10485759 bs=1 count=1",
206 path.c_str())));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700207 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b 4096 -F %s", path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000208 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700209 mount_path.c_str())));
210 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
211 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
212 mount_path.c_str())));
213 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
214 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
215 mount_path.c_str())));
216 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
217 mount_path.c_str())));
218 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
219 mount_path.c_str())));
220 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
221 mount_path.c_str())));
222 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
223 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
224 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000225 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700226 mount_path.c_str(), mount_path.c_str())));
227 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
228 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800229 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700230 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800231 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700232 mount_path.c_str())));
233 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800234
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000235 if (out_paths) {
236 out_paths->clear();
237 out_paths->push_back("");
238 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800239 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000240 out_paths->push_back("/hello");
241 out_paths->push_back("/some_dir");
242 out_paths->push_back("/some_dir/empty_dir");
243 out_paths->push_back("/some_dir/mnt");
244 out_paths->push_back("/some_dir/test");
245 out_paths->push_back("/some_dir/fifo");
246 out_paths->push_back("/cdev");
247 out_paths->push_back("/testlink");
248 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800249 out_paths->push_back("/srchardlink0");
250 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000251 out_paths->push_back("/lost+found");
252 }
253}
254
255void VerifyAllPaths(const string& parent, set<string> expected_paths) {
256 FilesystemIterator iter(parent, set<string>());
257 ino_t test_ino = 0;
258 ino_t testlink_ino = 0;
259 while (!iter.IsEnd()) {
260 string path = iter.GetFullPath();
261 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
262 EXPECT_EQ(1, expected_paths.erase(path));
263 if (utils::StringHasSuffix(path, "/hi") ||
264 utils::StringHasSuffix(path, "/hello") ||
265 utils::StringHasSuffix(path, "/test") ||
266 utils::StringHasSuffix(path, "/testlink")) {
267 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
268 if (utils::StringHasSuffix(path, "/test"))
269 test_ino = iter.GetStat().st_ino;
270 else if (utils::StringHasSuffix(path, "/testlink"))
271 testlink_ino = iter.GetStat().st_ino;
272 } else if (utils::StringHasSuffix(path, "/some_dir") ||
273 utils::StringHasSuffix(path, "/empty_dir") ||
274 utils::StringHasSuffix(path, "/mnt") ||
275 utils::StringHasSuffix(path, "/lost+found") ||
276 parent == path) {
277 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
278 } else if (utils::StringHasSuffix(path, "/fifo")) {
279 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
280 } else if (utils::StringHasSuffix(path, "/cdev")) {
281 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
282 } else if (utils::StringHasSuffix(path, "/sym")) {
283 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
284 } else {
285 LOG(INFO) << "got non hardcoded path: " << path;
286 }
287 iter.Increment();
288 }
289 EXPECT_EQ(testlink_ino, test_ino);
290 EXPECT_NE(0, test_ino);
291 EXPECT_FALSE(iter.IsErr());
292 EXPECT_TRUE(expected_paths.empty());
293 if (!expected_paths.empty()) {
294 for (set<string>::const_iterator it = expected_paths.begin();
295 it != expected_paths.end(); ++it) {
296 LOG(INFO) << "extra path: " << *it;
297 }
298 }
299}
300
Don Garrett58e8b1f2012-01-31 16:38:16 -0800301ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
302 string* mnt_path,
Thieu Le5c7d9752010-12-15 16:09:28 -0800303 unsigned long flags) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800304 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800305 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
306
Don Garrett58e8b1f2012-01-31 16:38:16 -0800307 string loop_dev;
308 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800309
310 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
311 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
312}
313
Alex Deymo53556ec2014-03-17 10:05:57 -0700314static gboolean RunGMainLoopOnTimeout(gpointer user_data) {
315 bool* timeout = static_cast<bool*>(user_data);
316 *timeout = true;
317 return FALSE; // Remove timeout source
318}
319
320void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate) {
321 GMainLoop* loop = g_main_loop_new(NULL, FALSE);
322 GMainContext* context = g_main_context_default();
323
324 bool timeout = false;
325 guint source_id = g_timeout_add(
326 timeout_msec, RunGMainLoopOnTimeout, &timeout);
327
328 while (!timeout && (terminate.is_null() || !terminate.Run()))
329 g_main_context_iteration(context, TRUE);
330
331 g_source_remove(source_id);
332 g_main_loop_unref(loop);
333}
334
Alex Deymo7b948f02014-03-10 17:01:10 -0700335int RunGMainLoopMaxIterations(int iterations) {
336 int result;
337 GMainContext* context = g_main_context_default();
338 for (result = 0;
339 result < iterations && g_main_context_iteration(context, FALSE);
340 result++) {}
341 return result;
342}
343
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700344GValue* GValueNewString(const char* str) {
345 GValue* gval = new GValue();
346 g_value_init(gval, G_TYPE_STRING);
347 g_value_set_string(gval, str);
348 return gval;
349}
350
351void GValueFree(gpointer arg) {
352 auto gval = reinterpret_cast<GValue*>(arg);
353 g_value_unset(gval);
354 delete gval;
355}
356
rspangler@google.com49fdf182009-10-10 00:57:34 +0000357} // namespace chromeos_update_engine