Update ASan/Android runtime and setup script to LLVM r200682.
[chromium-blink-merge.git] / google_apis / gcm / engine / gcm_store_impl_unittest.cc
blob4beb0ae2501ccce6c5208af63a1ce840516daa12
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/engine/gcm_store_impl.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "google_apis/gcm/base/mcs_message.h"
18 #include "google_apis/gcm/base/mcs_util.h"
19 #include "google_apis/gcm/protocol/mcs.pb.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 namespace gcm {
24 namespace {
26 // Number of persistent ids to use in tests.
27 const int kNumPersistentIds = 10;
29 // Number of per-app messages in tests.
30 const int kNumMessagesPerApp = 20;
32 // App name for testing.
33 const char kAppName[] = "my_app";
35 // Category name for testing.
36 const char kCategoryName[] = "my_category";
38 const uint64 kDeviceId = 22;
39 const uint64 kDeviceToken = 55;
41 class GCMStoreImplTest : public testing::Test {
42 public:
43 GCMStoreImplTest();
44 virtual ~GCMStoreImplTest();
46 scoped_ptr<GCMStore> BuildGCMStore();
48 std::string GetNextPersistentId();
50 void PumpLoop();
52 void LoadCallback(scoped_ptr<GCMStore::LoadResult>* result_dst,
53 scoped_ptr<GCMStore::LoadResult> result);
54 void UpdateCallback(bool success);
56 protected:
57 base::MessageLoop message_loop_;
58 base::ScopedTempDir temp_directory_;
59 bool expected_success_;
60 scoped_ptr<base::RunLoop> run_loop_;
63 GCMStoreImplTest::GCMStoreImplTest()
64 : expected_success_(true) {
65 EXPECT_TRUE(temp_directory_.CreateUniqueTempDir());
66 run_loop_.reset(new base::RunLoop());
69 GCMStoreImplTest::~GCMStoreImplTest() {}
71 scoped_ptr<GCMStore> GCMStoreImplTest::BuildGCMStore() {
72 return scoped_ptr<GCMStore>(new GCMStoreImpl(
73 true,
74 temp_directory_.path(),
75 message_loop_.message_loop_proxy()));
78 std::string GCMStoreImplTest::GetNextPersistentId() {
79 return base::Uint64ToString(base::Time::Now().ToInternalValue());
82 void GCMStoreImplTest::PumpLoop() { message_loop_.RunUntilIdle(); }
84 void GCMStoreImplTest::LoadCallback(
85 scoped_ptr<GCMStore::LoadResult>* result_dst,
86 scoped_ptr<GCMStore::LoadResult> result) {
87 ASSERT_TRUE(result->success);
88 *result_dst = result.Pass();
89 run_loop_->Quit();
90 run_loop_.reset(new base::RunLoop());
93 void GCMStoreImplTest::UpdateCallback(bool success) {
94 ASSERT_EQ(expected_success_, success);
97 // Verify creating a new database and loading it.
98 TEST_F(GCMStoreImplTest, LoadNew) {
99 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
100 scoped_ptr<GCMStore::LoadResult> load_result;
101 gcm_store->Load(base::Bind(
102 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
103 PumpLoop();
105 EXPECT_EQ(0U, load_result->device_android_id);
106 EXPECT_EQ(0U, load_result->device_security_token);
107 EXPECT_TRUE(load_result->incoming_messages.empty());
108 EXPECT_TRUE(load_result->outgoing_messages.empty());
109 EXPECT_EQ(1LL, load_result->serial_number_mappings.next_serial_number);
110 EXPECT_TRUE(load_result->serial_number_mappings.user_serial_numbers.empty());
113 TEST_F(GCMStoreImplTest, DeviceCredentials) {
114 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
115 scoped_ptr<GCMStore::LoadResult> load_result;
116 gcm_store->Load(base::Bind(
117 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
118 PumpLoop();
120 gcm_store->SetDeviceCredentials(
121 kDeviceId,
122 kDeviceToken,
123 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
124 PumpLoop();
126 gcm_store = BuildGCMStore().Pass();
127 gcm_store->Load(base::Bind(
128 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
129 PumpLoop();
131 ASSERT_EQ(kDeviceId, load_result->device_android_id);
132 ASSERT_EQ(kDeviceToken, load_result->device_security_token);
135 // Verify saving some incoming messages, reopening the directory, and then
136 // removing those incoming messages.
137 TEST_F(GCMStoreImplTest, IncomingMessages) {
138 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
139 scoped_ptr<GCMStore::LoadResult> load_result;
140 gcm_store->Load(base::Bind(
141 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
142 PumpLoop();
144 std::vector<std::string> persistent_ids;
145 for (int i = 0; i < kNumPersistentIds; ++i) {
146 persistent_ids.push_back(GetNextPersistentId());
147 gcm_store->AddIncomingMessage(
148 persistent_ids.back(),
149 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
150 PumpLoop();
153 gcm_store = BuildGCMStore().Pass();
154 gcm_store->Load(base::Bind(
155 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
156 PumpLoop();
158 ASSERT_EQ(persistent_ids, load_result->incoming_messages);
159 ASSERT_TRUE(load_result->outgoing_messages.empty());
161 gcm_store->RemoveIncomingMessages(
162 persistent_ids,
163 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
164 PumpLoop();
166 gcm_store = BuildGCMStore().Pass();
167 load_result->incoming_messages.clear();
168 gcm_store->Load(base::Bind(
169 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
170 PumpLoop();
172 ASSERT_TRUE(load_result->incoming_messages.empty());
173 ASSERT_TRUE(load_result->outgoing_messages.empty());
176 // Verify saving some outgoing messages, reopening the directory, and then
177 // removing those outgoing messages.
178 TEST_F(GCMStoreImplTest, OutgoingMessages) {
179 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
180 scoped_ptr<GCMStore::LoadResult> load_result;
181 gcm_store->Load(base::Bind(
182 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
183 PumpLoop();
185 std::vector<std::string> persistent_ids;
186 const int kNumPersistentIds = 10;
187 for (int i = 0; i < kNumPersistentIds; ++i) {
188 persistent_ids.push_back(GetNextPersistentId());
189 mcs_proto::DataMessageStanza message;
190 message.set_from(kAppName + persistent_ids.back());
191 message.set_category(kCategoryName + persistent_ids.back());
192 gcm_store->AddOutgoingMessage(
193 persistent_ids.back(),
194 MCSMessage(message),
195 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
196 PumpLoop();
199 gcm_store = BuildGCMStore().Pass();
200 gcm_store->Load(base::Bind(
201 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
202 PumpLoop();
204 ASSERT_TRUE(load_result->incoming_messages.empty());
205 ASSERT_EQ(load_result->outgoing_messages.size(), persistent_ids.size());
206 for (int i = 0; i < kNumPersistentIds; ++i) {
207 std::string id = persistent_ids[i];
208 ASSERT_TRUE(load_result->outgoing_messages[id].get());
209 const mcs_proto::DataMessageStanza* message =
210 reinterpret_cast<mcs_proto::DataMessageStanza*>(
211 load_result->outgoing_messages[id].get());
212 ASSERT_EQ(message->from(), kAppName + id);
213 ASSERT_EQ(message->category(), kCategoryName + id);
216 gcm_store->RemoveOutgoingMessages(
217 persistent_ids,
218 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
219 PumpLoop();
221 gcm_store = BuildGCMStore().Pass();
222 load_result->outgoing_messages.clear();
223 gcm_store->Load(base::Bind(
224 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
225 PumpLoop();
227 ASSERT_TRUE(load_result->incoming_messages.empty());
228 ASSERT_TRUE(load_result->outgoing_messages.empty());
231 // Verify incoming and outgoing messages don't conflict.
232 TEST_F(GCMStoreImplTest, IncomingAndOutgoingMessages) {
233 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
234 scoped_ptr<GCMStore::LoadResult> load_result;
235 gcm_store->Load(base::Bind(
236 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
237 PumpLoop();
239 std::vector<std::string> persistent_ids;
240 const int kNumPersistentIds = 10;
241 for (int i = 0; i < kNumPersistentIds; ++i) {
242 persistent_ids.push_back(GetNextPersistentId());
243 gcm_store->AddIncomingMessage(
244 persistent_ids.back(),
245 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
246 PumpLoop();
248 mcs_proto::DataMessageStanza message;
249 message.set_from(kAppName + persistent_ids.back());
250 message.set_category(kCategoryName + persistent_ids.back());
251 gcm_store->AddOutgoingMessage(
252 persistent_ids.back(),
253 MCSMessage(message),
254 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
255 PumpLoop();
258 gcm_store = BuildGCMStore().Pass();
259 gcm_store->Load(base::Bind(
260 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
261 PumpLoop();
263 ASSERT_EQ(persistent_ids, load_result->incoming_messages);
264 ASSERT_EQ(load_result->outgoing_messages.size(), persistent_ids.size());
265 for (int i = 0; i < kNumPersistentIds; ++i) {
266 std::string id = persistent_ids[i];
267 ASSERT_TRUE(load_result->outgoing_messages[id].get());
268 const mcs_proto::DataMessageStanza* message =
269 reinterpret_cast<mcs_proto::DataMessageStanza*>(
270 load_result->outgoing_messages[id].get());
271 ASSERT_EQ(message->from(), kAppName + id);
272 ASSERT_EQ(message->category(), kCategoryName + id);
275 gcm_store->RemoveIncomingMessages(
276 persistent_ids,
277 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
278 PumpLoop();
279 gcm_store->RemoveOutgoingMessages(
280 persistent_ids,
281 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
282 PumpLoop();
284 gcm_store = BuildGCMStore().Pass();
285 load_result->incoming_messages.clear();
286 load_result->outgoing_messages.clear();
287 gcm_store->Load(base::Bind(
288 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
289 PumpLoop();
291 ASSERT_TRUE(load_result->incoming_messages.empty());
292 ASSERT_TRUE(load_result->outgoing_messages.empty());
295 // Verify that the next serial number of persisted properly.
296 TEST_F(GCMStoreImplTest, NextSerialNumber) {
297 const int64 kNextSerialNumber = 77LL;
298 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
299 scoped_ptr<GCMStore::LoadResult> load_result;
300 gcm_store->Load(base::Bind(
301 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
302 PumpLoop();
304 gcm_store->SetNextSerialNumber(
305 kNextSerialNumber,
306 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
307 PumpLoop();
309 gcm_store = BuildGCMStore().Pass();
310 gcm_store->Load(base::Bind(
311 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
312 PumpLoop();
314 EXPECT_EQ(kNextSerialNumber,
315 load_result->serial_number_mappings.next_serial_number);
318 // Verify that user serial number mappings are persisted properly.
319 TEST_F(GCMStoreImplTest, UserSerialNumberMappings) {
320 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
321 scoped_ptr<GCMStore::LoadResult> load_result;
322 gcm_store->Load(base::Bind(
323 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
324 PumpLoop();
326 std::string username1 = "username1";
327 int64 serial_number1 = 34LL;
328 gcm_store->AddUserSerialNumber(
329 username1,
330 serial_number1,
331 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
333 std::string username2 = "username2";
334 int64 serial_number2 = 56LL;
335 gcm_store->AddUserSerialNumber(
336 username2,
337 serial_number2,
338 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
339 PumpLoop();
341 gcm_store = BuildGCMStore().Pass();
342 gcm_store->Load(base::Bind(
343 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
344 PumpLoop();
346 ASSERT_EQ(2u, load_result->serial_number_mappings.user_serial_numbers.size());
347 ASSERT_NE(
348 load_result->serial_number_mappings.user_serial_numbers.end(),
349 load_result->serial_number_mappings.user_serial_numbers.find(username1));
350 EXPECT_EQ(serial_number1,
351 load_result->serial_number_mappings.user_serial_numbers[username1]);
352 ASSERT_NE(
353 load_result->serial_number_mappings.user_serial_numbers.end(),
354 load_result->serial_number_mappings.user_serial_numbers.find(username2));
355 EXPECT_EQ(serial_number2,
356 load_result->serial_number_mappings.user_serial_numbers[username2]);
359 // Test that per-app message limits are enforced, persisted across restarts,
360 // and updated as messages are removed.
361 TEST_F(GCMStoreImplTest, PerAppMessageLimits) {
362 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
363 scoped_ptr<GCMStore::LoadResult> load_result;
364 gcm_store->Load(base::Bind(&GCMStoreImplTest::LoadCallback,
365 base::Unretained(this),
366 &load_result));
368 // Add the initial (below app limit) messages.
369 for (int i = 0; i < kNumMessagesPerApp; ++i) {
370 mcs_proto::DataMessageStanza message;
371 message.set_from(kAppName);
372 message.set_category(kCategoryName);
373 EXPECT_TRUE(gcm_store->AddOutgoingMessage(
374 base::IntToString(i),
375 MCSMessage(message),
376 base::Bind(&GCMStoreImplTest::UpdateCallback,
377 base::Unretained(this))));
378 PumpLoop();
381 // Attempting to add some more should fail.
382 for (int i = 0; i < kNumMessagesPerApp; ++i) {
383 mcs_proto::DataMessageStanza message;
384 message.set_from(kAppName);
385 message.set_category(kCategoryName);
386 EXPECT_FALSE(gcm_store->AddOutgoingMessage(
387 base::IntToString(i + kNumMessagesPerApp),
388 MCSMessage(message),
389 base::Bind(&GCMStoreImplTest::UpdateCallback,
390 base::Unretained(this))));
391 PumpLoop();
394 // Tear down and restore the database.
395 gcm_store = BuildGCMStore().Pass();
396 gcm_store->Load(base::Bind(&GCMStoreImplTest::LoadCallback,
397 base::Unretained(this),
398 &load_result));
399 PumpLoop();
401 // Adding more messages should still fail.
402 for (int i = 0; i < kNumMessagesPerApp; ++i) {
403 mcs_proto::DataMessageStanza message;
404 message.set_from(kAppName);
405 message.set_category(kCategoryName);
406 EXPECT_FALSE(gcm_store->AddOutgoingMessage(
407 base::IntToString(i + kNumMessagesPerApp),
408 MCSMessage(message),
409 base::Bind(&GCMStoreImplTest::UpdateCallback,
410 base::Unretained(this))));
411 PumpLoop();
414 // Remove the existing messages.
415 for (int i = 0; i < kNumMessagesPerApp; ++i) {
416 gcm_store->RemoveOutgoingMessage(
417 base::IntToString(i),
418 base::Bind(&GCMStoreImplTest::UpdateCallback,
419 base::Unretained(this)));
420 PumpLoop();
423 // Successfully add new messages.
424 for (int i = 0; i < kNumMessagesPerApp; ++i) {
425 mcs_proto::DataMessageStanza message;
426 message.set_from(kAppName);
427 message.set_category(kCategoryName);
428 EXPECT_TRUE(gcm_store->AddOutgoingMessage(
429 base::IntToString(i + kNumMessagesPerApp),
430 MCSMessage(message),
431 base::Bind(&GCMStoreImplTest::UpdateCallback,
432 base::Unretained(this))));
433 PumpLoop();
437 // When the database is destroyed, all database updates should fail. At the
438 // same time, they per-app message counts should not go up, as failures should
439 // result in decrementing the counts.
440 TEST_F(GCMStoreImplTest, AddMessageAfterDestroy) {
441 scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
442 scoped_ptr<GCMStore::LoadResult> load_result;
443 gcm_store->Load(base::Bind(&GCMStoreImplTest::LoadCallback,
444 base::Unretained(this),
445 &load_result));
446 PumpLoop();
447 gcm_store->Destroy(base::Bind(&GCMStoreImplTest::UpdateCallback,
448 base::Unretained(this)));
449 PumpLoop();
451 expected_success_ = false;
452 for (int i = 0; i < kNumMessagesPerApp * 2; ++i) {
453 mcs_proto::DataMessageStanza message;
454 message.set_from(kAppName);
455 message.set_category(kCategoryName);
456 // Because all adds are failing, none should hit the per-app message limits.
457 EXPECT_TRUE(gcm_store->AddOutgoingMessage(
458 base::IntToString(i),
459 MCSMessage(message),
460 base::Bind(&GCMStoreImplTest::UpdateCallback,
461 base::Unretained(this))));
462 PumpLoop();
466 } // namespace
468 } // namespace gcm