disable two ClientCertStoreChromeOSTest.* unit_tests on Valgrind bots
[chromium-blink-merge.git] / sync / internal_api / attachments / attachment_store_test_template.h
blob86ea20e9bc90c3cea4022476765529de90904936
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 #ifndef SYNC_INTERNAL_API_ATTACHMENTS_ATTACHMENT_STORE_TEST_TEMPLATE_H_
6 #define SYNC_INTERNAL_API_ATTACHMENTS_ATTACHMENT_STORE_TEST_TEMPLATE_H_
8 #include "sync/api/attachments/attachment_store.h"
10 #include "base/bind.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/ref_counted_memory.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/run_loop.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "sync/api/attachments/attachment.h"
17 #include "sync/internal_api/public/attachments/attachment_util.h"
18 #include "sync/protocol/sync.pb.h"
19 #include "testing/gmock/include/gmock/gmock-matchers.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 // AttachmentStoreTest defines tests for AttachmentStore. To instantiate these
23 // tests for a particular implementation you need to:
24 // - Include this file in test.
25 // - Create factory class for attachment store that implements factory method.
26 // - add INSTANTIATE_TYPED_TEST_CASE_P statement.
27 // Here is how to do it for MyAttachmentStore:
29 // class MyAttachmentStoreFactory {
30 // public:
31 // scoped_refptr<AttachmentStore> CreateAttachmentStore() {
32 // return new MyAttachmentStore();
33 // }
34 // };
36 // INSTANTIATE_TYPED_TEST_CASE_P(My,
37 // AttachmentStoreTest,
38 // MyAttachmentStoreFactory);
40 namespace syncer {
42 const char kTestData1[] = "test data 1";
43 const char kTestData2[] = "test data 2";
45 template <typename AttachmentStoreFactory>
46 class AttachmentStoreTest : public testing::Test {
47 protected:
48 AttachmentStoreFactory attachment_store_factory;
49 base::MessageLoop message_loop;
50 scoped_ptr<AttachmentStore> store;
51 scoped_ptr<AttachmentStoreForSync> store_for_sync;
52 AttachmentStore::Result result;
53 scoped_ptr<AttachmentMap> attachments;
54 scoped_ptr<AttachmentIdList> failed_attachment_ids;
55 scoped_ptr<AttachmentMetadataList> attachment_metadata;
57 AttachmentStore::ReadCallback read_callback;
58 AttachmentStore::WriteCallback write_callback;
59 AttachmentStore::DropCallback drop_callback;
60 AttachmentStore::ReadMetadataCallback read_metadata_callback;
62 scoped_refptr<base::RefCountedString> some_data1;
63 scoped_refptr<base::RefCountedString> some_data2;
65 AttachmentStoreTest() {}
67 void SetUp() override {
68 store = attachment_store_factory.CreateAttachmentStore();
69 store_for_sync = store->CreateAttachmentStoreForSync();
71 Clear();
72 read_callback = base::Bind(&AttachmentStoreTest::CopyResultAttachments,
73 base::Unretained(this),
74 &result,
75 &attachments,
76 &failed_attachment_ids);
77 write_callback = base::Bind(
78 &AttachmentStoreTest::CopyResult, base::Unretained(this), &result);
79 drop_callback = write_callback;
80 read_metadata_callback =
81 base::Bind(&AttachmentStoreTest::CopyResultMetadata,
82 base::Unretained(this), &result, &attachment_metadata);
84 some_data1 = new base::RefCountedString;
85 some_data1->data() = kTestData1;
87 some_data2 = new base::RefCountedString;
88 some_data2->data() = kTestData2;
91 void ClearAndPumpLoop() {
92 Clear();
93 base::RunLoop().RunUntilIdle();
96 private:
97 void Clear() {
98 result = AttachmentStore::UNSPECIFIED_ERROR;
99 attachments.reset();
100 failed_attachment_ids.reset();
101 attachment_metadata.reset();
104 void CopyResult(AttachmentStore::Result* destination_result,
105 const AttachmentStore::Result& source_result) {
106 *destination_result = source_result;
109 void CopyResultAttachments(
110 AttachmentStore::Result* destination_result,
111 scoped_ptr<AttachmentMap>* destination_attachments,
112 scoped_ptr<AttachmentIdList>* destination_failed_attachment_ids,
113 const AttachmentStore::Result& source_result,
114 scoped_ptr<AttachmentMap> source_attachments,
115 scoped_ptr<AttachmentIdList> source_failed_attachment_ids) {
116 CopyResult(destination_result, source_result);
117 *destination_attachments = source_attachments.Pass();
118 *destination_failed_attachment_ids = source_failed_attachment_ids.Pass();
121 void CopyResultMetadata(
122 AttachmentStore::Result* destination_result,
123 scoped_ptr<AttachmentMetadataList>* destination_metadata,
124 const AttachmentStore::Result& source_result,
125 scoped_ptr<AttachmentMetadataList> source_metadata) {
126 CopyResult(destination_result, source_result);
127 *destination_metadata = source_metadata.Pass();
131 TYPED_TEST_CASE_P(AttachmentStoreTest);
133 // Verify that CreateAttachmentStoreForSync() creates valid object.
134 TYPED_TEST_P(AttachmentStoreTest, CreateAttachmentStoreForSync) {
135 scoped_ptr<AttachmentStoreForSync> attachment_store_for_sync =
136 this->store->CreateAttachmentStoreForSync();
137 EXPECT_NE(nullptr, attachment_store_for_sync);
140 // Verify that we do not overwrite existing attachments and that we do not treat
141 // it as an error.
142 TYPED_TEST_P(AttachmentStoreTest, Write_NoOverwriteNoError) {
143 // Create two attachments with the same id but different data.
144 Attachment attachment1 = Attachment::Create(this->some_data1);
145 Attachment attachment2 =
146 Attachment::CreateFromParts(attachment1.GetId(), this->some_data2);
148 // Write the first one.
149 AttachmentList some_attachments;
150 some_attachments.push_back(attachment1);
151 this->store->Write(some_attachments, this->write_callback);
152 this->ClearAndPumpLoop();
153 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
155 // Write the second one.
156 some_attachments.clear();
157 some_attachments.push_back(attachment2);
158 this->store->Write(some_attachments, this->write_callback);
159 this->ClearAndPumpLoop();
160 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
162 // Read it back and see that it was not overwritten.
163 AttachmentIdList some_attachment_ids;
164 some_attachment_ids.push_back(attachment1.GetId());
165 this->store->Read(some_attachment_ids, this->read_callback);
166 this->ClearAndPumpLoop();
167 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
168 EXPECT_EQ(1U, this->attachments->size());
169 EXPECT_EQ(0U, this->failed_attachment_ids->size());
170 AttachmentMap::const_iterator a1 =
171 this->attachments->find(attachment1.GetId());
172 EXPECT_TRUE(a1 != this->attachments->end());
173 EXPECT_TRUE(attachment1.GetData()->Equals(a1->second.GetData()));
176 // Verify that we can write some attachments and read them back.
177 TYPED_TEST_P(AttachmentStoreTest, Write_RoundTrip) {
178 Attachment attachment1 = Attachment::Create(this->some_data1);
179 Attachment attachment2 = Attachment::Create(this->some_data2);
180 AttachmentList some_attachments;
181 some_attachments.push_back(attachment1);
182 some_attachments.push_back(attachment2);
184 this->store->Write(some_attachments, this->write_callback);
185 this->ClearAndPumpLoop();
186 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
188 AttachmentIdList some_attachment_ids;
189 some_attachment_ids.push_back(attachment1.GetId());
190 some_attachment_ids.push_back(attachment2.GetId());
191 this->store->Read(some_attachment_ids, this->read_callback);
192 this->ClearAndPumpLoop();
193 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
194 EXPECT_EQ(2U, this->attachments->size());
195 EXPECT_EQ(0U, this->failed_attachment_ids->size());
197 AttachmentMap::const_iterator a1 =
198 this->attachments->find(attachment1.GetId());
199 EXPECT_TRUE(a1 != this->attachments->end());
200 EXPECT_TRUE(attachment1.GetData()->Equals(a1->second.GetData()));
202 AttachmentMap::const_iterator a2 =
203 this->attachments->find(attachment2.GetId());
204 EXPECT_TRUE(a2 != this->attachments->end());
205 EXPECT_TRUE(attachment2.GetData()->Equals(a2->second.GetData()));
208 // Try to read two attachments when only one exists.
209 TYPED_TEST_P(AttachmentStoreTest, Read_OneNotFound) {
210 Attachment attachment1 = Attachment::Create(this->some_data1);
211 Attachment attachment2 = Attachment::Create(this->some_data2);
213 AttachmentList some_attachments;
214 // Write attachment1 only.
215 some_attachments.push_back(attachment1);
216 this->store->Write(some_attachments, this->write_callback);
217 this->ClearAndPumpLoop();
218 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
220 // Try to read both attachment1 and attachment2.
221 AttachmentIdList ids;
222 ids.push_back(attachment1.GetId());
223 ids.push_back(attachment2.GetId());
224 this->store->Read(ids, this->read_callback);
225 this->ClearAndPumpLoop();
227 // See that only attachment1 was read.
228 EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, this->result);
229 EXPECT_EQ(1U, this->attachments->size());
230 EXPECT_EQ(1U, this->failed_attachment_ids->size());
233 // Try to drop two attachments when only one exists. Verify that no error occurs
234 // and that the existing attachment was dropped.
235 TYPED_TEST_P(AttachmentStoreTest, Drop_DropTwoButOnlyOneExists) {
236 // First, create two attachments.
237 Attachment attachment1 = Attachment::Create(this->some_data1);
238 Attachment attachment2 = Attachment::Create(this->some_data2);
239 AttachmentList some_attachments;
240 some_attachments.push_back(attachment1);
241 some_attachments.push_back(attachment2);
242 this->store->Write(some_attachments, this->write_callback);
243 this->ClearAndPumpLoop();
244 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
246 // Drop attachment1 only.
247 AttachmentIdList ids;
248 ids.push_back(attachment1.GetId());
249 this->store->Drop(ids, this->drop_callback);
250 this->ClearAndPumpLoop();
251 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
253 // See that attachment1 is gone.
254 this->store->Read(ids, this->read_callback);
255 this->ClearAndPumpLoop();
256 EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, this->result);
257 EXPECT_EQ(0U, this->attachments->size());
258 EXPECT_EQ(1U, this->failed_attachment_ids->size());
259 EXPECT_EQ(attachment1.GetId(), (*this->failed_attachment_ids)[0]);
261 // Drop both attachment1 and attachment2.
262 ids.clear();
263 ids.push_back(attachment1.GetId());
264 ids.push_back(attachment2.GetId());
265 this->store->Drop(ids, this->drop_callback);
266 this->ClearAndPumpLoop();
267 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
269 // See that attachment2 is now gone.
270 ids.clear();
271 ids.push_back(attachment2.GetId());
272 this->store->Read(ids, this->read_callback);
273 this->ClearAndPumpLoop();
274 EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, this->result);
275 EXPECT_EQ(0U, this->attachments->size());
276 EXPECT_EQ(1U, this->failed_attachment_ids->size());
277 EXPECT_EQ(attachment2.GetId(), (*this->failed_attachment_ids)[0]);
280 // Verify that attempting to drop an attachment that does not exist is not an
281 // error.
282 TYPED_TEST_P(AttachmentStoreTest, Drop_DoesNotExist) {
283 Attachment attachment1 = Attachment::Create(this->some_data1);
284 AttachmentList some_attachments;
285 some_attachments.push_back(attachment1);
286 this->store->Write(some_attachments, this->write_callback);
287 this->ClearAndPumpLoop();
288 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
290 // Drop the attachment.
291 AttachmentIdList ids;
292 ids.push_back(attachment1.GetId());
293 this->store->Drop(ids, this->drop_callback);
294 this->ClearAndPumpLoop();
295 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
297 // See that it's gone.
298 this->store->Read(ids, this->read_callback);
299 this->ClearAndPumpLoop();
300 EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, this->result);
301 EXPECT_EQ(0U, this->attachments->size());
302 EXPECT_EQ(1U, this->failed_attachment_ids->size());
303 EXPECT_EQ(attachment1.GetId(), (*this->failed_attachment_ids)[0]);
305 // Drop again, see that no error occurs.
306 ids.clear();
307 ids.push_back(attachment1.GetId());
308 this->store->Drop(ids, this->drop_callback);
309 this->ClearAndPumpLoop();
310 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
313 // Verify getting metadata for specific attachments.
314 TYPED_TEST_P(AttachmentStoreTest, ReadMetadataById) {
315 Attachment attachment1 = Attachment::Create(this->some_data1);
316 Attachment attachment2 = Attachment::Create(this->some_data2);
318 AttachmentList some_attachments;
319 // Write attachment1 only.
320 some_attachments.push_back(attachment1);
321 this->store->Write(some_attachments, this->write_callback);
322 this->ClearAndPumpLoop();
323 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
325 // Try to read metadata for both attachment1 and attachment2.
326 AttachmentIdList ids;
327 ids.push_back(attachment1.GetId());
328 ids.push_back(attachment2.GetId());
329 this->store->ReadMetadataById(ids, this->read_metadata_callback);
330 this->ClearAndPumpLoop();
332 // See that only one entry was read.
333 EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, this->result);
334 EXPECT_EQ(1U, this->attachment_metadata->size());
336 // Now write attachment2.
337 some_attachments[0] = attachment2;
338 this->store->Write(some_attachments, this->write_callback);
339 this->ClearAndPumpLoop();
340 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
342 // Try to read metadata for both attachment1 and attachment2 again.
343 this->store->ReadMetadataById(ids, this->read_metadata_callback);
344 this->ClearAndPumpLoop();
345 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
346 EXPECT_EQ(2U, this->attachment_metadata->size());
348 // Verify that we've got both entries back in the right order.
349 AttachmentMetadataList::const_iterator iter =
350 this->attachment_metadata->begin();
351 EXPECT_EQ(attachment1.GetId(), iter->GetId());
352 ++iter;
353 EXPECT_EQ(attachment2.GetId(), iter->GetId());
356 // Verify that ReadMetadata/ReadMetadataForSync returns metadata for correct
357 // set of attachments.
358 TYPED_TEST_P(AttachmentStoreTest, ReadMetadata) {
359 // Try to read all metadata from an empty store.
360 this->store->ReadMetadata(this->read_metadata_callback);
361 this->ClearAndPumpLoop();
362 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
363 EXPECT_EQ(0U, this->attachment_metadata->size());
365 // Create and write attachments with different set of references.
366 Attachment attachment_mt = Attachment::Create(this->some_data1);
367 Attachment attachment_sync = Attachment::Create(this->some_data1);
368 Attachment attachment_both = Attachment::Create(this->some_data1);
370 AttachmentList attachments;
371 attachments.push_back(attachment_mt);
372 attachments.push_back(attachment_sync);
373 attachments.push_back(attachment_both);
374 this->store->Write(attachments, this->write_callback);
375 this->ClearAndPumpLoop();
376 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
378 AttachmentIdList ids;
379 ids.push_back(attachment_sync.GetId());
380 ids.push_back(attachment_both.GetId());
381 this->store_for_sync->SetSyncReference(ids);
383 ids.clear();
384 ids.push_back(attachment_sync.GetId());
385 this->store->Drop(ids, this->drop_callback);
386 this->ClearAndPumpLoop();
388 // Calling ReadMetadataById for above three attachments should only return
389 // attachments with model type reference.
390 ids.clear();
391 ids.push_back(attachment_mt.GetId());
392 ids.push_back(attachment_sync.GetId());
393 ids.push_back(attachment_both.GetId());
394 this->store->ReadMetadataById(ids, this->read_metadata_callback);
395 this->ClearAndPumpLoop();
396 EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, this->result);
397 EXPECT_EQ(2U, this->attachment_metadata->size());
398 AttachmentIdSet model_type_id_set;
399 model_type_id_set.insert(attachment_mt.GetId());
400 model_type_id_set.insert(attachment_both.GetId());
401 EXPECT_THAT(model_type_id_set,
402 testing::Contains((*this->attachment_metadata)[0].GetId()));
403 EXPECT_THAT(model_type_id_set,
404 testing::Contains((*this->attachment_metadata)[1].GetId()));
406 // Call to ReadMetadata() should only return attachments with model type
407 // reference.
408 this->store->ReadMetadata(this->read_metadata_callback);
409 this->ClearAndPumpLoop();
410 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
411 EXPECT_EQ(2U, this->attachment_metadata->size());
413 // Verify that we get all attachments back (the order is undefined).
414 EXPECT_THAT(model_type_id_set,
415 testing::Contains((*this->attachment_metadata)[0].GetId()));
416 EXPECT_THAT(model_type_id_set,
417 testing::Contains((*this->attachment_metadata)[1].GetId()));
419 // Call to ReadMetadataForSync() should only return attachments with sync
420 // reference.
421 this->store_for_sync->ReadMetadataForSync(this->read_metadata_callback);
422 this->ClearAndPumpLoop();
423 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
424 EXPECT_EQ(2U, this->attachment_metadata->size());
426 AttachmentIdSet sync_id_set;
427 sync_id_set.insert(attachment_sync.GetId());
428 sync_id_set.insert(attachment_both.GetId());
429 EXPECT_THAT(sync_id_set,
430 testing::Contains((*this->attachment_metadata)[0].GetId()));
431 EXPECT_THAT(sync_id_set,
432 testing::Contains((*this->attachment_metadata)[1].GetId()));
435 // Verify that setting/droping references gets reflected in ReadMetadata and
436 // that attachment is only deleted after last reference is droped.
437 TYPED_TEST_P(AttachmentStoreTest, SetSyncReference_DropSyncReference) {
438 Attachment attachment = Attachment::Create(this->some_data1);
439 AttachmentList attachments;
440 attachments.push_back(attachment);
441 AttachmentIdList ids;
442 ids.push_back(attachment.GetId());
444 // When writing attachment to store only model type reference should be set.
445 this->store->Write(attachments, this->write_callback);
447 this->store->ReadMetadata(this->read_metadata_callback);
448 this->ClearAndPumpLoop();
449 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
450 EXPECT_EQ(1U, this->attachment_metadata->size());
451 EXPECT_EQ(attachment.GetId(), this->attachment_metadata->begin()->GetId());
453 this->store_for_sync->ReadMetadataForSync(this->read_metadata_callback);
454 this->ClearAndPumpLoop();
455 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
456 EXPECT_EQ(0U, this->attachment_metadata->size());
458 // After call to SetSyncReference() ReadMetadataForSync should start returning
459 // attachment.
460 this->store_for_sync->SetSyncReference(ids);
462 this->store_for_sync->ReadMetadataForSync(this->read_metadata_callback);
463 this->ClearAndPumpLoop();
464 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
465 EXPECT_EQ(1U, this->attachment_metadata->size());
467 // Call SetSyncReference() to verify it is idempotent.
468 this->store_for_sync->SetSyncReference(ids);
469 this->ClearAndPumpLoop();
471 // Droping attachment should remove model type reference, but there is still
472 // sync reference.
473 this->store->Drop(ids, this->drop_callback);
474 this->ClearAndPumpLoop();
475 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
477 this->store->ReadMetadata(this->read_metadata_callback);
478 this->ClearAndPumpLoop();
479 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
480 EXPECT_EQ(0U, this->attachment_metadata->size());
482 this->store_for_sync->ReadMetadataForSync(this->read_metadata_callback);
483 this->ClearAndPumpLoop();
484 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
485 EXPECT_EQ(1U, this->attachment_metadata->size());
487 // ReadMetadataById should return UNSPECIFIED_ERROR, attachment doesn't have
488 // model type reference.
489 this->store->ReadMetadataById(ids, this->read_metadata_callback);
490 this->ClearAndPumpLoop();
491 EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, this->result);
492 EXPECT_EQ(0U, this->attachment_metadata->size());
494 // Call Drop() again to ensure it doesn't fail.
495 this->store->Drop(ids, this->drop_callback);
496 this->ClearAndPumpLoop();
497 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
499 // After droping sync reference attachment should be deleted from store.
500 // ReadMetadataForSync should return empty result.
501 this->store_for_sync->DropSyncReference(ids);
503 this->store_for_sync->ReadMetadataForSync(this->read_metadata_callback);
504 this->ClearAndPumpLoop();
505 EXPECT_EQ(AttachmentStore::SUCCESS, this->result);
506 EXPECT_EQ(0U, this->attachment_metadata->size());
509 REGISTER_TYPED_TEST_CASE_P(AttachmentStoreTest,
510 CreateAttachmentStoreForSync,
511 Write_NoOverwriteNoError,
512 Write_RoundTrip,
513 Read_OneNotFound,
514 Drop_DropTwoButOnlyOneExists,
515 Drop_DoesNotExist,
516 ReadMetadataById,
517 ReadMetadata,
518 SetSyncReference_DropSyncReference);
520 } // namespace syncer
522 #endif // SYNC_INTERNAL_API_ATTACHMENTS_ATTACHMENT_STORE_TEST_TEMPLATE_H_