Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: src/platform/update_engine/filesystem_copier_action_unittest.cc

Issue 1700018: AU: FilesystemCopierAction: copy bit-exactly (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: fixes for review Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
OLDNEW
« no previous file with comments | « src/platform/update_engine/filesystem_copier_action.cc ('k') | src/platform/update_engine/testrunner.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698