Home | History | Annotate | Download | only in attachments
      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 "sync/api/attachments/fake_attachment_store.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/ref_counted_memory.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/thread_task_runner_handle.h"
     12 #include "sync/api/attachments/attachment.h"
     13 #include "sync/protocol/sync.pb.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace syncer {
     17 
     18 const char kTestData1[] = "test data 1";
     19 const char kTestData2[] = "test data 2";
     20 
     21 class FakeAttachmentStoreTest : public testing::Test {
     22  protected:
     23   base::MessageLoop message_loop;
     24   scoped_refptr<FakeAttachmentStore> store;
     25   AttachmentStore::Result result;
     26   scoped_ptr<AttachmentMap> attachments;
     27   scoped_ptr<AttachmentIdList> failed_attachment_ids;
     28 
     29   AttachmentStore::ReadCallback read_callback;
     30   AttachmentStore::WriteCallback write_callback;
     31   AttachmentStore::DropCallback drop_callback;
     32 
     33   scoped_refptr<base::RefCountedString> some_data1;
     34   scoped_refptr<base::RefCountedString> some_data2;
     35 
     36   FakeAttachmentStoreTest()
     37       : store(new FakeAttachmentStore(base::ThreadTaskRunnerHandle::Get())) {}
     38 
     39   virtual void SetUp() {
     40     Clear();
     41     read_callback = base::Bind(&FakeAttachmentStoreTest::CopyResultAttachments,
     42                                base::Unretained(this),
     43                                &result,
     44                                &attachments,
     45                                &failed_attachment_ids);
     46     write_callback = base::Bind(
     47         &FakeAttachmentStoreTest::CopyResult, base::Unretained(this), &result);
     48     drop_callback = write_callback;
     49 
     50     some_data1 = new base::RefCountedString;
     51     some_data1->data() = kTestData1;
     52 
     53     some_data2 = new base::RefCountedString;
     54     some_data2->data() = kTestData2;
     55   }
     56 
     57   virtual void ClearAndPumpLoop() {
     58     Clear();
     59     message_loop.RunUntilIdle();
     60   }
     61 
     62  private:
     63   void Clear() {
     64     result = AttachmentStore::UNSPECIFIED_ERROR;
     65     attachments.reset();
     66     failed_attachment_ids.reset();
     67   }
     68 
     69   void CopyResult(AttachmentStore::Result* destination_result,
     70                   const AttachmentStore::Result& source_result) {
     71     *destination_result = source_result;
     72   }
     73 
     74   void CopyResultAttachments(
     75       AttachmentStore::Result* destination_result,
     76       scoped_ptr<AttachmentMap>* destination_attachments,
     77       scoped_ptr<AttachmentIdList>* destination_failed_attachment_ids,
     78       const AttachmentStore::Result& source_result,
     79       scoped_ptr<AttachmentMap> source_attachments,
     80       scoped_ptr<AttachmentIdList> source_failed_attachment_ids) {
     81     CopyResult(destination_result, source_result);
     82     *destination_attachments = source_attachments.Pass();
     83     *destination_failed_attachment_ids = source_failed_attachment_ids.Pass();
     84   }
     85 };
     86 
     87 // Verify that we do not overwrite existing attachments and that we do not treat
     88 // it as an error.
     89 TEST_F(FakeAttachmentStoreTest, Write_NoOverwriteNoError) {
     90   // Create two attachments with the same id but different data.
     91   Attachment attachment1 = Attachment::Create(some_data1);
     92   Attachment attachment2 =
     93       Attachment::CreateWithId(attachment1.GetId(), some_data2);
     94 
     95   // Write the first one.
     96   AttachmentList some_attachments;
     97   some_attachments.push_back(attachment1);
     98   store->Write(some_attachments, write_callback);
     99   ClearAndPumpLoop();
    100   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    101 
    102   // Write the second one.
    103   some_attachments.clear();
    104   some_attachments.push_back(attachment2);
    105   store->Write(some_attachments, write_callback);
    106   ClearAndPumpLoop();
    107   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    108 
    109   // Read it back and see that it was not overwritten.
    110   AttachmentIdList some_attachment_ids;
    111   some_attachment_ids.push_back(attachment1.GetId());
    112   store->Read(some_attachment_ids, read_callback);
    113   ClearAndPumpLoop();
    114   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    115   EXPECT_EQ(attachments->size(), 1U);
    116   EXPECT_EQ(failed_attachment_ids->size(), 0U);
    117   AttachmentMap::const_iterator a1 = attachments->find(attachment1.GetId());
    118   EXPECT_TRUE(a1 != attachments->end());
    119   EXPECT_TRUE(attachment1.GetData()->Equals(a1->second.GetData()));
    120 }
    121 
    122 // Verify that we can write some attachments and read them back.
    123 TEST_F(FakeAttachmentStoreTest, Write_RoundTrip) {
    124   Attachment attachment1 = Attachment::Create(some_data1);
    125   Attachment attachment2 = Attachment::Create(some_data2);
    126   AttachmentList some_attachments;
    127   some_attachments.push_back(attachment1);
    128   some_attachments.push_back(attachment2);
    129 
    130   store->Write(some_attachments, write_callback);
    131   ClearAndPumpLoop();
    132   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    133 
    134   AttachmentIdList some_attachment_ids;
    135   some_attachment_ids.push_back(attachment1.GetId());
    136   some_attachment_ids.push_back(attachment2.GetId());
    137   store->Read(some_attachment_ids, read_callback);
    138   ClearAndPumpLoop();
    139   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    140   EXPECT_EQ(attachments->size(), 2U);
    141   EXPECT_EQ(failed_attachment_ids->size(), 0U);
    142 
    143   AttachmentMap::const_iterator a1 = attachments->find(attachment1.GetId());
    144   EXPECT_TRUE(a1 != attachments->end());
    145   EXPECT_TRUE(attachment1.GetData()->Equals(a1->second.GetData()));
    146 
    147   AttachmentMap::const_iterator a2 = attachments->find(attachment2.GetId());
    148   EXPECT_TRUE(a2 != attachments->end());
    149   EXPECT_TRUE(attachment2.GetData()->Equals(a2->second.GetData()));
    150 }
    151 
    152 // Try to read two attachments when only one exists.
    153 TEST_F(FakeAttachmentStoreTest, Read_OneNotFound) {
    154   Attachment attachment1 = Attachment::Create(some_data1);
    155   Attachment attachment2 = Attachment::Create(some_data2);
    156 
    157   AttachmentList some_attachments;
    158   // Write attachment1 only.
    159   some_attachments.push_back(attachment1);
    160   store->Write(some_attachments, write_callback);
    161   ClearAndPumpLoop();
    162   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    163 
    164   // Try to read both attachment1 and attachment2.
    165   AttachmentIdList ids;
    166   ids.push_back(attachment1.GetId());
    167   ids.push_back(attachment2.GetId());
    168   store->Read(ids, read_callback);
    169   ClearAndPumpLoop();
    170 
    171   // See that only attachment1 was read.
    172   EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR);
    173   EXPECT_EQ(attachments->size(), 1U);
    174   EXPECT_EQ(failed_attachment_ids->size(), 1U);
    175 }
    176 
    177 // Try to drop two attachments when only one exists. Verify that no error occurs
    178 // and that the existing attachment was dropped.
    179 TEST_F(FakeAttachmentStoreTest, Drop_DropTwoButOnlyOneExists) {
    180   // First, create two attachments.
    181   Attachment attachment1 = Attachment::Create(some_data1);
    182   Attachment attachment2 = Attachment::Create(some_data2);
    183   AttachmentList some_attachments;
    184   some_attachments.push_back(attachment1);
    185   some_attachments.push_back(attachment2);
    186   store->Write(some_attachments, write_callback);
    187   ClearAndPumpLoop();
    188   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    189 
    190   // Drop attachment1 only.
    191   AttachmentIdList ids;
    192   ids.push_back(attachment1.GetId());
    193   store->Drop(ids, drop_callback);
    194   ClearAndPumpLoop();
    195   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    196 
    197   // See that attachment1 is gone.
    198   store->Read(ids, read_callback);
    199   ClearAndPumpLoop();
    200   EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR);
    201   EXPECT_EQ(attachments->size(), 0U);
    202   EXPECT_EQ(failed_attachment_ids->size(), 1U);
    203   EXPECT_EQ((*failed_attachment_ids)[0], attachment1.GetId());
    204 
    205   // Drop both attachment1 and attachment2.
    206   ids.clear();
    207   ids.push_back(attachment1.GetId());
    208   ids.push_back(attachment2.GetId());
    209   store->Drop(ids, drop_callback);
    210   ClearAndPumpLoop();
    211   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    212 
    213   // See that attachment2 is now gone.
    214   ids.clear();
    215   ids.push_back(attachment2.GetId());
    216   store->Read(ids, read_callback);
    217   ClearAndPumpLoop();
    218   EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR);
    219   EXPECT_EQ(attachments->size(), 0U);
    220   EXPECT_EQ(failed_attachment_ids->size(), 1U);
    221   EXPECT_EQ((*failed_attachment_ids)[0], attachment2.GetId());
    222 }
    223 
    224 // Verify that attempting to drop an attachment that does not exist is not an
    225 // error.
    226 TEST_F(FakeAttachmentStoreTest, Drop_DoesNotExist) {
    227   Attachment attachment1 = Attachment::Create(some_data1);
    228   AttachmentList some_attachments;
    229   some_attachments.push_back(attachment1);
    230   store->Write(some_attachments, write_callback);
    231   ClearAndPumpLoop();
    232   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    233 
    234   // Drop the attachment.
    235   AttachmentIdList ids;
    236   ids.push_back(attachment1.GetId());
    237   store->Drop(ids, drop_callback);
    238   ClearAndPumpLoop();
    239   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    240 
    241   // See that it's gone.
    242   store->Read(ids, read_callback);
    243   ClearAndPumpLoop();
    244   EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR);
    245   EXPECT_EQ(attachments->size(), 0U);
    246   EXPECT_EQ(failed_attachment_ids->size(), 1U);
    247   EXPECT_EQ((*failed_attachment_ids)[0], attachment1.GetId());
    248 
    249   // Drop again, see that no error occurs.
    250   ids.clear();
    251   ids.push_back(attachment1.GetId());
    252   store->Drop(ids, drop_callback);
    253   ClearAndPumpLoop();
    254   EXPECT_EQ(result, AttachmentStore::SUCCESS);
    255 }
    256 
    257 }  // namespace syncer
    258