1 // Copyright 2014 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 "base/run_loop.h" 6 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" 7 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" 8 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 9 #include "chrome/test/base/testing_profile.h" 10 #include "components/gcm_driver/fake_gcm_driver.h" 11 #include "components/gcm_driver/gcm_driver.h" 12 #include "components/invalidation/gcm_invalidation_bridge.h" 13 #include "content/public/test/test_browser_thread_bundle.h" 14 #include "google_apis/gaia/fake_identity_provider.h" 15 #include "google_apis/gaia/google_service_auth_error.h" 16 #include "net/base/ip_endpoint.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace invalidation { 20 namespace { 21 22 // Implementation of GCMDriver::Register that always succeeds with the same 23 // registrationId. 24 class CustomFakeGCMDriver : public gcm::FakeGCMDriver { 25 public: 26 CustomFakeGCMDriver() {} 27 virtual ~CustomFakeGCMDriver() {} 28 29 protected: 30 // FakeGCMDriver override: 31 virtual void RegisterImpl( 32 const std::string& app_id, 33 const std::vector<std::string>& sender_ids) OVERRIDE { 34 base::MessageLoop::current()->PostTask( 35 FROM_HERE, 36 base::Bind(&CustomFakeGCMDriver::RegisterFinished, 37 base::Unretained(this), 38 app_id, 39 std::string("registration.id"), 40 gcm::GCMClient::SUCCESS)); 41 } 42 43 private: 44 DISALLOW_COPY_AND_ASSIGN(CustomFakeGCMDriver); 45 }; 46 47 class GCMInvalidationBridgeTest : public ::testing::Test { 48 protected: 49 GCMInvalidationBridgeTest() 50 : connection_online_(false) {} 51 52 virtual ~GCMInvalidationBridgeTest() {} 53 54 virtual void SetUp() OVERRIDE { 55 TestingProfile::Builder builder; 56 builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), 57 &BuildAutoIssuingFakeProfileOAuth2TokenService); 58 profile_ = builder.Build(); 59 60 FakeProfileOAuth2TokenService* token_service = 61 (FakeProfileOAuth2TokenService*) 62 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()); 63 token_service->IssueRefreshTokenForUser("", "fake_refresh_token"); 64 gcm_driver_.reset(new CustomFakeGCMDriver()); 65 66 identity_provider_.reset(new FakeIdentityProvider(token_service)); 67 bridge_.reset(new GCMInvalidationBridge(gcm_driver_.get(), 68 identity_provider_.get())); 69 70 delegate_ = bridge_->CreateDelegate(); 71 delegate_->Initialize( 72 base::Bind(&GCMInvalidationBridgeTest::ConnectionStateChanged, 73 base::Unretained(this))); 74 RunLoop(); 75 } 76 77 void RunLoop() { 78 base::RunLoop run_loop; 79 run_loop.RunUntilIdle(); 80 } 81 82 public: 83 void RegisterFinished(const std::string& registration_id, 84 gcm::GCMClient::Result result) { 85 registration_id_ = registration_id; 86 } 87 88 void RequestTokenFinished(const GoogleServiceAuthError& error, 89 const std::string& token) { 90 issued_tokens_.push_back(token); 91 request_token_errors_.push_back(error); 92 } 93 94 void ConnectionStateChanged(bool online) { 95 connection_online_ = online; 96 } 97 98 content::TestBrowserThreadBundle thread_bundle_; 99 scoped_ptr<Profile> profile_; 100 scoped_ptr<gcm::GCMDriver> gcm_driver_; 101 scoped_ptr<FakeIdentityProvider> identity_provider_; 102 103 std::vector<std::string> issued_tokens_; 104 std::vector<GoogleServiceAuthError> request_token_errors_; 105 std::string registration_id_; 106 bool connection_online_; 107 108 scoped_ptr<GCMInvalidationBridge> bridge_; 109 scoped_ptr<syncer::GCMNetworkChannelDelegate> delegate_; 110 }; 111 112 TEST_F(GCMInvalidationBridgeTest, RequestToken) { 113 // Make sure that call to RequestToken reaches OAuth2TokenService and gets 114 // back to callback. 115 delegate_->RequestToken( 116 base::Bind(&GCMInvalidationBridgeTest::RequestTokenFinished, 117 base::Unretained(this))); 118 RunLoop(); 119 EXPECT_EQ(1U, issued_tokens_.size()); 120 EXPECT_NE("", issued_tokens_[0]); 121 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), request_token_errors_[0]); 122 } 123 124 TEST_F(GCMInvalidationBridgeTest, RequestTokenTwoConcurrentRequests) { 125 // First call should finish with REQUEST_CANCELLED error. 126 delegate_->RequestToken( 127 base::Bind(&GCMInvalidationBridgeTest::RequestTokenFinished, 128 base::Unretained(this))); 129 // Second request should succeed. 130 delegate_->RequestToken( 131 base::Bind(&GCMInvalidationBridgeTest::RequestTokenFinished, 132 base::Unretained(this))); 133 RunLoop(); 134 135 EXPECT_EQ(2U, issued_tokens_.size()); 136 137 EXPECT_EQ("", issued_tokens_[0]); 138 EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED, 139 request_token_errors_[0].state()); 140 141 EXPECT_NE("", issued_tokens_[1]); 142 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), request_token_errors_[1]); 143 } 144 145 TEST_F(GCMInvalidationBridgeTest, Register) { 146 EXPECT_TRUE(registration_id_.empty()); 147 delegate_->Register(base::Bind(&GCMInvalidationBridgeTest::RegisterFinished, 148 base::Unretained(this))); 149 RunLoop(); 150 151 EXPECT_FALSE(registration_id_.empty()); 152 } 153 154 TEST_F(GCMInvalidationBridgeTest, ConnectionState) { 155 EXPECT_FALSE(connection_online_); 156 bridge_->OnConnected(net::IPEndPoint()); 157 RunLoop(); 158 EXPECT_TRUE(connection_online_); 159 bridge_->OnDisconnected(); 160 RunLoop(); 161 EXPECT_FALSE(connection_online_); 162 } 163 164 } // namespace 165 } // namespace invalidation 166