| Darin Petkov | 7ed561b | 2011-10-04 02:59:03 -0700 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 | // found in the LICENSE file. | 
|  | 4 |  | 
| Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 5 | #include "update_engine/download_action.h" | 
|  | 6 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 7 | #include <glib.h> | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 8 | #include <gmock/gmock.h> | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 9 | #include <gtest/gtest.h> | 
| Darin Petkov | 73058b4 | 2010-10-06 16:32:19 -0700 | [diff] [blame] | 10 |  | 
| Ben Chan | 02f7c1d | 2014-10-18 15:18:02 -0700 | [diff] [blame] | 11 | #include <memory> | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 12 | #include <string> | 
|  | 13 | #include <utility> | 
|  | 14 | #include <vector> | 
|  | 15 |  | 
| Alex Vakulenko | 75039d7 | 2014-03-25 12:36:28 -0700 | [diff] [blame] | 16 | #include <base/files/file_path.h> | 
| Ben Chan | 06c76a4 | 2014-09-05 08:21:06 -0700 | [diff] [blame] | 17 | #include <base/files/file_util.h> | 
| Alex Vakulenko | 75039d7 | 2014-03-25 12:36:28 -0700 | [diff] [blame] | 18 | #include <base/strings/stringprintf.h> | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 19 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 20 | #include "update_engine/action_pipe.h" | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 21 | #include "update_engine/fake_p2p_manager_configuration.h" | 
| Gilad Arnold | 5bb4c90 | 2014-04-10 12:32:13 -0700 | [diff] [blame] | 22 | #include "update_engine/fake_system_state.h" | 
|  | 23 | #include "update_engine/mock_http_fetcher.h" | 
| Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 24 | #include "update_engine/mock_prefs.h" | 
| Gilad Arnold | 5bb4c90 | 2014-04-10 12:32:13 -0700 | [diff] [blame] | 25 | #include "update_engine/omaha_hash_calculator.h" | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 26 | #include "update_engine/test_utils.h" | 
| Gilad Arnold | 4a0321b | 2014-10-28 15:57:30 -0700 | [diff] [blame] | 27 | #include "update_engine/update_manager/fake_update_manager.h" | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 28 | #include "update_engine/utils.h" | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 29 |  | 
|  | 30 | namespace chromeos_update_engine { | 
|  | 31 |  | 
| Alex Deymo | f329b93 | 2014-10-30 01:37:48 -0700 | [diff] [blame] | 32 | using base::FilePath; | 
|  | 33 | using base::ReadFileToString; | 
|  | 34 | using base::WriteFile; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 35 | using std::string; | 
| Ben Chan | 02f7c1d | 2014-10-18 15:18:02 -0700 | [diff] [blame] | 36 | using std::unique_ptr; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 37 | using std::vector; | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 38 | using testing::AtLeast; | 
|  | 39 | using testing::InSequence; | 
| Gilad Arnold | 74b5f55 | 2014-10-07 08:17:16 -0700 | [diff] [blame] | 40 | using testing::Return; | 
| Alex Deymo | f329b93 | 2014-10-30 01:37:48 -0700 | [diff] [blame] | 41 | using testing::_; | 
| Alex Deymo | 10875d9 | 2014-11-10 21:52:57 -0800 | [diff] [blame] | 42 | using test_utils::ScopedTempFile; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 43 |  | 
|  | 44 | class DownloadActionTest : public ::testing::Test { }; | 
|  | 45 |  | 
|  | 46 | namespace { | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 47 | class DownloadActionDelegateMock : public DownloadActionDelegate { | 
|  | 48 | public: | 
|  | 49 | MOCK_METHOD1(SetDownloadStatus, void(bool active)); | 
|  | 50 | MOCK_METHOD2(BytesReceived, void(uint64_t bytes_received, uint64_t total)); | 
|  | 51 | }; | 
|  | 52 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 53 | class DownloadActionTestProcessorDelegate : public ActionProcessorDelegate { | 
|  | 54 | public: | 
| David Zeuthen | a99981f | 2013-04-29 13:42:47 -0700 | [diff] [blame] | 55 | explicit DownloadActionTestProcessorDelegate(ErrorCode expected_code) | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 56 | : loop_(nullptr), | 
| Darin Petkov | c97435c | 2010-07-20 12:37:43 -0700 | [diff] [blame] | 57 | processing_done_called_(false), | 
|  | 58 | expected_code_(expected_code) {} | 
| Alex Deymo | 610277e | 2014-11-11 21:18:11 -0800 | [diff] [blame] | 59 | ~DownloadActionTestProcessorDelegate() override { | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 60 | EXPECT_TRUE(processing_done_called_); | 
|  | 61 | } | 
| Yunlian Jiang | 35866ed | 2015-01-29 13:09:20 -0800 | [diff] [blame] | 62 | void ProcessingDone(const ActionProcessor* processor, | 
|  | 63 | ErrorCode code) override { | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 64 | ASSERT_TRUE(loop_); | 
|  | 65 | g_main_loop_quit(loop_); | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 66 | chromeos::Blob found_data; | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 67 | ASSERT_TRUE(utils::ReadFile(path_, &found_data)); | 
| Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 68 | if (expected_code_ != ErrorCode::kDownloadWriteError) { | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 69 | ASSERT_EQ(expected_data_.size(), found_data.size()); | 
|  | 70 | for (unsigned i = 0; i < expected_data_.size(); i++) { | 
|  | 71 | EXPECT_EQ(expected_data_[i], found_data[i]); | 
|  | 72 | } | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 73 | } | 
|  | 74 | processing_done_called_ = true; | 
|  | 75 | } | 
|  | 76 |  | 
| Yunlian Jiang | 35866ed | 2015-01-29 13:09:20 -0800 | [diff] [blame] | 77 | void ActionCompleted(ActionProcessor* processor, | 
|  | 78 | AbstractAction* action, | 
|  | 79 | ErrorCode code) override { | 
| Darin Petkov | c97435c | 2010-07-20 12:37:43 -0700 | [diff] [blame] | 80 | const string type = action->Type(); | 
|  | 81 | if (type == DownloadAction::StaticType()) { | 
|  | 82 | EXPECT_EQ(expected_code_, code); | 
|  | 83 | } else { | 
| Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 84 | EXPECT_EQ(ErrorCode::kSuccess, code); | 
| Darin Petkov | c97435c | 2010-07-20 12:37:43 -0700 | [diff] [blame] | 85 | } | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 86 | } | 
|  | 87 |  | 
|  | 88 | GMainLoop *loop_; | 
|  | 89 | string path_; | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 90 | chromeos::Blob expected_data_; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 91 | bool processing_done_called_; | 
| David Zeuthen | a99981f | 2013-04-29 13:42:47 -0700 | [diff] [blame] | 92 | ErrorCode expected_code_; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 93 | }; | 
|  | 94 |  | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 95 | class TestDirectFileWriter : public DirectFileWriter { | 
|  | 96 | public: | 
|  | 97 | TestDirectFileWriter() : fail_write_(0), current_write_(0) {} | 
|  | 98 | void set_fail_write(int fail_write) { fail_write_ = fail_write; } | 
|  | 99 |  | 
| Don Garrett | e410e0f | 2011-11-10 15:39:01 -0800 | [diff] [blame] | 100 | virtual bool Write(const void* bytes, size_t count) { | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 101 | if (++current_write_ == fail_write_) { | 
| Don Garrett | e410e0f | 2011-11-10 15:39:01 -0800 | [diff] [blame] | 102 | return false; | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 103 | } | 
|  | 104 | return DirectFileWriter::Write(bytes, count); | 
|  | 105 | } | 
|  | 106 |  | 
|  | 107 | private: | 
|  | 108 | // If positive, fail on the |fail_write_| call to Write. | 
|  | 109 | int fail_write_; | 
|  | 110 | int current_write_; | 
|  | 111 | }; | 
|  | 112 |  | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 113 | struct StartProcessorInRunLoopArgs { | 
|  | 114 | ActionProcessor* processor; | 
|  | 115 | MockHttpFetcher* http_fetcher; | 
|  | 116 | }; | 
|  | 117 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 118 | gboolean StartProcessorInRunLoop(gpointer data) { | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 119 | ActionProcessor* processor = | 
|  | 120 | reinterpret_cast<StartProcessorInRunLoopArgs*>(data)->processor; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 121 | processor->StartProcessing(); | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 122 | MockHttpFetcher* http_fetcher = | 
|  | 123 | reinterpret_cast<StartProcessorInRunLoopArgs*>(data)->http_fetcher; | 
|  | 124 | http_fetcher->SetOffset(1); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 125 | return FALSE; | 
|  | 126 | } | 
|  | 127 |  | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 128 | void TestWithData(const chromeos::Blob& data, | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 129 | int fail_write, | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 130 | bool use_download_delegate) { | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 131 | GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 
|  | 132 |  | 
|  | 133 | // TODO(adlr): see if we need a different file for build bots | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 134 | ScopedTempFile output_temp_file; | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 135 | TestDirectFileWriter writer; | 
|  | 136 | writer.set_fail_write(fail_write); | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 137 |  | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 138 | // We pull off the first byte from data and seek past it. | 
|  | 139 |  | 
| Darin Petkov | 7ed561b | 2011-10-04 02:59:03 -0700 | [diff] [blame] | 140 | string hash = | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 141 | OmahaHashCalculator::OmahaHashOfBytes(&data[1], data.size() - 1); | 
| Darin Petkov | 7ed561b | 2011-10-04 02:59:03 -0700 | [diff] [blame] | 142 | uint64_t size = data.size(); | 
|  | 143 | InstallPlan install_plan(false, | 
| Gilad Arnold | 21504f0 | 2013-05-24 08:51:22 -0700 | [diff] [blame] | 144 | false, | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 145 | "", | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 146 | size, | 
| Darin Petkov | c97435c | 2010-07-20 12:37:43 -0700 | [diff] [blame] | 147 | hash, | 
| Jay Srinivasan | 51dcf26 | 2012-09-13 17:24:32 -0700 | [diff] [blame] | 148 | 0, | 
|  | 149 | "", | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 150 | output_temp_file.GetPath(), | 
| David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 151 | "", | 
| Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 152 | "", | 
|  | 153 | "", | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 154 | ""); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 155 | ObjectFeederAction<InstallPlan> feeder_action; | 
|  | 156 | feeder_action.set_obj(install_plan); | 
| Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 157 | MockPrefs prefs; | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 158 | MockHttpFetcher* http_fetcher = new MockHttpFetcher(data.data(), | 
| Andrew de los Reyes | 4516810 | 2010-11-22 11:13:50 -0800 | [diff] [blame] | 159 | data.size(), | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 160 | nullptr); | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 161 | // takes ownership of passed in HttpFetcher | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 162 | DownloadAction download_action(&prefs, nullptr, http_fetcher); | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 163 | download_action.SetTestFileWriter(&writer); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 164 | BondActions(&feeder_action, &download_action); | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 165 | DownloadActionDelegateMock download_delegate; | 
|  | 166 | if (use_download_delegate) { | 
|  | 167 | InSequence s; | 
|  | 168 | download_action.set_delegate(&download_delegate); | 
|  | 169 | EXPECT_CALL(download_delegate, SetDownloadStatus(true)).Times(1); | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 170 | if (data.size() > kMockHttpFetcherChunkSize) | 
|  | 171 | EXPECT_CALL(download_delegate, | 
|  | 172 | BytesReceived(1 + kMockHttpFetcherChunkSize, _)); | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 173 | EXPECT_CALL(download_delegate, BytesReceived(_, _)).Times(AtLeast(1)); | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 174 | EXPECT_CALL(download_delegate, SetDownloadStatus(false)).Times(1); | 
|  | 175 | } | 
| Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 176 | ErrorCode expected_code = ErrorCode::kSuccess; | 
| Darin Petkov | 7ed561b | 2011-10-04 02:59:03 -0700 | [diff] [blame] | 177 | if (fail_write > 0) | 
| Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 178 | expected_code = ErrorCode::kDownloadWriteError; | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 179 | DownloadActionTestProcessorDelegate delegate(expected_code); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 180 | delegate.loop_ = loop; | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 181 | delegate.expected_data_ = chromeos::Blob(data.begin() + 1, data.end()); | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 182 | delegate.path_ = output_temp_file.GetPath(); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 183 | ActionProcessor processor; | 
|  | 184 | processor.set_delegate(&delegate); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 185 | processor.EnqueueAction(&feeder_action); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 186 | processor.EnqueueAction(&download_action); | 
|  | 187 |  | 
| Andrew de los Reyes | 34e41a1 | 2010-10-26 20:07:58 -0700 | [diff] [blame] | 188 | StartProcessorInRunLoopArgs args; | 
|  | 189 | args.processor = &processor; | 
|  | 190 | args.http_fetcher = http_fetcher; | 
|  | 191 | g_timeout_add(0, &StartProcessorInRunLoop, &args); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 192 | g_main_loop_run(loop); | 
|  | 193 | g_main_loop_unref(loop); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 194 | } | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 195 | }  // namespace | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 196 |  | 
|  | 197 | TEST(DownloadActionTest, SimpleTest) { | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 198 | chromeos::Blob small; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 199 | const char* foo = "foo"; | 
|  | 200 | small.insert(small.end(), foo, foo + strlen(foo)); | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 201 | TestWithData(small, | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 202 | 0,  // fail_write | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 203 | true);  // use_download_delegate | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 204 | } | 
|  | 205 |  | 
|  | 206 | TEST(DownloadActionTest, LargeTest) { | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 207 | chromeos::Blob big(5 * kMockHttpFetcherChunkSize); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 208 | char c = '0'; | 
|  | 209 | for (unsigned int i = 0; i < big.size(); i++) { | 
|  | 210 | big[i] = c; | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 211 | c = ('9' == c) ? '0' : c + 1; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 212 | } | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 213 | TestWithData(big, | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 214 | 0,  // fail_write | 
|  | 215 | true);  // use_download_delegate | 
|  | 216 | } | 
|  | 217 |  | 
|  | 218 | TEST(DownloadActionTest, FailWriteTest) { | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 219 | chromeos::Blob big(5 * kMockHttpFetcherChunkSize); | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 220 | char c = '0'; | 
|  | 221 | for (unsigned int i = 0; i < big.size(); i++) { | 
|  | 222 | big[i] = c; | 
|  | 223 | c = ('9' == c) ? '0' : c + 1; | 
|  | 224 | } | 
|  | 225 | TestWithData(big, | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 226 | 2,  // fail_write | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 227 | true);  // use_download_delegate | 
| Darin Petkov | c97435c | 2010-07-20 12:37:43 -0700 | [diff] [blame] | 228 | } | 
|  | 229 |  | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 230 | TEST(DownloadActionTest, NoDownloadDelegateTest) { | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 231 | chromeos::Blob small; | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 232 | const char* foo = "foofoo"; | 
|  | 233 | small.insert(small.end(), foo, foo + strlen(foo)); | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 234 | TestWithData(small, | 
| Darin Petkov | 9ce452b | 2010-11-17 14:33:28 -0800 | [diff] [blame] | 235 | 0,  // fail_write | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 236 | false);  // use_download_delegate | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 237 | } | 
|  | 238 |  | 
|  | 239 | namespace { | 
|  | 240 | class TerminateEarlyTestProcessorDelegate : public ActionProcessorDelegate { | 
|  | 241 | public: | 
|  | 242 | void ProcessingStopped(const ActionProcessor* processor) { | 
|  | 243 | ASSERT_TRUE(loop_); | 
|  | 244 | g_main_loop_quit(loop_); | 
|  | 245 | } | 
|  | 246 | GMainLoop *loop_; | 
|  | 247 | }; | 
|  | 248 |  | 
|  | 249 | gboolean TerminateEarlyTestStarter(gpointer data) { | 
|  | 250 | ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); | 
|  | 251 | processor->StartProcessing(); | 
|  | 252 | CHECK(processor->IsRunning()); | 
|  | 253 | processor->StopProcessing(); | 
|  | 254 | return FALSE; | 
|  | 255 | } | 
|  | 256 |  | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 257 | void TestTerminateEarly(bool use_download_delegate) { | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 258 | GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 
|  | 259 |  | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 260 | chromeos::Blob data(kMockHttpFetcherChunkSize + | 
|  | 261 | kMockHttpFetcherChunkSize / 2); | 
|  | 262 | memset(data.data(), 0, data.size()); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 263 |  | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 264 | ScopedTempFile temp_file; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 265 | { | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 266 | DirectFileWriter writer; | 
|  | 267 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 268 | // takes ownership of passed in HttpFetcher | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 269 | ObjectFeederAction<InstallPlan> feeder_action; | 
| Gilad Arnold | 21504f0 | 2013-05-24 08:51:22 -0700 | [diff] [blame] | 270 | InstallPlan install_plan(false, false, "", 0, "", 0, "", | 
| Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 271 | temp_file.GetPath(), "", "", "", ""); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 272 | feeder_action.set_obj(install_plan); | 
| Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 273 | MockPrefs prefs; | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 274 | DownloadAction download_action(&prefs, nullptr, | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 275 | new MockHttpFetcher(data.data(), | 
| Andrew de los Reyes | 4516810 | 2010-11-22 11:13:50 -0800 | [diff] [blame] | 276 | data.size(), | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 277 | nullptr)); | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 278 | download_action.SetTestFileWriter(&writer); | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 279 | DownloadActionDelegateMock download_delegate; | 
|  | 280 | if (use_download_delegate) { | 
|  | 281 | InSequence s; | 
|  | 282 | download_action.set_delegate(&download_delegate); | 
|  | 283 | EXPECT_CALL(download_delegate, SetDownloadStatus(true)).Times(1); | 
|  | 284 | EXPECT_CALL(download_delegate, SetDownloadStatus(false)).Times(1); | 
|  | 285 | } | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 286 | TerminateEarlyTestProcessorDelegate delegate; | 
|  | 287 | delegate.loop_ = loop; | 
|  | 288 | ActionProcessor processor; | 
|  | 289 | processor.set_delegate(&delegate); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 290 | processor.EnqueueAction(&feeder_action); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 291 | processor.EnqueueAction(&download_action); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 292 | BondActions(&feeder_action, &download_action); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 293 |  | 
|  | 294 | g_timeout_add(0, &TerminateEarlyTestStarter, &processor); | 
|  | 295 | g_main_loop_run(loop); | 
|  | 296 | g_main_loop_unref(loop); | 
|  | 297 | } | 
|  | 298 |  | 
|  | 299 | // 1 or 0 chunks should have come through | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 300 | const off_t resulting_file_size(utils::FileSize(temp_file.GetPath())); | 
|  | 301 | EXPECT_GE(resulting_file_size, 0); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 302 | if (resulting_file_size != 0) | 
|  | 303 | EXPECT_EQ(kMockHttpFetcherChunkSize, resulting_file_size); | 
|  | 304 | } | 
|  | 305 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 306 | }  // namespace | 
| Darin Petkov | 9d911fa | 2010-08-19 09:36:08 -0700 | [diff] [blame] | 307 |  | 
|  | 308 | TEST(DownloadActionTest, TerminateEarlyTest) { | 
|  | 309 | TestTerminateEarly(true); | 
|  | 310 | } | 
|  | 311 |  | 
|  | 312 | TEST(DownloadActionTest, TerminateEarlyNoDownloadDelegateTest) { | 
|  | 313 | TestTerminateEarly(false); | 
|  | 314 | } | 
|  | 315 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 316 | class DownloadActionTestAction; | 
|  | 317 |  | 
|  | 318 | template<> | 
|  | 319 | class ActionTraits<DownloadActionTestAction> { | 
|  | 320 | public: | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 321 | typedef InstallPlan OutputObjectType; | 
|  | 322 | typedef InstallPlan InputObjectType; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 323 | }; | 
|  | 324 |  | 
|  | 325 | // This is a simple Action class for testing. | 
| Yunlian Jiang | 2dac576 | 2013-04-12 09:53:09 -0700 | [diff] [blame] | 326 | class DownloadActionTestAction : public Action<DownloadActionTestAction> { | 
|  | 327 | public: | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 328 | DownloadActionTestAction() : did_run_(false) {} | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 329 | typedef InstallPlan InputObjectType; | 
|  | 330 | typedef InstallPlan OutputObjectType; | 
|  | 331 | ActionPipe<InstallPlan>* in_pipe() { return in_pipe_.get(); } | 
|  | 332 | ActionPipe<InstallPlan>* out_pipe() { return out_pipe_.get(); } | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 333 | ActionProcessor* processor() { return processor_; } | 
|  | 334 | void PerformAction() { | 
|  | 335 | did_run_ = true; | 
|  | 336 | ASSERT_TRUE(HasInputObject()); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 337 | EXPECT_TRUE(expected_input_object_ == GetInputObject()); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 338 | ASSERT_TRUE(processor()); | 
| Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 339 | processor()->ActionComplete(this, ErrorCode::kSuccess); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 340 | } | 
|  | 341 | string Type() const { return "DownloadActionTestAction"; } | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 342 | InstallPlan expected_input_object_; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 343 | bool did_run_; | 
|  | 344 | }; | 
|  | 345 |  | 
|  | 346 | namespace { | 
|  | 347 | // This class is an ActionProcessorDelegate that simply terminates the | 
|  | 348 | // run loop when the ActionProcessor has completed processing. It's used | 
|  | 349 | // only by the test PassObjectOutTest. | 
|  | 350 | class PassObjectOutTestProcessorDelegate : public ActionProcessorDelegate { | 
|  | 351 | public: | 
| David Zeuthen | a99981f | 2013-04-29 13:42:47 -0700 | [diff] [blame] | 352 | void ProcessingDone(const ActionProcessor* processor, ErrorCode code) { | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 353 | ASSERT_TRUE(loop_); | 
|  | 354 | g_main_loop_quit(loop_); | 
|  | 355 | } | 
|  | 356 | GMainLoop *loop_; | 
|  | 357 | }; | 
|  | 358 |  | 
|  | 359 | gboolean PassObjectOutTestStarter(gpointer data) { | 
|  | 360 | ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); | 
|  | 361 | processor->StartProcessing(); | 
|  | 362 | return FALSE; | 
|  | 363 | } | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 364 | }  // namespace | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 365 |  | 
|  | 366 | TEST(DownloadActionTest, PassObjectOutTest) { | 
|  | 367 | GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 
|  | 368 |  | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 369 | DirectFileWriter writer; | 
|  | 370 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 371 | // takes ownership of passed in HttpFetcher | 
| Darin Petkov | 7ed561b | 2011-10-04 02:59:03 -0700 | [diff] [blame] | 372 | InstallPlan install_plan(false, | 
| Gilad Arnold | 21504f0 | 2013-05-24 08:51:22 -0700 | [diff] [blame] | 373 | false, | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 374 | "", | 
| Darin Petkov | 50332f1 | 2010-09-24 11:44:47 -0700 | [diff] [blame] | 375 | 1, | 
| Andrew de los Reyes | 1e338b8 | 2010-01-22 14:57:27 -0800 | [diff] [blame] | 376 | OmahaHashCalculator::OmahaHashOfString("x"), | 
| Jay Srinivasan | 51dcf26 | 2012-09-13 17:24:32 -0700 | [diff] [blame] | 377 | 0, | 
|  | 378 | "", | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 379 | "/dev/null", | 
| David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 380 | "/dev/null", | 
| Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 381 | "/dev/null", | 
|  | 382 | "/dev/null", | 
| David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 383 | ""); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 384 | ObjectFeederAction<InstallPlan> feeder_action; | 
|  | 385 | feeder_action.set_obj(install_plan); | 
| Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 386 | MockPrefs prefs; | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 387 | DownloadAction download_action(&prefs, nullptr, | 
|  | 388 | new MockHttpFetcher("x", 1, nullptr)); | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 389 | download_action.SetTestFileWriter(&writer); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 390 |  | 
|  | 391 | DownloadActionTestAction test_action; | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 392 | test_action.expected_input_object_ = install_plan; | 
|  | 393 | BondActions(&feeder_action, &download_action); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 394 | BondActions(&download_action, &test_action); | 
|  | 395 |  | 
|  | 396 | ActionProcessor processor; | 
|  | 397 | PassObjectOutTestProcessorDelegate delegate; | 
|  | 398 | delegate.loop_ = loop; | 
|  | 399 | processor.set_delegate(&delegate); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 400 | processor.EnqueueAction(&feeder_action); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 401 | processor.EnqueueAction(&download_action); | 
|  | 402 | processor.EnqueueAction(&test_action); | 
|  | 403 |  | 
|  | 404 | g_timeout_add(0, &PassObjectOutTestStarter, &processor); | 
|  | 405 | g_main_loop_run(loop); | 
|  | 406 | g_main_loop_unref(loop); | 
|  | 407 |  | 
|  | 408 | EXPECT_EQ(true, test_action.did_run_); | 
|  | 409 | } | 
|  | 410 |  | 
|  | 411 | TEST(DownloadActionTest, BadOutFileTest) { | 
|  | 412 | GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 
|  | 413 |  | 
|  | 414 | const string path("/fake/path/that/cant/be/created/because/of/missing/dirs"); | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 415 | DirectFileWriter writer; | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 416 |  | 
|  | 417 | // takes ownership of passed in HttpFetcher | 
| Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 418 | InstallPlan install_plan( | 
|  | 419 | false, false, "", 0, "", 0, "", path, "", "", "", ""); | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 420 | ObjectFeederAction<InstallPlan> feeder_action; | 
|  | 421 | feeder_action.set_obj(install_plan); | 
| Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 422 | MockPrefs prefs; | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 423 | DownloadAction download_action(&prefs, nullptr, | 
|  | 424 | new MockHttpFetcher("x", 1, nullptr)); | 
| Andrew de los Reyes | f918517 | 2010-05-03 11:07:05 -0700 | [diff] [blame] | 425 | download_action.SetTestFileWriter(&writer); | 
| Darin Petkov | c1a8b42 | 2010-07-19 11:34:49 -0700 | [diff] [blame] | 426 |  | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 427 | BondActions(&feeder_action, &download_action); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 428 |  | 
|  | 429 | ActionProcessor processor; | 
| adlr@google.com | c98a7ed | 2009-12-04 18:54:03 +0000 | [diff] [blame] | 430 | processor.EnqueueAction(&feeder_action); | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 431 | processor.EnqueueAction(&download_action); | 
|  | 432 | processor.StartProcessing(); | 
|  | 433 | ASSERT_FALSE(processor.IsRunning()); | 
|  | 434 |  | 
|  | 435 | g_main_loop_unref(loop); | 
|  | 436 | } | 
|  | 437 |  | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 438 | gboolean StartProcessorInRunLoopForP2P(gpointer user_data) { | 
|  | 439 | ActionProcessor* processor = reinterpret_cast<ActionProcessor*>(user_data); | 
|  | 440 | processor->StartProcessing(); | 
|  | 441 | return FALSE; | 
|  | 442 | } | 
|  | 443 |  | 
|  | 444 | // Test fixture for P2P tests. | 
|  | 445 | class P2PDownloadActionTest : public testing::Test { | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 446 | protected: | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 447 | P2PDownloadActionTest() | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 448 | : loop_(nullptr), | 
| Gilad Arnold | 4a0321b | 2014-10-28 15:57:30 -0700 | [diff] [blame] | 449 | start_at_offset_(0), | 
|  | 450 | fake_um_(fake_system_state_.fake_clock()) {} | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 451 |  | 
| Alex Deymo | 610277e | 2014-11-11 21:18:11 -0800 | [diff] [blame] | 452 | ~P2PDownloadActionTest() override {} | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 453 |  | 
|  | 454 | // Derived from testing::Test. | 
| Alex Deymo | 610277e | 2014-11-11 21:18:11 -0800 | [diff] [blame] | 455 | void SetUp() override { | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 456 | loop_ = g_main_loop_new(g_main_context_default(), FALSE); | 
|  | 457 | } | 
|  | 458 |  | 
|  | 459 | // Derived from testing::Test. | 
| Alex Deymo | 610277e | 2014-11-11 21:18:11 -0800 | [diff] [blame] | 460 | void TearDown() override { | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 461 | if (loop_ != nullptr) | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 462 | g_main_loop_unref(loop_); | 
|  | 463 | } | 
|  | 464 |  | 
|  | 465 | // To be called by tests to setup the download. The | 
|  | 466 | // |starting_offset| parameter is for where to resume. | 
|  | 467 | void SetupDownload(off_t starting_offset) { | 
|  | 468 | start_at_offset_ = starting_offset; | 
|  | 469 | // Prepare data 10 kB of data. | 
|  | 470 | data_.clear(); | 
|  | 471 | for (unsigned int i = 0; i < 10 * 1000; i++) | 
|  | 472 | data_ += 'a' + (i % 25); | 
|  | 473 |  | 
|  | 474 | // Setup p2p. | 
|  | 475 | FakeP2PManagerConfiguration *test_conf = new FakeP2PManagerConfiguration(); | 
| David Zeuthen | 41f2cf5 | 2014-11-05 12:29:45 -0500 | [diff] [blame] | 476 | p2p_manager_.reset(P2PManager::Construct( | 
| Gilad Arnold | 4a0321b | 2014-10-28 15:57:30 -0700 | [diff] [blame] | 477 | test_conf, nullptr, &fake_um_, "cros_au", 3, | 
| David Zeuthen | 41f2cf5 | 2014-11-05 12:29:45 -0500 | [diff] [blame] | 478 | base::TimeDelta::FromDays(5))); | 
| Gilad Arnold | 5bb4c90 | 2014-04-10 12:32:13 -0700 | [diff] [blame] | 479 | fake_system_state_.set_p2p_manager(p2p_manager_.get()); | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 480 | } | 
|  | 481 |  | 
|  | 482 | // To be called by tests to perform the download. The | 
|  | 483 | // |use_p2p_to_share| parameter is used to indicate whether the | 
|  | 484 | // payload should be shared via p2p. | 
|  | 485 | void StartDownload(bool use_p2p_to_share) { | 
| Gilad Arnold | 74b5f55 | 2014-10-07 08:17:16 -0700 | [diff] [blame] | 486 | EXPECT_CALL(*fake_system_state_.mock_payload_state(), | 
|  | 487 | GetUsingP2PForSharing()) | 
|  | 488 | .WillRepeatedly(Return(use_p2p_to_share)); | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 489 |  | 
|  | 490 | ScopedTempFile output_temp_file; | 
|  | 491 | TestDirectFileWriter writer; | 
|  | 492 | InstallPlan install_plan(false, | 
|  | 493 | false, | 
|  | 494 | "", | 
|  | 495 | data_.length(), | 
|  | 496 | "1234hash", | 
|  | 497 | 0, | 
|  | 498 | "", | 
|  | 499 | output_temp_file.GetPath(), | 
| David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 500 | "", | 
| Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 501 | "", | 
|  | 502 | "", | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 503 | ""); | 
|  | 504 | ObjectFeederAction<InstallPlan> feeder_action; | 
|  | 505 | feeder_action.set_obj(install_plan); | 
| Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 506 | MockPrefs prefs; | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 507 | http_fetcher_ = new MockHttpFetcher(data_.c_str(), | 
|  | 508 | data_.length(), | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 509 | nullptr); | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 510 | // Note that DownloadAction takes ownership of the passed in HttpFetcher. | 
| Gilad Arnold | 5bb4c90 | 2014-04-10 12:32:13 -0700 | [diff] [blame] | 511 | download_action_.reset(new DownloadAction(&prefs, &fake_system_state_, | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 512 | http_fetcher_)); | 
|  | 513 | download_action_->SetTestFileWriter(&writer); | 
|  | 514 | BondActions(&feeder_action, download_action_.get()); | 
| Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 515 | DownloadActionTestProcessorDelegate delegate(ErrorCode::kSuccess); | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 516 | delegate.loop_ = loop_; | 
| Alex Vakulenko | f68bbbc | 2015-02-09 12:53:18 -0800 | [diff] [blame] | 517 | delegate.expected_data_ = chromeos::Blob(data_.begin() + start_at_offset_, | 
|  | 518 | data_.end()); | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 519 | delegate.path_ = output_temp_file.GetPath(); | 
|  | 520 | processor_.set_delegate(&delegate); | 
|  | 521 | processor_.EnqueueAction(&feeder_action); | 
|  | 522 | processor_.EnqueueAction(download_action_.get()); | 
|  | 523 |  | 
|  | 524 | g_timeout_add(0, &StartProcessorInRunLoopForP2P, this); | 
|  | 525 | g_main_loop_run(loop_); | 
|  | 526 | } | 
|  | 527 |  | 
|  | 528 | // The DownloadAction instance under test. | 
| Ben Chan | 02f7c1d | 2014-10-18 15:18:02 -0700 | [diff] [blame] | 529 | unique_ptr<DownloadAction> download_action_; | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 530 |  | 
|  | 531 | // The HttpFetcher used in the test. | 
|  | 532 | MockHttpFetcher* http_fetcher_; | 
|  | 533 |  | 
|  | 534 | // The P2PManager used in the test. | 
| Ben Chan | 02f7c1d | 2014-10-18 15:18:02 -0700 | [diff] [blame] | 535 | unique_ptr<P2PManager> p2p_manager_; | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 536 |  | 
|  | 537 | // The ActionProcessor used for running the actions. | 
|  | 538 | ActionProcessor processor_; | 
|  | 539 |  | 
|  | 540 | // A fake system state. | 
| Gilad Arnold | 5bb4c90 | 2014-04-10 12:32:13 -0700 | [diff] [blame] | 541 | FakeSystemState fake_system_state_; | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 542 |  | 
|  | 543 | // The data being downloaded. | 
|  | 544 | string data_; | 
|  | 545 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 546 | private: | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 547 | // Callback used in StartDownload() method. | 
|  | 548 | static gboolean StartProcessorInRunLoopForP2P(gpointer user_data) { | 
|  | 549 | class P2PDownloadActionTest *test = | 
|  | 550 | reinterpret_cast<P2PDownloadActionTest*>(user_data); | 
|  | 551 | test->processor_.StartProcessing(); | 
|  | 552 | test->http_fetcher_->SetOffset(test->start_at_offset_); | 
|  | 553 | return FALSE; | 
|  | 554 | } | 
|  | 555 |  | 
|  | 556 | // Mainloop used to make StartDownload() synchronous. | 
|  | 557 | GMainLoop *loop_; | 
|  | 558 |  | 
|  | 559 | // The requested starting offset passed to SetupDownload(). | 
|  | 560 | off_t start_at_offset_; | 
| Gilad Arnold | 4a0321b | 2014-10-28 15:57:30 -0700 | [diff] [blame] | 561 |  | 
|  | 562 | chromeos_update_manager::FakeUpdateManager fake_um_; | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 563 | }; | 
|  | 564 |  | 
|  | 565 | TEST_F(P2PDownloadActionTest, IsWrittenTo) { | 
| Alex Deymo | 10875d9 | 2014-11-10 21:52:57 -0800 | [diff] [blame] | 566 | if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { | 
| David Zeuthen | 910ec5b | 2013-09-26 12:10:58 -0700 | [diff] [blame] | 567 | LOG(WARNING) << "Skipping test because /tmp does not support xattr. " | 
|  | 568 | << "Please update your system to support this feature."; | 
|  | 569 | return; | 
|  | 570 | } | 
|  | 571 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 572 | SetupDownload(0);     // starting_offset | 
|  | 573 | StartDownload(true);  // use_p2p_to_share | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 574 |  | 
|  | 575 | // Check the p2p file and its content matches what was sent. | 
|  | 576 | string file_id = download_action_->p2p_file_id(); | 
| Gilad Arnold | 74b5f55 | 2014-10-07 08:17:16 -0700 | [diff] [blame] | 577 | EXPECT_NE("", file_id); | 
|  | 578 | EXPECT_EQ(data_.length(), p2p_manager_->FileGetSize(file_id)); | 
|  | 579 | EXPECT_EQ(data_.length(), p2p_manager_->FileGetExpectedSize(file_id)); | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 580 | string p2p_file_contents; | 
|  | 581 | EXPECT_TRUE(ReadFileToString(p2p_manager_->FileGetPath(file_id), | 
|  | 582 | &p2p_file_contents)); | 
|  | 583 | EXPECT_EQ(data_, p2p_file_contents); | 
|  | 584 | } | 
|  | 585 |  | 
|  | 586 | TEST_F(P2PDownloadActionTest, DeleteIfHoleExists) { | 
| Alex Deymo | 10875d9 | 2014-11-10 21:52:57 -0800 | [diff] [blame] | 587 | if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { | 
| David Zeuthen | 910ec5b | 2013-09-26 12:10:58 -0700 | [diff] [blame] | 588 | LOG(WARNING) << "Skipping test because /tmp does not support xattr. " | 
|  | 589 | << "Please update your system to support this feature."; | 
|  | 590 | return; | 
|  | 591 | } | 
|  | 592 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 593 | SetupDownload(1000);  // starting_offset | 
|  | 594 | StartDownload(true);  // use_p2p_to_share | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 595 |  | 
|  | 596 | // DownloadAction should convey that the file is not being shared. | 
|  | 597 | // and that we don't have any p2p files. | 
|  | 598 | EXPECT_EQ(download_action_->p2p_file_id(), ""); | 
|  | 599 | EXPECT_EQ(p2p_manager_->CountSharedFiles(), 0); | 
|  | 600 | } | 
|  | 601 |  | 
|  | 602 | TEST_F(P2PDownloadActionTest, CanAppend) { | 
| Alex Deymo | 10875d9 | 2014-11-10 21:52:57 -0800 | [diff] [blame] | 603 | if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { | 
| David Zeuthen | 910ec5b | 2013-09-26 12:10:58 -0700 | [diff] [blame] | 604 | LOG(WARNING) << "Skipping test because /tmp does not support xattr. " | 
|  | 605 | << "Please update your system to support this feature."; | 
|  | 606 | return; | 
|  | 607 | } | 
|  | 608 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 609 | SetupDownload(1000);  // starting_offset | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 610 |  | 
|  | 611 | // Prepare the file with existing data before starting to write to | 
|  | 612 | // it via DownloadAction. | 
|  | 613 | string file_id = utils::CalculateP2PFileId("1234hash", data_.length()); | 
|  | 614 | ASSERT_TRUE(p2p_manager_->FileShare(file_id, data_.length())); | 
|  | 615 | string existing_data; | 
|  | 616 | for (unsigned int i = 0; i < 1000; i++) | 
|  | 617 | existing_data += '0' + (i % 10); | 
|  | 618 | ASSERT_EQ(WriteFile(p2p_manager_->FileGetPath(file_id), existing_data.c_str(), | 
|  | 619 | 1000), 1000); | 
|  | 620 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 621 | StartDownload(true);  // use_p2p_to_share | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 622 |  | 
|  | 623 | // DownloadAction should convey the same file_id and the file should | 
|  | 624 | // have the expected size. | 
|  | 625 | EXPECT_EQ(download_action_->p2p_file_id(), file_id); | 
|  | 626 | EXPECT_EQ(p2p_manager_->FileGetSize(file_id), data_.length()); | 
|  | 627 | EXPECT_EQ(p2p_manager_->FileGetExpectedSize(file_id), data_.length()); | 
|  | 628 | string p2p_file_contents; | 
|  | 629 | // Check that the first 1000 bytes wasn't touched and that we | 
|  | 630 | // appended the remaining as appropriate. | 
|  | 631 | EXPECT_TRUE(ReadFileToString(p2p_manager_->FileGetPath(file_id), | 
|  | 632 | &p2p_file_contents)); | 
|  | 633 | EXPECT_EQ(existing_data, p2p_file_contents.substr(0, 1000)); | 
|  | 634 | EXPECT_EQ(data_.substr(1000), p2p_file_contents.substr(1000)); | 
|  | 635 | } | 
|  | 636 |  | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 637 | TEST_F(P2PDownloadActionTest, DeletePartialP2PFileIfResumingWithoutP2P) { | 
| Alex Deymo | 10875d9 | 2014-11-10 21:52:57 -0800 | [diff] [blame] | 638 | if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { | 
| David Zeuthen | 910ec5b | 2013-09-26 12:10:58 -0700 | [diff] [blame] | 639 | LOG(WARNING) << "Skipping test because /tmp does not support xattr. " | 
|  | 640 | << "Please update your system to support this feature."; | 
|  | 641 | return; | 
|  | 642 | } | 
|  | 643 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 644 | SetupDownload(1000);  // starting_offset | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 645 |  | 
|  | 646 | // Prepare the file with all existing data before starting to write | 
|  | 647 | // to it via DownloadAction. | 
|  | 648 | string file_id = utils::CalculateP2PFileId("1234hash", data_.length()); | 
|  | 649 | ASSERT_TRUE(p2p_manager_->FileShare(file_id, data_.length())); | 
|  | 650 | string existing_data; | 
|  | 651 | for (unsigned int i = 0; i < 1000; i++) | 
|  | 652 | existing_data += '0' + (i % 10); | 
|  | 653 | ASSERT_EQ(WriteFile(p2p_manager_->FileGetPath(file_id), existing_data.c_str(), | 
|  | 654 | 1000), 1000); | 
|  | 655 |  | 
|  | 656 | // Check that the file is there. | 
|  | 657 | EXPECT_EQ(p2p_manager_->FileGetSize(file_id), 1000); | 
|  | 658 | EXPECT_EQ(p2p_manager_->CountSharedFiles(), 1); | 
|  | 659 |  | 
| Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 660 | StartDownload(false);  // use_p2p_to_share | 
| David Zeuthen | 8f191b2 | 2013-08-06 12:27:50 -0700 | [diff] [blame] | 661 |  | 
|  | 662 | // DownloadAction should have deleted the p2p file. Check that it's gone. | 
|  | 663 | EXPECT_EQ(p2p_manager_->FileGetSize(file_id), -1); | 
|  | 664 | EXPECT_EQ(p2p_manager_->CountSharedFiles(), 0); | 
|  | 665 | } | 
|  | 666 |  | 
| rspangler@google.com | 49fdf18 | 2009-10-10 00:57:34 +0000 | [diff] [blame] | 667 | }  // namespace chromeos_update_engine |