Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1870)

Side by Side Diff: google_apis/gcm/engine/connection_factory_impl_unittest.cc

Issue 54743007: [GCM] Add connection factory for creating MCS connections (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 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.
4
5 #include "google_apis/gcm/engine/connection_factory_impl.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/time/time.h"
10 #include "net/base/backoff_entry.h"
11 #include "net/http/http_network_session.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 class Policy;
15
16 namespace gcm {
17 namespace {
18
19 const char kMCSEndpoint[] = "http://my.server";
20
21 const int kBackoffDelayMs = 1;
22 const int kBackoffMultiplier = 2;
23
24 // A backoff policy with small enough delays that tests aren't burdened.
25 const net::BackoffEntry::Policy kTestBackoffPolicy = {
26 // Number of initial errors (in sequence) to ignore before applying
27 // exponential back-off rules.
28 0,
29
30 // Initial delay for exponential back-off in ms.
31 kBackoffDelayMs,
32
33 // Factor by which the waiting time will be multiplied.
34 kBackoffMultiplier,
35
36 // Fuzzing percentage. ex: 10% will spread requests randomly
37 // between 90%-100% of the calculated time.
38 0,
39
40 // Maximum amount of time we are willing to delay our request in ms.
41 10,
42
43 // Time to keep an entry from being discarded even when it
44 // has no significant state, -1 to never discard.
45 -1,
46
47 // Don't use initial delay unless the last request was an error.
48 false,
49 };
50
51 // Helper for calculating total expected exponential backoff delay given an
52 // arbitrary number of failed attempts. See BackoffEntry::CalculateReleaseTime.
53 int CalculateBackoff(int num_attempts) {
54 int delay = kBackoffDelayMs;
55 for (int i = 1; i < num_attempts; ++i) {
56 delay += kBackoffDelayMs*pow(kBackoffMultiplier, i - 1);
57 }
58 DVLOG(1) << "Expected backoff " << delay << " milliseconds.";
59 return delay;
60 }
61
62 // Helper methods that are never actually called due to real connections being
63 // stubbed out.
64 void ReadContinuation(
65 scoped_ptr<google::protobuf::MessageLite> message) {
66 // Do nothing.
akalin 2013/11/21 04:13:09 if they aren't called, perhaps ADD_FAILURE() to as
Nicolas Zea 2013/11/22 05:39:18 Done.
67 }
68 void WriteContinuation() {
akalin 2013/11/21 04:13:09 newline before
Nicolas Zea 2013/11/22 05:39:18 Done.
69 // Do nothing.
70 }
71
72 // A connection factory that stubs out network requests and overrides the
73 // backoff policy.
74 class TestConnectionFactoryImpl : public ConnectionFactoryImpl {
75 public:
76 TestConnectionFactoryImpl(const base::Closure& finished_callback);
77 virtual ~TestConnectionFactoryImpl();
78
79 // Overridden stubs.
80 virtual void ConnectImpl() OVERRIDE;
81 virtual void InitHandler() OVERRIDE;
82 virtual scoped_ptr<net::BackoffEntry> CreateBackoffEntry(
83 const net::BackoffEntry::Policy* const policy) OVERRIDE;
84
85 // Helpers for verifying connection attempts are made. Connection results
86 // must be consumed.
87 void SetConnectResult(int connect_result);
88 void SetMultipleConnectResults(int connect_result, int num_expected_attempts);
89
90 private:
91 // The result to return on the next connect attempt.
92 int connect_result_;
93 // The number of expected connection attempts;
94 int num_expected_attempts_;
95 // Whether all expected connection attempts have been fulfilled since an
96 // expectation was last set.
97 bool connections_fulfilled_;
98 // Callback to invoke when all connection attempts have been made.
99 base::Closure finished_callback_;
100 };
101
102 TestConnectionFactoryImpl::TestConnectionFactoryImpl(
103 const base::Closure& finished_callback)
104 : ConnectionFactoryImpl(GURL(kMCSEndpoint), NULL, NULL),
105 connect_result_(net::ERR_UNEXPECTED),
106 num_expected_attempts_(0),
107 connections_fulfilled_(true),
108 finished_callback_(finished_callback) {
109 }
110
111 TestConnectionFactoryImpl::~TestConnectionFactoryImpl() {
112 EXPECT_EQ(0, num_expected_attempts_);
113 }
114
115 void TestConnectionFactoryImpl::ConnectImpl() {
116 ASSERT_GT(num_expected_attempts_, 0);
117
118 OnConnectDone(connect_result_);
119 --num_expected_attempts_;
120 if (num_expected_attempts_ == 0) {
121 connect_result_ = net::ERR_UNEXPECTED;
122 connections_fulfilled_ = true;
123 finished_callback_.Run();
124 }
125 }
126
127 void TestConnectionFactoryImpl::InitHandler() {
128 EXPECT_NE(connect_result_, net::ERR_UNEXPECTED);
129 }
130
131 scoped_ptr<net::BackoffEntry> TestConnectionFactoryImpl::CreateBackoffEntry(
132 const net::BackoffEntry::Policy* const policy) {
133 return scoped_ptr<net::BackoffEntry>(
134 new net::BackoffEntry(&kTestBackoffPolicy));
135 }
136
137 void TestConnectionFactoryImpl::SetConnectResult(int connect_result) {
138 DCHECK_NE(connect_result, net::ERR_UNEXPECTED);
139 ASSERT_EQ(0, num_expected_attempts_);
140 connections_fulfilled_ = false;
141 connect_result_ = connect_result;
142 num_expected_attempts_ = 1;
143 }
144
145 void TestConnectionFactoryImpl::SetMultipleConnectResults(
146 int connect_result,
147 int num_expected_attempts) {
148 DCHECK_NE(connect_result, net::ERR_UNEXPECTED);
149 DCHECK_GT(num_expected_attempts, 0);
150 ASSERT_EQ(0, num_expected_attempts_);
151 connections_fulfilled_ = false;
152 connect_result_ = connect_result;
153 num_expected_attempts_ = num_expected_attempts;
154 }
155
156 class ConnectionFactoryImplTest : public testing::Test {
157 public:
158 ConnectionFactoryImplTest();
159 virtual ~ConnectionFactoryImplTest();
160
161 TestConnectionFactoryImpl* factory() { return &factory_; }
162
163 void WaitForConnections();
164
165 private:
166 void ConnectionsComplete();
167
168 TestConnectionFactoryImpl factory_;
169 base::MessageLoop message_loop_;
170 scoped_ptr<base::RunLoop> run_loop_;
171 };
172
173 ConnectionFactoryImplTest::ConnectionFactoryImplTest()
174 : factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete,
175 base::Unretained(this))),
176 run_loop_(new base::RunLoop()) {}
177 ConnectionFactoryImplTest::~ConnectionFactoryImplTest() {}
178
179 void ConnectionFactoryImplTest::WaitForConnections() {
180 run_loop_->Run();
181 run_loop_.reset(new base::RunLoop());
182 }
183
184 void ConnectionFactoryImplTest::ConnectionsComplete() {
185 if (!run_loop_)
186 return;
187 run_loop_->Quit();
188 }
189
190 // Verify building a connection handler works.
191 TEST_F(ConnectionFactoryImplTest, BuildConnectionHandler) {
192 EXPECT_FALSE(factory()->IsEndpointReachable());
193 ConnectionHandler* handler = factory()->BuildConnectionHandler(
194 base::Bind(&ReadContinuation),
195 base::Bind(&WriteContinuation));
196 ASSERT_TRUE(handler);
197 EXPECT_FALSE(factory()->IsEndpointReachable());
198 }
199
200 // An initial successful connection should not result in backoff.
201 TEST_F(ConnectionFactoryImplTest, ConnectSuccess) {
202 factory()->BuildConnectionHandler(
203 ConnectionHandler::ProtoReceivedCallback(),
204 ConnectionHandler::ProtoSentCallback());
205 factory()->SetConnectResult(net::OK);
206 factory()->Connect(mcs_proto::LoginRequest());
207 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
208 }
209
210 // A connection failure should result in backoff.
211 TEST_F(ConnectionFactoryImplTest, ConnectFail) {
212 factory()->BuildConnectionHandler(
213 ConnectionHandler::ProtoReceivedCallback(),
214 ConnectionHandler::ProtoSentCallback());
215 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
216 factory()->Connect(mcs_proto::LoginRequest());
217 EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
218 }
219
220 // A connection success after a failure should reset backoff.
221 TEST_F(ConnectionFactoryImplTest, FailThenSucceed) {
222 factory()->BuildConnectionHandler(
223 ConnectionHandler::ProtoReceivedCallback(),
224 ConnectionHandler::ProtoSentCallback());
225 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
226 base::TimeTicks connect_time = base::TimeTicks::Now();
227 factory()->Connect(mcs_proto::LoginRequest());
228 WaitForConnections();
229 base::TimeTicks retry_time = factory()->NextRetryAttempt();
230 EXPECT_FALSE(retry_time.is_null());
231 EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1));
232 factory()->SetConnectResult(net::OK);
233 WaitForConnections();
234 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
235 }
236
237 // Multiple connection failures should retry with an exponentially increasing
238 // backoff, then reset on success.
239 TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
240 factory()->BuildConnectionHandler(
241 ConnectionHandler::ProtoReceivedCallback(),
242 ConnectionHandler::ProtoSentCallback());
243
244 const int kNumAttempts = 5;
245 factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED,
246 kNumAttempts);
247
248 base::TimeTicks connect_time = base::TimeTicks::Now();
249 factory()->Connect(mcs_proto::LoginRequest());
250 WaitForConnections();
251 base::TimeTicks retry_time = factory()->NextRetryAttempt();
252 EXPECT_FALSE(retry_time.is_null());
253 EXPECT_GE((retry_time - connect_time).InMilliseconds(),
254 CalculateBackoff(kNumAttempts));
255
256 factory()->SetConnectResult(net::OK);
257 WaitForConnections();
258 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
259 }
260
261 // IP events should reset backoff.
262 TEST_F(ConnectionFactoryImplTest, FailThenIPEvent) {
263 factory()->BuildConnectionHandler(
264 ConnectionHandler::ProtoReceivedCallback(),
265 ConnectionHandler::ProtoSentCallback());
266 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
267 factory()->Connect(mcs_proto::LoginRequest());
268 WaitForConnections();
269 EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
270
271 factory()->OnIPAddressChanged();
272 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
273 }
274
275 // Connection type events should reset backoff.
276 TEST_F(ConnectionFactoryImplTest, FailThenConnectionTypeEvent) {
277 factory()->BuildConnectionHandler(
278 ConnectionHandler::ProtoReceivedCallback(),
279 ConnectionHandler::ProtoSentCallback());
280 factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
281 factory()->Connect(mcs_proto::LoginRequest());
282 WaitForConnections();
283 EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
284
285 factory()->OnConnectionTypeChanged(
286 net::NetworkChangeNotifier::CONNECTION_WIFI);
287 EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
288 }
289
290 } // namespace
291 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698