Roll src/third_party/WebKit f298044:aa8346d (svn 202628:202629)
[chromium-blink-merge.git] / chrome / browser / safe_browsing / download_feedback_service_unittest.cc
blob1f04532cce5198ea45201151ea666ae79baaa303
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/download_feedback_service.h"
7 #include <vector>
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "chrome/browser/safe_browsing/download_feedback.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/test/mock_download_item.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "net/url_request/url_request_test_util.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using ::testing::_;
22 using ::testing::Return;
23 using ::testing::SaveArg;
25 namespace safe_browsing {
27 namespace {
29 class FakeDownloadFeedback : public DownloadFeedback {
30 public:
31 FakeDownloadFeedback(net::URLRequestContextGetter* request_context_getter,
32 base::TaskRunner* file_task_runner,
33 const base::FilePath& file_path,
34 const std::string& ping_request,
35 const std::string& ping_response,
36 base::Closure deletion_callback)
37 : ping_request_(ping_request),
38 ping_response_(ping_response),
39 deletion_callback_(deletion_callback),
40 start_called_(false) {
43 ~FakeDownloadFeedback() override { deletion_callback_.Run(); }
45 void Start(const base::Closure& finish_callback) override {
46 start_called_ = true;
47 finish_callback_ = finish_callback;
50 const std::string& GetPingRequestForTesting() const override {
51 return ping_request_;
54 const std::string& GetPingResponseForTesting() const override {
55 return ping_response_;
58 base::Closure finish_callback() const {
59 return finish_callback_;
62 bool start_called() const {
63 return start_called_;
66 private:
67 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
68 scoped_refptr<base::TaskRunner> file_task_runner_;
69 base::FilePath file_path_;
70 std::string ping_request_;
71 std::string ping_response_;
73 base::Closure finish_callback_;
74 base::Closure deletion_callback_;
75 bool start_called_;
78 class FakeDownloadFeedbackFactory : public DownloadFeedbackFactory {
79 public:
80 ~FakeDownloadFeedbackFactory() override {}
82 DownloadFeedback* CreateDownloadFeedback(
83 net::URLRequestContextGetter* request_context_getter,
84 base::TaskRunner* file_task_runner,
85 const base::FilePath& file_path,
86 const std::string& ping_request,
87 const std::string& ping_response) override {
88 FakeDownloadFeedback* feedback = new FakeDownloadFeedback(
89 request_context_getter,
90 file_task_runner,
91 file_path,
92 ping_request,
93 ping_response,
94 base::Bind(&FakeDownloadFeedbackFactory::DownloadFeedbackDeleted,
95 base::Unretained(this),
96 feedbacks_.size()));
97 feedbacks_.push_back(feedback);
98 return feedback;
101 void DownloadFeedbackDeleted(size_t n) {
102 feedbacks_[n] = NULL;
105 FakeDownloadFeedback* feedback(size_t n) const {
106 return feedbacks_[n];
109 size_t num_feedbacks() const {
110 return feedbacks_.size();
113 private:
114 std::vector<FakeDownloadFeedback*> feedbacks_;
117 bool WillStorePings(DownloadProtectionService::DownloadCheckResult result,
118 int64 size) {
119 content::MockDownloadItem item;
120 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(size));
122 EXPECT_FALSE(DownloadFeedbackService::IsEnabledForDownload(item));
123 DownloadFeedbackService::MaybeStorePingsForDownload(result, &item, "a", "b");
124 return DownloadFeedbackService::IsEnabledForDownload(item);
127 } // namespace
129 class DownloadFeedbackServiceTest : public testing::Test {
130 public:
131 DownloadFeedbackServiceTest()
132 : file_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread(
133 content::BrowserThread::FILE)),
134 io_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread(
135 content::BrowserThread::IO)),
136 request_context_getter_(
137 new net::TestURLRequestContextGetter(io_task_runner_)) {
140 void SetUp() override {
141 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
142 DownloadFeedback::RegisterFactory(&download_feedback_factory_);
145 void TearDown() override { DownloadFeedback::RegisterFactory(NULL); }
147 base::FilePath CreateTestFile(int n) const {
148 base::FilePath upload_file_path(
149 temp_dir_.path().AppendASCII("test file " + base::IntToString(n)));
150 const std::string upload_file_data = "data";
151 int wrote = base::WriteFile(
152 upload_file_path, upload_file_data.data(), upload_file_data.size());
153 EXPECT_EQ(static_cast<int>(upload_file_data.size()), wrote);
154 return upload_file_path;
157 FakeDownloadFeedback* feedback(size_t n) const {
158 return download_feedback_factory_.feedback(n);
161 size_t num_feedbacks() const {
162 return download_feedback_factory_.num_feedbacks();
165 protected:
166 base::ScopedTempDir temp_dir_;
167 content::TestBrowserThreadBundle thread_bundle_;
168 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
169 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
170 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
171 FakeDownloadFeedbackFactory download_feedback_factory_;
174 TEST_F(DownloadFeedbackServiceTest, MaybeStorePingsForDownload) {
175 const int64 ok_size = DownloadFeedback::kMaxUploadSize;
176 const int64 bad_size = DownloadFeedback::kMaxUploadSize + 1;
178 EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, ok_size));
179 EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, ok_size));
180 EXPECT_TRUE(WillStorePings(DownloadProtectionService::UNCOMMON, ok_size));
181 EXPECT_TRUE(
182 WillStorePings(DownloadProtectionService::DANGEROUS_HOST, ok_size));
184 EXPECT_FALSE(WillStorePings(DownloadProtectionService::SAFE, bad_size));
185 EXPECT_FALSE(WillStorePings(DownloadProtectionService::DANGEROUS, bad_size));
186 EXPECT_FALSE(WillStorePings(DownloadProtectionService::UNCOMMON, bad_size));
187 EXPECT_FALSE(
188 WillStorePings(DownloadProtectionService::DANGEROUS_HOST, bad_size));
191 TEST_F(DownloadFeedbackServiceTest, SingleFeedbackComplete) {
192 const base::FilePath file_path(CreateTestFile(0));
193 const std::string ping_request = "ping";
194 const std::string ping_response = "resp";
196 content::DownloadItem::AcquireFileCallback download_discarded_callback;
198 content::MockDownloadItem item;
199 EXPECT_CALL(item, GetDangerType())
200 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
201 EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(1000));
202 EXPECT_CALL(item, StealDangerousDownload(_))
203 .WillOnce(SaveArg<0>(&download_discarded_callback));
205 DownloadFeedbackService service(request_context_getter_.get(),
206 file_task_runner_.get());
207 service.MaybeStorePingsForDownload(
208 DownloadProtectionService::UNCOMMON, &item, ping_request, ping_response);
209 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item));
210 service.BeginFeedbackForDownload(&item);
211 ASSERT_FALSE(download_discarded_callback.is_null());
212 EXPECT_EQ(0U, num_feedbacks());
214 download_discarded_callback.Run(file_path);
215 ASSERT_EQ(1U, num_feedbacks());
216 ASSERT_TRUE(feedback(0));
217 EXPECT_TRUE(feedback(0)->start_called());
218 EXPECT_EQ(ping_request, feedback(0)->GetPingRequestForTesting());
219 EXPECT_EQ(ping_response, feedback(0)->GetPingResponseForTesting());
221 feedback(0)->finish_callback().Run();
222 EXPECT_FALSE(feedback(0));
224 // File should still exist since our FakeDownloadFeedback does not delete it.
225 base::RunLoop().RunUntilIdle();
226 EXPECT_TRUE(base::PathExists(file_path));
229 TEST_F(DownloadFeedbackServiceTest, MultiplePendingFeedbackComplete) {
230 const std::string ping_request = "ping";
231 const std::string ping_response = "resp";
232 const size_t num_downloads = 3;
234 content::DownloadItem::AcquireFileCallback
235 download_discarded_callback[num_downloads];
237 base::FilePath file_path[num_downloads];
238 content::MockDownloadItem item[num_downloads];
239 for (size_t i = 0; i < num_downloads; ++i) {
240 file_path[i] = CreateTestFile(i);
241 EXPECT_CALL(item[i], GetDangerType())
242 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
243 EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000));
244 EXPECT_CALL(item[i], StealDangerousDownload(_))
245 .WillOnce(SaveArg<0>(&download_discarded_callback[i]));
246 DownloadFeedbackService::MaybeStorePingsForDownload(
247 DownloadProtectionService::UNCOMMON, &item[i], ping_request,
248 ping_response);
249 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i]));
253 DownloadFeedbackService service(request_context_getter_.get(),
254 file_task_runner_.get());
255 for (size_t i = 0; i < num_downloads; ++i) {
256 SCOPED_TRACE(i);
257 service.BeginFeedbackForDownload(&item[i]);
258 ASSERT_FALSE(download_discarded_callback[i].is_null());
260 EXPECT_EQ(0U, num_feedbacks());
262 for (size_t i = 0; i < num_downloads; ++i) {
263 download_discarded_callback[i].Run(file_path[i]);
266 ASSERT_EQ(3U, num_feedbacks());
267 EXPECT_TRUE(feedback(0)->start_called());
268 EXPECT_FALSE(feedback(1)->start_called());
269 EXPECT_FALSE(feedback(2)->start_called());
271 feedback(0)->finish_callback().Run();
273 EXPECT_FALSE(feedback(0));
274 EXPECT_TRUE(feedback(1)->start_called());
275 EXPECT_FALSE(feedback(2)->start_called());
277 feedback(1)->finish_callback().Run();
279 EXPECT_FALSE(feedback(0));
280 EXPECT_FALSE(feedback(1));
281 EXPECT_TRUE(feedback(2)->start_called());
283 feedback(2)->finish_callback().Run();
285 EXPECT_FALSE(feedback(0));
286 EXPECT_FALSE(feedback(1));
287 EXPECT_FALSE(feedback(2));
290 base::RunLoop().RunUntilIdle();
291 // These files should still exist since the FakeDownloadFeedback does not
292 // delete them.
293 EXPECT_TRUE(base::PathExists(file_path[0]));
294 EXPECT_TRUE(base::PathExists(file_path[1]));
295 EXPECT_TRUE(base::PathExists(file_path[2]));
298 TEST_F(DownloadFeedbackServiceTest, MultiFeedbackWithIncomplete) {
299 const std::string ping_request = "ping";
300 const std::string ping_response = "resp";
301 const size_t num_downloads = 3;
303 content::DownloadItem::AcquireFileCallback
304 download_discarded_callback[num_downloads];
306 base::FilePath file_path[num_downloads];
307 content::MockDownloadItem item[num_downloads];
308 for (size_t i = 0; i < num_downloads; ++i) {
309 file_path[i] = CreateTestFile(i);
310 EXPECT_CALL(item[i], GetDangerType())
311 .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT));
312 EXPECT_CALL(item[i], GetReceivedBytes()).WillRepeatedly(Return(1000));
313 EXPECT_CALL(item[i], StealDangerousDownload(_))
314 .WillOnce(SaveArg<0>(&download_discarded_callback[i]));
315 DownloadFeedbackService::MaybeStorePingsForDownload(
316 DownloadProtectionService::UNCOMMON, &item[i], ping_request,
317 ping_response);
318 ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item[i]));
322 DownloadFeedbackService service(request_context_getter_.get(),
323 file_task_runner_.get());
324 for (size_t i = 0; i < num_downloads; ++i) {
325 SCOPED_TRACE(i);
326 service.BeginFeedbackForDownload(&item[i]);
327 ASSERT_FALSE(download_discarded_callback[i].is_null());
329 EXPECT_EQ(0U, num_feedbacks());
331 download_discarded_callback[0].Run(file_path[0]);
332 ASSERT_EQ(1U, num_feedbacks());
333 ASSERT_TRUE(feedback(0));
334 EXPECT_TRUE(feedback(0)->start_called());
336 download_discarded_callback[1].Run(file_path[1]);
337 ASSERT_EQ(2U, num_feedbacks());
338 ASSERT_TRUE(feedback(1));
339 EXPECT_FALSE(feedback(1)->start_called());
341 feedback(0)->finish_callback().Run();
342 EXPECT_FALSE(feedback(0));
343 EXPECT_TRUE(feedback(1)->start_called());
346 EXPECT_EQ(2U, num_feedbacks());
347 for (size_t i = 0; i < num_feedbacks(); ++i) {
348 SCOPED_TRACE(i);
349 EXPECT_FALSE(feedback(i));
352 // Running a download acquired callback after the DownloadFeedbackService is
353 // destroyed should delete the file.
354 download_discarded_callback[2].Run(file_path[2]);
355 EXPECT_EQ(2U, num_feedbacks());
357 // File should still exist since the FileUtilProxy task hasn't run yet.
358 EXPECT_TRUE(base::PathExists(file_path[2]));
360 base::RunLoop().RunUntilIdle();
361 // File should be deleted since the AcquireFileCallback ran after the service
362 // was deleted.
363 EXPECT_FALSE(base::PathExists(file_path[2]));
365 // These files should still exist since the FakeDownloadFeedback does not
366 // delete them.
367 EXPECT_TRUE(base::PathExists(file_path[0]));
368 EXPECT_TRUE(base::PathExists(file_path[1]));
371 } // namespace safe_browsing