Blink roll 168462:168490
[chromium-blink-merge.git] / google_apis / gcm / gcm_client_impl_unittest.cc
blobd45a0fc66cd9d6aad144ca6d0601ef019ae28d27
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.
5 #include "google_apis/gcm/gcm_client_impl.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/test/simple_test_clock.h"
11 #include "components/encryptor/os_crypt.h"
12 #include "google_apis/gcm/base/mcs_message.h"
13 #include "google_apis/gcm/base/mcs_util.h"
14 #include "google_apis/gcm/engine/fake_connection_factory.h"
15 #include "google_apis/gcm/engine/fake_connection_handler.h"
16 #include "google_apis/gcm/protocol/android_checkin.pb.h"
17 #include "google_apis/gcm/protocol/checkin.pb.h"
18 #include "google_apis/gcm/protocol/mcs.pb.h"
19 #include "net/url_request/test_url_fetcher_factory.h"
20 #include "net/url_request/url_fetcher_delegate.h"
21 #include "net/url_request/url_request_test_util.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 namespace gcm {
26 namespace {
28 enum LastEvent {
29 NONE,
30 LOADING_COMPLETED,
31 REGISTRATION_COMPLETED,
32 UNREGISTRATION_COMPLETED,
33 MESSAGE_SEND_ERROR,
34 MESSAGE_RECEIVED,
35 MESSAGES_DELETED,
38 const uint64 kDeviceAndroidId = 54321;
39 const uint64 kDeviceSecurityToken = 12345;
40 const char kRegistrationResponsePrefix[] = "token=";
41 const char kUnregistrationResponsePrefix[] = "deleted=";
43 // Helper for building arbitrary data messages.
44 MCSMessage BuildDownstreamMessage(
45 const std::string& project_id,
46 const std::string& app_id,
47 const std::map<std::string, std::string>& data) {
48 mcs_proto::DataMessageStanza data_message;
49 data_message.set_from(project_id);
50 data_message.set_category(app_id);
51 for (std::map<std::string, std::string>::const_iterator iter = data.begin();
52 iter != data.end();
53 ++iter) {
54 mcs_proto::AppData* app_data = data_message.add_app_data();
55 app_data->set_key(iter->first);
56 app_data->set_value(iter->second);
58 return MCSMessage(kDataMessageStanzaTag, data_message);
61 class FakeMCSClient : public MCSClient {
62 public:
63 FakeMCSClient(base::Clock* clock,
64 ConnectionFactory* connection_factory);
65 virtual ~FakeMCSClient();
66 virtual void Login(uint64 android_id, uint64 security_token) OVERRIDE;
67 virtual void SendMessage(const MCSMessage& message) OVERRIDE;
68 void set_gcm_store(GCMStore* gcm_store);
70 uint64 last_android_id() const { return last_android_id_; }
71 uint64 last_security_token() const { return last_security_token_; }
72 uint8 last_message_tag() const { return last_message_tag_; }
73 const mcs_proto::DataMessageStanza& last_data_message_stanza() const {
74 return last_data_message_stanza_;
77 private:
78 uint64 last_android_id_;
79 uint64 last_security_token_;
80 uint8 last_message_tag_;
81 mcs_proto::DataMessageStanza last_data_message_stanza_;
84 FakeMCSClient::FakeMCSClient(base::Clock* clock,
85 ConnectionFactory* connection_factory)
86 : MCSClient("", clock, connection_factory, NULL),
87 last_android_id_(0u),
88 last_security_token_(0u),
89 last_message_tag_(kNumProtoTypes) {
92 FakeMCSClient::~FakeMCSClient() {
95 void FakeMCSClient::set_gcm_store(GCMStore* gcm_store) {
96 SetGCMStoreForTesting(gcm_store);
99 void FakeMCSClient::Login(uint64 android_id, uint64 security_token) {
100 last_android_id_ = android_id;
101 last_security_token_ = security_token;
104 void FakeMCSClient::SendMessage(const MCSMessage& message) {
105 last_message_tag_ = message.tag();
106 if (last_message_tag_ == kDataMessageStanzaTag) {
107 last_data_message_stanza_.CopyFrom(
108 reinterpret_cast<const mcs_proto::DataMessageStanza&>(
109 message.GetProtobuf()));
113 } // namespace
115 class GCMClientImplTest : public testing::Test,
116 public GCMClient::Delegate {
117 public:
118 GCMClientImplTest();
119 virtual ~GCMClientImplTest();
121 virtual void SetUp() OVERRIDE;
123 void BuildGCMClient();
124 void InitializeGCMClient();
125 void ReceiveMessageFromMCS(const MCSMessage& message);
126 void CompleteCheckin(uint64 android_id, uint64 security_token);
127 void CompleteRegistration(const std::string& registration_id);
128 void CompleteUnregistration(const std::string& app_id);
130 // GCMClient::Delegate overrides (for verification).
131 virtual void OnRegisterFinished(const std::string& app_id,
132 const std::string& registration_id,
133 GCMClient::Result result) OVERRIDE;
134 virtual void OnUnregisterFinished(const std::string& app_id,
135 bool success) OVERRIDE;
136 virtual void OnSendFinished(const std::string& app_id,
137 const std::string& message_id,
138 GCMClient::Result result) OVERRIDE {}
139 virtual void OnMessageReceived(const std::string& registration_id,
140 const GCMClient::IncomingMessage& message)
141 OVERRIDE;
142 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
143 virtual void OnMessageSendError(const std::string& app_id,
144 const std::string& message_id,
145 GCMClient::Result result) OVERRIDE;
146 virtual void OnGCMReady() OVERRIDE;
148 GCMClientImpl* gcm_client() const { return gcm_client_.get(); }
149 FakeMCSClient* mcs_client() const {
150 return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get());
153 LastEvent last_event() const { return last_event_; }
154 const std::string& last_app_id() const { return last_app_id_; }
155 const std::string& last_registration_id() const {
156 return last_registration_id_;
158 const std::string& last_message_id() const { return last_message_id_; }
159 GCMClient::Result last_result() const { return last_result_; }
160 const GCMClient::IncomingMessage& last_message() const {
161 return last_message_;
164 int64 CurrentTime();
166 private:
167 // Tooling.
168 void PumpLoop();
169 void PumpLoopUntilIdle();
170 void QuitLoop();
172 base::SimpleTestClock* clock() const {
173 return reinterpret_cast<base::SimpleTestClock*>(gcm_client_->clock_.get());
176 // Variables used for verification.
177 LastEvent last_event_;
178 std::string last_app_id_;
179 std::string last_registration_id_;
180 std::string last_message_id_;
181 GCMClient::Result last_result_;
182 GCMClient::IncomingMessage last_message_;
184 scoped_ptr<GCMClientImpl> gcm_client_;
185 scoped_ptr<FakeConnectionFactory> connection_factory_;
187 base::MessageLoop message_loop_;
188 scoped_ptr<base::RunLoop> run_loop_;
189 net::TestURLFetcherFactory url_fetcher_factory_;
191 // Injected to GCM client:
192 base::ScopedTempDir temp_directory_;
193 scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
196 GCMClientImplTest::GCMClientImplTest()
197 : last_event_(NONE),
198 last_result_(GCMClient::UNKNOWN_ERROR),
199 url_request_context_getter_(new net::TestURLRequestContextGetter(
200 message_loop_.message_loop_proxy())) {
203 GCMClientImplTest::~GCMClientImplTest() {}
205 void GCMClientImplTest::SetUp() {
206 ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
207 run_loop_.reset(new base::RunLoop);
208 BuildGCMClient();
209 InitializeGCMClient();
212 void GCMClientImplTest::PumpLoop() {
213 run_loop_->Run();
214 run_loop_.reset(new base::RunLoop());
217 void GCMClientImplTest::PumpLoopUntilIdle() {
218 run_loop_->RunUntilIdle();
219 run_loop_.reset(new base::RunLoop());
222 void GCMClientImplTest::QuitLoop() {
223 if (run_loop_ && run_loop_->running())
224 run_loop_->Quit();
227 void GCMClientImplTest::BuildGCMClient() {
228 gcm_client_.reset(new GCMClientImpl());
231 void GCMClientImplTest::CompleteCheckin(uint64 android_id,
232 uint64 security_token) {
233 checkin_proto::AndroidCheckinResponse response;
234 response.set_stats_ok(true);
235 response.set_android_id(android_id);
236 response.set_security_token(security_token);
238 std::string response_string;
239 response.SerializeToString(&response_string);
241 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
242 ASSERT_TRUE(fetcher);
243 fetcher->set_response_code(net::HTTP_OK);
244 fetcher->SetResponseString(response_string);
245 fetcher->delegate()->OnURLFetchComplete(fetcher);
246 url_fetcher_factory_.RemoveFetcherFromMap(0);
249 void GCMClientImplTest::CompleteRegistration(
250 const std::string& registration_id) {
251 std::string response(kRegistrationResponsePrefix);
252 response.append(registration_id);
253 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
254 ASSERT_TRUE(fetcher);
255 fetcher->set_response_code(net::HTTP_OK);
256 fetcher->SetResponseString(response);
257 fetcher->delegate()->OnURLFetchComplete(fetcher);
260 void GCMClientImplTest::CompleteUnregistration(
261 const std::string& app_id) {
262 std::string response(kUnregistrationResponsePrefix);
263 response.append(app_id);
264 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
265 ASSERT_TRUE(fetcher);
266 fetcher->set_response_code(net::HTTP_OK);
267 fetcher->SetResponseString(response);
268 fetcher->delegate()->OnURLFetchComplete(fetcher);
271 void GCMClientImplTest::InitializeGCMClient() {
272 // Creating and advancing the clock.
273 gcm_client_->clock_.reset(new base::SimpleTestClock);
274 clock()->Advance(base::TimeDelta::FromMilliseconds(1));
275 // Creating and injecting the mcs_client.
276 connection_factory_.reset(new FakeConnectionFactory());
277 gcm_client_->SetMCSClientForTesting(scoped_ptr<MCSClient>(
278 new FakeMCSClient(clock(), connection_factory_.get())).Pass());
279 // Actual initialization.
280 checkin_proto::ChromeBuildProto chrome_build_proto;
281 gcm_client_->Initialize(chrome_build_proto,
282 temp_directory_.path(),
283 std::vector<std::string>(),
284 message_loop_.message_loop_proxy(),
285 url_request_context_getter_,
286 this);
288 #if defined(OS_MACOSX)
289 // On OSX, prevent the Keychain permissions popup during unit tests.
290 OSCrypt::UseMockKeychain(true); // Must be after Initialize.
291 #endif
293 // Starting loading and check-in.
294 gcm_client_->Load();
296 // Ensuring that mcs_client is using the same gcm_store as gcm_client.
297 mcs_client()->set_gcm_store(gcm_client_->gcm_store_.get());
298 PumpLoopUntilIdle();
299 CompleteCheckin(kDeviceAndroidId, kDeviceSecurityToken);
302 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
303 gcm_client_->OnMessageReceivedFromMCS(message);
306 void GCMClientImplTest::OnGCMReady() {
307 last_event_ = LOADING_COMPLETED;
308 QuitLoop();
311 void GCMClientImplTest::OnMessageReceived(
312 const std::string& registration_id,
313 const GCMClient::IncomingMessage& message) {
314 last_event_ = MESSAGE_RECEIVED;
315 last_app_id_ = registration_id;
316 last_message_ = message;
317 QuitLoop();
320 void GCMClientImplTest::OnRegisterFinished(const std::string& app_id,
321 const std::string& registration_id,
322 GCMClient::Result result) {
323 last_event_ = REGISTRATION_COMPLETED;
324 last_app_id_ = app_id;
325 last_registration_id_ = registration_id;
326 last_result_ = result;
329 void GCMClientImplTest::OnUnregisterFinished(const std::string& app_id,
330 bool success) {
331 last_event_ = UNREGISTRATION_COMPLETED;
332 last_app_id_ = app_id;
333 last_result_ = success ? GCMClient::SUCCESS : GCMClient::UNKNOWN_ERROR;
336 void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
337 last_event_ = MESSAGES_DELETED;
338 last_app_id_ = app_id;
341 void GCMClientImplTest::OnMessageSendError(const std::string& app_id,
342 const std::string& message_id,
343 GCMClient::Result result) {
344 last_event_ = MESSAGE_SEND_ERROR;
345 last_app_id_ = app_id;
346 last_message_id_ = message_id;
347 last_result_ = result;
350 int64 GCMClientImplTest::CurrentTime() {
351 return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond;
354 TEST_F(GCMClientImplTest, LoadingCompleted) {
355 EXPECT_EQ(LOADING_COMPLETED, last_event());
356 EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id());
357 EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token());
360 TEST_F(GCMClientImplTest, CheckOut) {
361 EXPECT_TRUE(mcs_client());
362 gcm_client()->CheckOut();
363 EXPECT_FALSE(mcs_client());
366 TEST_F(GCMClientImplTest, RegisterApp) {
367 std::vector<std::string> senders;
368 senders.push_back("sender");
369 gcm_client()->Register("app_id", "cert", senders);
370 CompleteRegistration("reg_id");
372 EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
373 EXPECT_EQ("app_id", last_app_id());
374 EXPECT_EQ("reg_id", last_registration_id());
375 EXPECT_EQ(GCMClient::SUCCESS, last_result());
378 TEST_F(GCMClientImplTest, UnregisterApp) {
379 gcm_client()->Unregister("app_id");
380 CompleteUnregistration("app_id");
382 EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
383 EXPECT_EQ("app_id", last_app_id());
384 EXPECT_EQ(GCMClient::SUCCESS, last_result());
387 TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
388 std::map<std::string, std::string> expected_data;
389 expected_data["message_type"] = "gcm";
390 expected_data["key"] = "value";
391 expected_data["key2"] = "value2";
392 MCSMessage message(BuildDownstreamMessage(
393 "project_id", "app_id", expected_data));
394 EXPECT_TRUE(message.IsValid());
395 ReceiveMessageFromMCS(message);
397 expected_data.erase(expected_data.find("message_type"));
398 EXPECT_EQ(MESSAGE_RECEIVED, last_event());
399 EXPECT_EQ("app_id", last_app_id());
400 EXPECT_EQ(expected_data.size(), last_message().data.size());
401 EXPECT_EQ(expected_data, last_message().data);
404 TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
405 std::map<std::string, std::string> expected_data;
406 expected_data["message_type"] = "send_error";
407 expected_data["google.message_id"] = "007";
408 MCSMessage message(BuildDownstreamMessage(
409 "project_id", "app_id", expected_data));
410 EXPECT_TRUE(message.IsValid());
411 ReceiveMessageFromMCS(message);
413 EXPECT_EQ(MESSAGE_SEND_ERROR, last_event());
414 EXPECT_EQ("app_id", last_app_id());
415 EXPECT_EQ("007", last_message_id());
418 TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) {
419 std::map<std::string, std::string> expected_data;
420 expected_data["message_type"] = "deleted_messages";
421 MCSMessage message(BuildDownstreamMessage(
422 "project_id", "app_id", expected_data));
423 EXPECT_TRUE(message.IsValid());
424 ReceiveMessageFromMCS(message);
426 EXPECT_EQ(MESSAGES_DELETED, last_event());
427 EXPECT_EQ("app_id", last_app_id());
430 TEST_F(GCMClientImplTest, SendMessage) {
431 mcs_proto::DataMessageStanza stanza;
432 stanza.set_ttl(500);
434 GCMClient::OutgoingMessage message;
435 message.id = "007";
436 message.time_to_live = 500;
437 message.data["key"] = "value";
438 gcm_client()->Send("app_id", "project_id", message);
440 EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag());
441 EXPECT_EQ("app_id", mcs_client()->last_data_message_stanza().category());
442 EXPECT_EQ("project_id", mcs_client()->last_data_message_stanza().to());
443 EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl());
444 EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent());
445 EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id());
446 EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from());
447 EXPECT_EQ("project_id", mcs_client()->last_data_message_stanza().to());
448 EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key());
449 EXPECT_EQ("value",
450 mcs_client()->last_data_message_stanza().app_data(0).value());
453 } // namespace gcm