Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / sync / notifier / gcm_network_channel_unittest.cc
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 "google_apis/gaia/google_service_auth_error.h"
7 #include "net/url_request/test_url_fetcher_factory.h"
8 #include "net/url_request/url_request_test_util.h"
9 #include "sync/notifier/gcm_network_channel.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace syncer {
13 namespace {
14
15 class TestGCMNetworkChannelDelegate : public GCMNetworkChannelDelegate {
16  public:
17   TestGCMNetworkChannelDelegate()
18       : register_call_count_(0) {}
19
20   virtual void RequestToken(RequestTokenCallback callback) OVERRIDE {
21     request_token_callback = callback;
22   }
23
24   virtual void InvalidateToken(const std::string& token) OVERRIDE {
25     invalidated_token = token;
26   }
27
28   virtual void Register(RegisterCallback callback) OVERRIDE {
29     ++register_call_count_;
30     register_callback = callback;
31   }
32
33   RequestTokenCallback request_token_callback;
34   std::string invalidated_token;
35   RegisterCallback register_callback;
36   int register_call_count_;
37 };
38
39 // Backoff policy for test. Run first 5 retries without delay.
40 const net::BackoffEntry::Policy kTestBackoffPolicy = {
41   // Number of initial errors (in sequence) to ignore before applying
42   // exponential back-off rules.
43   5,
44
45   // Initial delay for exponential back-off in ms.
46   2000, // 2 seconds.
47
48   // Factor by which the waiting time will be multiplied.
49   2,
50
51   // Fuzzing percentage. ex: 10% will spread requests randomly
52   // between 90%-100% of the calculated time.
53   0.2, // 20%.
54
55   // Maximum amount of time we are willing to delay our request in ms.
56   1000 * 3600 * 4, // 4 hours.
57
58   // Time to keep an entry from being discarded even when it
59   // has no significant state, -1 to never discard.
60   -1,
61
62   // Don't use initial delay unless the last request was an error.
63   false,
64 };
65
66 class TestGCMNetworkChannel : public GCMNetworkChannel {
67  public:
68   TestGCMNetworkChannel(
69       scoped_refptr<net::URLRequestContextGetter> request_context_getter,
70       scoped_ptr<GCMNetworkChannelDelegate> delegate)
71       :  GCMNetworkChannel(request_context_getter, delegate.Pass()) {
72     ResetRegisterBackoffEntryForTest(&kTestBackoffPolicy);
73   }
74 };
75
76 class GCMNetworkChannelTest
77     : public ::testing::Test,
78       public SyncNetworkChannel::Observer {
79  protected:
80   GCMNetworkChannelTest()
81       : delegate_(NULL),
82         url_fetchers_created_count_(0) {
83   }
84
85   virtual ~GCMNetworkChannelTest() {
86   }
87
88   virtual void SetUp() {
89     request_context_getter_ = new net::TestURLRequestContextGetter(
90         base::MessageLoopProxy::current());
91     // Ownership of delegate goes to GCNMentworkChannel but test needs pointer
92     // to it.
93     delegate_ = new TestGCMNetworkChannelDelegate();
94     scoped_ptr<GCMNetworkChannelDelegate> delegate(delegate_);
95     gcm_network_channel_.reset(new TestGCMNetworkChannel(
96         request_context_getter_,
97         delegate.Pass()));
98     gcm_network_channel_->AddObserver(this);
99     gcm_network_channel_->SetMessageReceiver(
100         invalidation::NewPermanentCallback(
101             this, &GCMNetworkChannelTest::OnIncomingMessage));
102     url_fetcher_factory_.reset(new net::FakeURLFetcherFactory(NULL,
103         base::Bind(&GCMNetworkChannelTest::CreateURLFetcher,
104             base::Unretained(this))));
105   }
106
107   virtual void TearDown() {
108     gcm_network_channel_->RemoveObserver(this);
109   }
110
111   virtual void OnNetworkChannelStateChanged(
112       InvalidatorState invalidator_state) OVERRIDE {
113   }
114
115   void OnIncomingMessage(std::string incoming_message) {
116   }
117
118   GCMNetworkChannel* network_channel() {
119     return gcm_network_channel_.get();
120   }
121
122   TestGCMNetworkChannelDelegate* delegate() {
123     return delegate_;
124   }
125
126   int url_fetchers_created_count() {
127     return url_fetchers_created_count_;
128   }
129
130   net::FakeURLFetcherFactory* url_fetcher_factory() {
131     return url_fetcher_factory_.get();
132   }
133
134   scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
135       const GURL& url,
136       net::URLFetcherDelegate* delegate,
137       const std::string& response_data,
138       net::HttpStatusCode response_code,
139       net::URLRequestStatus::Status status) {
140     ++url_fetchers_created_count_;
141     return scoped_ptr<net::FakeURLFetcher>(new net::FakeURLFetcher(
142         url, delegate, response_data, response_code, status));
143   }
144
145   void RunLoopUntilIdle() {
146     base::RunLoop run_loop;
147     run_loop.RunUntilIdle();
148   }
149
150  private:
151   base::MessageLoop message_loop_;
152   TestGCMNetworkChannelDelegate* delegate_;
153   scoped_ptr<GCMNetworkChannel> gcm_network_channel_;
154   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
155   scoped_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
156   int url_fetchers_created_count_;
157 };
158
159 TEST_F(GCMNetworkChannelTest, HappyCase) {
160   GURL url("http://invalid.url.com");
161   url_fetcher_factory()->SetFakeResponse(url, std::string(), net::HTTP_OK,
162                                          net::URLRequestStatus::SUCCESS);
163
164   // After construction GCMNetworkChannel should have called Register.
165   EXPECT_FALSE(delegate()->register_callback.is_null());
166   // Return valid registration id.
167   delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
168
169   network_channel()->SendMessage("abra.cadabra");
170   // SendMessage should have triggered RequestToken. No HTTP request should be
171   // started yet.
172   EXPECT_FALSE(delegate()->request_token_callback.is_null());
173   EXPECT_EQ(url_fetchers_created_count(), 0);
174   // Return valid access token. This should trigger HTTP request.
175   delegate()->request_token_callback.Run(
176       GoogleServiceAuthError::AuthErrorNone(), "access.token");
177   RunLoopUntilIdle();
178   EXPECT_EQ(url_fetchers_created_count(), 1);
179
180   // Return another access token. Message should be cleared by now and shouldn't
181   // be sent.
182   delegate()->request_token_callback.Run(
183       GoogleServiceAuthError::AuthErrorNone(), "access.token2");
184   RunLoopUntilIdle();
185   EXPECT_EQ(url_fetchers_created_count(), 1);
186 }
187
188 TEST_F(GCMNetworkChannelTest, FailedRegister) {
189   // After construction GCMNetworkChannel should have called Register.
190   EXPECT_FALSE(delegate()->register_callback.is_null());
191   EXPECT_EQ(1, delegate()->register_call_count_);
192   // Return transient error from Register call.
193   delegate()->register_callback.Run("", gcm::GCMClient::NETWORK_ERROR);
194   RunLoopUntilIdle();
195   // GcmNetworkChannel should have scheduled Register retry.
196   EXPECT_EQ(2, delegate()->register_call_count_);
197   // Return persistent error from Register call.
198   delegate()->register_callback.Run("", gcm::GCMClient::NOT_SIGNED_IN);
199   RunLoopUntilIdle();
200   // GcmNetworkChannel should give up trying.
201   EXPECT_EQ(2, delegate()->register_call_count_);
202
203   network_channel()->SendMessage("abra.cadabra");
204   // SendMessage shouldn't trigger RequestToken.
205   EXPECT_TRUE(delegate()->request_token_callback.is_null());
206   EXPECT_EQ(0, url_fetchers_created_count());
207 }
208
209 TEST_F(GCMNetworkChannelTest, RegisterFinishesAfterSendMessage) {
210   GURL url("http://invalid.url.com");
211   url_fetcher_factory()->SetFakeResponse(url, "", net::HTTP_OK,
212       net::URLRequestStatus::SUCCESS);
213
214   // After construction GCMNetworkChannel should have called Register.
215   EXPECT_FALSE(delegate()->register_callback.is_null());
216
217   network_channel()->SendMessage("abra.cadabra");
218   // SendMessage shouldn't trigger RequestToken.
219   EXPECT_TRUE(delegate()->request_token_callback.is_null());
220   EXPECT_EQ(url_fetchers_created_count(), 0);
221
222   // Return valid registration id.
223   delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
224
225   EXPECT_FALSE(delegate()->request_token_callback.is_null());
226   EXPECT_EQ(url_fetchers_created_count(), 0);
227   // Return valid access token. This should trigger HTTP request.
228   delegate()->request_token_callback.Run(
229       GoogleServiceAuthError::AuthErrorNone(), "access.token");
230   RunLoopUntilIdle();
231   EXPECT_EQ(url_fetchers_created_count(), 1);
232 }
233
234 TEST_F(GCMNetworkChannelTest, RequestTokenFailure) {
235   // After construction GCMNetworkChannel should have called Register.
236   EXPECT_FALSE(delegate()->register_callback.is_null());
237   // Return valid registration id.
238   delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
239
240   network_channel()->SendMessage("abra.cadabra");
241   // SendMessage should have triggered RequestToken. No HTTP request should be
242   // started yet.
243   EXPECT_FALSE(delegate()->request_token_callback.is_null());
244   EXPECT_EQ(url_fetchers_created_count(), 0);
245   // RequestToken returns failure.
246   delegate()->request_token_callback.Run(
247       GoogleServiceAuthError::FromConnectionError(1), "");
248
249   // Should be no HTTP requests.
250   EXPECT_EQ(url_fetchers_created_count(), 0);
251 }
252
253 TEST_F(GCMNetworkChannelTest, AuthErrorFromServer) {
254   // Setup fake response to return AUTH_ERROR.
255   GURL url("http://invalid.url.com");
256   url_fetcher_factory()->SetFakeResponse(url, "", net::HTTP_UNAUTHORIZED,
257       net::URLRequestStatus::SUCCESS);
258
259   // After construction GCMNetworkChannel should have called Register.
260   EXPECT_FALSE(delegate()->register_callback.is_null());
261   // Return valid registration id.
262   delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
263
264   network_channel()->SendMessage("abra.cadabra");
265   // SendMessage should have triggered RequestToken. No HTTP request should be
266   // started yet.
267   EXPECT_FALSE(delegate()->request_token_callback.is_null());
268   EXPECT_EQ(url_fetchers_created_count(), 0);
269   // Return valid access token. This should trigger HTTP request.
270   delegate()->request_token_callback.Run(
271       GoogleServiceAuthError::AuthErrorNone(), "access.token");
272   RunLoopUntilIdle();
273   EXPECT_EQ(url_fetchers_created_count(), 1);
274   EXPECT_EQ(delegate()->invalidated_token, "access.token");
275 }
276
277 // Following two tests are to check for memory leaks/crashes when Register and
278 // RequestToken don't complete by the teardown.
279 TEST_F(GCMNetworkChannelTest, RegisterNeverCompletes) {
280   network_channel()->SendMessage("abra.cadabra");
281   // Register should be called by now. Let's not complete and see what happens.
282   EXPECT_FALSE(delegate()->register_callback.is_null());
283 }
284
285 TEST_F(GCMNetworkChannelTest, RequestTokenNeverCompletes) {
286   network_channel()->SendMessage("abra.cadabra");
287   // Return valid registration id.
288   delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
289   // RequestToken should be called by now. Let's not complete and see what
290   // happens.
291   EXPECT_FALSE(delegate()->request_token_callback.is_null());
292 }
293
294 }  // namespace
295 }  // namespace syncer