| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium OS 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 <string> | 5 #include <string> |
| 6 #include <vector> | 6 #include <vector> |
| 7 #include <glib.h> | 7 #include <glib.h> |
| 8 #include <gtest/gtest.h> | 8 #include <gtest/gtest.h> |
| 9 #include "update_engine/action_pipe.h" | 9 #include "update_engine/action_pipe.h" |
| 10 #include "update_engine/download_action.h" | 10 #include "update_engine/download_action.h" |
| 11 #include "update_engine/mock_http_fetcher.h" | 11 #include "update_engine/mock_http_fetcher.h" |
| 12 #include "update_engine/omaha_hash_calculator.h" | 12 #include "update_engine/omaha_hash_calculator.h" |
| 13 #include "update_engine/test_utils.h" | 13 #include "update_engine/test_utils.h" |
| 14 #include "update_engine/utils.h" |
| 14 | 15 |
| 15 namespace chromeos_update_engine { | 16 namespace chromeos_update_engine { |
| 16 | 17 |
| 17 using std::string; | 18 using std::string; |
| 18 using std::vector; | 19 using std::vector; |
| 19 | 20 |
| 20 class DownloadActionTest : public ::testing::Test { }; | 21 class DownloadActionTest : public ::testing::Test { }; |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 class DownloadActionTestProcessorDelegate : public ActionProcessorDelegate { | 24 class DownloadActionTestProcessorDelegate : public ActionProcessorDelegate { |
| 24 public: | 25 public: |
| 25 DownloadActionTestProcessorDelegate() | 26 DownloadActionTestProcessorDelegate() |
| 26 : loop_(NULL), processing_done_called_(false) {} | 27 : loop_(NULL), processing_done_called_(false) {} |
| 27 virtual ~DownloadActionTestProcessorDelegate() { | 28 virtual ~DownloadActionTestProcessorDelegate() { |
| 28 EXPECT_TRUE(processing_done_called_); | 29 EXPECT_TRUE(processing_done_called_); |
| 29 } | 30 } |
| 30 virtual void ProcessingDone(const ActionProcessor* processor) { | 31 virtual void ProcessingDone(const ActionProcessor* processor) { |
| 31 ASSERT_TRUE(loop_); | 32 ASSERT_TRUE(loop_); |
| 32 g_main_loop_quit(loop_); | 33 g_main_loop_quit(loop_); |
| 33 vector<char> found_data = ReadFile(path_); | 34 vector<char> found_data; |
| 35 ASSERT_TRUE(utils::ReadFile(path_, &found_data)); |
| 34 ASSERT_EQ(expected_data_.size(), found_data.size()); | 36 ASSERT_EQ(expected_data_.size(), found_data.size()); |
| 35 for (unsigned i = 0; i < expected_data_.size(); i++) { | 37 for (unsigned i = 0; i < expected_data_.size(); i++) { |
| 36 EXPECT_EQ(expected_data_[i], found_data[i]); | 38 EXPECT_EQ(expected_data_[i], found_data[i]); |
| 37 } | 39 } |
| 38 processing_done_called_ = true; | 40 processing_done_called_ = true; |
| 39 } | 41 } |
| 40 | 42 |
| 41 virtual void ActionCompleted(const ActionProcessor* processor, | 43 virtual void ActionCompleted(ActionProcessor* processor, |
| 42 const AbstractAction* action, | 44 AbstractAction* action, |
| 43 bool success) { | 45 bool success) { |
| 44 // make sure actions always succeed | 46 // make sure actions always succeed |
| 45 EXPECT_TRUE(success); | 47 EXPECT_TRUE(success); |
| 46 } | 48 } |
| 47 | 49 |
| 48 GMainLoop *loop_; | 50 GMainLoop *loop_; |
| 49 string path_; | 51 string path_; |
| 50 vector<char> expected_data_; | 52 vector<char> expected_data_; |
| 51 bool processing_done_called_; | 53 bool processing_done_called_; |
| 52 }; | 54 }; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 69 use_data = GzipCompressData(data); | 71 use_data = GzipCompressData(data); |
| 70 } else { | 72 } else { |
| 71 use_data = data; | 73 use_data = data; |
| 72 } | 74 } |
| 73 | 75 |
| 74 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 76 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
| 75 | 77 |
| 76 // TODO(adlr): see if we need a different file for build bots | 78 // TODO(adlr): see if we need a different file for build bots |
| 77 const string path("/tmp/DownloadActionTest"); | 79 const string path("/tmp/DownloadActionTest"); |
| 78 // takes ownership of passed in HttpFetcher | 80 // takes ownership of passed in HttpFetcher |
| 79 DownloadAction download_action("", path, 0, | 81 InstallPlan install_plan(compress, "", |
| 80 OmahaHashCalculator::OmahaHashOfData(use_data), | 82 OmahaHashCalculator::OmahaHashOfData(use_data), |
| 81 compress, new MockHttpFetcher(&use_data[0], | 83 compress ? "" : path, compress ? path : ""); |
| 82 use_data.size())); | 84 ObjectFeederAction<InstallPlan> feeder_action; |
| 85 feeder_action.set_obj(install_plan); |
| 86 DownloadAction download_action(new MockHttpFetcher(&use_data[0], |
| 87 use_data.size())); |
| 88 BondActions(&feeder_action, &download_action); |
| 89 |
| 83 DownloadActionTestProcessorDelegate delegate; | 90 DownloadActionTestProcessorDelegate delegate; |
| 84 delegate.loop_ = loop; | 91 delegate.loop_ = loop; |
| 85 delegate.expected_data_ = data; | 92 delegate.expected_data_ = data; |
| 86 delegate.path_ = path; | 93 delegate.path_ = path; |
| 87 ActionProcessor processor; | 94 ActionProcessor processor; |
| 88 processor.set_delegate(&delegate); | 95 processor.set_delegate(&delegate); |
| 96 processor.EnqueueAction(&feeder_action); |
| 89 processor.EnqueueAction(&download_action); | 97 processor.EnqueueAction(&download_action); |
| 90 | 98 |
| 91 g_timeout_add(0, &StartProcessorInRunLoop, &processor); | 99 g_timeout_add(0, &StartProcessorInRunLoop, &processor); |
| 92 g_main_loop_run(loop); | 100 g_main_loop_run(loop); |
| 93 g_main_loop_unref(loop); | 101 g_main_loop_unref(loop); |
| 94 | 102 |
| 95 // remove temp file; don't care if there are errors here | 103 // remove temp file; don't care if there are errors here |
| 96 unlink(path.c_str()); | 104 unlink(path.c_str()); |
| 97 } | 105 } |
| 98 } // namespace {} | 106 } // namespace {} |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 | 149 |
| 142 TEST(DownloadActionTest, TerminateEarlyTest) { | 150 TEST(DownloadActionTest, TerminateEarlyTest) { |
| 143 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 151 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
| 144 | 152 |
| 145 vector<char> data(kMockHttpFetcherChunkSize + kMockHttpFetcherChunkSize / 2); | 153 vector<char> data(kMockHttpFetcherChunkSize + kMockHttpFetcherChunkSize / 2); |
| 146 memset(&data[0], 0, data.size()); | 154 memset(&data[0], 0, data.size()); |
| 147 | 155 |
| 148 const string path("/tmp/DownloadActionTest"); | 156 const string path("/tmp/DownloadActionTest"); |
| 149 { | 157 { |
| 150 // takes ownership of passed in HttpFetcher | 158 // takes ownership of passed in HttpFetcher |
| 151 DownloadAction download_action("", path, 0, "", false, | 159 ObjectFeederAction<InstallPlan> feeder_action; |
| 152 new MockHttpFetcher(&data[0], data.size())); | 160 InstallPlan install_plan(false, "", "", path, ""); |
| 161 feeder_action.set_obj(install_plan); |
| 162 DownloadAction download_action(new MockHttpFetcher(&data[0], data.size())); |
| 153 TerminateEarlyTestProcessorDelegate delegate; | 163 TerminateEarlyTestProcessorDelegate delegate; |
| 154 delegate.loop_ = loop; | 164 delegate.loop_ = loop; |
| 155 ActionProcessor processor; | 165 ActionProcessor processor; |
| 156 processor.set_delegate(&delegate); | 166 processor.set_delegate(&delegate); |
| 167 processor.EnqueueAction(&feeder_action); |
| 157 processor.EnqueueAction(&download_action); | 168 processor.EnqueueAction(&download_action); |
| 169 BondActions(&feeder_action, &download_action); |
| 158 | 170 |
| 159 g_timeout_add(0, &TerminateEarlyTestStarter, &processor); | 171 g_timeout_add(0, &TerminateEarlyTestStarter, &processor); |
| 160 g_main_loop_run(loop); | 172 g_main_loop_run(loop); |
| 161 g_main_loop_unref(loop); | 173 g_main_loop_unref(loop); |
| 162 } | 174 } |
| 163 | 175 |
| 164 // 1 or 0 chunks should have come through | 176 // 1 or 0 chunks should have come through |
| 165 const off_t resulting_file_size(FileSize(path)); | 177 const off_t resulting_file_size(FileSize(path)); |
| 166 if (resulting_file_size != 0) | 178 if (resulting_file_size != 0) |
| 167 EXPECT_EQ(kMockHttpFetcherChunkSize, resulting_file_size); | 179 EXPECT_EQ(kMockHttpFetcherChunkSize, resulting_file_size); |
| 168 } | 180 } |
| 169 | 181 |
| 170 class DownloadActionTestAction; | 182 class DownloadActionTestAction; |
| 171 | 183 |
| 172 template<> | 184 template<> |
| 173 class ActionTraits<DownloadActionTestAction> { | 185 class ActionTraits<DownloadActionTestAction> { |
| 174 public: | 186 public: |
| 175 typedef string OutputObjectType; | 187 typedef InstallPlan OutputObjectType; |
| 176 typedef string InputObjectType; | 188 typedef InstallPlan InputObjectType; |
| 177 }; | 189 }; |
| 178 | 190 |
| 179 // This is a simple Action class for testing. | 191 // This is a simple Action class for testing. |
| 180 struct DownloadActionTestAction : public Action<DownloadActionTestAction> { | 192 struct DownloadActionTestAction : public Action<DownloadActionTestAction> { |
| 181 DownloadActionTestAction() : did_run_(false) {} | 193 DownloadActionTestAction() : did_run_(false) {} |
| 182 typedef string InputObjectType; | 194 typedef InstallPlan InputObjectType; |
| 183 typedef string OutputObjectType; | 195 typedef InstallPlan OutputObjectType; |
| 184 ActionPipe<string>* in_pipe() { return in_pipe_.get(); } | 196 ActionPipe<InstallPlan>* in_pipe() { return in_pipe_.get(); } |
| 185 ActionPipe<string>* out_pipe() { return out_pipe_.get(); } | 197 ActionPipe<InstallPlan>* out_pipe() { return out_pipe_.get(); } |
| 186 ActionProcessor* processor() { return processor_; } | 198 ActionProcessor* processor() { return processor_; } |
| 187 void PerformAction() { | 199 void PerformAction() { |
| 188 did_run_ = true; | 200 did_run_ = true; |
| 189 ASSERT_TRUE(HasInputObject()); | 201 ASSERT_TRUE(HasInputObject()); |
| 190 EXPECT_EQ(expected_input_object_, GetInputObject()); | 202 EXPECT_TRUE(expected_input_object_ == GetInputObject()); |
| 191 ASSERT_TRUE(processor()); | 203 ASSERT_TRUE(processor()); |
| 192 processor()->ActionComplete(this, true); | 204 processor()->ActionComplete(this, true); |
| 193 } | 205 } |
| 194 string Type() const { return "DownloadActionTestAction"; } | 206 string Type() const { return "DownloadActionTestAction"; } |
| 195 string expected_input_object_; | 207 InstallPlan expected_input_object_; |
| 196 bool did_run_; | 208 bool did_run_; |
| 197 }; | 209 }; |
| 198 | 210 |
| 199 namespace { | 211 namespace { |
| 200 // This class is an ActionProcessorDelegate that simply terminates the | 212 // This class is an ActionProcessorDelegate that simply terminates the |
| 201 // run loop when the ActionProcessor has completed processing. It's used | 213 // run loop when the ActionProcessor has completed processing. It's used |
| 202 // only by the test PassObjectOutTest. | 214 // only by the test PassObjectOutTest. |
| 203 class PassObjectOutTestProcessorDelegate : public ActionProcessorDelegate { | 215 class PassObjectOutTestProcessorDelegate : public ActionProcessorDelegate { |
| 204 public: | 216 public: |
| 205 void ProcessingDone(const ActionProcessor* processor) { | 217 void ProcessingDone(const ActionProcessor* processor) { |
| 206 ASSERT_TRUE(loop_); | 218 ASSERT_TRUE(loop_); |
| 207 g_main_loop_quit(loop_); | 219 g_main_loop_quit(loop_); |
| 208 } | 220 } |
| 209 GMainLoop *loop_; | 221 GMainLoop *loop_; |
| 210 }; | 222 }; |
| 211 | 223 |
| 212 gboolean PassObjectOutTestStarter(gpointer data) { | 224 gboolean PassObjectOutTestStarter(gpointer data) { |
| 213 ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); | 225 ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); |
| 214 processor->StartProcessing(); | 226 processor->StartProcessing(); |
| 215 return FALSE; | 227 return FALSE; |
| 216 } | 228 } |
| 217 } | 229 } |
| 218 | 230 |
| 219 TEST(DownloadActionTest, PassObjectOutTest) { | 231 TEST(DownloadActionTest, PassObjectOutTest) { |
| 220 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 232 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
| 221 | 233 |
| 222 const string path("/tmp/DownloadActionTest"); | 234 const string path("/tmp/DownloadActionTest"); |
| 223 | 235 |
| 224 // takes ownership of passed in HttpFetcher | 236 // takes ownership of passed in HttpFetcher |
| 225 DownloadAction download_action("", path, 0, | 237 InstallPlan install_plan(false, "", |
| 226 OmahaHashCalculator::OmahaHashOfString("x"), | 238 OmahaHashCalculator::OmahaHashOfString("x"), path, |
| 227 false, new MockHttpFetcher("x", 1)); | 239 ""); |
| 240 ObjectFeederAction<InstallPlan> feeder_action; |
| 241 feeder_action.set_obj(install_plan); |
| 242 DownloadAction download_action(new MockHttpFetcher("x", 1)); |
| 228 | 243 |
| 229 DownloadActionTestAction test_action; | 244 DownloadActionTestAction test_action; |
| 230 test_action.expected_input_object_ = path; | 245 test_action.expected_input_object_ = install_plan; |
| 246 BondActions(&feeder_action, &download_action); |
| 231 BondActions(&download_action, &test_action); | 247 BondActions(&download_action, &test_action); |
| 232 | 248 |
| 233 ActionProcessor processor; | 249 ActionProcessor processor; |
| 234 PassObjectOutTestProcessorDelegate delegate; | 250 PassObjectOutTestProcessorDelegate delegate; |
| 235 delegate.loop_ = loop; | 251 delegate.loop_ = loop; |
| 236 processor.set_delegate(&delegate); | 252 processor.set_delegate(&delegate); |
| 253 processor.EnqueueAction(&feeder_action); |
| 237 processor.EnqueueAction(&download_action); | 254 processor.EnqueueAction(&download_action); |
| 238 processor.EnqueueAction(&test_action); | 255 processor.EnqueueAction(&test_action); |
| 239 | 256 |
| 240 g_timeout_add(0, &PassObjectOutTestStarter, &processor); | 257 g_timeout_add(0, &PassObjectOutTestStarter, &processor); |
| 241 g_main_loop_run(loop); | 258 g_main_loop_run(loop); |
| 242 g_main_loop_unref(loop); | 259 g_main_loop_unref(loop); |
| 243 | 260 |
| 244 EXPECT_EQ(true, test_action.did_run_); | 261 EXPECT_EQ(true, test_action.did_run_); |
| 245 } | 262 } |
| 246 | 263 |
| 247 TEST(DownloadActionTest, BadOutFileTest) { | 264 TEST(DownloadActionTest, BadOutFileTest) { |
| 248 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 265 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
| 249 | 266 |
| 250 const string path("/fake/path/that/cant/be/created/because/of/missing/dirs"); | 267 const string path("/fake/path/that/cant/be/created/because/of/missing/dirs"); |
| 251 | 268 |
| 252 // takes ownership of passed in HttpFetcher | 269 // takes ownership of passed in HttpFetcher |
| 253 DownloadAction download_action("", path, 0, "", false, | 270 InstallPlan install_plan(false, "", "", path, ""); |
| 254 new MockHttpFetcher("x", 1)); | 271 ObjectFeederAction<InstallPlan> feeder_action; |
| 272 feeder_action.set_obj(install_plan); |
| 273 DownloadAction download_action(new MockHttpFetcher("x", 1)); |
| 274 BondActions(&feeder_action, &download_action); |
| 255 | 275 |
| 256 ActionProcessor processor; | 276 ActionProcessor processor; |
| 277 processor.EnqueueAction(&feeder_action); |
| 257 processor.EnqueueAction(&download_action); | 278 processor.EnqueueAction(&download_action); |
| 258 processor.StartProcessing(); | 279 processor.StartProcessing(); |
| 259 ASSERT_FALSE(processor.IsRunning()); | 280 ASSERT_FALSE(processor.IsRunning()); |
| 260 | 281 |
| 261 g_main_loop_unref(loop); | 282 g_main_loop_unref(loop); |
| 262 } | 283 } |
| 263 | 284 |
| 264 } // namespace chromeos_update_engine | 285 } // namespace chromeos_update_engine |
| OLD | NEW |