blob: 86c15ac48682acf94ab634145745a788c5c6052b [file] [log] [blame]
adlr@google.com3defe6a2009-12-04 20:57:17 +00001// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2// 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>
10#include "update_engine/filesystem_copier_action.h"
11#include "update_engine/filesystem_iterator.h"
12#include "update_engine/omaha_hash_calculator.h"
13#include "update_engine/test_utils.h"
14#include "update_engine/utils.h"
15
16using std::set;
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080017using std::string;
adlr@google.com3defe6a2009-12-04 20:57:17 +000018using std::vector;
19
20namespace chromeos_update_engine {
21
22class FilesystemCopierActionTest : public ::testing::Test {
23 protected:
24 void DoTest(bool double_copy, bool run_out_of_space);
25 string TestDir() { return "./FilesystemCopierActionTestDir"; }
26 void SetUp() {
27 System(string("mkdir -p ") + TestDir());
28 }
29 void TearDown() {
30 System(string("rm -rf ") + TestDir());
31 }
32};
33
34class FilesystemCopierActionTestDelegate : public ActionProcessorDelegate {
35 public:
36 FilesystemCopierActionTestDelegate() : ran_(false), success_(false) {}
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080037 void ProcessingDone(const ActionProcessor* processor, bool success) {
adlr@google.com3defe6a2009-12-04 20:57:17 +000038 g_main_loop_quit(loop_);
39 }
40 void ActionCompleted(ActionProcessor* processor,
41 AbstractAction* action,
42 bool success) {
43 if (action->Type() == FilesystemCopierAction::StaticType()) {
44 ran_ = true;
45 success_ = success;
46 }
47 }
48 void set_loop(GMainLoop* loop) {
49 loop_ = loop;
50 }
51 bool ran() { return ran_; }
52 bool success() { return success_; }
53 private:
54 GMainLoop* loop_;
55 bool ran_;
56 bool success_;
57};
58
59gboolean StartProcessorInRunLoop(gpointer data) {
60 ActionProcessor* processor = reinterpret_cast<ActionProcessor*>(data);
61 processor->StartProcessing();
62 return FALSE;
63}
64
65TEST_F(FilesystemCopierActionTest, RunAsRootSimpleTest) {
66 ASSERT_EQ(0, getuid());
67 DoTest(false, false);
68}
69void FilesystemCopierActionTest::DoTest(bool double_copy,
70 bool run_out_of_space) {
71 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE);
72
73 // make two populated ext images, mount them both (one in the other),
74 // and copy to a loop device setup to correspond to another file.
75
76 const string a_image(TestDir() + "/a_image");
77 const string b_image(TestDir() + "/b_image");
78 const string out_image(TestDir() + "/out_image");
79
80 vector<string> expected_paths_vector;
81 CreateExtImageAtPath(a_image, &expected_paths_vector);
82 CreateExtImageAtPath(b_image, NULL);
83
84 // create 5 MiB file
85 ASSERT_EQ(0, System(string("dd if=/dev/zero of=") + out_image
86 + " seek=5242879 bs=1 count=1"));
87
88 // mount them both
89 System(("mkdir -p " + TestDir() + "/mnt").c_str());
90 ASSERT_EQ(0, System(string("mount -o loop ") + a_image + " " +
91 TestDir() + "/mnt"));
92 ASSERT_EQ(0,
93 System(string("mount -o loop ") + b_image + " " +
94 TestDir() + "/mnt/some_dir/mnt"));
95
96 if (run_out_of_space)
97 ASSERT_EQ(0, System(string("dd if=/dev/zero of=") +
98 TestDir() + "/mnt/big_zero bs=5M count=1"));
99
100 string dev = GetUnusedLoopDevice();
101
102 EXPECT_EQ(0, System(string("losetup ") + dev + " " + out_image));
103
104 InstallPlan install_plan;
105 install_plan.is_full_update = false;
106 install_plan.install_path = dev;
107
108 ActionProcessor processor;
109 FilesystemCopierActionTestDelegate delegate;
110 delegate.set_loop(loop);
111 processor.set_delegate(&delegate);
112
113 ObjectFeederAction<InstallPlan> feeder_action;
114 FilesystemCopierAction copier_action;
115 FilesystemCopierAction copier_action2;
116 ObjectCollectorAction<InstallPlan> collector_action;
117
118 BondActions(&feeder_action, &copier_action);
119 if (double_copy) {
120 BondActions(&copier_action, &copier_action2);
121 BondActions(&copier_action2, &collector_action);
122 } else {
123 BondActions(&copier_action, &collector_action);
124 }
125
126 processor.EnqueueAction(&feeder_action);
127 processor.EnqueueAction(&copier_action);
128 if (double_copy)
129 processor.EnqueueAction(&copier_action2);
130 processor.EnqueueAction(&collector_action);
131
132 copier_action.set_copy_source(TestDir() + "/mnt");
133 feeder_action.set_obj(install_plan);
134
135 g_timeout_add(0, &StartProcessorInRunLoop, &processor);
136 g_main_loop_run(loop);
137 g_main_loop_unref(loop);
138
139 EXPECT_EQ(0, System(string("losetup -d ") + dev));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700140 EXPECT_EQ(0, System(string("umount -d ") + TestDir() + "/mnt/some_dir/mnt"));
141 EXPECT_EQ(0, System(string("umount -d ") + TestDir() + "/mnt"));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000142 EXPECT_EQ(0, unlink(a_image.c_str()));
143 EXPECT_EQ(0, unlink(b_image.c_str()));
144
145 EXPECT_TRUE(delegate.ran());
146 if (run_out_of_space) {
147 EXPECT_FALSE(delegate.success());
148 EXPECT_EQ(0, unlink(out_image.c_str()));
149 EXPECT_EQ(0, rmdir((TestDir() + "/mnt").c_str()));
150 return;
151 }
152 EXPECT_TRUE(delegate.success());
153
154 EXPECT_EQ(0, System(string("mount -o loop ") + out_image + " " +
155 TestDir() + "/mnt"));
156 // Make sure everything in the out_image is there
157 expected_paths_vector.push_back("/update_engine_copy_success");
158 for (vector<string>::iterator it = expected_paths_vector.begin();
159 it != expected_paths_vector.end(); ++it) {
160 *it = TestDir() + "/mnt" + *it;
161 }
162 set<string> expected_paths(expected_paths_vector.begin(),
163 expected_paths_vector.end());
164 VerifyAllPaths(TestDir() + "/mnt", expected_paths);
165 string file_data;
166 EXPECT_TRUE(utils::ReadFileToString(TestDir() + "/mnt/hi", &file_data));
167 EXPECT_EQ("hi\n", file_data);
168 EXPECT_TRUE(utils::ReadFileToString(TestDir() + "/mnt/hello", &file_data));
169 EXPECT_EQ("hello\n", file_data);
170 EXPECT_EQ("/some/target", Readlink(TestDir() + "/mnt/sym"));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700171 EXPECT_EQ(0, System(string("umount -d ") + TestDir() + "/mnt"));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000172
173 EXPECT_EQ(0, unlink(out_image.c_str()));
174 EXPECT_EQ(0, rmdir((TestDir() + "/mnt").c_str()));
175
176 EXPECT_FALSE(copier_action.skipped_copy());
177 LOG(INFO) << "collected plan:";
178 collector_action.object().Dump();
179 LOG(INFO) << "expected plan:";
180 install_plan.Dump();
181 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
265TEST_F(FilesystemCopierActionTest, RunAsRootSkipUpdateTest) {
266 ASSERT_EQ(0, getuid());
267 DoTest(true, false);
268}
269
270TEST_F(FilesystemCopierActionTest, RunAsRootNoSpaceTest) {
271 ASSERT_EQ(0, getuid());
272 DoTest(false, true);
273}
274
275} // namespace chromeos_update_engine