blob: f31f1f82ac190e812568a637852b26e828fba6ef [file] [log] [blame]
Tao Bao0c7839a2016-10-10 15:48:37 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tao Bao89929022016-11-08 20:51:31 -080017#include <sys/stat.h>
18#include <sys/types.h>
19#include <unistd.h>
20
Tao Bao0c7839a2016-10-10 15:48:37 -070021#include <string>
22
Tao Bao51d516e2016-11-03 14:49:01 -070023#include <android-base/file.h>
Tao Bao0c7839a2016-10-10 15:48:37 -070024#include <android-base/properties.h>
Tao Bao51d516e2016-11-03 14:49:01 -070025#include <android-base/test_utils.h>
Tao Baobedf5fc2016-11-18 12:01:26 -080026#include <bootloader_message/bootloader_message.h>
Tao Bao0c7839a2016-10-10 15:48:37 -070027#include <gtest/gtest.h>
Tao Baoef0eb3b2016-11-14 21:29:52 -080028#include <ziparchive/zip_archive.h>
Tao Bao0c7839a2016-10-10 15:48:37 -070029
Tao Baoef0eb3b2016-11-14 21:29:52 -080030#include "common/test_constants.h"
Tao Bao0c7839a2016-10-10 15:48:37 -070031#include "edify/expr.h"
32#include "error_code.h"
33#include "updater/install.h"
Tao Baoef0eb3b2016-11-14 21:29:52 -080034#include "updater/updater.h"
Tao Bao0c7839a2016-10-10 15:48:37 -070035
36struct selabel_handle *sehandle = nullptr;
37
Tao Baoef0eb3b2016-11-14 21:29:52 -080038static void expect(const char* expected, const char* expr_str, CauseCode cause_code,
39 UpdaterInfo* info = nullptr) {
40 Expr* e;
41 int error_count = 0;
42 ASSERT_EQ(0, parse_string(expr_str, &e, &error_count));
43 ASSERT_EQ(0, error_count);
Tao Bao0c7839a2016-10-10 15:48:37 -070044
Tao Baoef0eb3b2016-11-14 21:29:52 -080045 State state(expr_str, info);
Tao Bao0c7839a2016-10-10 15:48:37 -070046
Tao Baoef0eb3b2016-11-14 21:29:52 -080047 std::string result;
48 bool status = Evaluate(&state, e, &result);
Tao Bao0c7839a2016-10-10 15:48:37 -070049
Tao Baoef0eb3b2016-11-14 21:29:52 -080050 if (expected == nullptr) {
51 ASSERT_FALSE(status);
52 } else {
53 ASSERT_TRUE(status);
54 ASSERT_STREQ(expected, result.c_str());
55 }
Tao Bao0c7839a2016-10-10 15:48:37 -070056
Tao Baoef0eb3b2016-11-14 21:29:52 -080057 // Error code is set in updater/updater.cpp only, by parsing State.errmsg.
58 ASSERT_EQ(kNoError, state.error_code);
Tao Bao361342c2016-02-08 11:15:50 -080059
Tao Baoef0eb3b2016-11-14 21:29:52 -080060 // Cause code should always be available.
61 ASSERT_EQ(cause_code, state.cause_code);
Tao Bao0c7839a2016-10-10 15:48:37 -070062}
63
64class UpdaterTest : public ::testing::Test {
65 protected:
66 virtual void SetUp() {
67 RegisterBuiltins();
68 RegisterInstallFunctions();
Tao Bao0c7839a2016-10-10 15:48:37 -070069 }
70};
71
72TEST_F(UpdaterTest, getprop) {
73 expect(android::base::GetProperty("ro.product.device", "").c_str(),
74 "getprop(\"ro.product.device\")",
Tao Bao361342c2016-02-08 11:15:50 -080075 kNoCause);
Tao Bao0c7839a2016-10-10 15:48:37 -070076
77 expect(android::base::GetProperty("ro.build.fingerprint", "").c_str(),
78 "getprop(\"ro.build.fingerprint\")",
Tao Bao361342c2016-02-08 11:15:50 -080079 kNoCause);
Tao Bao0c7839a2016-10-10 15:48:37 -070080
81 // getprop() accepts only one parameter.
Tao Bao361342c2016-02-08 11:15:50 -080082 expect(nullptr, "getprop()", kArgsParsingFailure);
83 expect(nullptr, "getprop(\"arg1\", \"arg2\")", kArgsParsingFailure);
84}
85
86TEST_F(UpdaterTest, sha1_check) {
87 // sha1_check(data) returns the SHA-1 of the data.
88 expect("81fe8bfe87576c3ecb22426f8e57847382917acf", "sha1_check(\"abcd\")", kNoCause);
89 expect("da39a3ee5e6b4b0d3255bfef95601890afd80709", "sha1_check(\"\")", kNoCause);
90
91 // sha1_check(data, sha1_hex, [sha1_hex, ...]) returns the matched SHA-1.
92 expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
93 "sha1_check(\"abcd\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
94 kNoCause);
95
96 expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
97 "sha1_check(\"abcd\", \"wrong_sha1\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
98 kNoCause);
99
100 // Or "" if there's no match.
101 expect("",
102 "sha1_check(\"abcd\", \"wrong_sha1\")",
103 kNoCause);
104
105 expect("",
106 "sha1_check(\"abcd\", \"wrong_sha1\", \"wrong_sha2\")",
107 kNoCause);
108
109 // sha1_check() expects at least one argument.
110 expect(nullptr, "sha1_check()", kArgsParsingFailure);
Tao Bao0c7839a2016-10-10 15:48:37 -0700111}
Tao Bao51d516e2016-11-03 14:49:01 -0700112
113TEST_F(UpdaterTest, file_getprop) {
114 // file_getprop() expects two arguments.
115 expect(nullptr, "file_getprop()", kArgsParsingFailure);
116 expect(nullptr, "file_getprop(\"arg1\")", kArgsParsingFailure);
117 expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
118
119 // File doesn't exist.
120 expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFileGetPropFailure);
121
122 // Reject too large files (current limit = 65536).
123 TemporaryFile temp_file1;
124 std::string buffer(65540, '\0');
125 ASSERT_TRUE(android::base::WriteStringToFile(buffer, temp_file1.path));
126
127 // Read some keys.
128 TemporaryFile temp_file2;
129 std::string content("ro.product.name=tardis\n"
130 "# comment\n\n\n"
131 "ro.product.model\n"
132 "ro.product.board = magic \n");
133 ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file2.path));
134
135 std::string script1("file_getprop(\"" + std::string(temp_file2.path) +
136 "\", \"ro.product.name\")");
137 expect("tardis", script1.c_str(), kNoCause);
138
139 std::string script2("file_getprop(\"" + std::string(temp_file2.path) +
140 "\", \"ro.product.board\")");
141 expect("magic", script2.c_str(), kNoCause);
142
143 // No match.
144 std::string script3("file_getprop(\"" + std::string(temp_file2.path) +
145 "\", \"ro.product.wrong\")");
146 expect("", script3.c_str(), kNoCause);
147
148 std::string script4("file_getprop(\"" + std::string(temp_file2.path) +
149 "\", \"ro.product.name=\")");
150 expect("", script4.c_str(), kNoCause);
151
152 std::string script5("file_getprop(\"" + std::string(temp_file2.path) +
153 "\", \"ro.product.nam\")");
154 expect("", script5.c_str(), kNoCause);
155
156 std::string script6("file_getprop(\"" + std::string(temp_file2.path) +
157 "\", \"ro.product.model\")");
158 expect("", script6.c_str(), kNoCause);
159}
Tao Bao0831d0b2016-11-03 23:25:04 -0700160
161TEST_F(UpdaterTest, delete) {
162 // Delete none.
163 expect("0", "delete()", kNoCause);
164 expect("0", "delete(\"/doesntexist\")", kNoCause);
165 expect("0", "delete(\"/doesntexist1\", \"/doesntexist2\")", kNoCause);
166 expect("0", "delete(\"/doesntexist1\", \"/doesntexist2\", \"/doesntexist3\")", kNoCause);
167
168 // Delete one file.
169 TemporaryFile temp_file1;
170 ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file1.path));
171 std::string script1("delete(\"" + std::string(temp_file1.path) + "\")");
172 expect("1", script1.c_str(), kNoCause);
173
174 // Delete two files.
175 TemporaryFile temp_file2;
176 ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file2.path));
177 TemporaryFile temp_file3;
178 ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file3.path));
179 std::string script2("delete(\"" + std::string(temp_file2.path) + "\", \"" +
180 std::string(temp_file3.path) + "\")");
181 expect("2", script2.c_str(), kNoCause);
182
183 // Delete already deleted files.
184 expect("0", script2.c_str(), kNoCause);
185
186 // Delete one out of three.
187 TemporaryFile temp_file4;
188 ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file4.path));
189 std::string script3("delete(\"/doesntexist1\", \"" + std::string(temp_file4.path) +
190 "\", \"/doesntexist2\")");
191 expect("1", script3.c_str(), kNoCause);
192}
Tao Baoa659d792016-11-03 23:25:04 -0700193
194TEST_F(UpdaterTest, rename) {
195 // rename() expects two arguments.
196 expect(nullptr, "rename()", kArgsParsingFailure);
197 expect(nullptr, "rename(\"arg1\")", kArgsParsingFailure);
198 expect(nullptr, "rename(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
199
200 // src_name or dst_name cannot be empty.
201 expect(nullptr, "rename(\"\", \"arg2\")", kArgsParsingFailure);
202 expect(nullptr, "rename(\"arg1\", \"\")", kArgsParsingFailure);
203
204 // File doesn't exist (both of src and dst).
205 expect(nullptr, "rename(\"/doesntexist\", \"/doesntexisteither\")" , kFileRenameFailure);
206
207 // Can't create parent directory.
208 TemporaryFile temp_file1;
209 ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file1.path));
210 std::string script1("rename(\"" + std::string(temp_file1.path) + "\", \"/proc/0/file1\")");
211 expect(nullptr, script1.c_str(), kFileRenameFailure);
212
213 // Rename.
214 TemporaryFile temp_file2;
215 std::string script2("rename(\"" + std::string(temp_file1.path) + "\", \"" +
216 std::string(temp_file2.path) + "\")");
217 expect(temp_file2.path, script2.c_str(), kNoCause);
218
219 // Already renamed.
220 expect(temp_file2.path, script2.c_str(), kNoCause);
Tianjie Xud75003d2016-11-04 11:31:29 -0700221
222 // Parents create successfully.
223 TemporaryFile temp_file3;
224 TemporaryDir td;
Tao Bao89929022016-11-08 20:51:31 -0800225 std::string temp_dir(td.path);
226 std::string dst_file = temp_dir + "/aaa/bbb/a.txt";
227 std::string script3("rename(\"" + std::string(temp_file3.path) + "\", \"" + dst_file + "\")");
228 expect(dst_file.c_str(), script3.c_str(), kNoCause);
229
230 // Clean up the temp files under td.
231 ASSERT_EQ(0, unlink(dst_file.c_str()));
232 ASSERT_EQ(0, rmdir((temp_dir + "/aaa/bbb").c_str()));
233 ASSERT_EQ(0, rmdir((temp_dir + "/aaa").c_str()));
Tianjie Xud75003d2016-11-04 11:31:29 -0700234}
235
236TEST_F(UpdaterTest, symlink) {
237 // symlink expects 1+ argument.
238 expect(nullptr, "symlink()", kArgsParsingFailure);
239
240 // symlink should fail if src is an empty string.
241 TemporaryFile temp_file1;
242 std::string script1("symlink(\"" + std::string(temp_file1.path) + "\", \"\")");
243 expect(nullptr, script1.c_str(), kSymlinkFailure);
244
Tao Bao89929022016-11-08 20:51:31 -0800245 std::string script2("symlink(\"" + std::string(temp_file1.path) + "\", \"src1\", \"\")");
Tianjie Xud75003d2016-11-04 11:31:29 -0700246 expect(nullptr, script2.c_str(), kSymlinkFailure);
Tao Bao89929022016-11-08 20:51:31 -0800247
248 // symlink failed to remove old src.
249 std::string script3("symlink(\"" + std::string(temp_file1.path) + "\", \"/proc\")");
250 expect(nullptr, script3.c_str(), kSymlinkFailure);
251
252 // symlink can create symlinks.
253 TemporaryFile temp_file;
254 std::string content = "magicvalue";
255 ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path));
256
257 TemporaryDir td;
258 std::string src1 = std::string(td.path) + "/symlink1";
259 std::string src2 = std::string(td.path) + "/symlink2";
260 std::string script4("symlink(\"" + std::string(temp_file.path) + "\", \"" +
261 src1 + "\", \"" + src2 + "\")");
262 expect("t", script4.c_str(), kNoCause);
263
264 // Verify the created symlinks.
265 struct stat sb;
266 ASSERT_TRUE(lstat(src1.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode));
267 ASSERT_TRUE(lstat(src2.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode));
268
269 // Clean up the leftovers.
270 ASSERT_EQ(0, unlink(src1.c_str()));
271 ASSERT_EQ(0, unlink(src2.c_str()));
Tao Baoa659d792016-11-03 23:25:04 -0700272}
Tao Baoef0eb3b2016-11-14 21:29:52 -0800273
Tao Bao1036d362016-11-17 22:49:56 -0800274TEST_F(UpdaterTest, package_extract_dir) {
275 // package_extract_dir expects 2 arguments.
276 expect(nullptr, "package_extract_dir()", kArgsParsingFailure);
277 expect(nullptr, "package_extract_dir(\"arg1\")", kArgsParsingFailure);
278 expect(nullptr, "package_extract_dir(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
279
280 std::string zip_path = from_testdata_base("ziptest_valid.zip");
281 ZipArchiveHandle handle;
282 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
283
284 // Need to set up the ziphandle.
285 UpdaterInfo updater_info;
286 updater_info.package_zip = handle;
287
288 // Extract "b/c.txt" and "b/d.txt" with package_extract_dir("b", "<dir>").
289 TemporaryDir td;
290 std::string temp_dir(td.path);
291 std::string script("package_extract_dir(\"b\", \"" + temp_dir + "\")");
292 expect("t", script.c_str(), kNoCause, &updater_info);
293
294 // Verify.
295 std::string data;
296 std::string file_c = temp_dir + "/c.txt";
297 ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
298 ASSERT_EQ(kCTxtContents, data);
299
300 std::string file_d = temp_dir + "/d.txt";
301 ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
302 ASSERT_EQ(kDTxtContents, data);
303
304 // Modify the contents in order to retry. It's expected to be overwritten.
305 ASSERT_TRUE(android::base::WriteStringToFile("random", file_c));
306 ASSERT_TRUE(android::base::WriteStringToFile("random", file_d));
307
308 // Extract again and verify.
309 expect("t", script.c_str(), kNoCause, &updater_info);
310
311 ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
312 ASSERT_EQ(kCTxtContents, data);
313 ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
314 ASSERT_EQ(kDTxtContents, data);
315
316 // Clean up the temp files under td.
317 ASSERT_EQ(0, unlink(file_c.c_str()));
318 ASSERT_EQ(0, unlink(file_d.c_str()));
319
320 // Extracting "b/" (with slash) should give the same result.
321 script = "package_extract_dir(\"b/\", \"" + temp_dir + "\")";
322 expect("t", script.c_str(), kNoCause, &updater_info);
323
324 ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
325 ASSERT_EQ(kCTxtContents, data);
326 ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
327 ASSERT_EQ(kDTxtContents, data);
328
329 ASSERT_EQ(0, unlink(file_c.c_str()));
330 ASSERT_EQ(0, unlink(file_d.c_str()));
331
332 // Extracting "" is allowed. The entries will carry the path name.
333 script = "package_extract_dir(\"\", \"" + temp_dir + "\")";
334 expect("t", script.c_str(), kNoCause, &updater_info);
335
336 std::string file_a = temp_dir + "/a.txt";
337 ASSERT_TRUE(android::base::ReadFileToString(file_a, &data));
338 ASSERT_EQ(kATxtContents, data);
339 std::string file_b = temp_dir + "/b.txt";
340 ASSERT_TRUE(android::base::ReadFileToString(file_b, &data));
341 ASSERT_EQ(kBTxtContents, data);
342 std::string file_b_c = temp_dir + "/b/c.txt";
343 ASSERT_TRUE(android::base::ReadFileToString(file_b_c, &data));
344 ASSERT_EQ(kCTxtContents, data);
345 std::string file_b_d = temp_dir + "/b/d.txt";
346 ASSERT_TRUE(android::base::ReadFileToString(file_b_d, &data));
347 ASSERT_EQ(kDTxtContents, data);
348
349 ASSERT_EQ(0, unlink(file_a.c_str()));
350 ASSERT_EQ(0, unlink(file_b.c_str()));
351 ASSERT_EQ(0, unlink(file_b_c.c_str()));
352 ASSERT_EQ(0, unlink(file_b_d.c_str()));
353 ASSERT_EQ(0, rmdir((temp_dir + "/b").c_str()));
354
355 // Extracting non-existent entry should still give "t".
356 script = "package_extract_dir(\"doesntexist\", \"" + temp_dir + "\")";
357 expect("t", script.c_str(), kNoCause, &updater_info);
358
359 // Only relative zip_path is allowed.
360 script = "package_extract_dir(\"/b\", \"" + temp_dir + "\")";
361 expect("", script.c_str(), kNoCause, &updater_info);
362
363 // Only absolute dest_path is allowed.
364 script = "package_extract_dir(\"b\", \"path\")";
365 expect("", script.c_str(), kNoCause, &updater_info);
366
367 CloseArchive(handle);
368}
369
Tao Baoef0eb3b2016-11-14 21:29:52 -0800370// TODO: Test extracting to block device.
371TEST_F(UpdaterTest, package_extract_file) {
372 // package_extract_file expects 1 or 2 arguments.
373 expect(nullptr, "package_extract_file()", kArgsParsingFailure);
374 expect(nullptr, "package_extract_file(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
375
376 std::string zip_path = from_testdata_base("ziptest_valid.zip");
377 ZipArchiveHandle handle;
378 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
379
380 // Need to set up the ziphandle.
381 UpdaterInfo updater_info;
382 updater_info.package_zip = handle;
383
384 // Two-argument version.
385 TemporaryFile temp_file1;
386 std::string script("package_extract_file(\"a.txt\", \"" + std::string(temp_file1.path) + "\")");
387 expect("t", script.c_str(), kNoCause, &updater_info);
388
389 // Verify the extracted entry.
390 std::string data;
391 ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
392 ASSERT_EQ(kATxtContents, data);
393
394 // Now extract another entry to the same location, which should overwrite.
395 script = "package_extract_file(\"b.txt\", \"" + std::string(temp_file1.path) + "\")";
396 expect("t", script.c_str(), kNoCause, &updater_info);
397
398 ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
399 ASSERT_EQ(kBTxtContents, data);
400
401 // Missing zip entry. The two-argument version doesn't abort.
402 script = "package_extract_file(\"doesntexist\", \"" + std::string(temp_file1.path) + "\")";
403 expect("", script.c_str(), kNoCause, &updater_info);
404
405 // Extract to /dev/full should fail.
406 script = "package_extract_file(\"a.txt\", \"/dev/full\")";
407 expect("", script.c_str(), kNoCause, &updater_info);
408
409 // One-argument version.
410 script = "sha1_check(package_extract_file(\"a.txt\"))";
411 expect(kATxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
412
413 script = "sha1_check(package_extract_file(\"b.txt\"))";
414 expect(kBTxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
415
416 // Missing entry. The one-argument version aborts the evaluation.
417 script = "package_extract_file(\"doesntexist\")";
418 expect(nullptr, script.c_str(), kPackageExtractFileFailure, &updater_info);
419
420 CloseArchive(handle);
421}
Tao Baod0f30882016-11-03 23:52:01 -0700422
423TEST_F(UpdaterTest, write_value) {
424 // write_value() expects two arguments.
425 expect(nullptr, "write_value()", kArgsParsingFailure);
426 expect(nullptr, "write_value(\"arg1\")", kArgsParsingFailure);
427 expect(nullptr, "write_value(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
428
429 // filename cannot be empty.
430 expect(nullptr, "write_value(\"value\", \"\")", kArgsParsingFailure);
431
432 // Write some value to file.
433 TemporaryFile temp_file;
434 std::string value = "magicvalue";
435 std::string script("write_value(\"" + value + "\", \"" + std::string(temp_file.path) + "\")");
436 expect("t", script.c_str(), kNoCause);
437
438 // Verify the content.
439 std::string content;
440 ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
441 ASSERT_EQ(value, content);
442
443 // Allow writing empty string.
444 script = "write_value(\"\", \"" + std::string(temp_file.path) + "\")";
445 expect("t", script.c_str(), kNoCause);
446
447 // Verify the content.
448 ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
449 ASSERT_EQ("", content);
450
451 // It should fail gracefully when write fails.
452 script = "write_value(\"value\", \"/proc/0/file1\")";
453 expect("", script.c_str(), kNoCause);
454}
Tao Baobedf5fc2016-11-18 12:01:26 -0800455
456TEST_F(UpdaterTest, get_stage) {
457 // get_stage() expects one argument.
458 expect(nullptr, "get_stage()", kArgsParsingFailure);
459 expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure);
460 expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
461
462 // Set up a local file as BCB.
463 TemporaryFile tf;
464 std::string temp_file(tf.path);
465 bootloader_message boot;
466 strlcpy(boot.stage, "2/3", sizeof(boot.stage));
467 std::string err;
468 ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
469
470 // Can read the stage value.
471 std::string script("get_stage(\"" + temp_file + "\")");
472 expect("2/3", script.c_str(), kNoCause);
473
474 // Bad BCB path.
475 script = "get_stage(\"doesntexist\")";
476 expect("", script.c_str(), kNoCause);
477}
478
479TEST_F(UpdaterTest, set_stage) {
480 // set_stage() expects two arguments.
481 expect(nullptr, "set_stage()", kArgsParsingFailure);
482 expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure);
483 expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
484
485 // Set up a local file as BCB.
486 TemporaryFile tf;
487 std::string temp_file(tf.path);
488 bootloader_message boot;
489 strlcpy(boot.command, "command", sizeof(boot.command));
490 strlcpy(boot.stage, "2/3", sizeof(boot.stage));
491 std::string err;
492 ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
493
494 // Write with set_stage().
495 std::string script("set_stage(\"" + temp_file + "\", \"1/3\")");
496 expect(tf.path, script.c_str(), kNoCause);
497
498 // Verify.
499 bootloader_message boot_verify;
500 ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err));
501
502 // Stage should be updated, with command part untouched.
503 ASSERT_STREQ("1/3", boot_verify.stage);
504 ASSERT_STREQ(boot.command, boot_verify.command);
505
506 // Bad BCB path.
507 script = "set_stage(\"doesntexist\", \"1/3\")";
508 expect("", script.c_str(), kNoCause);
509
510 script = "set_stage(\"/dev/full\", \"1/3\")";
511 expect("", script.c_str(), kNoCause);
512}