blob: 3ccea2bc7df79b96f417913ebff79421a948ec6d [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 Reyesc7020782010-04-28 10:46:04 -070025 void DoTest(bool run_out_of_space, bool terminate_early);
adlr@google.com3defe6a2009-12-04 20:57:17 +000026 void SetUp() {
adlr@google.com3defe6a2009-12-04 20:57:17 +000027 }
28 void TearDown() {
adlr@google.com3defe6a2009-12-04 20:57:17 +000029 }
30};
31
32class FilesystemCopierActionTestDelegate : public ActionProcessorDelegate {
33 public:
34 FilesystemCopierActionTestDelegate() : ran_(false), success_(false) {}
Andrew de los Reyesc7020782010-04-28 10:46:04 -070035 void ExitMainLoop() {
36 while (g_main_context_pending(NULL)) {
37 g_main_context_iteration(NULL, false);
38 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000039 g_main_loop_quit(loop_);
40 }
Andrew de los Reyesc7020782010-04-28 10:46:04 -070041 void ProcessingDone(const ActionProcessor* processor, bool success) {
42 ExitMainLoop();
43 }
44 void ProcessingStopped(const ActionProcessor* processor) {
45 ExitMainLoop();
46 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000047 void ActionCompleted(ActionProcessor* processor,
48 AbstractAction* action,
49 bool success) {
50 if (action->Type() == FilesystemCopierAction::StaticType()) {
51 ran_ = true;
52 success_ = success;
53 }
54 }
55 void set_loop(GMainLoop* loop) {
56 loop_ = loop;
57 }
58 bool ran() { return ran_; }
59 bool success() { return success_; }
60 private:
61 GMainLoop* loop_;
62 bool ran_;
63 bool success_;
64};
65
Andrew de los Reyesc7020782010-04-28 10:46:04 -070066struct StartProcessorCallbackArgs {
67 ActionProcessor* processor;
68 FilesystemCopierAction* filesystem_copier_action;
69 bool terminate_early;
70};
71
adlr@google.com3defe6a2009-12-04 20:57:17 +000072gboolean StartProcessorInRunLoop(gpointer data) {
Andrew de los Reyesc7020782010-04-28 10:46:04 -070073 StartProcessorCallbackArgs* args =
74 reinterpret_cast<StartProcessorCallbackArgs*>(data);
75 ActionProcessor* processor = args->processor;
adlr@google.com3defe6a2009-12-04 20:57:17 +000076 processor->StartProcessing();
Andrew de los Reyesc7020782010-04-28 10:46:04 -070077 if (args->terminate_early) {
78 EXPECT_TRUE(args->filesystem_copier_action);
79 args->processor->StopProcessing();
80 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000081 return FALSE;
82}
83
84TEST_F(FilesystemCopierActionTest, RunAsRootSimpleTest) {
85 ASSERT_EQ(0, getuid());
86 DoTest(false, false);
87}
Andrew de los Reyesc7020782010-04-28 10:46:04 -070088void FilesystemCopierActionTest::DoTest(bool run_out_of_space,
89 bool terminate_early) {
adlr@google.com3defe6a2009-12-04 20:57:17 +000090 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
91
Andrew de los Reyesc7020782010-04-28 10:46:04 -070092 string a_loop_file;
93 string b_loop_file;
94
95 EXPECT_TRUE(utils::MakeTempFile("/tmp/a_loop_file.XXXXXX",
96 &a_loop_file,
97 NULL));
98 ScopedPathUnlinker a_loop_file_unlinker(a_loop_file);
99 EXPECT_TRUE(utils::MakeTempFile("/tmp/b_loop_file.XXXXXX",
100 &b_loop_file,
101 NULL));
102 ScopedPathUnlinker b_loop_file_unlinker(b_loop_file);
103
104 // Make random data for a, zero filled data for b.
105 const size_t kLoopFileSize = 10 * 1024 * 1024 + 512;
106 vector<char> a_loop_data(kLoopFileSize);
107 FillWithData(&a_loop_data);
108 vector<char> b_loop_data(run_out_of_space ?
109 (kLoopFileSize - 1) :
110 kLoopFileSize,
111 '\0'); // Fill with 0s
adlr@google.com3defe6a2009-12-04 20:57:17 +0000112
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700113 // Write data to disk
114 EXPECT_TRUE(WriteFileVector(a_loop_file, a_loop_data));
115 EXPECT_TRUE(WriteFileVector(b_loop_file, b_loop_data));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000116
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700117 // Make loop devices for the files
118 string a_dev = GetUnusedLoopDevice();
119 EXPECT_FALSE(a_dev.empty());
120 EXPECT_EQ(0, System(StringPrintf("losetup %s %s",
121 a_dev.c_str(),
122 a_loop_file.c_str())));
123 ScopedLoopbackDeviceReleaser a_dev_releaser(a_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000124
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700125 string b_dev = GetUnusedLoopDevice();
126 EXPECT_FALSE(b_dev.empty());
127 EXPECT_EQ(0, System(StringPrintf("losetup %s %s",
128 b_dev.c_str(),
129 b_loop_file.c_str())));
130 ScopedLoopbackDeviceReleaser b_dev_releaser(b_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000131
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700132 // Set up the action objects
adlr@google.com3defe6a2009-12-04 20:57:17 +0000133 InstallPlan install_plan;
134 install_plan.is_full_update = false;
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700135 install_plan.install_path = b_dev;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000136
137 ActionProcessor processor;
138 FilesystemCopierActionTestDelegate delegate;
139 delegate.set_loop(loop);
140 processor.set_delegate(&delegate);
141
142 ObjectFeederAction<InstallPlan> feeder_action;
143 FilesystemCopierAction copier_action;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000144 ObjectCollectorAction<InstallPlan> collector_action;
145
146 BondActions(&feeder_action, &copier_action);
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700147 BondActions(&copier_action, &collector_action);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000148
149 processor.EnqueueAction(&feeder_action);
150 processor.EnqueueAction(&copier_action);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000151 processor.EnqueueAction(&collector_action);
152
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700153 copier_action.set_copy_source(a_dev);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000154 feeder_action.set_obj(install_plan);
155
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700156 StartProcessorCallbackArgs start_callback_args;
157 start_callback_args.processor = &processor;
158 start_callback_args.filesystem_copier_action = &copier_action;
159 start_callback_args.terminate_early = terminate_early;
160
161 g_timeout_add(0, &StartProcessorInRunLoop, &start_callback_args);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000162 g_main_loop_run(loop);
163 g_main_loop_unref(loop);
164
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700165 if (!terminate_early)
166 EXPECT_TRUE(delegate.ran());
167 if (run_out_of_space || terminate_early) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000168 EXPECT_FALSE(delegate.success());
adlr@google.com3defe6a2009-12-04 20:57:17 +0000169 return;
170 }
171 EXPECT_TRUE(delegate.success());
172
adlr@google.com3defe6a2009-12-04 20:57:17 +0000173 // Make sure everything in the out_image is there
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700174 vector<char> a_out;
175 vector<char> b_out;
176 EXPECT_TRUE(utils::ReadFile(a_dev, &a_out));
177 EXPECT_TRUE(utils::ReadFile(b_dev, &b_out));
178 EXPECT_TRUE(ExpectVectorsEq(a_out, b_out));
179 EXPECT_TRUE(ExpectVectorsEq(a_loop_data, a_out));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000180
adlr@google.com3defe6a2009-12-04 20:57:17 +0000181 EXPECT_TRUE(collector_action.object() == install_plan);
182}
183
184class FilesystemCopierActionTest2Delegate : public ActionProcessorDelegate {
185 public:
186 void ActionCompleted(ActionProcessor* processor,
187 AbstractAction* action,
188 bool success) {
189 if (action->Type() == FilesystemCopierAction::StaticType()) {
190 ran_ = true;
191 success_ = success;
192 }
193 }
194 GMainLoop *loop_;
195 bool ran_;
196 bool success_;
197};
198
199TEST_F(FilesystemCopierActionTest, MissingInputObjectTest) {
200 ActionProcessor processor;
201 FilesystemCopierActionTest2Delegate delegate;
202
203 processor.set_delegate(&delegate);
204
205 FilesystemCopierAction copier_action;
206 ObjectCollectorAction<InstallPlan> collector_action;
207
208 BondActions(&copier_action, &collector_action);
209
210 processor.EnqueueAction(&copier_action);
211 processor.EnqueueAction(&collector_action);
212 processor.StartProcessing();
213 EXPECT_FALSE(processor.IsRunning());
214 EXPECT_TRUE(delegate.ran_);
215 EXPECT_FALSE(delegate.success_);
216}
217
218TEST_F(FilesystemCopierActionTest, FullUpdateTest) {
219 ActionProcessor processor;
220 FilesystemCopierActionTest2Delegate delegate;
221
222 processor.set_delegate(&delegate);
223
224 ObjectFeederAction<InstallPlan> feeder_action;
Andrew de los Reyes1e338b82010-01-22 14:57:27 -0800225 InstallPlan install_plan(true, "", "", "");
adlr@google.com3defe6a2009-12-04 20:57:17 +0000226 feeder_action.set_obj(install_plan);
227 FilesystemCopierAction copier_action;
228 ObjectCollectorAction<InstallPlan> collector_action;
229
230 BondActions(&feeder_action, &copier_action);
231 BondActions(&copier_action, &collector_action);
232
233 processor.EnqueueAction(&feeder_action);
234 processor.EnqueueAction(&copier_action);
235 processor.EnqueueAction(&collector_action);
236 processor.StartProcessing();
237 EXPECT_FALSE(processor.IsRunning());
238 EXPECT_TRUE(delegate.ran_);
239 EXPECT_TRUE(delegate.success_);
240}
241
242TEST_F(FilesystemCopierActionTest, NonExistentDriveTest) {
243 ActionProcessor processor;
244 FilesystemCopierActionTest2Delegate delegate;
245
246 processor.set_delegate(&delegate);
247
248 ObjectFeederAction<InstallPlan> feeder_action;
Andrew de los Reyes1e338b82010-01-22 14:57:27 -0800249 InstallPlan install_plan(false, "", "", "/some/missing/file/path");
adlr@google.com3defe6a2009-12-04 20:57:17 +0000250 feeder_action.set_obj(install_plan);
251 FilesystemCopierAction copier_action;
252 ObjectCollectorAction<InstallPlan> collector_action;
253
254 BondActions(&copier_action, &collector_action);
255
256 processor.EnqueueAction(&feeder_action);
257 processor.EnqueueAction(&copier_action);
258 processor.EnqueueAction(&collector_action);
259 processor.StartProcessing();
260 EXPECT_FALSE(processor.IsRunning());
261 EXPECT_TRUE(delegate.ran_);
262 EXPECT_FALSE(delegate.success_);
263}
264
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700265TEST_F(FilesystemCopierActionTest, RunAsRootNoSpaceTest) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000266 ASSERT_EQ(0, getuid());
267 DoTest(true, false);
268}
269
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700270TEST_F(FilesystemCopierActionTest, RunAsRootTerminateEarlyTest) {
adlr@google.com3defe6a2009-12-04 20:57:17 +0000271 ASSERT_EQ(0, getuid());
272 DoTest(false, true);
273}
274
275} // namespace chromeos_update_engine