OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <glib.h> | 5 #include <glib.h> |
6 #include <set> | 6 #include <set> |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 #include <gtest/gtest.h> | 9 #include <gtest/gtest.h> |
| 10 #include "base/string_util.h" |
10 #include "update_engine/filesystem_copier_action.h" | 11 #include "update_engine/filesystem_copier_action.h" |
11 #include "update_engine/filesystem_iterator.h" | 12 #include "update_engine/filesystem_iterator.h" |
12 #include "update_engine/omaha_hash_calculator.h" | 13 #include "update_engine/omaha_hash_calculator.h" |
13 #include "update_engine/test_utils.h" | 14 #include "update_engine/test_utils.h" |
14 #include "update_engine/utils.h" | 15 #include "update_engine/utils.h" |
15 | 16 |
16 using std::set; | 17 using std::set; |
17 using std::string; | 18 using std::string; |
18 using std::vector; | 19 using std::vector; |
19 | 20 |
20 namespace chromeos_update_engine { | 21 namespace chromeos_update_engine { |
21 | 22 |
22 class FilesystemCopierActionTest : public ::testing::Test { | 23 class FilesystemCopierActionTest : public ::testing::Test { |
23 protected: | 24 protected: |
24 void DoTest(bool double_copy, bool run_out_of_space); | 25 void DoTest(bool run_out_of_space, bool terminate_early); |
25 string TestDir() { return "./FilesystemCopierActionTestDir"; } | |
26 void SetUp() { | 26 void SetUp() { |
27 System(string("mkdir -p ") + TestDir()); | |
28 } | 27 } |
29 void TearDown() { | 28 void TearDown() { |
30 System(string("rm -rf ") + TestDir()); | |
31 } | 29 } |
32 }; | 30 }; |
33 | 31 |
34 class FilesystemCopierActionTestDelegate : public ActionProcessorDelegate { | 32 class FilesystemCopierActionTestDelegate : public ActionProcessorDelegate { |
35 public: | 33 public: |
36 FilesystemCopierActionTestDelegate() : ran_(false), success_(false) {} | 34 FilesystemCopierActionTestDelegate() : ran_(false), success_(false) {} |
| 35 void ExitMainLoop() { |
| 36 while (g_main_context_pending(NULL)) { |
| 37 g_main_context_iteration(NULL, false); |
| 38 } |
| 39 g_main_loop_quit(loop_); |
| 40 } |
37 void ProcessingDone(const ActionProcessor* processor, bool success) { | 41 void ProcessingDone(const ActionProcessor* processor, bool success) { |
38 g_main_loop_quit(loop_); | 42 ExitMainLoop(); |
| 43 } |
| 44 void ProcessingStopped(const ActionProcessor* processor) { |
| 45 ExitMainLoop(); |
39 } | 46 } |
40 void ActionCompleted(ActionProcessor* processor, | 47 void ActionCompleted(ActionProcessor* processor, |
41 AbstractAction* action, | 48 AbstractAction* action, |
42 bool success) { | 49 bool success) { |
43 if (action->Type() == FilesystemCopierAction::StaticType()) { | 50 if (action->Type() == FilesystemCopierAction::StaticType()) { |
44 ran_ = true; | 51 ran_ = true; |
45 success_ = success; | 52 success_ = success; |
46 } | 53 } |
47 } | 54 } |
48 void set_loop(GMainLoop* loop) { | 55 void set_loop(GMainLoop* loop) { |
49 loop_ = loop; | 56 loop_ = loop; |
50 } | 57 } |
51 bool ran() { return ran_; } | 58 bool ran() { return ran_; } |
52 bool success() { return success_; } | 59 bool success() { return success_; } |
53 private: | 60 private: |
54 GMainLoop* loop_; | 61 GMainLoop* loop_; |
55 bool ran_; | 62 bool ran_; |
56 bool success_; | 63 bool success_; |
57 }; | 64 }; |
58 | 65 |
| 66 struct StartProcessorCallbackArgs { |
| 67 ActionProcessor* processor; |
| 68 FilesystemCopierAction* filesystem_copier_action; |
| 69 bool terminate_early; |
| 70 }; |
| 71 |
59 gboolean StartProcessorInRunLoop(gpointer data) { | 72 gboolean StartProcessorInRunLoop(gpointer data) { |
60 ActionProcessor* processor = reinterpret_cast<ActionProcessor*>(data); | 73 StartProcessorCallbackArgs* args = |
| 74 reinterpret_cast<StartProcessorCallbackArgs*>(data); |
| 75 ActionProcessor* processor = args->processor; |
61 processor->StartProcessing(); | 76 processor->StartProcessing(); |
| 77 if (args->terminate_early) { |
| 78 EXPECT_TRUE(args->filesystem_copier_action); |
| 79 args->processor->StopProcessing(); |
| 80 } |
62 return FALSE; | 81 return FALSE; |
63 } | 82 } |
64 | 83 |
65 TEST_F(FilesystemCopierActionTest, RunAsRootSimpleTest) { | 84 TEST_F(FilesystemCopierActionTest, RunAsRootSimpleTest) { |
66 ASSERT_EQ(0, getuid()); | 85 ASSERT_EQ(0, getuid()); |
67 DoTest(false, false); | 86 DoTest(false, false); |
68 } | 87 } |
69 void FilesystemCopierActionTest::DoTest(bool double_copy, | 88 void FilesystemCopierActionTest::DoTest(bool run_out_of_space, |
70 bool run_out_of_space) { | 89 bool terminate_early) { |
71 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 90 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
72 | 91 |
73 // make two populated ext images, mount them both (one in the other), | 92 string a_loop_file; |
74 // and copy to a loop device setup to correspond to another 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 |
75 | 112 |
76 const string a_image(TestDir() + "/a_image"); | 113 // Write data to disk |
77 const string b_image(TestDir() + "/b_image"); | 114 EXPECT_TRUE(WriteFileVector(a_loop_file, a_loop_data)); |
78 const string out_image(TestDir() + "/out_image"); | 115 EXPECT_TRUE(WriteFileVector(b_loop_file, b_loop_data)); |
79 | 116 |
80 vector<string> expected_paths_vector; | 117 // Make loop devices for the files |
81 CreateExtImageAtPath(a_image, &expected_paths_vector); | 118 string a_dev = GetUnusedLoopDevice(); |
82 CreateExtImageAtPath(b_image, NULL); | 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); |
83 | 124 |
84 // create 5 MiB file | 125 string b_dev = GetUnusedLoopDevice(); |
85 ASSERT_EQ(0, System(string("dd if=/dev/zero of=") + out_image | 126 EXPECT_FALSE(b_dev.empty()); |
86 + " seek=5242879 bs=1 count=1")); | 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); |
87 | 131 |
88 // mount them both | 132 // Set up the action objects |
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; | 133 InstallPlan install_plan; |
105 install_plan.is_full_update = false; | 134 install_plan.is_full_update = false; |
106 install_plan.install_path = dev; | 135 install_plan.install_path = b_dev; |
107 | 136 |
108 ActionProcessor processor; | 137 ActionProcessor processor; |
109 FilesystemCopierActionTestDelegate delegate; | 138 FilesystemCopierActionTestDelegate delegate; |
110 delegate.set_loop(loop); | 139 delegate.set_loop(loop); |
111 processor.set_delegate(&delegate); | 140 processor.set_delegate(&delegate); |
112 | 141 |
113 ObjectFeederAction<InstallPlan> feeder_action; | 142 ObjectFeederAction<InstallPlan> feeder_action; |
114 FilesystemCopierAction copier_action; | 143 FilesystemCopierAction copier_action; |
115 FilesystemCopierAction copier_action2; | |
116 ObjectCollectorAction<InstallPlan> collector_action; | 144 ObjectCollectorAction<InstallPlan> collector_action; |
117 | 145 |
118 BondActions(&feeder_action, &copier_action); | 146 BondActions(&feeder_action, &copier_action); |
119 if (double_copy) { | 147 BondActions(&copier_action, &collector_action); |
120 BondActions(&copier_action, &copier_action2); | |
121 BondActions(&copier_action2, &collector_action); | |
122 } else { | |
123 BondActions(&copier_action, &collector_action); | |
124 } | |
125 | 148 |
126 processor.EnqueueAction(&feeder_action); | 149 processor.EnqueueAction(&feeder_action); |
127 processor.EnqueueAction(&copier_action); | 150 processor.EnqueueAction(&copier_action); |
128 if (double_copy) | |
129 processor.EnqueueAction(&copier_action2); | |
130 processor.EnqueueAction(&collector_action); | 151 processor.EnqueueAction(&collector_action); |
131 | 152 |
132 copier_action.set_copy_source(TestDir() + "/mnt"); | 153 copier_action.set_copy_source(a_dev); |
133 feeder_action.set_obj(install_plan); | 154 feeder_action.set_obj(install_plan); |
134 | 155 |
135 g_timeout_add(0, &StartProcessorInRunLoop, &processor); | 156 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); |
136 g_main_loop_run(loop); | 162 g_main_loop_run(loop); |
137 g_main_loop_unref(loop); | 163 g_main_loop_unref(loop); |
138 | 164 |
139 EXPECT_EQ(0, System(string("losetup -d ") + dev)); | 165 if (!terminate_early) |
140 EXPECT_EQ(0, System(string("umount -d ") + TestDir() + "/mnt/some_dir/mnt")); | 166 EXPECT_TRUE(delegate.ran()); |
141 EXPECT_EQ(0, System(string("umount -d ") + TestDir() + "/mnt")); | 167 if (run_out_of_space || terminate_early) { |
142 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()); | 168 EXPECT_FALSE(delegate.success()); |
148 EXPECT_EQ(0, unlink(out_image.c_str())); | |
149 EXPECT_EQ(0, rmdir((TestDir() + "/mnt").c_str())); | |
150 return; | 169 return; |
151 } | 170 } |
152 EXPECT_TRUE(delegate.success()); | 171 EXPECT_TRUE(delegate.success()); |
153 | 172 |
154 EXPECT_EQ(0, System(string("mount -o loop ") + out_image + " " + | |
155 TestDir() + "/mnt")); | |
156 // Make sure everything in the out_image is there | 173 // Make sure everything in the out_image is there |
157 expected_paths_vector.push_back("/update_engine_copy_success"); | 174 vector<char> a_out; |
158 for (vector<string>::iterator it = expected_paths_vector.begin(); | 175 vector<char> b_out; |
159 it != expected_paths_vector.end(); ++it) { | 176 EXPECT_TRUE(utils::ReadFile(a_dev, &a_out)); |
160 *it = TestDir() + "/mnt" + *it; | 177 EXPECT_TRUE(utils::ReadFile(b_dev, &b_out)); |
161 } | 178 EXPECT_TRUE(ExpectVectorsEq(a_out, b_out)); |
162 set<string> expected_paths(expected_paths_vector.begin(), | 179 EXPECT_TRUE(ExpectVectorsEq(a_loop_data, a_out)); |
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")); | |
171 EXPECT_EQ(0, System(string("umount -d ") + TestDir() + "/mnt")); | |
172 | 180 |
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); | 181 EXPECT_TRUE(collector_action.object() == install_plan); |
182 } | 182 } |
183 | 183 |
184 class FilesystemCopierActionTest2Delegate : public ActionProcessorDelegate { | 184 class FilesystemCopierActionTest2Delegate : public ActionProcessorDelegate { |
185 public: | 185 public: |
186 void ActionCompleted(ActionProcessor* processor, | 186 void ActionCompleted(ActionProcessor* processor, |
187 AbstractAction* action, | 187 AbstractAction* action, |
188 bool success) { | 188 bool success) { |
189 if (action->Type() == FilesystemCopierAction::StaticType()) { | 189 if (action->Type() == FilesystemCopierAction::StaticType()) { |
190 ran_ = true; | 190 ran_ = true; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 | 255 |
256 processor.EnqueueAction(&feeder_action); | 256 processor.EnqueueAction(&feeder_action); |
257 processor.EnqueueAction(&copier_action); | 257 processor.EnqueueAction(&copier_action); |
258 processor.EnqueueAction(&collector_action); | 258 processor.EnqueueAction(&collector_action); |
259 processor.StartProcessing(); | 259 processor.StartProcessing(); |
260 EXPECT_FALSE(processor.IsRunning()); | 260 EXPECT_FALSE(processor.IsRunning()); |
261 EXPECT_TRUE(delegate.ran_); | 261 EXPECT_TRUE(delegate.ran_); |
262 EXPECT_FALSE(delegate.success_); | 262 EXPECT_FALSE(delegate.success_); |
263 } | 263 } |
264 | 264 |
265 TEST_F(FilesystemCopierActionTest, RunAsRootSkipUpdateTest) { | 265 TEST_F(FilesystemCopierActionTest, RunAsRootNoSpaceTest) { |
266 ASSERT_EQ(0, getuid()); | 266 ASSERT_EQ(0, getuid()); |
267 DoTest(true, false); | 267 DoTest(true, false); |
268 } | 268 } |
269 | 269 |
270 TEST_F(FilesystemCopierActionTest, RunAsRootNoSpaceTest) { | 270 TEST_F(FilesystemCopierActionTest, RunAsRootTerminateEarlyTest) { |
271 ASSERT_EQ(0, getuid()); | 271 ASSERT_EQ(0, getuid()); |
272 DoTest(false, true); | 272 DoTest(false, true); |
273 } | 273 } |
274 | 274 |
275 } // namespace chromeos_update_engine | 275 } // namespace chromeos_update_engine |
OLD | NEW |