// Copyright 2015 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 "components/sync_driver/sync_stopped_reporter.h" #include #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/non_thread_safe.h" #include "net/http/http_status_code.h" #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_request_test_util.h" #include "sync/protocol/sync.pb.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" using browser_sync::SyncStoppedReporter; const char kTestURL[] = "http://chromium.org/test"; const char kTestURLTrailingSlash[] = "http://chromium.org/test/"; const char kEventURL[] = "http://chromium.org/test/event"; const char kTestUserAgent[] = "the_fifth_element"; const char kAuthToken[] = "multipass"; const char kCacheGuid[] = "leeloo"; const char kBirthday[] = "2263"; const char kAuthHeaderPrefix[] = "Bearer "; class SyncStoppedReporterTest : public testing::Test { public: SyncStoppedReporterTest() {} ~SyncStoppedReporterTest() override {} void SetUp() override { request_context_ = new net::TestURLRequestContextGetter( message_loop_.task_runner()); } void RequestFinishedCallback(const SyncStoppedReporter::Result& result) { request_result_ = result; } GURL test_url() { return GURL(kTestURL); } std::string user_agent() const { return std::string(kTestUserAgent); } SyncStoppedReporter::ResultCallback callback() { return base::Bind(&SyncStoppedReporterTest::RequestFinishedCallback, base::Unretained(this)); } const SyncStoppedReporter::Result& request_result() const { return request_result_; } net::URLRequestContextGetter* request_context() { return request_context_.get(); } private: base::MessageLoop message_loop_; scoped_refptr request_context_; SyncStoppedReporter::Result request_result_; DISALLOW_COPY_AND_ASSIGN(SyncStoppedReporterTest); }; // Test that the event URL gets constructed correctly. TEST_F(SyncStoppedReporterTest, EventURL) { net::TestURLFetcherFactory factory; SyncStoppedReporter ssr(GURL(kTestURL), user_agent(), request_context(), callback()); ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); EXPECT_EQ(kEventURL, fetcher->GetOriginalURL().spec()); } // Test that the event URL gets constructed correctly with a trailing slash. TEST_F(SyncStoppedReporterTest, EventURLWithSlash) { net::TestURLFetcherFactory factory; SyncStoppedReporter ssr(GURL(kTestURLTrailingSlash), user_agent(), request_context(), callback()); ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); EXPECT_EQ(kEventURL, fetcher->GetOriginalURL().spec()); } // Test that the URLFetcher gets configured correctly. TEST_F(SyncStoppedReporterTest, FetcherConfiguration) { net::TestURLFetcherFactory factory; SyncStoppedReporter ssr(test_url(), user_agent(), request_context(), callback()); ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); // Ensure the headers are set correctly. net::HttpRequestHeaders headers; std::string header; fetcher->GetExtraRequestHeaders(&headers); headers.GetHeader(net::HttpRequestHeaders::kAuthorization, &header); std::string auth_header(kAuthHeaderPrefix); auth_header.append(kAuthToken); EXPECT_EQ(auth_header, header); headers.GetHeader(net::HttpRequestHeaders::kUserAgent, &header); EXPECT_EQ(user_agent(), header); sync_pb::EventRequest event_request; event_request.ParseFromString(fetcher->upload_data()); EXPECT_EQ(kCacheGuid, event_request.sync_disabled().cache_guid()); EXPECT_EQ(kBirthday, event_request.sync_disabled().store_birthday()); EXPECT_EQ(kEventURL, fetcher->GetOriginalURL().spec()); } TEST_F(SyncStoppedReporterTest, HappyCase) { net::TestURLFetcherFactory factory; SyncStoppedReporter ssr(test_url(), user_agent(), request_context(), callback()); ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); fetcher->set_response_code(net::HTTP_OK); ssr.OnURLFetchComplete(fetcher); base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_EQ(SyncStoppedReporter::RESULT_SUCCESS, request_result()); } TEST_F(SyncStoppedReporterTest, ServerNotFound) { net::TestURLFetcherFactory factory; SyncStoppedReporter ssr(test_url(), user_agent(), request_context(), callback()); ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); fetcher->set_response_code(net::HTTP_NOT_FOUND); ssr.OnURLFetchComplete(fetcher); base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_EQ(SyncStoppedReporter::RESULT_ERROR, request_result()); } TEST_F(SyncStoppedReporterTest, DestructionDuringRequestHandler) { net::TestURLFetcherFactory factory; factory.set_remove_fetcher_on_delete(true); { SyncStoppedReporter ssr(test_url(), user_agent(), request_context(), callback()); ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); EXPECT_FALSE(factory.GetFetcherByID(0) == nullptr); } EXPECT_TRUE(factory.GetFetcherByID(0) == nullptr); } TEST_F(SyncStoppedReporterTest, Timeout) { SyncStoppedReporter ssr(test_url(), user_agent(), request_context(), callback()); // A task runner that can trigger the timeout immediately. scoped_refptr task_runner( new base::TestSimpleTaskRunner()); ssr.SetTimerTaskRunnerForTest(task_runner); // Begin request. ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); // Trigger the timeout. ASSERT_TRUE(task_runner->HasPendingTask()); task_runner->RunPendingTasks(); base::RunLoop run_loop; run_loop.RunUntilIdle(); EXPECT_EQ(SyncStoppedReporter::RESULT_TIMEOUT, request_result()); } TEST_F(SyncStoppedReporterTest, NoCallback) { net::TestURLFetcherFactory factory; SyncStoppedReporter ssr(GURL(kTestURL), user_agent(), request_context(), SyncStoppedReporter::ResultCallback()); ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); fetcher->set_response_code(net::HTTP_OK); ssr.OnURLFetchComplete(fetcher); } TEST_F(SyncStoppedReporterTest, NoCallbackTimeout) { SyncStoppedReporter ssr(GURL(kTestURL), user_agent(), request_context(), SyncStoppedReporter::ResultCallback()); // A task runner that can trigger the timeout immediately. scoped_refptr task_runner( new base::TestSimpleTaskRunner()); ssr.SetTimerTaskRunnerForTest(task_runner); // Begin request. ssr.ReportSyncStopped(kAuthToken, kCacheGuid, kBirthday); // Trigger the timeout. ASSERT_TRUE(task_runner->HasPendingTask()); task_runner->RunPendingTasks(); }