blob: 03aa86aa16996ddf307c5cc839b01c794803060c [file] [log] [blame]
Andrew de los Reyesc7020782010-04-28 10:46:04 -07001// Copyright (c) 2010 The Chromium 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
5#include <glib.h>
6#include <set>
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -08007#include <string>
adlr@google.com3defe6a2009-12-04 20:57:17 +00008#include <vector>
9#include <gtest/gtest.h>
Andrew de los Reyesc7020782010-04-28 10:46:04 -070010#include "base/string_util.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000011#include "update_engine/filesystem_copier_action.h"
12#include "update_engine/filesystem_iterator.h"
13#include "update_engine/omaha_hash_calculator.h"
14#include "update_engine/test_utils.h"
15#include "update_engine/utils.h"
16
17using std::set;
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080018using std::string;
adlr@google.com3defe6a2009-12-04 20:57:17 +000019using std::vector;
20
21namespace chromeos_update_engine {
22
23class FilesystemCopierActionTest : public ::testing::Test {
24 protected:
Andrew de los Reyesf9185172010-05-03 11:07:05 -070025 void DoTest(bool run_out_of_space,
26 bool terminate_early,
27 bool use_kernel_partition);
adlr@google.com3defe6a2009-12-04 20:57:17 +000028 void SetUp() {
adlr@google.com3defe6a2009-12-04 20:57:17 +000029 }
30 void TearDown() {
adlr@google.com3defe6a2009-12-04 20:57:17 +000031 }
32};
33
34class FilesystemCopierActionTestDelegate : public ActionProcessorDelegate {
35 public:
Darin Petkovc1a8b422010-07-19 11:34:49 -070036 FilesystemCopierActionTestDelegate() : ran_(false), code_(kActionCodeError) {}
Andrew de los Reyesc7020782010-04-28 10:46:04 -070037 void ExitMainLoop() {
38 while (g_main_context_pending(NULL)) {
39 g_main_context_iteration(NULL, false);
40 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000041 g_main_loop_quit(loop_);
42 }
Darin Petkovc1a8b422010-07-19 11:34:49 -070043 void ProcessingDone(const ActionProcessor* processor, ActionExitCode code) {
Andrew de los Reyesc7020782010-04-28 10:46:04 -070044 ExitMainLoop();
45 }
46 void ProcessingStopped(const ActionProcessor* processor) {
47 ExitMainLoop();
48 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000049 void ActionCompleted(ActionProcessor* processor,
50 AbstractAction* action,
Darin Petkovc1a8b422010-07-19 11:34:49 -070051 ActionExitCode code) {
adlr@google.com3defe6a2009-12-04 20:57:17 +000052 if (action->Type() == FilesystemCopierAction::StaticType()) {
53 ran_ = true;
Darin Petkovc1a8b422010-07-19 11:34:49 -070054 code_ = code;
adlr@google.com3defe6a2009-12-04 20:57:17 +000055 }
56 }
57 void set_loop(GMainLoop* loop) {
58 loop_ = loop;
59 }
60 bool ran() { return ran_; }
Darin Petkovc1a8b422010-07-19 11:34:49 -070061 ActionExitCode code() { return code_; }
adlr@google.com3defe6a2009-12-04 20:57:17 +000062 private:
63 GMainLoop* loop_;
64 bool ran_;
Darin Petkovc1a8b422010-07-19 11:34:49 -070065 ActionExitCode code_;
adlr@google.com3defe6a2009-12-04 20:57:17 +000066};
67
Andrew de los Reyesc7020782010-04-28 10:46:04 -070068struct StartProcessorCallbackArgs {
69 ActionProcessor* processor;
70 FilesystemCopierAction* filesystem_copier_action;
71 bool terminate_early;
72};
73
adlr@google.com3defe6a2009-12-04 20:57:17 +000074gboolean StartProcessorInRunLoop(gpointer data) {
Andrew de los Reyesc7020782010-04-28 10:46:04 -070075 StartProcessorCallbackArgs* args =
76 reinterpret_cast<StartProcessorCallbackArgs*>(data);
77 ActionProcessor* processor = args->processor;
adlr@google.com3defe6a2009-12-04 20:57:17 +000078 processor->StartProcessing();
Andrew de los Reyesc7020782010-04-28 10:46:04 -070079 if (args->terminate_early) {
80 EXPECT_TRUE(args->filesystem_copier_action);
81 args->processor->StopProcessing();
82 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000083 return FALSE;
84}
85
86TEST_F(FilesystemCopierActionTest, RunAsRootSimpleTest) {
87 ASSERT_EQ(0, getuid());
Andrew de los Reyesf9185172010-05-03 11:07:05 -070088 DoTest(false, false, false);
89
90 DoTest(false, false, true);
adlr@google.com3defe6a2009-12-04 20:57:17 +000091}
Andrew de los Reyesc7020782010-04-28 10:46:04 -070092void FilesystemCopierActionTest::DoTest(bool run_out_of_space,
Andrew de los Reyesf9185172010-05-03 11:07:05 -070093 bool terminate_early,
94 bool use_kernel_partition) {
adlr@google.com3defe6a2009-12-04 20:57:17 +000095 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
96
Andrew de los Reyesc7020782010-04-28 10:46:04 -070097 string a_loop_file;
98 string b_loop_file;
Darin Petkovc1a8b422010-07-19 11:34:49 -070099
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700100 EXPECT_TRUE(utils::MakeTempFile("/tmp/a_loop_file.XXXXXX",
101 &a_loop_file,
102 NULL));
103 ScopedPathUnlinker a_loop_file_unlinker(a_loop_file);
104 EXPECT_TRUE(utils::MakeTempFile("/tmp/b_loop_file.XXXXXX",
105 &b_loop_file,
106 NULL));
107 ScopedPathUnlinker b_loop_file_unlinker(b_loop_file);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700108
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700109 // Make random data for a, zero filled data for b.
110 const size_t kLoopFileSize = 10 * 1024 * 1024 + 512;
111 vector<char> a_loop_data(kLoopFileSize);
112 FillWithData(&a_loop_data);
113 vector<char> b_loop_data(run_out_of_space ?
114 (kLoopFileSize - 1) :
115 kLoopFileSize,
116 '\0'); // Fill with 0s
adlr@google.com3defe6a2009-12-04 20:57:17 +0000117
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700118 // Write data to disk
119 EXPECT_TRUE(WriteFileVector(a_loop_file, a_loop_data));
120 EXPECT_TRUE(WriteFileVector(b_loop_file, b_loop_data));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000121
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700122 // Make loop devices for the files
123 string a_dev = GetUnusedLoopDevice();
124 EXPECT_FALSE(a_dev.empty());
125 EXPECT_EQ(0, System(StringPrintf("losetup %s %s",
126 a_dev.c_str(),
127 a_loop_file.c_str())));
128 ScopedLoopbackDeviceReleaser a_dev_releaser(a_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000129
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700130 string b_dev = GetUnusedLoopDevice();
131 EXPECT_FALSE(b_dev.empty());
132 EXPECT_EQ(0, System(StringPrintf("losetup %s %s",
133 b_dev.c_str(),
134 b_loop_file.c_str())));
135 ScopedLoopbackDeviceReleaser b_dev_releaser(b_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000136
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700137 // Set up the action objects
adlr@google.com3defe6a2009-12-04 20:57:17 +0000138 InstallPlan install_plan;
139 install_plan.is_full_update = false;
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700140 if (use_kernel_partition)
141 install_plan.kernel_install_path = b_dev;
142 else
143 install_plan.install_path = b_dev;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000144
145 ActionProcessor processor;
146 FilesystemCopierActionTestDelegate delegate;
147 delegate.set_loop(loop);
148 processor.set_delegate(&delegate);
149
150 ObjectFeederAction<InstallPlan> feeder_action;
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700151 FilesystemCopierAction copier_action(use_kernel_partition);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000152 ObjectCollectorAction<InstallPlan> collector_action;
153
154 BondActions(&feeder_action, &copier_action);
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700155 BondActions(&copier_action, &collector_action);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000156
157 processor.EnqueueAction(&feeder_action);
158 processor.EnqueueAction(&copier_action);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000159 processor.EnqueueAction(&collector_action);
160
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700161 copier_action.set_copy_source(a_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000162 feeder_action.set_obj(install_plan);
163
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700164 StartProcessorCallbackArgs start_callback_args;
165 start_callback_args.processor = &processor;
166 start_callback_args.filesystem_copier_action = &copier_action;
167 start_callback_args.terminate_early = terminate_early;
168
169 g_timeout_add(0, &StartProcessorInRunLoop, &start_callback_args);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000170 g_main_loop_run(loop);
171 g_main_loop_unref(loop);
172
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700173 if (!terminate_early)
174 EXPECT_TRUE(delegate.ran());
175 if (run_out_of_space || terminate_early) {
Darin Petkovc1a8b422010-07-19 11:34:49 -0700176 EXPECT_EQ(kActionCodeError, delegate.code());
adlr@google.com3defe6a2009-12-04 20:57:17 +0000177 return;
178 }
Darin Petkovc1a8b422010-07-19 11:34:49 -0700179 EXPECT_EQ(kActionCodeSuccess, delegate.code());
adlr@google.com3defe6a2009-12-04 20:57:17 +0000180
adlr@google.com3defe6a2009-12-04 20:57:17 +0000181 // Make sure everything in the out_image is there
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700182 vector<char> a_out;
183 vector<char> b_out;
184 EXPECT_TRUE(utils::ReadFile(a_dev, &a_out));
185 EXPECT_TRUE(utils::ReadFile(b_dev, &b_out));
186 EXPECT_TRUE(ExpectVectorsEq(a_out, b_out));
187 EXPECT_TRUE(ExpectVectorsEq(a_loop_data, a_out));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000188
adlr@google.com3defe6a2009-12-04 20:57:17 +0000189 EXPECT_TRUE(collector_action.object() == install_plan);
190}
191
192class FilesystemCopierActionTest2Delegate : public ActionProcessorDelegate {
193 public:
194 void ActionCompleted(ActionProcessor* processor,
195 AbstractAction* action,
Darin Petkovc1a8b422010-07-19 11:34:49 -0700196 ActionExitCode code) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000197 if (action->Type() == FilesystemCopierAction::StaticType()) {
198 ran_ = true;
Darin Petkovc1a8b422010-07-19 11:34:49 -0700199 code_ = code;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000200 }
201 }
202 GMainLoop *loop_;
203 bool ran_;
Darin Petkovc1a8b422010-07-19 11:34:49 -0700204 ActionExitCode code_;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000205};
206
207TEST_F(FilesystemCopierActionTest, MissingInputObjectTest) {
208 ActionProcessor processor;
209 FilesystemCopierActionTest2Delegate delegate;
210
211 processor.set_delegate(&delegate);
212
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700213 FilesystemCopierAction copier_action(false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000214 ObjectCollectorAction<InstallPlan> collector_action;
215
216 BondActions(&copier_action, &collector_action);
217
218 processor.EnqueueAction(&copier_action);
219 processor.EnqueueAction(&collector_action);
220 processor.StartProcessing();
221 EXPECT_FALSE(processor.IsRunning());
222 EXPECT_TRUE(delegate.ran_);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700223 EXPECT_EQ(kActionCodeError, delegate.code_);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000224}
225
226TEST_F(FilesystemCopierActionTest, FullUpdateTest) {
227 ActionProcessor processor;
228 FilesystemCopierActionTest2Delegate delegate;
229
230 processor.set_delegate(&delegate);
231
232 ObjectFeederAction<InstallPlan> feeder_action;
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700233 const char* kUrl = "http://some/url";
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700234 InstallPlan install_plan(true, kUrl, 0, "", "", "");
adlr@google.com3defe6a2009-12-04 20:57:17 +0000235 feeder_action.set_obj(install_plan);
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700236 FilesystemCopierAction copier_action(false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000237 ObjectCollectorAction<InstallPlan> collector_action;
238
239 BondActions(&feeder_action, &copier_action);
240 BondActions(&copier_action, &collector_action);
241
242 processor.EnqueueAction(&feeder_action);
243 processor.EnqueueAction(&copier_action);
244 processor.EnqueueAction(&collector_action);
245 processor.StartProcessing();
246 EXPECT_FALSE(processor.IsRunning());
247 EXPECT_TRUE(delegate.ran_);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700248 EXPECT_EQ(kActionCodeSuccess, delegate.code_);
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700249 EXPECT_EQ(kUrl, collector_action.object().download_url);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000250}
251
252TEST_F(FilesystemCopierActionTest, NonExistentDriveTest) {
253 ActionProcessor processor;
254 FilesystemCopierActionTest2Delegate delegate;
255
256 processor.set_delegate(&delegate);
257
258 ObjectFeederAction<InstallPlan> feeder_action;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700259 InstallPlan install_plan(false, "", 0, "", "/no/such/file", "/no/such/file");
adlr@google.com3defe6a2009-12-04 20:57:17 +0000260 feeder_action.set_obj(install_plan);
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700261 FilesystemCopierAction copier_action(false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000262 ObjectCollectorAction<InstallPlan> collector_action;
263
264 BondActions(&copier_action, &collector_action);
265
266 processor.EnqueueAction(&feeder_action);
267 processor.EnqueueAction(&copier_action);
268 processor.EnqueueAction(&collector_action);
269 processor.StartProcessing();
270 EXPECT_FALSE(processor.IsRunning());
271 EXPECT_TRUE(delegate.ran_);
Darin Petkovc1a8b422010-07-19 11:34:49 -0700272 EXPECT_EQ(kActionCodeError, delegate.code_);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000273}
274
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700275TEST_F(FilesystemCopierActionTest, RunAsRootNoSpaceTest) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000276 ASSERT_EQ(0, getuid());
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700277 DoTest(true, false, false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000278}
279
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700280TEST_F(FilesystemCopierActionTest, RunAsRootTerminateEarlyTest) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000281 ASSERT_EQ(0, getuid());
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700282 DoTest(false, true, false);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000283}
284
285} // namespace chromeos_update_engine