privet_url_fetcher_unittest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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/local_discovery/privet_url_fetcher.h"
6#include "net/url_request/test_url_fetcher_factory.h"
7#include "net/url_request/url_request_test_util.h"
8#include "testing/gmock/include/gmock/gmock.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11using testing::StrictMock;
12
13namespace local_discovery {
14
15namespace {
16
17const char kSamplePrivetURL[] =
18    "http://10.0.0.8:7676/privet/register?action=start";
19const char kSamplePrivetToken[] = "MyToken";
20const char kEmptyPrivetToken[] = "\"\"";
21
22const char kSampleParsableJSON[] = "{ \"hello\" : 2 }";
23const char kSampleUnparsableJSON[] = "{ \"hello\" : }";
24const char kSampleJSONWithError[] = "{ \"error\" : \"unittest_example\" }";
25
26class MockPrivetURLFetcherDelegate : public PrivetURLFetcher::Delegate {
27 public:
28  MockPrivetURLFetcherDelegate() : raw_mode_(false) {
29  }
30
31  virtual ~MockPrivetURLFetcherDelegate() {
32  }
33
34  virtual void OnError(PrivetURLFetcher* fetcher,
35                       PrivetURLFetcher::ErrorType error) OVERRIDE {
36    OnErrorInternal(error);
37  }
38
39  MOCK_METHOD1(OnErrorInternal, void(PrivetURLFetcher::ErrorType error));
40
41  virtual void OnParsedJson(PrivetURLFetcher* fetcher,
42                            const base::DictionaryValue& value,
43                            bool has_error) OVERRIDE {
44    saved_value_.reset(value.DeepCopy());
45    OnParsedJsonInternal(has_error);
46  }
47
48  MOCK_METHOD1(OnParsedJsonInternal, void(bool has_error));
49
50  virtual void OnNeedPrivetToken(
51      PrivetURLFetcher* fetcher,
52      const PrivetURLFetcher::TokenCallback& callback) {
53  }
54
55  bool OnRawData(PrivetURLFetcher* fetcher,
56                 bool response_is_file,
57                 const std::string& data,
58                 const base::FilePath& response_file) {
59    if (!raw_mode_) return false;
60
61    if (response_is_file) {
62      EXPECT_TRUE(response_file != base::FilePath());
63      OnFileInternal();
64    } else {
65      OnRawDataInternal(data);
66    }
67
68    return true;
69  }
70
71  MOCK_METHOD1(OnRawDataInternal, void(std::string data));
72
73  MOCK_METHOD0(OnFileInternal, void());
74
75  const base::DictionaryValue* saved_value() { return saved_value_.get(); }
76
77  void SetRawMode(bool raw_mode) {
78    raw_mode_ = raw_mode;
79  }
80
81 private:
82  scoped_ptr<base::DictionaryValue> saved_value_;
83  bool raw_mode_;
84};
85
86class PrivetURLFetcherTest : public ::testing::Test {
87 public:
88  PrivetURLFetcherTest() {
89    request_context_= new net::TestURLRequestContextGetter(
90        base::MessageLoopProxy::current());
91    privet_urlfetcher_.reset(new PrivetURLFetcher(
92        GURL(kSamplePrivetURL),
93        net::URLFetcher::POST,
94        request_context_.get(),
95        &delegate_));
96
97    PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL).GetOrigin().spec(),
98                                      kSamplePrivetToken);
99  }
100  virtual ~PrivetURLFetcherTest() {
101  }
102
103  void RunFor(base::TimeDelta time_period) {
104    base::CancelableCallback<void()> callback(base::Bind(
105        &PrivetURLFetcherTest::Stop, base::Unretained(this)));
106    base::MessageLoop::current()->PostDelayedTask(
107        FROM_HERE, callback.callback(), time_period);
108
109    base::MessageLoop::current()->Run();
110    callback.Cancel();
111  }
112
113  void Stop() {
114    base::MessageLoop::current()->Quit();
115  }
116
117 protected:
118  base::MessageLoop loop_;
119  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
120  net::TestURLFetcherFactory fetcher_factory_;
121  scoped_ptr<PrivetURLFetcher> privet_urlfetcher_;
122  StrictMock<MockPrivetURLFetcherDelegate> delegate_;
123};
124
125TEST_F(PrivetURLFetcherTest, FetchSuccess) {
126  privet_urlfetcher_->Start();
127  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
128  ASSERT_TRUE(fetcher != NULL);
129  fetcher->SetResponseString(kSampleParsableJSON);
130  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
131                                            net::OK));
132  fetcher->set_response_code(200);
133
134  EXPECT_CALL(delegate_, OnParsedJsonInternal(false));
135  fetcher->delegate()->OnURLFetchComplete(fetcher);
136
137  const base::DictionaryValue* value = delegate_.saved_value();
138  int hello_value;
139  ASSERT_TRUE(value != NULL);
140  ASSERT_TRUE(value->GetInteger("hello", &hello_value));
141  EXPECT_EQ(2, hello_value);
142}
143
144TEST_F(PrivetURLFetcherTest, HTTP503Retry) {
145  privet_urlfetcher_->Start();
146  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
147  ASSERT_TRUE(fetcher != NULL);
148  fetcher->SetResponseString(kSampleParsableJSON);
149  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
150                                            net::OK));
151  fetcher->set_response_code(503);
152
153  fetcher->delegate()->OnURLFetchComplete(fetcher);
154
155  RunFor(base::TimeDelta::FromSeconds(7));
156  fetcher = fetcher_factory_.GetFetcherByID(0);
157
158  ASSERT_TRUE(fetcher != NULL);
159  fetcher->SetResponseString(kSampleParsableJSON);
160  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
161                                            net::OK));
162  fetcher->set_response_code(200);
163
164  EXPECT_CALL(delegate_, OnParsedJsonInternal(false));
165  fetcher->delegate()->OnURLFetchComplete(fetcher);
166}
167
168TEST_F(PrivetURLFetcherTest, ResponseCodeError) {
169  privet_urlfetcher_->Start();
170  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
171  ASSERT_TRUE(fetcher != NULL);
172  fetcher->SetResponseString(kSampleParsableJSON);
173  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
174                                            net::OK));
175  fetcher->set_response_code(404);
176
177  EXPECT_CALL(delegate_,
178              OnErrorInternal(PrivetURLFetcher::RESPONSE_CODE_ERROR));
179  fetcher->delegate()->OnURLFetchComplete(fetcher);
180}
181
182TEST_F(PrivetURLFetcherTest, JsonParseError) {
183  privet_urlfetcher_->Start();
184  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
185  ASSERT_TRUE(fetcher != NULL);
186  fetcher->SetResponseString(kSampleUnparsableJSON);
187  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
188                                            net::OK));
189  fetcher->set_response_code(200);
190
191  EXPECT_CALL(delegate_,
192              OnErrorInternal(PrivetURLFetcher::JSON_PARSE_ERROR));
193  fetcher->delegate()->OnURLFetchComplete(fetcher);
194}
195
196TEST_F(PrivetURLFetcherTest, Header) {
197  privet_urlfetcher_->Start();
198  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
199  ASSERT_TRUE(fetcher != NULL);
200  net::HttpRequestHeaders headers;
201  fetcher->GetExtraRequestHeaders(&headers);
202
203  std::string header_token;
204  ASSERT_TRUE(headers.GetHeader("X-Privet-Token", &header_token));
205  EXPECT_EQ(kSamplePrivetToken, header_token);
206}
207
208TEST_F(PrivetURLFetcherTest, Header2) {
209  PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL).GetOrigin().spec(),
210                                    "");
211
212  privet_urlfetcher_->SendEmptyPrivetToken();
213  privet_urlfetcher_->Start();
214
215  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
216  ASSERT_TRUE(fetcher != NULL);
217  net::HttpRequestHeaders headers;
218  fetcher->GetExtraRequestHeaders(&headers);
219
220  std::string header_token;
221  ASSERT_TRUE(headers.GetHeader("X-Privet-Token", &header_token));
222  EXPECT_EQ(kEmptyPrivetToken, header_token);
223}
224
225TEST_F(PrivetURLFetcherTest, AlwaysSendEmpty) {
226  PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL).GetOrigin().spec(),
227                                    "SampleToken");
228
229  privet_urlfetcher_->SendEmptyPrivetToken();
230  privet_urlfetcher_->Start();
231
232  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
233  ASSERT_TRUE(fetcher != NULL);
234  net::HttpRequestHeaders headers;
235  fetcher->GetExtraRequestHeaders(&headers);
236
237  std::string header_token;
238  ASSERT_TRUE(headers.GetHeader("X-Privet-Token", &header_token));
239  EXPECT_EQ(kEmptyPrivetToken, header_token);
240}
241
242TEST_F(PrivetURLFetcherTest, FetchHasError) {
243  privet_urlfetcher_->Start();
244  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
245  ASSERT_TRUE(fetcher != NULL);
246  fetcher->SetResponseString(kSampleJSONWithError);
247  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
248                                            net::OK));
249  fetcher->set_response_code(200);
250
251  EXPECT_CALL(delegate_, OnParsedJsonInternal(true));
252  fetcher->delegate()->OnURLFetchComplete(fetcher);
253}
254
255TEST_F(PrivetURLFetcherTest, FetcherRawData) {
256  delegate_.SetRawMode(true);
257  privet_urlfetcher_->Start();
258  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
259  ASSERT_TRUE(fetcher != NULL);
260  fetcher->SetResponseString(kSampleJSONWithError);
261  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
262                                            net::OK));
263  fetcher->set_response_code(200);
264
265  EXPECT_CALL(delegate_, OnRawDataInternal(kSampleJSONWithError));
266  fetcher->delegate()->OnURLFetchComplete(fetcher);
267}
268
269TEST_F(PrivetURLFetcherTest, RangeRequest) {
270  delegate_.SetRawMode(true);
271  privet_urlfetcher_->SetByteRange(200, 300);
272  privet_urlfetcher_->Start();
273  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
274  ASSERT_TRUE(fetcher != NULL);
275  net::HttpRequestHeaders headers;
276  fetcher->GetExtraRequestHeaders(&headers);
277
278  std::string header_range;
279  ASSERT_TRUE(headers.GetHeader("Range", &header_range));
280  EXPECT_EQ("bytes=200-300", header_range);
281}
282
283TEST_F(PrivetURLFetcherTest, FetcherToFile) {
284  delegate_.SetRawMode(true);
285  privet_urlfetcher_->SaveResponseToFile();
286  privet_urlfetcher_->Start();
287  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
288  ASSERT_TRUE(fetcher != NULL);
289  fetcher->SetResponseFilePath(
290      base::FilePath(FILE_PATH_LITERAL("sample/file")));
291  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
292                                            net::OK));
293  fetcher->set_response_code(200);
294
295  EXPECT_CALL(delegate_, OnFileInternal());
296  fetcher->delegate()->OnURLFetchComplete(fetcher);
297}
298
299}  // namespace
300
301}  // namespace local_discovery
302