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 "base/location.h"
6 #include "base/single_thread_task_runner.h"
7 #include "base/thread_task_runner_handle.h"
8 #include "chrome/browser/local_discovery/privet_url_fetcher.h"
9 #include "net/url_request/test_url_fetcher_factory.h"
10 #include "net/url_request/url_request_test_util.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 using testing::StrictMock
;
16 namespace local_discovery
{
20 const char kSamplePrivetURL
[] =
21 "http://10.0.0.8:7676/privet/register?action=start";
22 const char kSamplePrivetToken
[] = "MyToken";
23 const char kEmptyPrivetToken
[] = "\"\"";
25 const char kSampleParsableJSON
[] = "{ \"hello\" : 2 }";
26 const char kSampleUnparsableJSON
[] = "{ \"hello\" : }";
27 const char kSampleJSONWithError
[] = "{ \"error\" : \"unittest_example\" }";
29 class MockPrivetURLFetcherDelegate
: public PrivetURLFetcher::Delegate
{
31 MockPrivetURLFetcherDelegate() : raw_mode_(false) {
34 ~MockPrivetURLFetcherDelegate() override
{
37 void OnError(PrivetURLFetcher
* fetcher
,
38 PrivetURLFetcher::ErrorType error
) override
{
39 OnErrorInternal(error
);
42 MOCK_METHOD1(OnErrorInternal
, void(PrivetURLFetcher::ErrorType error
));
44 void OnParsedJson(PrivetURLFetcher
* fetcher
,
45 const base::DictionaryValue
& value
,
46 bool has_error
) override
{
47 saved_value_
.reset(value
.DeepCopy());
48 OnParsedJsonInternal(has_error
);
51 MOCK_METHOD1(OnParsedJsonInternal
, void(bool has_error
));
53 virtual void OnNeedPrivetToken(
54 PrivetURLFetcher
* fetcher
,
55 const PrivetURLFetcher::TokenCallback
& callback
) {
58 bool OnRawData(PrivetURLFetcher
* fetcher
,
59 bool response_is_file
,
60 const std::string
& data
,
61 const base::FilePath
& response_file
) {
62 if (!raw_mode_
) return false;
64 if (response_is_file
) {
65 EXPECT_TRUE(response_file
!= base::FilePath());
68 OnRawDataInternal(data
);
74 MOCK_METHOD1(OnRawDataInternal
, void(std::string data
));
76 MOCK_METHOD0(OnFileInternal
, void());
78 const base::DictionaryValue
* saved_value() { return saved_value_
.get(); }
80 void SetRawMode(bool raw_mode
) {
84 std::string
GetAuthToken() { return "MyAuthToken"; }
87 scoped_ptr
<base::DictionaryValue
> saved_value_
;
91 class PrivetURLFetcherTest
: public ::testing::Test
{
93 PrivetURLFetcherTest() {
94 request_context_
= new net::TestURLRequestContextGetter(
95 base::ThreadTaskRunnerHandle::Get());
96 privet_urlfetcher_
.reset(new PrivetURLFetcher(
97 GURL(kSamplePrivetURL
),
98 net::URLFetcher::POST
,
99 request_context_
.get(),
102 PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL
).GetOrigin().spec(),
105 virtual ~PrivetURLFetcherTest() {
108 void RunFor(base::TimeDelta time_period
) {
109 base::CancelableCallback
<void()> callback(base::Bind(
110 &PrivetURLFetcherTest::Stop
, base::Unretained(this)));
111 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
112 FROM_HERE
, callback
.callback(), time_period
);
114 base::MessageLoop::current()->Run();
119 base::MessageLoop::current()->Quit();
123 base::MessageLoop loop_
;
124 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
125 net::TestURLFetcherFactory fetcher_factory_
;
126 scoped_ptr
<PrivetURLFetcher
> privet_urlfetcher_
;
127 StrictMock
<MockPrivetURLFetcherDelegate
> delegate_
;
130 TEST_F(PrivetURLFetcherTest
, FetchSuccess
) {
131 privet_urlfetcher_
->Start();
132 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
133 ASSERT_TRUE(fetcher
!= NULL
);
134 fetcher
->SetResponseString(kSampleParsableJSON
);
135 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
137 fetcher
->set_response_code(200);
139 EXPECT_CALL(delegate_
, OnParsedJsonInternal(false));
140 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
142 const base::DictionaryValue
* value
= delegate_
.saved_value();
144 ASSERT_TRUE(value
!= NULL
);
145 ASSERT_TRUE(value
->GetInteger("hello", &hello_value
));
146 EXPECT_EQ(2, hello_value
);
149 TEST_F(PrivetURLFetcherTest
, HTTP503Retry
) {
150 privet_urlfetcher_
->Start();
151 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
152 ASSERT_TRUE(fetcher
!= NULL
);
153 fetcher
->SetResponseString(kSampleParsableJSON
);
154 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
156 fetcher
->set_response_code(503);
158 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
160 RunFor(base::TimeDelta::FromSeconds(7));
161 fetcher
= fetcher_factory_
.GetFetcherByID(0);
163 ASSERT_TRUE(fetcher
!= NULL
);
164 fetcher
->SetResponseString(kSampleParsableJSON
);
165 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
167 fetcher
->set_response_code(200);
169 EXPECT_CALL(delegate_
, OnParsedJsonInternal(false));
170 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
173 TEST_F(PrivetURLFetcherTest
, ResponseCodeError
) {
174 privet_urlfetcher_
->Start();
175 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
176 ASSERT_TRUE(fetcher
!= NULL
);
177 fetcher
->SetResponseString(kSampleParsableJSON
);
178 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
180 fetcher
->set_response_code(404);
182 EXPECT_CALL(delegate_
,
183 OnErrorInternal(PrivetURLFetcher::RESPONSE_CODE_ERROR
));
184 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
187 TEST_F(PrivetURLFetcherTest
, JsonParseError
) {
188 privet_urlfetcher_
->Start();
189 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
190 ASSERT_TRUE(fetcher
!= NULL
);
191 fetcher
->SetResponseString(kSampleUnparsableJSON
);
192 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
194 fetcher
->set_response_code(200);
196 EXPECT_CALL(delegate_
,
197 OnErrorInternal(PrivetURLFetcher::JSON_PARSE_ERROR
));
198 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
201 TEST_F(PrivetURLFetcherTest
, Header
) {
202 privet_urlfetcher_
->Start();
203 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
204 ASSERT_TRUE(fetcher
!= NULL
);
205 net::HttpRequestHeaders headers
;
206 fetcher
->GetExtraRequestHeaders(&headers
);
208 std::string header_token
;
209 ASSERT_TRUE(headers
.GetHeader("X-Privet-Token", &header_token
));
210 EXPECT_EQ(kSamplePrivetToken
, header_token
);
213 TEST_F(PrivetURLFetcherTest
, Header2
) {
214 PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL
).GetOrigin().spec(),
217 privet_urlfetcher_
->SendEmptyPrivetToken();
218 privet_urlfetcher_
->Start();
220 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
221 ASSERT_TRUE(fetcher
!= NULL
);
222 net::HttpRequestHeaders headers
;
223 fetcher
->GetExtraRequestHeaders(&headers
);
225 std::string header_token
;
226 ASSERT_TRUE(headers
.GetHeader("X-Privet-Token", &header_token
));
227 EXPECT_EQ(kEmptyPrivetToken
, header_token
);
230 TEST_F(PrivetURLFetcherTest
, AlwaysSendEmpty
) {
231 PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL
).GetOrigin().spec(),
234 privet_urlfetcher_
->SendEmptyPrivetToken();
235 privet_urlfetcher_
->Start();
237 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
238 ASSERT_TRUE(fetcher
!= NULL
);
239 net::HttpRequestHeaders headers
;
240 fetcher
->GetExtraRequestHeaders(&headers
);
242 std::string header_token
;
243 ASSERT_TRUE(headers
.GetHeader("X-Privet-Token", &header_token
));
244 EXPECT_EQ(kEmptyPrivetToken
, header_token
);
247 TEST_F(PrivetURLFetcherTest
, FetchHasError
) {
248 privet_urlfetcher_
->Start();
249 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
250 ASSERT_TRUE(fetcher
!= NULL
);
251 fetcher
->SetResponseString(kSampleJSONWithError
);
252 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
254 fetcher
->set_response_code(200);
256 EXPECT_CALL(delegate_
, OnParsedJsonInternal(true));
257 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
260 TEST_F(PrivetURLFetcherTest
, FetcherRawData
) {
261 delegate_
.SetRawMode(true);
262 privet_urlfetcher_
->Start();
263 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
264 ASSERT_TRUE(fetcher
!= NULL
);
265 fetcher
->SetResponseString(kSampleJSONWithError
);
266 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
268 fetcher
->set_response_code(200);
270 EXPECT_CALL(delegate_
, OnRawDataInternal(kSampleJSONWithError
));
271 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
274 TEST_F(PrivetURLFetcherTest
, RangeRequest
) {
275 delegate_
.SetRawMode(true);
276 privet_urlfetcher_
->SetByteRange(200, 300);
277 privet_urlfetcher_
->Start();
278 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
279 ASSERT_TRUE(fetcher
!= NULL
);
280 net::HttpRequestHeaders headers
;
281 fetcher
->GetExtraRequestHeaders(&headers
);
283 std::string header_range
;
284 ASSERT_TRUE(headers
.GetHeader("Range", &header_range
));
285 EXPECT_EQ("bytes=200-300", header_range
);
288 TEST_F(PrivetURLFetcherTest
, FetcherToFile
) {
289 delegate_
.SetRawMode(true);
290 privet_urlfetcher_
->SaveResponseToFile();
291 privet_urlfetcher_
->Start();
292 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
293 ASSERT_TRUE(fetcher
!= NULL
);
294 fetcher
->SetResponseFilePath(
295 base::FilePath(FILE_PATH_LITERAL("sample/file")));
296 fetcher
->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS
,
298 fetcher
->set_response_code(200);
300 EXPECT_CALL(delegate_
, OnFileInternal());
301 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
304 TEST_F(PrivetURLFetcherTest
, V3Mode
) {
305 delegate_
.SetRawMode(true);
306 privet_urlfetcher_
->V3Mode();
307 privet_urlfetcher_
->Start();
308 net::TestURLFetcher
* fetcher
= fetcher_factory_
.GetFetcherByID(0);
309 ASSERT_TRUE(fetcher
!= NULL
);
310 fetcher
->SetResponseFilePath(
311 base::FilePath(FILE_PATH_LITERAL("sample/file")));
312 net::HttpRequestHeaders headers
;
313 fetcher
->GetExtraRequestHeaders(&headers
);
315 std::string header_token
;
316 ASSERT_FALSE(headers
.GetHeader("X-Privet-Token", &header_token
));
317 ASSERT_FALSE(headers
.GetHeader("X-Privet-Auth", &header_token
));
318 ASSERT_TRUE(headers
.GetHeader("Authorization", &header_token
));
319 ASSERT_EQ("MyAuthToken", header_token
);
324 } // namespace local_discovery