1// Copyright 2012 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/internal_api/public/test/test_entry_factory.h"
6
7#include "sync/syncable/directory.h"
8#include "sync/syncable/entry.h"
9#include "sync/syncable/mutable_entry.h"
10#include "sync/syncable/syncable_id.h"
11#include "sync/syncable/syncable_read_transaction.h"
12#include "sync/syncable/syncable_util.h"
13#include "sync/syncable/syncable_write_transaction.h"
14#include "sync/test/engine/test_id_factory.h"
15
16using std::string;
17
18namespace syncer {
19
20using syncable::Id;
21using syncable::MutableEntry;
22using syncable::UNITTEST;
23using syncable::WriteTransaction;
24
25TestEntryFactory::TestEntryFactory(syncable::Directory *dir)
26    : directory_(dir), next_revision_(1) {
27}
28
29TestEntryFactory::~TestEntryFactory() { }
30
31int64 TestEntryFactory::CreateUnappliedNewItemWithParent(
32    const string& item_id,
33    const sync_pb::EntitySpecifics& specifics,
34    const string& parent_id) {
35  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
36  MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
37      Id::CreateFromServerId(item_id));
38  DCHECK(entry.good());
39  entry.PutServerVersion(GetNextRevision());
40  entry.PutIsUnappliedUpdate(true);
41
42  entry.PutServerNonUniqueName(item_id);
43  entry.PutServerParentId(Id::CreateFromServerId(parent_id));
44  entry.PutServerIsDir(true);
45  entry.PutServerSpecifics(specifics);
46  return entry.GetMetahandle();
47}
48
49int64 TestEntryFactory::CreateUnappliedNewBookmarkItemWithParent(
50    const string& item_id,
51    const sync_pb::EntitySpecifics& specifics,
52    const string& parent_id) {
53  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
54  MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
55      Id::CreateFromServerId(item_id));
56  DCHECK(entry.good());
57  entry.PutServerVersion(GetNextRevision());
58  entry.PutIsUnappliedUpdate(true);
59
60  entry.PutServerNonUniqueName(item_id);
61  entry.PutServerParentId(Id::CreateFromServerId(parent_id));
62  entry.PutServerIsDir(true);
63  entry.PutServerSpecifics(specifics);
64
65  return entry.GetMetahandle();
66}
67
68int64 TestEntryFactory::CreateUnappliedNewItem(
69    const string& item_id,
70    const sync_pb::EntitySpecifics& specifics,
71    bool is_unique) {
72  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
73  MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
74      Id::CreateFromServerId(item_id));
75  DCHECK(entry.good());
76  entry.PutServerVersion(GetNextRevision());
77  entry.PutIsUnappliedUpdate(true);
78  entry.PutServerNonUniqueName(item_id);
79  entry.PutServerParentId(syncable::GetNullId());
80  entry.PutServerIsDir(is_unique);
81  entry.PutServerSpecifics(specifics);
82  if (is_unique) { // For top-level nodes.
83    entry.PutUniqueServerTag(
84              ModelTypeToRootTag(GetModelTypeFromSpecifics(specifics)));
85  }
86  return entry.GetMetahandle();
87}
88
89void TestEntryFactory::CreateUnsyncedItem(
90    const Id& item_id,
91    const Id& parent_id,
92    const string& name,
93    bool is_folder,
94    ModelType model_type,
95    int64* metahandle_out) {
96  if (is_folder) {
97    DCHECK_EQ(model_type, BOOKMARKS);
98  }
99
100  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
101
102  MutableEntry entry(&trans, syncable::CREATE, model_type, parent_id, name);
103  DCHECK(entry.good());
104  entry.PutId(item_id);
105  entry.PutBaseVersion(
106      item_id.ServerKnows() ? GetNextRevision() : 0);
107  entry.PutIsUnsynced(true);
108  entry.PutIsDir(is_folder);
109  entry.PutIsDel(false);
110  entry.PutParentId(parent_id);
111  sync_pb::EntitySpecifics default_specifics;
112  AddDefaultFieldValue(model_type, &default_specifics);
113  entry.PutSpecifics(default_specifics);
114
115  if (item_id.ServerKnows()) {
116    entry.PutServerSpecifics(default_specifics);
117    entry.PutServerIsDir(false);
118    entry.PutServerParentId(parent_id);
119    entry.PutServerIsDel(false);
120  }
121  if (metahandle_out)
122    *metahandle_out = entry.GetMetahandle();
123}
124
125int64 TestEntryFactory::CreateUnappliedAndUnsyncedBookmarkItem(
126    const string& name) {
127  int64 metahandle = 0;
128  CreateUnsyncedItem(
129      TestIdFactory::MakeServer(name), TestIdFactory::root(),
130      name, false, BOOKMARKS, &metahandle);
131
132  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
133  MutableEntry entry(&trans, syncable::GET_BY_HANDLE, metahandle);
134  if (!entry.good()) {
135    NOTREACHED();
136    return syncable::kInvalidMetaHandle;
137  }
138
139  entry.PutIsUnappliedUpdate(true);
140  entry.PutServerVersion(GetNextRevision());
141
142  return metahandle;
143}
144
145int64 TestEntryFactory::CreateSyncedItem(
146    const std::string& name, ModelType model_type, bool is_folder) {
147  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
148
149  syncable::Id parent_id(TestIdFactory::root());
150  syncable::Id item_id(TestIdFactory::MakeServer(name));
151  int64 version = GetNextRevision();
152
153  MutableEntry entry(&trans, syncable::CREATE, model_type, parent_id, name);
154  if (!entry.good()) {
155    NOTREACHED();
156    return syncable::kInvalidMetaHandle;
157  }
158
159  entry.PutId(item_id);
160  entry.PutBaseVersion(version);
161  entry.PutIsUnsynced(false);
162  entry.PutNonUniqueName(name);
163  entry.PutIsDir(is_folder);
164  entry.PutIsDel(false);
165  entry.PutParentId(parent_id);
166
167  entry.PutServerVersion(GetNextRevision());
168  entry.PutIsUnappliedUpdate(false);
169  entry.PutServerNonUniqueName(name);
170  entry.PutServerParentId(parent_id);
171  entry.PutServerIsDir(is_folder);
172  entry.PutServerIsDel(false);
173  entry.PutServerSpecifics(entry.GetSpecifics());
174
175  return entry.GetMetahandle();
176}
177
178int64 TestEntryFactory::CreateUnappliedRootNode(
179    ModelType model_type) {
180  syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, directory_);
181  sync_pb::EntitySpecifics specifics;
182  AddDefaultFieldValue(model_type, &specifics);
183  syncable::Id node_id = TestIdFactory::MakeServer("xyz");
184  syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
185                               node_id);
186  DCHECK(entry.good());
187  // Make it look like sort of like a pending creation from the server.
188  // The SERVER_PARENT_ID and UNIQUE_CLIENT_TAG aren't quite right, but
189  // it's good enough for our purposes.
190  entry.PutServerVersion(1);
191  entry.PutIsUnappliedUpdate(true);
192  entry.PutServerIsDir(false);
193  entry.PutServerParentId(TestIdFactory::root());
194  entry.PutServerSpecifics(specifics);
195  entry.PutNonUniqueName("xyz");
196
197  return entry.GetMetahandle();
198}
199
200bool TestEntryFactory::SetServerSpecificsForItem(
201    int64 meta_handle,
202    const sync_pb::EntitySpecifics specifics) {
203  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
204  MutableEntry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
205  if (!entry.good()) {
206    return false;
207  }
208  entry.PutServerSpecifics(specifics);
209  entry.PutIsUnappliedUpdate(true);
210  return true;
211}
212
213bool TestEntryFactory::SetLocalSpecificsForItem(
214    int64 meta_handle,
215    const sync_pb::EntitySpecifics specifics) {
216  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
217  MutableEntry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
218  if (!entry.good()) {
219    return false;
220  }
221  entry.PutSpecifics(specifics);
222  entry.PutIsUnsynced(true);
223  return true;
224}
225
226const sync_pb::EntitySpecifics& TestEntryFactory::GetServerSpecificsForItem(
227    int64 meta_handle) const {
228  syncable::ReadTransaction trans(FROM_HERE, directory_);
229  syncable::Entry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
230  DCHECK(entry.good());
231  return entry.GetServerSpecifics();
232}
233
234const sync_pb::EntitySpecifics& TestEntryFactory::GetLocalSpecificsForItem(
235    int64 meta_handle) const {
236  syncable::ReadTransaction trans(FROM_HERE, directory_);
237  syncable::Entry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
238  DCHECK(entry.good());
239  return entry.GetSpecifics();
240}
241
242bool TestEntryFactory::SetServerAttachmentMetadataForItem(
243    int64 meta_handle,
244    const sync_pb::AttachmentMetadata metadata) {
245  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
246  MutableEntry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
247  if (!entry.good()) {
248    return false;
249  }
250  entry.PutServerAttachmentMetadata(metadata);
251  entry.PutIsUnappliedUpdate(true);
252  return true;
253
254}
255
256bool TestEntryFactory::SetLocalAttachmentMetadataForItem(
257    int64 meta_handle,
258    const sync_pb::AttachmentMetadata metadata) {
259  WriteTransaction trans(FROM_HERE, UNITTEST, directory_);
260  MutableEntry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
261  if (!entry.good()) {
262    return false;
263  }
264  entry.PutAttachmentMetadata(metadata);
265  entry.PutIsUnsynced(true);
266  return true;
267}
268
269const sync_pb::AttachmentMetadata&
270TestEntryFactory::GetServerAttachmentMetadataForItem(int64 meta_handle) const {
271  syncable::ReadTransaction trans(FROM_HERE, directory_);
272  syncable::Entry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
273  DCHECK(entry.good());
274  return entry.GetServerAttachmentMetadata();
275}
276
277const sync_pb::AttachmentMetadata&
278TestEntryFactory::GetLocalAttachmentMetadataForItem(int64 meta_handle) const {
279  syncable::ReadTransaction trans(FROM_HERE, directory_);
280  syncable::Entry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
281  DCHECK(entry.good());
282  return entry.GetAttachmentMetadata();
283}
284
285bool TestEntryFactory::GetIsUnsyncedForItem(int64 meta_handle) const {
286  syncable::ReadTransaction trans(FROM_HERE, directory_);
287  syncable::Entry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
288  if (!entry.good()) {
289    NOTREACHED();
290    return false;
291  }
292  return entry.GetIsUnsynced();
293}
294
295bool TestEntryFactory::GetIsUnappliedForItem(int64 meta_handle) const {
296  syncable::ReadTransaction trans(FROM_HERE, directory_);
297  syncable::Entry entry(&trans, syncable::GET_BY_HANDLE, meta_handle);
298  if (!entry.good()) {
299    NOTREACHED();
300    return false;
301  }
302  return entry.GetIsUnappliedUpdate();
303}
304
305int64 TestEntryFactory::GetNextRevision() {
306  return next_revision_++;
307}
308
309}  // namespace syncer
310