blob: 032a24da4a15be125ef6880c437030acd9199a09 [file] [log] [blame]
Darin Petkov0406e402010-10-06 21:33:11 -07001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Darin Petkov698d0412010-10-13 10:59:44 -07005#include <fcntl.h>
6
adlr@google.com3defe6a2009-12-04 20:57:17 +00007#include <set>
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -08008#include <string>
adlr@google.com3defe6a2009-12-04 20:57:17 +00009#include <vector>
Darin Petkov698d0412010-10-13 10:59:44 -070010
11#include <base/eintr_wrapper.h>
12#include <base/string_util.h>
13#include <glib.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000014#include <gtest/gtest.h>
Darin Petkov698d0412010-10-13 10:59:44 -070015
adlr@google.com3defe6a2009-12-04 20:57:17 +000016#include "update_engine/filesystem_copier_action.h"
17#include "update_engine/filesystem_iterator.h"
18#include "update_engine/omaha_hash_calculator.h"
19#include "update_engine/test_utils.h"
20#include "update_engine/utils.h"
21
22using std::set;
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080023using std::string;
adlr@google.com3defe6a2009-12-04 20:57:17 +000024using std::vector;
25
26namespace chromeos_update_engine {
27
28class FilesystemCopierActionTest : public ::testing::Test {
29 protected:
Andrew de los Reyesf9185172010-05-03 11:07:05 -070030 void DoTest(bool run_out_of_space,
31 bool terminate_early,
32 bool use_kernel_partition);
adlr@google.com3defe6a2009-12-04 20:57:17 +000033 void SetUp() {
adlr@google.com3defe6a2009-12-04 20:57:17 +000034 }
35 void TearDown() {
adlr@google.com3defe6a2009-12-04 20:57:17 +000036 }
37};
38
39class FilesystemCopierActionTestDelegate : public ActionProcessorDelegate {
40 public:
Darin Petkovc1a8b422010-07-19 11:34:49 -070041 FilesystemCopierActionTestDelegate() : ran_(false), code_(kActionCodeError) {}
Andrew de los Reyesc7020782010-04-28 10:46:04 -070042 void ExitMainLoop() {
43 while (g_main_context_pending(NULL)) {
44 g_main_context_iteration(NULL, false);
45 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000046 g_main_loop_quit(loop_);
47 }
Darin Petkovc1a8b422010-07-19 11:34:49 -070048 void ProcessingDone(const ActionProcessor* processor, ActionExitCode code) {
Andrew de los Reyesc7020782010-04-28 10:46:04 -070049 ExitMainLoop();
50 }
51 void ProcessingStopped(const ActionProcessor* processor) {
52 ExitMainLoop();
53 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000054 void ActionCompleted(ActionProcessor* processor,
55 AbstractAction* action,
Darin Petkovc1a8b422010-07-19 11:34:49 -070056 ActionExitCode code) {
adlr@google.com3defe6a2009-12-04 20:57:17 +000057 if (action->Type() == FilesystemCopierAction::StaticType()) {
58 ran_ = true;
Darin Petkovc1a8b422010-07-19 11:34:49 -070059 code_ = code;
adlr@google.com3defe6a2009-12-04 20:57:17 +000060 }
61 }
62 void set_loop(GMainLoop* loop) {
63 loop_ = loop;
64 }
65 bool ran() { return ran_; }
Darin Petkovc1a8b422010-07-19 11:34:49 -070066 ActionExitCode code() { return code_; }
adlr@google.com3defe6a2009-12-04 20:57:17 +000067 private:
68 GMainLoop* loop_;
69 bool ran_;
Darin Petkovc1a8b422010-07-19 11:34:49 -070070 ActionExitCode code_;
adlr@google.com3defe6a2009-12-04 20:57:17 +000071};
72
Andrew de los Reyesc7020782010-04-28 10:46:04 -070073struct StartProcessorCallbackArgs {
74 ActionProcessor* processor;
75 FilesystemCopierAction* filesystem_copier_action;
76 bool terminate_early;
77};
78
adlr@google.com3defe6a2009-12-04 20:57:17 +000079gboolean StartProcessorInRunLoop(gpointer data) {
Andrew de los Reyesc7020782010-04-28 10:46:04 -070080 StartProcessorCallbackArgs* args =
81 reinterpret_cast<StartProcessorCallbackArgs*>(data);
82 ActionProcessor* processor = args->processor;
adlr@google.com3defe6a2009-12-04 20:57:17 +000083 processor->StartProcessing();
Andrew de los Reyesc7020782010-04-28 10:46:04 -070084 if (args->terminate_early) {
85 EXPECT_TRUE(args->filesystem_copier_action);
86 args->processor->StopProcessing();
87 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000088 return FALSE;
89}
90
91TEST_F(FilesystemCopierActionTest, RunAsRootSimpleTest) {
92 ASSERT_EQ(0, getuid());
Andrew de los Reyesf9185172010-05-03 11:07:05 -070093 DoTest(false, false, false);
94
95 DoTest(false, false, true);
adlr@google.com3defe6a2009-12-04 20:57:17 +000096}
Andrew de los Reyesc7020782010-04-28 10:46:04 -070097void FilesystemCopierActionTest::DoTest(bool run_out_of_space,
Andrew de los Reyesf9185172010-05-03 11:07:05 -070098 bool terminate_early,
99 bool use_kernel_partition) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000100 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
101
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700102 string a_loop_file;
103 string b_loop_file;
Darin Petkovc1a8b422010-07-19 11:34:49 -0700104
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700105 EXPECT_TRUE(utils::MakeTempFile("/tmp/a_loop_file.XXXXXX",
106 &a_loop_file,
107 NULL));
108 ScopedPathUnlinker a_loop_file_unlinker(a_loop_file);
109 EXPECT_TRUE(utils::MakeTempFile("/tmp/b_loop_file.XXXXXX",
110 &b_loop_file,
111 NULL));
112 ScopedPathUnlinker b_loop_file_unlinker(b_loop_file);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700113
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700114 // Make random data for a, zero filled data for b.
115 const size_t kLoopFileSize = 10 * 1024 * 1024 + 512;
116 vector<char> a_loop_data(kLoopFileSize);
117 FillWithData(&a_loop_data);
118 vector<char> b_loop_data(run_out_of_space ?
119 (kLoopFileSize - 1) :
120 kLoopFileSize,
121 '\0'); // Fill with 0s
adlr@google.com3defe6a2009-12-04 20:57:17 +0000122
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700123 // Write data to disk
124 EXPECT_TRUE(WriteFileVector(a_loop_file, a_loop_data));
125 EXPECT_TRUE(WriteFileVector(b_loop_file, b_loop_data));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000126
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700127 // Make loop devices for the files
128 string a_dev = GetUnusedLoopDevice();
129 EXPECT_FALSE(a_dev.empty());
130 EXPECT_EQ(0, System(StringPrintf("losetup %s %s",
131 a_dev.c_str(),
132 a_loop_file.c_str())));
133 ScopedLoopbackDeviceReleaser a_dev_releaser(a_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000134
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700135 string b_dev = GetUnusedLoopDevice();
136 EXPECT_FALSE(b_dev.empty());
137 EXPECT_EQ(0, System(StringPrintf("losetup %s %s",
138 b_dev.c_str(),
139 b_loop_file.c_str())));
140 ScopedLoopbackDeviceReleaser b_dev_releaser(b_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000141
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700142 // Set up the action objects
adlr@google.com3defe6a2009-12-04 20:57:17 +0000143 InstallPlan install_plan;
144 install_plan.is_full_update = false;
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700145 if (use_kernel_partition)
146 install_plan.kernel_install_path = b_dev;
147 else
148 install_plan.install_path = b_dev;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000149
150 ActionProcessor processor;
151 FilesystemCopierActionTestDelegate delegate;
152 delegate.set_loop(loop);
153 processor.set_delegate(&delegate);
154
155 ObjectFeederAction<InstallPlan> feeder_action;
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700156 FilesystemCopierAction copier_action(use_kernel_partition);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000157 ObjectCollectorAction<InstallPlan> collector_action;
158
159 BondActions(&feeder_action, &copier_action);
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700160 BondActions(&copier_action, &collector_action);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000161
162 processor.EnqueueAction(&feeder_action);
163 processor.EnqueueAction(&copier_action);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000164 processor.EnqueueAction(&collector_action);
165
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700166 copier_action.set_copy_source(a_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000167 feeder_action.set_obj(install_plan);
168
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700169 StartProcessorCallbackArgs start_callback_args;
170 start_callback_args.processor = &processor;
171 start_callback_args.filesystem_copier_action = &copier_action;
172 start_callback_args.terminate_early = terminate_early;
173
174 g_timeout_add(0, &StartProcessorInRunLoop, &start_callback_args);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000175 g_main_loop_run(loop);
176 g_main_loop_unref(loop);
177
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700178 if (!terminate_early)
179 EXPECT_TRUE(delegate.ran());
180 if (run_out_of_space || terminate_early) {
Darin Petkovc1a8b422010-07-19 11:34:49 -0700181 EXPECT_EQ(kActionCodeError, delegate.code());
adlr@google.com3defe6a2009-12-04 20:57:17 +0000182 return;
183 }
Darin Petkovc1a8b422010-07-19 11:34:49 -0700184 EXPECT_EQ(kActionCodeSuccess, delegate.code());
adlr@google.com3defe6a2009-12-04 20:57:17 +0000185
adlr@google.com3defe6a2009-12-04 20:57:17 +0000186 // Make sure everything in the out_image is there
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700187 vector<char> a_out;
188 vector<char> b_out;
189 EXPECT_TRUE(utils::ReadFile(a_dev, &a_out));
190 EXPECT_TRUE(utils::ReadFile(b_dev, &b_out));
191 EXPECT_TRUE(ExpectVectorsEq(a_out, b_out));
192 EXPECT_TRUE(ExpectVectorsEq(a_loop_data, a_out));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000193
adlr@google.com3defe6a2009-12-04 20:57:17 +0000194 EXPECT_TRUE(collector_action.object() == install_plan);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800195 if (terminate_early) {
196 // sleep so OS can clean up
197 sleep(1);
198 }
adlr@google.com3defe6a2009-12-04 20:57:17 +0000199}
200
201class FilesystemCopierActionTest2Delegate : public ActionProcessorDelegate {
202 public:
203 void ActionCompleted(ActionProcessor* processor,
204 AbstractAction* action,
Darin Petkovc1a8b422010-07-19 11:34:49 -0700205 ActionExitCode code) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000206 if (action->Type() == FilesystemCopierAction::StaticType()) {
207 ran_ = true;
Darin Petkovc1a8b422010-07-19 11:34:49 -0700208 code_ = code;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000209 }
210 }
211 GMainLoop *loop_;
212 bool ran_;
Darin Petkovc1a8b422010-07-19 11:34:49 -0700213 ActionExitCode code_;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000214};
215
216TEST_F(FilesystemCopierActionTest, MissingInputObjectTest) {
217 ActionProcessor processor;
218 FilesystemCopierActionTest2Delegate delegate;
219
220 processor.set_delegate(&delegate);
221
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700222 FilesystemCopierAction copier_action(false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000223 ObjectCollectorAction<InstallPlan> collector_action;
224
225 BondActions(&copier_action, &collector_action);
226
227 processor.EnqueueAction(&copier_action);
228 processor.EnqueueAction(&collector_action);
229 processor.StartProcessing();
230 EXPECT_FALSE(processor.IsRunning());
231 EXPECT_TRUE(delegate.ran_);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700232 EXPECT_EQ(kActionCodeError, delegate.code_);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000233}
234
235TEST_F(FilesystemCopierActionTest, FullUpdateTest) {
236 ActionProcessor processor;
237 FilesystemCopierActionTest2Delegate delegate;
238
239 processor.set_delegate(&delegate);
240
241 ObjectFeederAction<InstallPlan> feeder_action;
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700242 const char* kUrl = "http://some/url";
Darin Petkov0406e402010-10-06 21:33:11 -0700243 InstallPlan install_plan(true, false, kUrl, 0, "", "", "");
adlr@google.com3defe6a2009-12-04 20:57:17 +0000244 feeder_action.set_obj(install_plan);
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700245 FilesystemCopierAction copier_action(false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000246 ObjectCollectorAction<InstallPlan> collector_action;
247
248 BondActions(&feeder_action, &copier_action);
249 BondActions(&copier_action, &collector_action);
250
251 processor.EnqueueAction(&feeder_action);
252 processor.EnqueueAction(&copier_action);
253 processor.EnqueueAction(&collector_action);
254 processor.StartProcessing();
255 EXPECT_FALSE(processor.IsRunning());
256 EXPECT_TRUE(delegate.ran_);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700257 EXPECT_EQ(kActionCodeSuccess, delegate.code_);
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700258 EXPECT_EQ(kUrl, collector_action.object().download_url);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000259}
260
Darin Petkov9b230572010-10-08 10:20:09 -0700261TEST_F(FilesystemCopierActionTest, ResumeTest) {
262 ActionProcessor processor;
263 FilesystemCopierActionTest2Delegate delegate;
264
265 processor.set_delegate(&delegate);
266
267 ObjectFeederAction<InstallPlan> feeder_action;
268 const char* kUrl = "http://some/url";
269 InstallPlan install_plan(false, true, kUrl, 0, "", "", "");
270 feeder_action.set_obj(install_plan);
271 FilesystemCopierAction copier_action(false);
272 ObjectCollectorAction<InstallPlan> collector_action;
273
274 BondActions(&feeder_action, &copier_action);
275 BondActions(&copier_action, &collector_action);
276
277 processor.EnqueueAction(&feeder_action);
278 processor.EnqueueAction(&copier_action);
279 processor.EnqueueAction(&collector_action);
280 processor.StartProcessing();
281 EXPECT_FALSE(processor.IsRunning());
282 EXPECT_TRUE(delegate.ran_);
283 EXPECT_EQ(kActionCodeSuccess, delegate.code_);
284 EXPECT_EQ(kUrl, collector_action.object().download_url);
285}
286
adlr@google.com3defe6a2009-12-04 20:57:17 +0000287TEST_F(FilesystemCopierActionTest, NonExistentDriveTest) {
288 ActionProcessor processor;
289 FilesystemCopierActionTest2Delegate delegate;
290
291 processor.set_delegate(&delegate);
292
293 ObjectFeederAction<InstallPlan> feeder_action;
Darin Petkov0406e402010-10-06 21:33:11 -0700294 InstallPlan install_plan(false,
295 false,
296 "",
297 0,
298 "",
299 "/no/such/file",
300 "/no/such/file");
adlr@google.com3defe6a2009-12-04 20:57:17 +0000301 feeder_action.set_obj(install_plan);
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700302 FilesystemCopierAction copier_action(false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000303 ObjectCollectorAction<InstallPlan> collector_action;
304
305 BondActions(&copier_action, &collector_action);
306
307 processor.EnqueueAction(&feeder_action);
308 processor.EnqueueAction(&copier_action);
309 processor.EnqueueAction(&collector_action);
310 processor.StartProcessing();
311 EXPECT_FALSE(processor.IsRunning());
312 EXPECT_TRUE(delegate.ran_);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700313 EXPECT_EQ(kActionCodeError, delegate.code_);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000314}
315
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700316TEST_F(FilesystemCopierActionTest, RunAsRootNoSpaceTest) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000317 ASSERT_EQ(0, getuid());
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700318 DoTest(true, false, false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000319}
320
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700321TEST_F(FilesystemCopierActionTest, RunAsRootTerminateEarlyTest) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000322 ASSERT_EQ(0, getuid());
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700323 DoTest(false, true, false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000324}
325
Darin Petkov698d0412010-10-13 10:59:44 -0700326TEST_F(FilesystemCopierActionTest, RunAsRootDetermineFilesystemSizeTest) {
327 string img;
328 EXPECT_TRUE(utils::MakeTempFile("/tmp/img.XXXXXX", &img, NULL));
329 ScopedPathUnlinker img_unlinker(img);
330 CreateExtImageAtPath(img, NULL);
331 // Extend the "partition" holding the file system from 10MiB to 20MiB.
332 EXPECT_EQ(0, System(StringPrintf(
333 "dd if=/dev/zero of=%s seek=20971519 bs=1 count=1",
334 img.c_str())));
335 EXPECT_EQ(20 * 1024 * 1024, utils::FileSize(img));
336
337 for (int i = 0; i < 2; ++i) {
338 bool is_kernel = i == 1;
339 FilesystemCopierAction action(is_kernel);
340 EXPECT_EQ(kint64max, action.filesystem_size_);
341 {
342 int fd = HANDLE_EINTR(open(img.c_str(), O_RDONLY));
343 EXPECT_TRUE(fd > 0);
344 ScopedFdCloser fd_closer(&fd);
345 action.DetermineFilesystemSize(fd);
346 }
347 EXPECT_EQ(is_kernel ? kint64max : 10 * 1024 * 1024,
348 action.filesystem_size_);
349 }
350}
351
352
adlr@google.com3defe6a2009-12-04 20:57:17 +0000353} // namespace chromeos_update_engine