blob: 70eb35c96245c1ffbd144d171bce1d4482dd9023 [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
adlr@google.comc98a7ed2009-12-04 18:54:03 +00007#include <errno.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +00008#include <stdio.h>
9#include <stdlib.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070010#include <sys/stat.h>
11#include <sys/types.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000012#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 Deymo161c4a12014-05-16 15:56:21 -070018#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070019#include <base/strings/string_util.h>
20#include <base/strings/stringprintf.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070021
rspangler@google.com49fdf182009-10-10 00:57:34 +000022#include "update_engine/file_writer.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070023#include "update_engine/payload_generator/filesystem_iterator.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000024#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000025
Alex Deymo161c4a12014-05-16 15:56:21 -070026using base::StringPrintf;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000027using std::set;
rspangler@google.com49fdf182009-10-10 00:57:34 +000028using std::string;
29using std::vector;
30
31namespace chromeos_update_engine {
32
Gilad Arnolda6742b32014-01-11 00:18:34 -080033const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
Gilad Arnold61d9d2c2013-07-22 17:54:52 -070034
adlr@google.comc98a7ed2009-12-04 18:54:03 +000035bool WriteFileVector(const std::string& path, const std::vector<char>& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080036 return utils::WriteFile(path.c_str(), &data[0], data.size());
adlr@google.comc98a7ed2009-12-04 18:54:03 +000037}
38
39bool WriteFileString(const std::string& path, const std::string& data) {
Andrew de los Reyes970bb282009-12-09 16:34:04 -080040 return utils::WriteFile(path.c_str(), data.data(), data.size());
rspangler@google.com49fdf182009-10-10 00:57:34 +000041}
42
adlr@google.comc98a7ed2009-12-04 18:54:03 +000043std::string Readlink(const std::string& path) {
44 vector<char> buf(PATH_MAX + 1);
45 ssize_t r = readlink(path.c_str(), &buf[0], buf.size());
46 if (r < 0)
47 return "";
48 CHECK_LT(r, static_cast<ssize_t>(buf.size()));
49 buf.resize(r);
50 string ret;
51 ret.insert(ret.begin(), buf.begin(), buf.end());
52 return ret;
53}
54
rspangler@google.com49fdf182009-10-10 00:57:34 +000055std::vector<char> GzipCompressData(const std::vector<char>& data) {
56 const char fname[] = "/tmp/GzipCompressDataTemp";
adlr@google.comc98a7ed2009-12-04 18:54:03 +000057 if (!WriteFileVector(fname, data)) {
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070058 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000059 return vector<char>();
60 }
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070061 EXPECT_EQ(0, system((string("cat ") + fname + "|gzip>" +
62 fname + ".gz").c_str()));
63 EXPECT_EQ(0, system((string("rm ") + fname).c_str()));
adlr@google.comc98a7ed2009-12-04 18:54:03 +000064 vector<char> ret;
65 EXPECT_TRUE(utils::ReadFile(string(fname) + ".gz", &ret));
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070066 EXPECT_EQ(0, system((string("rm ") + fname + ".gz").c_str()));
rspangler@google.com49fdf182009-10-10 00:57:34 +000067 return ret;
68}
69
adlr@google.comc98a7ed2009-12-04 18:54:03 +000070vector<char> GenerateSampleMbr() {
71 // This is the actual MBR from my dev machine. Partition 1 (the first)
72 // is currently marked bootable
Han Shen2643cb72012-06-26 14:45:33 -070073 unsigned char mbr[512] = {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000074 0xeb, 0x48, 0x90, 0x10, 0x8e, 0xd0, 0xbc, 0x00,
75 0xb0, 0xb8, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0,
76 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9,
77 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x21, 0x06, 0x00,
78 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b,
79 0x83, 0xc6, 0x10, 0x81, 0xfe, 0xfe, 0x07, 0x75,
80 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb,
81 0x00, 0x7c, 0xb2, 0x80, 0x8a, 0x74, 0x03, 0x02,
82 0xff, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
83 0x00, 0x02, 0xfa, 0x90, 0x90, 0xf6, 0xc2, 0x80,
84 0x75, 0x02, 0xb2, 0x80, 0xea, 0x59, 0x7c, 0x00,
85 0x00, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc,
86 0x00, 0x20, 0xfb, 0xa0, 0x40, 0x7c, 0x3c, 0xff,
87 0x74, 0x02, 0x88, 0xc2, 0x52, 0xbe, 0x7f, 0x7d,
88 0xe8, 0x34, 0x01, 0xf6, 0xc2, 0x80, 0x74, 0x54,
89 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x5a,
90 0x52, 0x72, 0x49, 0x81, 0xfb, 0x55, 0xaa, 0x75,
91 0x43, 0xa0, 0x41, 0x7c, 0x84, 0xc0, 0x75, 0x05,
92 0x83, 0xe1, 0x01, 0x74, 0x37, 0x66, 0x8b, 0x4c,
93 0x10, 0xbe, 0x05, 0x7c, 0xc6, 0x44, 0xff, 0x01,
94 0x66, 0x8b, 0x1e, 0x44, 0x7c, 0xc7, 0x04, 0x10,
95 0x00, 0xc7, 0x44, 0x02, 0x01, 0x00, 0x66, 0x89,
96 0x5c, 0x08, 0xc7, 0x44, 0x06, 0x00, 0x70, 0x66,
97 0x31, 0xc0, 0x89, 0x44, 0x04, 0x66, 0x89, 0x44,
98 0x0c, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x05, 0xbb,
99 0x00, 0x70, 0xeb, 0x7d, 0xb4, 0x08, 0xcd, 0x13,
100 0x73, 0x0a, 0xf6, 0xc2, 0x80, 0x0f, 0x84, 0xea,
101 0x00, 0xe9, 0x8d, 0x00, 0xbe, 0x05, 0x7c, 0xc6,
102 0x44, 0xff, 0x00, 0x66, 0x31, 0xc0, 0x88, 0xf0,
103 0x40, 0x66, 0x89, 0x44, 0x04, 0x31, 0xd2, 0x88,
104 0xca, 0xc1, 0xe2, 0x02, 0x88, 0xe8, 0x88, 0xf4,
105 0x40, 0x89, 0x44, 0x08, 0x31, 0xc0, 0x88, 0xd0,
106 0xc0, 0xe8, 0x02, 0x66, 0x89, 0x04, 0x66, 0xa1,
107 0x44, 0x7c, 0x66, 0x31, 0xd2, 0x66, 0xf7, 0x34,
108 0x88, 0x54, 0x0a, 0x66, 0x31, 0xd2, 0x66, 0xf7,
109 0x74, 0x04, 0x88, 0x54, 0x0b, 0x89, 0x44, 0x0c,
110 0x3b, 0x44, 0x08, 0x7d, 0x3c, 0x8a, 0x54, 0x0d,
111 0xc0, 0xe2, 0x06, 0x8a, 0x4c, 0x0a, 0xfe, 0xc1,
112 0x08, 0xd1, 0x8a, 0x6c, 0x0c, 0x5a, 0x8a, 0x74,
113 0x0b, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31, 0xdb,
114 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x72, 0x2a, 0x8c,
115 0xc3, 0x8e, 0x06, 0x48, 0x7c, 0x60, 0x1e, 0xb9,
116 0x00, 0x01, 0x8e, 0xdb, 0x31, 0xf6, 0x31, 0xff,
117 0xfc, 0xf3, 0xa5, 0x1f, 0x61, 0xff, 0x26, 0x42,
118 0x7c, 0xbe, 0x85, 0x7d, 0xe8, 0x40, 0x00, 0xeb,
119 0x0e, 0xbe, 0x8a, 0x7d, 0xe8, 0x38, 0x00, 0xeb,
120 0x06, 0xbe, 0x94, 0x7d, 0xe8, 0x30, 0x00, 0xbe,
121 0x99, 0x7d, 0xe8, 0x2a, 0x00, 0xeb, 0xfe, 0x47,
122 0x52, 0x55, 0x42, 0x20, 0x00, 0x47, 0x65, 0x6f,
123 0x6d, 0x00, 0x48, 0x61, 0x72, 0x64, 0x20, 0x44,
124 0x69, 0x73, 0x6b, 0x00, 0x52, 0x65, 0x61, 0x64,
125 0x00, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00,
126 0xbb, 0x01, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac,
127 0x3c, 0x00, 0x75, 0xf4, 0xc3, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x50, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x80, 0x01,
130 0x01, 0x00, 0x83, 0xfe, 0xff, 0xff, 0x3f, 0x00,
131 0x00, 0x00, 0x09, 0x7f, 0x32, 0x06, 0x00, 0xfe,
132 0xff, 0xff, 0x05, 0xfe, 0xff, 0xff, 0x48, 0x7f,
133 0x32, 0x06, 0x79, 0x59, 0x2d, 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, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
138 };
139 vector<char> ret;
Han Shen2643cb72012-06-26 14:45:33 -0700140 ret.insert(ret.begin(), reinterpret_cast<char *>(mbr),
141 reinterpret_cast<char *>(mbr + sizeof(mbr)));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000142 return ret;
143}
144
Gilad Arnold19a45f02012-07-19 12:36:10 -0700145// Binds provided |filename| to an unused loopback device, whose name is written
146// to the string pointed to by |lo_dev_name_p|. Returns true on success, false
147// otherwise (along with corresponding test failures), in which case the content
148// of |lo_dev_name_p| is unknown.
149bool BindToUnusedLoopDevice(const string& filename, string* lo_dev_name_p) {
150 CHECK(lo_dev_name_p);
Don Garrett58e8b1f2012-01-31 16:38:16 -0800151
Gilad Arnold19a45f02012-07-19 12:36:10 -0700152 // Bind to an unused loopback device, sanity check the device name.
153 lo_dev_name_p->clear();
154 if (!(utils::ReadPipe("losetup --show -f " + filename, lo_dev_name_p) &&
155 StartsWithASCII(*lo_dev_name_p, "/dev/loop", true))) {
156 ADD_FAILURE();
157 return false;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000158 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000159
Gilad Arnold19a45f02012-07-19 12:36:10 -0700160 // Strip anything from the first newline char.
161 size_t newline_pos = lo_dev_name_p->find('\n');
162 if (newline_pos != string::npos)
163 lo_dev_name_p->erase(newline_pos);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000164
Gilad Arnold19a45f02012-07-19 12:36:10 -0700165 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000166}
167
Andrew de los Reyes80061062010-02-04 14:25:00 -0800168bool ExpectVectorsEq(const vector<char>& expected, const vector<char>& actual) {
169 EXPECT_EQ(expected.size(), actual.size());
170 if (expected.size() != actual.size())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000171 return false;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700172 bool is_all_eq = true;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800173 for (unsigned int i = 0; i < expected.size(); i++) {
174 EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
Gilad Arnold617bbc22012-05-15 08:48:13 -0700175 is_all_eq = is_all_eq && (expected[i] == actual[i]);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000176 }
Gilad Arnold617bbc22012-05-15 08:48:13 -0700177 return is_all_eq;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000178}
179
Andrew de los Reyes80061062010-02-04 14:25:00 -0800180void FillWithData(vector<char>* buffer) {
181 size_t input_counter = 0;
182 for (vector<char>::iterator it = buffer->begin(); it != buffer->end(); ++it) {
183 *it = kRandomString[input_counter];
184 input_counter++;
185 input_counter %= sizeof(kRandomString);
186 }
187}
188
Thieu Le5c7d9752010-12-15 16:09:28 -0800189void CreateEmptyExtImageAtPath(const string& path,
190 size_t size,
191 int block_size) {
192 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
193 " seek=%zu bs=1 count=1",
194 path.c_str(), size)));
195 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b %d -F %s",
196 block_size, path.c_str())));
197}
198
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000199void CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700200 // create 10MiB sparse file, mounted at a unique location.
201 string mount_path;
202 CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
Alex Deymoa58b62a2013-08-08 21:21:48 -0700203 ScopedDirRemover mount_path_unlinker(mount_path);
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700204
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000205 EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
206 " seek=10485759 bs=1 count=1",
207 path.c_str())));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700208 EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -b 4096 -F %s", path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000209 EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700210 mount_path.c_str())));
211 EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
212 EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
213 mount_path.c_str())));
214 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
215 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
216 mount_path.c_str())));
217 EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
218 mount_path.c_str())));
219 EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
220 mount_path.c_str())));
221 EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
222 mount_path.c_str())));
223 EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
224 EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
225 mount_path.c_str())));
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000226 EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700227 mount_path.c_str(), mount_path.c_str())));
228 EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
229 mount_path.c_str())));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800230 EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700231 mount_path.c_str(), mount_path.c_str())));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800232 EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
Gilad Arnold61d9d2c2013-07-22 17:54:52 -0700233 mount_path.c_str())));
234 EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
Thieu Le5c7d9752010-12-15 16:09:28 -0800235
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000236 if (out_paths) {
237 out_paths->clear();
238 out_paths->push_back("");
239 out_paths->push_back("/hi");
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800240 out_paths->push_back("/boguslink");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000241 out_paths->push_back("/hello");
242 out_paths->push_back("/some_dir");
243 out_paths->push_back("/some_dir/empty_dir");
244 out_paths->push_back("/some_dir/mnt");
245 out_paths->push_back("/some_dir/test");
246 out_paths->push_back("/some_dir/fifo");
247 out_paths->push_back("/cdev");
248 out_paths->push_back("/testlink");
249 out_paths->push_back("/sym");
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800250 out_paths->push_back("/srchardlink0");
251 out_paths->push_back("/srchardlink1");
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000252 out_paths->push_back("/lost+found");
253 }
254}
255
256void VerifyAllPaths(const string& parent, set<string> expected_paths) {
257 FilesystemIterator iter(parent, set<string>());
258 ino_t test_ino = 0;
259 ino_t testlink_ino = 0;
260 while (!iter.IsEnd()) {
261 string path = iter.GetFullPath();
262 EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
263 EXPECT_EQ(1, expected_paths.erase(path));
264 if (utils::StringHasSuffix(path, "/hi") ||
265 utils::StringHasSuffix(path, "/hello") ||
266 utils::StringHasSuffix(path, "/test") ||
267 utils::StringHasSuffix(path, "/testlink")) {
268 EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
269 if (utils::StringHasSuffix(path, "/test"))
270 test_ino = iter.GetStat().st_ino;
271 else if (utils::StringHasSuffix(path, "/testlink"))
272 testlink_ino = iter.GetStat().st_ino;
273 } else if (utils::StringHasSuffix(path, "/some_dir") ||
274 utils::StringHasSuffix(path, "/empty_dir") ||
275 utils::StringHasSuffix(path, "/mnt") ||
276 utils::StringHasSuffix(path, "/lost+found") ||
277 parent == path) {
278 EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
279 } else if (utils::StringHasSuffix(path, "/fifo")) {
280 EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
281 } else if (utils::StringHasSuffix(path, "/cdev")) {
282 EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
283 } else if (utils::StringHasSuffix(path, "/sym")) {
284 EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
285 } else {
286 LOG(INFO) << "got non hardcoded path: " << path;
287 }
288 iter.Increment();
289 }
290 EXPECT_EQ(testlink_ino, test_ino);
291 EXPECT_NE(0, test_ino);
292 EXPECT_FALSE(iter.IsErr());
293 EXPECT_TRUE(expected_paths.empty());
294 if (!expected_paths.empty()) {
295 for (set<string>::const_iterator it = expected_paths.begin();
296 it != expected_paths.end(); ++it) {
297 LOG(INFO) << "extra path: " << *it;
298 }
299 }
300}
301
Don Garrett58e8b1f2012-01-31 16:38:16 -0800302ScopedLoopMounter::ScopedLoopMounter(const string& file_path,
303 string* mnt_path,
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700304 unsigned long flags) { // NOLINT - long
Gilad Arnolda6742b32014-01-11 00:18:34 -0800305 EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
Thieu Le5c7d9752010-12-15 16:09:28 -0800306 dir_remover_.reset(new ScopedDirRemover(*mnt_path));
307
Don Garrett58e8b1f2012-01-31 16:38:16 -0800308 string loop_dev;
309 loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
Thieu Le5c7d9752010-12-15 16:09:28 -0800310
311 EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
312 unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
313}
314
Alex Deymo53556ec2014-03-17 10:05:57 -0700315static gboolean RunGMainLoopOnTimeout(gpointer user_data) {
316 bool* timeout = static_cast<bool*>(user_data);
317 *timeout = true;
318 return FALSE; // Remove timeout source
319}
320
321void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700322 GMainLoop* loop = g_main_loop_new(nullptr, FALSE);
Alex Deymo53556ec2014-03-17 10:05:57 -0700323 GMainContext* context = g_main_context_default();
324
325 bool timeout = false;
326 guint source_id = g_timeout_add(
327 timeout_msec, RunGMainLoopOnTimeout, &timeout);
328
329 while (!timeout && (terminate.is_null() || !terminate.Run()))
330 g_main_context_iteration(context, TRUE);
331
332 g_source_remove(source_id);
333 g_main_loop_unref(loop);
334}
335
Alex Deymo7b948f02014-03-10 17:01:10 -0700336int RunGMainLoopMaxIterations(int iterations) {
337 int result;
338 GMainContext* context = g_main_context_default();
339 for (result = 0;
340 result < iterations && g_main_context_iteration(context, FALSE);
341 result++) {}
342 return result;
343}
344
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700345GValue* GValueNewString(const char* str) {
Alex Deymo5665d0c2014-05-28 17:45:43 -0700346 GValue* gval = g_new0(GValue, 1);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700347 g_value_init(gval, G_TYPE_STRING);
348 g_value_set_string(gval, str);
349 return gval;
350}
351
352void GValueFree(gpointer arg) {
353 auto gval = reinterpret_cast<GValue*>(arg);
354 g_value_unset(gval);
Alex Deymo5665d0c2014-05-28 17:45:43 -0700355 g_free(gval);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700356}
357
rspangler@google.com49fdf182009-10-10 00:57:34 +0000358} // namespace chromeos_update_engine