// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/local_discovery/privet_url_fetcher.h" #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using testing::StrictMock; namespace local_discovery { namespace { const char kSamplePrivetURL[] = "http://10.0.0.8:7676/privet/register?action=start"; const char kSamplePrivetToken[] = "MyToken"; const char kEmptyPrivetToken[] = "\"\""; const char kSampleParsableJSON[] = "{ \"hello\" : 2 }"; const char kSampleUnparsableJSON[] = "{ \"hello\" : }"; const char kSampleJSONWithError[] = "{ \"error\" : \"unittest_example\" }"; class MockPrivetURLFetcherDelegate : public PrivetURLFetcher::Delegate { public: MockPrivetURLFetcherDelegate() : raw_mode_(false) { } virtual ~MockPrivetURLFetcherDelegate() { } virtual void OnError(PrivetURLFetcher* fetcher, PrivetURLFetcher::ErrorType error) OVERRIDE { OnErrorInternal(error); } MOCK_METHOD1(OnErrorInternal, void(PrivetURLFetcher::ErrorType error)); virtual void OnParsedJson(PrivetURLFetcher* fetcher, const base::DictionaryValue* value, bool has_error) OVERRIDE { saved_value_.reset(value->DeepCopy()); OnParsedJsonInternal(has_error); } MOCK_METHOD1(OnParsedJsonInternal, void(bool has_error)); virtual void OnNeedPrivetToken( PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) { } bool OnRawData(PrivetURLFetcher* fetcher, bool response_is_file, const std::string& data, const base::FilePath& response_file) { if (!raw_mode_) return false; if (response_is_file) { EXPECT_TRUE(response_file != base::FilePath()); OnFileInternal(); } else { OnRawDataInternal(data); } return true; } MOCK_METHOD1(OnRawDataInternal, void(std::string data)); MOCK_METHOD0(OnFileInternal, void()); const base::DictionaryValue* saved_value() { return saved_value_.get(); } void SetRawMode(bool raw_mode) { raw_mode_ = raw_mode; } private: scoped_ptr saved_value_; bool raw_mode_; }; class PrivetURLFetcherTest : public ::testing::Test { public: PrivetURLFetcherTest() { request_context_= new net::TestURLRequestContextGetter( base::MessageLoopProxy::current()); privet_urlfetcher_.reset(new PrivetURLFetcher( GURL(kSamplePrivetURL), net::URLFetcher::POST, request_context_.get(), &delegate_)); PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL).GetOrigin().spec(), kSamplePrivetToken); } virtual ~PrivetURLFetcherTest() { } void RunFor(base::TimeDelta time_period) { base::CancelableCallback callback(base::Bind( &PrivetURLFetcherTest::Stop, base::Unretained(this))); base::MessageLoop::current()->PostDelayedTask( FROM_HERE, callback.callback(), time_period); base::MessageLoop::current()->Run(); callback.Cancel(); } void Stop() { base::MessageLoop::current()->Quit(); } protected: base::MessageLoop loop_; scoped_refptr request_context_; net::TestURLFetcherFactory fetcher_factory_; scoped_ptr privet_urlfetcher_; StrictMock delegate_; }; TEST_F(PrivetURLFetcherTest, FetchSuccess) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(200); EXPECT_CALL(delegate_, OnParsedJsonInternal(false)); fetcher->delegate()->OnURLFetchComplete(fetcher); const base::DictionaryValue* value = delegate_.saved_value(); int hello_value; ASSERT_TRUE(value != NULL); ASSERT_TRUE(value->GetInteger("hello", &hello_value)); EXPECT_EQ(2, hello_value); } TEST_F(PrivetURLFetcherTest, HTTP503Retry) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(503); fetcher->delegate()->OnURLFetchComplete(fetcher); RunFor(base::TimeDelta::FromSeconds(7)); fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(200); EXPECT_CALL(delegate_, OnParsedJsonInternal(false)); fetcher->delegate()->OnURLFetchComplete(fetcher); } TEST_F(PrivetURLFetcherTest, ResponseCodeError) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(404); EXPECT_CALL(delegate_, OnErrorInternal(PrivetURLFetcher::RESPONSE_CODE_ERROR)); fetcher->delegate()->OnURLFetchComplete(fetcher); } TEST_F(PrivetURLFetcherTest, JsonParseError) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseString(kSampleUnparsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(200); EXPECT_CALL(delegate_, OnErrorInternal(PrivetURLFetcher::JSON_PARSE_ERROR)); fetcher->delegate()->OnURLFetchComplete(fetcher); } TEST_F(PrivetURLFetcherTest, Header) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); net::HttpRequestHeaders headers; fetcher->GetExtraRequestHeaders(&headers); std::string header_token; ASSERT_TRUE(headers.GetHeader("X-Privet-Token", &header_token)); EXPECT_EQ(kSamplePrivetToken, header_token); } TEST_F(PrivetURLFetcherTest, Header2) { PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL).GetOrigin().spec(), ""); privet_urlfetcher_->AllowEmptyPrivetToken(); privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); net::HttpRequestHeaders headers; fetcher->GetExtraRequestHeaders(&headers); std::string header_token; ASSERT_TRUE(headers.GetHeader("X-Privet-Token", &header_token)); EXPECT_EQ(kEmptyPrivetToken, header_token); } TEST_F(PrivetURLFetcherTest, FetchHasError) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseString(kSampleJSONWithError); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(200); EXPECT_CALL(delegate_, OnParsedJsonInternal(true)); fetcher->delegate()->OnURLFetchComplete(fetcher); } TEST_F(PrivetURLFetcherTest, FetcherRawData) { delegate_.SetRawMode(true); privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseString(kSampleJSONWithError); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(200); EXPECT_CALL(delegate_, OnRawDataInternal(kSampleJSONWithError)); fetcher->delegate()->OnURLFetchComplete(fetcher); } TEST_F(PrivetURLFetcherTest, RangeRequest) { delegate_.SetRawMode(true); privet_urlfetcher_->SetByteRange(200, 300); privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); net::HttpRequestHeaders headers; fetcher->GetExtraRequestHeaders(&headers); std::string header_range; ASSERT_TRUE(headers.GetHeader("Range", &header_range)); EXPECT_EQ("bytes=200-300", header_range); } TEST_F(PrivetURLFetcherTest, FetcherToFile) { delegate_.SetRawMode(true); privet_urlfetcher_->SaveResponseToFile(); privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher != NULL); fetcher->SetResponseFilePath( base::FilePath(FILE_PATH_LITERAL("sample/file"))); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(200); EXPECT_CALL(delegate_, OnFileInternal()); fetcher->delegate()->OnURLFetchComplete(fetcher); } } // namespace } // namespace local_discovery