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.
4
5#include "chrome/browser/safe_browsing/two_phase_uploader.h"
6
7#include "base/files/file_path.h"
8#include "base/message_loop/message_loop.h"
9#include "chrome/browser/safe_browsing/local_two_phase_testserver.h"
10#include "content/public/test/test_browser_thread_bundle.h"
11#include "content/public/test/test_utils.h"
12#include "net/base/net_errors.h"
13#include "net/url_request/url_fetcher.h"
14#include "net/url_request/url_request_test_util.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17using content::BrowserThread;
18using content::MessageLoopRunner;
19
20namespace {
21
22class Delegate {
23 public:
24  Delegate() : state_(TwoPhaseUploader::STATE_NONE) {
25  }
26
27  void ProgressCallback(int64 current, int64 total) {}
28
29  void FinishCallback(scoped_refptr<MessageLoopRunner> runner,
30                      TwoPhaseUploader::State state,
31                      int net_error,
32                      int response_code,
33                      const std::string& response) {
34    state_ = state;
35    net_error_ = net_error;
36    response_code_ = response_code;
37    response_ = response;
38    runner->Quit();
39  }
40
41  TwoPhaseUploader::State state_;
42  int net_error_;
43  int response_code_;
44  std::string response_;
45};
46
47base::FilePath GetTestFilePath() {
48  base::FilePath file_path;
49  PathService::Get(base::DIR_SOURCE_ROOT, &file_path);
50  file_path = file_path.Append(FILE_PATH_LITERAL("net"));
51  file_path = file_path.Append(FILE_PATH_LITERAL("data"));
52  file_path = file_path.Append(FILE_PATH_LITERAL("url_request_unittest"));
53  file_path = file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt"));
54  return file_path;
55}
56
57}  // namespace
58
59class TwoPhaseUploaderTest : public testing::Test {
60 public:
61  TwoPhaseUploaderTest()
62      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
63        url_request_context_getter_(new net::TestURLRequestContextGetter(
64            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) {
65  }
66
67 protected:
68  content::TestBrowserThreadBundle thread_bundle_;
69
70  scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
71};
72
73TEST_F(TwoPhaseUploaderTest, UploadFile) {
74  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
75  LocalTwoPhaseTestServer test_server;
76  ASSERT_TRUE(test_server.Start());
77  Delegate delegate;
78  scoped_ptr<TwoPhaseUploader> uploader(TwoPhaseUploader::Create(
79      url_request_context_getter_.get(),
80      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
81      test_server.GetURL("start"),
82      "metadata",
83      GetTestFilePath(),
84      base::Bind(&Delegate::ProgressCallback, base::Unretained(&delegate)),
85      base::Bind(
86          &Delegate::FinishCallback, base::Unretained(&delegate), runner)));
87  uploader->Start();
88  runner->Run();
89  EXPECT_EQ(TwoPhaseUploader::STATE_SUCCESS, delegate.state_);
90  EXPECT_EQ(net::OK, delegate.net_error_);
91  EXPECT_EQ(200, delegate.response_code_);
92  EXPECT_EQ(
93      "/start\n"                                     // path of start request
94      "4c24b2612e94e2ae622e54397663f2b7bf0a2e17\n"   // sha1sum of "metadata"
95      "944857cc626f2cafe232521986b4c6d3f9993c97\n",  // sha1sum of test file
96      delegate.response_);
97}
98
99TEST_F(TwoPhaseUploaderTest, BadPhaseOneResponse) {
100  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
101  LocalTwoPhaseTestServer test_server;
102  ASSERT_TRUE(test_server.Start());
103  Delegate delegate;
104  scoped_ptr<TwoPhaseUploader> uploader(TwoPhaseUploader::Create(
105      url_request_context_getter_.get(),
106      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
107      test_server.GetURL("start?p1code=500"),
108      "metadata",
109      GetTestFilePath(),
110      base::Bind(&Delegate::ProgressCallback, base::Unretained(&delegate)),
111      base::Bind(
112          &Delegate::FinishCallback, base::Unretained(&delegate), runner)));
113  uploader->Start();
114  runner->Run();
115  EXPECT_EQ(TwoPhaseUploader::UPLOAD_METADATA, delegate.state_);
116  EXPECT_EQ(net::OK, delegate.net_error_);
117  EXPECT_EQ(500, delegate.response_code_);
118  EXPECT_EQ("", delegate.response_);
119}
120
121TEST_F(TwoPhaseUploaderTest, BadPhaseTwoResponse) {
122  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
123  LocalTwoPhaseTestServer test_server;
124  ASSERT_TRUE(test_server.Start());
125  Delegate delegate;
126  scoped_ptr<TwoPhaseUploader> uploader(TwoPhaseUploader::Create(
127      url_request_context_getter_.get(),
128      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
129      test_server.GetURL("start?p2code=500"),
130      "metadata",
131      GetTestFilePath(),
132      base::Bind(&Delegate::ProgressCallback, base::Unretained(&delegate)),
133      base::Bind(
134          &Delegate::FinishCallback, base::Unretained(&delegate), runner)));
135  uploader->Start();
136  runner->Run();
137  EXPECT_EQ(TwoPhaseUploader::UPLOAD_FILE, delegate.state_);
138  EXPECT_EQ(net::OK, delegate.net_error_);
139  EXPECT_EQ(500, delegate.response_code_);
140  EXPECT_EQ(
141      "/start\n"                                     // path of start request
142      "4c24b2612e94e2ae622e54397663f2b7bf0a2e17\n"   // sha1sum of "metadata"
143      "944857cc626f2cafe232521986b4c6d3f9993c97\n",  // sha1sum of test file
144      delegate.response_);
145}
146
147TEST_F(TwoPhaseUploaderTest, PhaseOneConnectionClosed) {
148  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
149  LocalTwoPhaseTestServer test_server;
150  ASSERT_TRUE(test_server.Start());
151  Delegate delegate;
152  scoped_ptr<TwoPhaseUploader> uploader(TwoPhaseUploader::Create(
153      url_request_context_getter_.get(),
154      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
155      test_server.GetURL("start?p1close=1"),
156      "metadata",
157      GetTestFilePath(),
158      base::Bind(&Delegate::ProgressCallback, base::Unretained(&delegate)),
159      base::Bind(
160          &Delegate::FinishCallback, base::Unretained(&delegate), runner)));
161  uploader->Start();
162  runner->Run();
163  EXPECT_EQ(TwoPhaseUploader::UPLOAD_METADATA, delegate.state_);
164  EXPECT_EQ(net::ERR_EMPTY_RESPONSE, delegate.net_error_);
165  EXPECT_EQ(net::URLFetcher::RESPONSE_CODE_INVALID, delegate.response_code_);
166  EXPECT_EQ("", delegate.response_);
167}
168
169TEST_F(TwoPhaseUploaderTest, PhaseTwoConnectionClosed) {
170  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
171  LocalTwoPhaseTestServer test_server;
172  ASSERT_TRUE(test_server.Start());
173  Delegate delegate;
174  scoped_ptr<TwoPhaseUploader> uploader(TwoPhaseUploader::Create(
175      url_request_context_getter_.get(),
176      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
177      test_server.GetURL("start?p2close=1"),
178      "metadata",
179      GetTestFilePath(),
180      base::Bind(&Delegate::ProgressCallback, base::Unretained(&delegate)),
181      base::Bind(
182          &Delegate::FinishCallback, base::Unretained(&delegate), runner)));
183  uploader->Start();
184  runner->Run();
185  EXPECT_EQ(TwoPhaseUploader::UPLOAD_FILE, delegate.state_);
186  EXPECT_EQ(net::ERR_EMPTY_RESPONSE, delegate.net_error_);
187  EXPECT_EQ(net::URLFetcher::RESPONSE_CODE_INVALID, delegate.response_code_);
188  EXPECT_EQ("", delegate.response_);
189}
190