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 <gmock/gmock.h> |
8 #include <gtest/gtest.h> | 9 #include <gtest/gtest.h> |
9 #include "update_engine/action_pipe.h" | 10 #include "update_engine/action_pipe.h" |
10 #include "update_engine/download_action.h" | 11 #include "update_engine/download_action.h" |
11 #include "update_engine/mock_http_fetcher.h" | 12 #include "update_engine/mock_http_fetcher.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 namespace chromeos_update_engine { | 17 namespace chromeos_update_engine { |
17 | 18 |
18 using std::string; | 19 using std::string; |
19 using std::vector; | 20 using std::vector; |
| 21 using testing::_; |
| 22 using testing::AtLeast; |
| 23 using testing::InSequence; |
20 | 24 |
21 class DownloadActionTest : public ::testing::Test { }; | 25 class DownloadActionTest : public ::testing::Test { }; |
22 | 26 |
23 namespace { | 27 namespace { |
| 28 class DownloadActionDelegateMock : public DownloadActionDelegate { |
| 29 public: |
| 30 MOCK_METHOD1(SetDownloadStatus, void(bool active)); |
| 31 MOCK_METHOD2(BytesReceived, void(uint64_t bytes_received, uint64_t total)); |
| 32 }; |
| 33 |
24 class DownloadActionTestProcessorDelegate : public ActionProcessorDelegate { | 34 class DownloadActionTestProcessorDelegate : public ActionProcessorDelegate { |
25 public: | 35 public: |
26 explicit DownloadActionTestProcessorDelegate(ActionExitCode expected_code) | 36 explicit DownloadActionTestProcessorDelegate(ActionExitCode expected_code) |
27 : loop_(NULL), | 37 : loop_(NULL), |
28 processing_done_called_(false), | 38 processing_done_called_(false), |
29 expected_code_(expected_code) {} | 39 expected_code_(expected_code) {} |
30 virtual ~DownloadActionTestProcessorDelegate() { | 40 virtual ~DownloadActionTestProcessorDelegate() { |
31 EXPECT_TRUE(processing_done_called_); | 41 EXPECT_TRUE(processing_done_called_); |
32 } | 42 } |
33 virtual void ProcessingDone(const ActionProcessor* processor, | 43 virtual void ProcessingDone(const ActionProcessor* processor, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 GMainLoop *loop; | 76 GMainLoop *loop; |
67 ActionProcessor *processor; | 77 ActionProcessor *processor; |
68 }; | 78 }; |
69 | 79 |
70 gboolean StartProcessorInRunLoop(gpointer data) { | 80 gboolean StartProcessorInRunLoop(gpointer data) { |
71 ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); | 81 ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); |
72 processor->StartProcessing(); | 82 processor->StartProcessing(); |
73 return FALSE; | 83 return FALSE; |
74 } | 84 } |
75 | 85 |
76 void TestWithData(const vector<char>& data, bool hash_test) { | 86 void TestWithData(const vector<char>& data, |
| 87 bool hash_test, |
| 88 bool use_download_delegate) { |
77 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 89 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
78 | 90 |
79 // TODO(adlr): see if we need a different file for build bots | 91 // TODO(adlr): see if we need a different file for build bots |
80 ScopedTempFile output_temp_file; | 92 ScopedTempFile output_temp_file; |
81 DirectFileWriter writer; | 93 DirectFileWriter writer; |
82 | 94 |
83 // takes ownership of passed in HttpFetcher | 95 // takes ownership of passed in HttpFetcher |
84 string hash = hash_test ? | 96 string hash = hash_test ? |
85 OmahaHashCalculator::OmahaHashOfString("random string") : | 97 OmahaHashCalculator::OmahaHashOfString("random string") : |
86 OmahaHashCalculator::OmahaHashOfData(data); | 98 OmahaHashCalculator::OmahaHashOfData(data); |
87 InstallPlan install_plan(true, | 99 InstallPlan install_plan(true, |
88 "", | 100 "", |
89 0, | 101 0, |
90 hash, | 102 hash, |
91 output_temp_file.GetPath(), | 103 output_temp_file.GetPath(), |
92 ""); | 104 ""); |
93 ObjectFeederAction<InstallPlan> feeder_action; | 105 ObjectFeederAction<InstallPlan> feeder_action; |
94 feeder_action.set_obj(install_plan); | 106 feeder_action.set_obj(install_plan); |
95 DownloadAction download_action(new MockHttpFetcher(&data[0], | 107 DownloadAction download_action(new MockHttpFetcher(&data[0], |
96 data.size())); | 108 data.size())); |
97 download_action.SetTestFileWriter(&writer); | 109 download_action.SetTestFileWriter(&writer); |
98 BondActions(&feeder_action, &download_action); | 110 BondActions(&feeder_action, &download_action); |
99 | 111 DownloadActionDelegateMock download_delegate; |
| 112 if (use_download_delegate) { |
| 113 InSequence s; |
| 114 download_action.set_delegate(&download_delegate); |
| 115 EXPECT_CALL(download_delegate, SetDownloadStatus(true)).Times(1); |
| 116 EXPECT_CALL(download_delegate, BytesReceived(_, _)).Times(AtLeast(1)); |
| 117 EXPECT_CALL(download_delegate, SetDownloadStatus(false)).Times(1); |
| 118 } |
100 DownloadActionTestProcessorDelegate delegate( | 119 DownloadActionTestProcessorDelegate delegate( |
101 hash_test ? kActionCodeDownloadHashMismatchError : kActionCodeSuccess); | 120 hash_test ? kActionCodeDownloadHashMismatchError : kActionCodeSuccess); |
102 delegate.loop_ = loop; | 121 delegate.loop_ = loop; |
103 delegate.expected_data_ = data; | 122 delegate.expected_data_ = data; |
104 delegate.path_ = output_temp_file.GetPath(); | 123 delegate.path_ = output_temp_file.GetPath(); |
105 ActionProcessor processor; | 124 ActionProcessor processor; |
106 processor.set_delegate(&delegate); | 125 processor.set_delegate(&delegate); |
107 processor.EnqueueAction(&feeder_action); | 126 processor.EnqueueAction(&feeder_action); |
108 processor.EnqueueAction(&download_action); | 127 processor.EnqueueAction(&download_action); |
109 | 128 |
110 g_timeout_add(0, &StartProcessorInRunLoop, &processor); | 129 g_timeout_add(0, &StartProcessorInRunLoop, &processor); |
111 g_main_loop_run(loop); | 130 g_main_loop_run(loop); |
112 g_main_loop_unref(loop); | 131 g_main_loop_unref(loop); |
113 } | 132 } |
114 } // namespace {} | 133 } // namespace {} |
115 | 134 |
116 TEST(DownloadActionTest, SimpleTest) { | 135 TEST(DownloadActionTest, SimpleTest) { |
117 vector<char> small; | 136 vector<char> small; |
118 const char* foo = "foo"; | 137 const char* foo = "foo"; |
119 small.insert(small.end(), foo, foo + strlen(foo)); | 138 small.insert(small.end(), foo, foo + strlen(foo)); |
120 TestWithData(small, false); | 139 TestWithData(small, false, true); |
121 } | 140 } |
122 | 141 |
123 TEST(DownloadActionTest, LargeTest) { | 142 TEST(DownloadActionTest, LargeTest) { |
124 vector<char> big(5 * kMockHttpFetcherChunkSize); | 143 vector<char> big(5 * kMockHttpFetcherChunkSize); |
125 char c = '0'; | 144 char c = '0'; |
126 for (unsigned int i = 0; i < big.size(); i++) { | 145 for (unsigned int i = 0; i < big.size(); i++) { |
127 big[i] = c; | 146 big[i] = c; |
128 if ('9' == c) | 147 if ('9' == c) |
129 c = '0'; | 148 c = '0'; |
130 else | 149 else |
131 c++; | 150 c++; |
132 } | 151 } |
133 TestWithData(big, false); | 152 TestWithData(big, false, true); |
134 } | 153 } |
135 | 154 |
136 TEST(DownloadActionTest, BadHashTest) { | 155 TEST(DownloadActionTest, BadHashTest) { |
137 vector<char> small; | 156 vector<char> small; |
138 const char* foo = "foo"; | 157 const char* foo = "foo"; |
139 small.insert(small.end(), foo, foo + strlen(foo)); | 158 small.insert(small.end(), foo, foo + strlen(foo)); |
140 TestWithData(small, true); | 159 TestWithData(small, true, true); |
| 160 } |
| 161 |
| 162 TEST(DownloadActionTest, NoDownloadDelegateTest) { |
| 163 vector<char> small; |
| 164 const char* foo = "foofoo"; |
| 165 small.insert(small.end(), foo, foo + strlen(foo)); |
| 166 TestWithData(small, false, false); |
141 } | 167 } |
142 | 168 |
143 namespace { | 169 namespace { |
144 class TerminateEarlyTestProcessorDelegate : public ActionProcessorDelegate { | 170 class TerminateEarlyTestProcessorDelegate : public ActionProcessorDelegate { |
145 public: | 171 public: |
146 void ProcessingStopped(const ActionProcessor* processor) { | 172 void ProcessingStopped(const ActionProcessor* processor) { |
147 ASSERT_TRUE(loop_); | 173 ASSERT_TRUE(loop_); |
148 g_main_loop_quit(loop_); | 174 g_main_loop_quit(loop_); |
149 } | 175 } |
150 GMainLoop *loop_; | 176 GMainLoop *loop_; |
151 }; | 177 }; |
152 | 178 |
153 gboolean TerminateEarlyTestStarter(gpointer data) { | 179 gboolean TerminateEarlyTestStarter(gpointer data) { |
154 ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); | 180 ActionProcessor *processor = reinterpret_cast<ActionProcessor*>(data); |
155 processor->StartProcessing(); | 181 processor->StartProcessing(); |
156 CHECK(processor->IsRunning()); | 182 CHECK(processor->IsRunning()); |
157 processor->StopProcessing(); | 183 processor->StopProcessing(); |
158 return FALSE; | 184 return FALSE; |
159 } | 185 } |
160 | 186 |
161 } // namespace {} | 187 void TestTerminateEarly(bool use_download_delegate) { |
162 | |
163 TEST(DownloadActionTest, TerminateEarlyTest) { | |
164 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 188 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
165 | 189 |
166 vector<char> data(kMockHttpFetcherChunkSize + kMockHttpFetcherChunkSize / 2); | 190 vector<char> data(kMockHttpFetcherChunkSize + kMockHttpFetcherChunkSize / 2); |
167 memset(&data[0], 0, data.size()); | 191 memset(&data[0], 0, data.size()); |
168 | 192 |
169 ScopedTempFile temp_file; | 193 ScopedTempFile temp_file; |
170 { | 194 { |
171 DirectFileWriter writer; | 195 DirectFileWriter writer; |
172 | 196 |
173 // takes ownership of passed in HttpFetcher | 197 // takes ownership of passed in HttpFetcher |
174 ObjectFeederAction<InstallPlan> feeder_action; | 198 ObjectFeederAction<InstallPlan> feeder_action; |
175 InstallPlan install_plan(true, "", 0, "", temp_file.GetPath(), ""); | 199 InstallPlan install_plan(true, "", 0, "", temp_file.GetPath(), ""); |
176 feeder_action.set_obj(install_plan); | 200 feeder_action.set_obj(install_plan); |
177 DownloadAction download_action(new MockHttpFetcher(&data[0], data.size())); | 201 DownloadAction download_action(new MockHttpFetcher(&data[0], data.size())); |
178 download_action.SetTestFileWriter(&writer); | 202 download_action.SetTestFileWriter(&writer); |
| 203 DownloadActionDelegateMock download_delegate; |
| 204 if (use_download_delegate) { |
| 205 InSequence s; |
| 206 download_action.set_delegate(&download_delegate); |
| 207 EXPECT_CALL(download_delegate, SetDownloadStatus(true)).Times(1); |
| 208 EXPECT_CALL(download_delegate, SetDownloadStatus(false)).Times(1); |
| 209 } |
179 TerminateEarlyTestProcessorDelegate delegate; | 210 TerminateEarlyTestProcessorDelegate delegate; |
180 delegate.loop_ = loop; | 211 delegate.loop_ = loop; |
181 ActionProcessor processor; | 212 ActionProcessor processor; |
182 processor.set_delegate(&delegate); | 213 processor.set_delegate(&delegate); |
183 processor.EnqueueAction(&feeder_action); | 214 processor.EnqueueAction(&feeder_action); |
184 processor.EnqueueAction(&download_action); | 215 processor.EnqueueAction(&download_action); |
185 BondActions(&feeder_action, &download_action); | 216 BondActions(&feeder_action, &download_action); |
186 | 217 |
187 g_timeout_add(0, &TerminateEarlyTestStarter, &processor); | 218 g_timeout_add(0, &TerminateEarlyTestStarter, &processor); |
188 g_main_loop_run(loop); | 219 g_main_loop_run(loop); |
189 g_main_loop_unref(loop); | 220 g_main_loop_unref(loop); |
190 } | 221 } |
191 | 222 |
192 // 1 or 0 chunks should have come through | 223 // 1 or 0 chunks should have come through |
193 const off_t resulting_file_size(utils::FileSize(temp_file.GetPath())); | 224 const off_t resulting_file_size(utils::FileSize(temp_file.GetPath())); |
194 EXPECT_GE(resulting_file_size, 0); | 225 EXPECT_GE(resulting_file_size, 0); |
195 if (resulting_file_size != 0) | 226 if (resulting_file_size != 0) |
196 EXPECT_EQ(kMockHttpFetcherChunkSize, resulting_file_size); | 227 EXPECT_EQ(kMockHttpFetcherChunkSize, resulting_file_size); |
197 } | 228 } |
198 | 229 |
| 230 } // namespace {} |
| 231 |
| 232 TEST(DownloadActionTest, TerminateEarlyTest) { |
| 233 TestTerminateEarly(true); |
| 234 } |
| 235 |
| 236 TEST(DownloadActionTest, TerminateEarlyNoDownloadDelegateTest) { |
| 237 TestTerminateEarly(false); |
| 238 } |
| 239 |
199 class DownloadActionTestAction; | 240 class DownloadActionTestAction; |
200 | 241 |
201 template<> | 242 template<> |
202 class ActionTraits<DownloadActionTestAction> { | 243 class ActionTraits<DownloadActionTestAction> { |
203 public: | 244 public: |
204 typedef InstallPlan OutputObjectType; | 245 typedef InstallPlan OutputObjectType; |
205 typedef InstallPlan InputObjectType; | 246 typedef InstallPlan InputObjectType; |
206 }; | 247 }; |
207 | 248 |
208 // This is a simple Action class for testing. | 249 // This is a simple Action class for testing. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 ActionProcessor processor; | 341 ActionProcessor processor; |
301 processor.EnqueueAction(&feeder_action); | 342 processor.EnqueueAction(&feeder_action); |
302 processor.EnqueueAction(&download_action); | 343 processor.EnqueueAction(&download_action); |
303 processor.StartProcessing(); | 344 processor.StartProcessing(); |
304 ASSERT_FALSE(processor.IsRunning()); | 345 ASSERT_FALSE(processor.IsRunning()); |
305 | 346 |
306 g_main_loop_unref(loop); | 347 g_main_loop_unref(loop); |
307 } | 348 } |
308 | 349 |
309 } // namespace chromeos_update_engine | 350 } // namespace chromeos_update_engine |
OLD | NEW |