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