- add sources.
[platform/framework/web/crosswalk.git] / src / sync / engine / sync_directory_commit_contribution_unittest.cc
1 // Copyright 2013 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/engine/sync_directory_commit_contribution.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "sync/sessions/status_controller.h"
9 #include "sync/syncable/entry.h"
10 #include "sync/syncable/mutable_entry.h"
11 #include "sync/syncable/syncable_read_transaction.h"
12 #include "sync/syncable/syncable_write_transaction.h"
13 #include "sync/test/engine/test_directory_setter_upper.h"
14 #include "sync/test/engine/test_id_factory.h"
15 #include "sync/test/engine/test_syncable_utils.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace syncer {
19
20 class SyncDirectoryCommitContributionTest : public ::testing::Test {
21  public:
22   virtual void SetUp() OVERRIDE {
23     dir_maker_.SetUp();
24
25     syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir());
26     CreateTypeRoot(&trans, dir(), PREFERENCES);
27     CreateTypeRoot(&trans, dir(), EXTENSIONS);
28   }
29
30   virtual void TearDown() OVERRIDE {
31     dir_maker_.TearDown();
32   }
33
34  protected:
35   int64 CreateUnsyncedItem(syncable::WriteTransaction* trans,
36                            ModelType type,
37                            const std::string& tag) {
38     syncable::Entry parent_entry(
39         trans,
40         syncable::GET_BY_SERVER_TAG,
41         ModelTypeToRootTag(type));
42     syncable::MutableEntry entry(
43         trans,
44         syncable::CREATE,
45         type,
46         parent_entry.GetId(),
47         tag);
48     entry.PutIsUnsynced(true);
49     return entry.GetMetahandle();
50   }
51
52   void CreateSuccessfulCommitResponse(
53       const sync_pb::SyncEntity& entity,
54       sync_pb::CommitResponse::EntryResponse* response) {
55     response->set_response_type(sync_pb::CommitResponse::SUCCESS);
56     response->set_non_unique_name(entity.name());
57     response->set_version(entity.version() + 1);
58     response->set_parent_id_string(entity.parent_id_string());
59
60     if (entity.id_string()[0] == '-')  // Look for the - in 'c-1234' style IDs.
61       response->set_id_string(id_factory_.NewServerId().GetServerId());
62     else
63       response->set_id_string(entity.id_string());
64   }
65
66   syncable::Directory* dir() {
67     return dir_maker_.directory();
68   }
69
70   TestIdFactory id_factory_;
71
72  private:
73   base::MessageLoop loop_;  // Neeed to initialize the directory.
74   TestDirectorySetterUpper dir_maker_;
75 };
76
77 // Verify that the SyncDirectoryCommitContribution contains only entries of its
78 // specified type.
79 TEST_F(SyncDirectoryCommitContributionTest, GatherByTypes) {
80   int64 pref1;
81   {
82     syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir());
83     pref1 = CreateUnsyncedItem(&trans, PREFERENCES, "pref1");
84     CreateUnsyncedItem(&trans, PREFERENCES, "pref2");
85     CreateUnsyncedItem(&trans, EXTENSIONS, "extension1");
86   }
87
88   scoped_ptr<SyncDirectoryCommitContribution> cc(
89       SyncDirectoryCommitContribution::Build(dir(), PREFERENCES, 5));
90   ASSERT_EQ(2U, cc->GetNumEntries());
91
92   const std::vector<int64>& metahandles = cc->metahandles_;
93   EXPECT_TRUE(std::find(metahandles.begin(), metahandles.end(), pref1) !=
94               metahandles.end());
95   EXPECT_TRUE(std::find(metahandles.begin(), metahandles.end(), pref1) !=
96               metahandles.end());
97
98   cc->CleanUp();
99 }
100
101 // Verify that the SyncDirectoryCommitContributionTest builder function
102 // truncates if necessary.
103 TEST_F(SyncDirectoryCommitContributionTest, GatherAndTruncate) {
104   int64 pref1;
105   int64 pref2;
106   {
107     syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir());
108     pref1 = CreateUnsyncedItem(&trans, PREFERENCES, "pref1");
109     pref2 = CreateUnsyncedItem(&trans, PREFERENCES, "pref2");
110     CreateUnsyncedItem(&trans, EXTENSIONS, "extension1");
111   }
112
113   scoped_ptr<SyncDirectoryCommitContribution> cc(
114       SyncDirectoryCommitContribution::Build(dir(), PREFERENCES, 1));
115   ASSERT_EQ(1U, cc->GetNumEntries());
116
117   int64 only_metahandle = cc->metahandles_[0];
118   EXPECT_TRUE(only_metahandle == pref1 || only_metahandle == pref2);
119
120   cc->CleanUp();
121 }
122
123 // Sanity check for building commits from SyncDirectoryCommitContributions.
124 // This test makes two CommitContribution objects of different types and uses
125 // them to initialize a commit message.  Then it checks that the contents of the
126 // commit message match those of the directory they came from.
127 TEST_F(SyncDirectoryCommitContributionTest, PrepareCommit) {
128   {
129     syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir());
130     CreateUnsyncedItem(&trans, PREFERENCES, "pref1");
131     CreateUnsyncedItem(&trans, PREFERENCES, "pref2");
132     CreateUnsyncedItem(&trans, EXTENSIONS, "extension1");
133   }
134
135   scoped_ptr<SyncDirectoryCommitContribution> pref_cc(
136       SyncDirectoryCommitContribution::Build(dir(), PREFERENCES, 25));
137   scoped_ptr<SyncDirectoryCommitContribution> ext_cc(
138       SyncDirectoryCommitContribution::Build(dir(), EXTENSIONS, 25));
139
140   sync_pb::ClientToServerMessage message;
141   pref_cc->AddToCommitMessage(&message);
142   ext_cc->AddToCommitMessage(&message);
143
144   const sync_pb::CommitMessage& commit_message = message.commit();
145
146   std::set<syncable::Id> ids_for_commit;
147   ASSERT_EQ(3, commit_message.entries_size());
148   for (int i = 0; i < commit_message.entries_size(); ++i) {
149     const sync_pb::SyncEntity& entity = commit_message.entries(i);
150     // The entities in this test have client-style IDs since they've never been
151     // committed before, so we must use CreateFromClientString to re-create them
152     // from the commit message.
153     ids_for_commit.insert(syncable::Id::CreateFromClientString(
154             entity.id_string()));
155   }
156
157   ASSERT_EQ(3U, ids_for_commit.size());
158   {
159     syncable::ReadTransaction trans(FROM_HERE, dir());
160     for (std::set<syncable::Id>::iterator it = ids_for_commit.begin();
161          it != ids_for_commit.end(); ++it) {
162       SCOPED_TRACE(it->value());
163       syncable::Entry entry(&trans, syncable::GET_BY_ID, *it);
164       ASSERT_TRUE(entry.good());
165       EXPECT_TRUE(entry.GetSyncing());
166     }
167   }
168
169   pref_cc->CleanUp();
170   ext_cc->CleanUp();
171 }
172
173 // Creates some unsynced items, pretends to commit them, and hands back a
174 // specially crafted response to the syncer in order to test commit response
175 // processing.  The response simulates a succesful commit scenario.
176 TEST_F(SyncDirectoryCommitContributionTest, ProcessCommitResponse) {
177   int64 pref1_handle;
178   int64 pref2_handle;
179   int64 ext1_handle;
180   {
181     syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir());
182     pref1_handle = CreateUnsyncedItem(&trans, PREFERENCES, "pref1");
183     pref2_handle = CreateUnsyncedItem(&trans, PREFERENCES, "pref2");
184     ext1_handle = CreateUnsyncedItem(&trans, EXTENSIONS, "extension1");
185   }
186
187   scoped_ptr<SyncDirectoryCommitContribution> pref_cc(
188       SyncDirectoryCommitContribution::Build(dir(), PREFERENCES, 25));
189   scoped_ptr<SyncDirectoryCommitContribution> ext_cc(
190       SyncDirectoryCommitContribution::Build(dir(), EXTENSIONS, 25));
191
192   sync_pb::ClientToServerMessage message;
193   pref_cc->AddToCommitMessage(&message);
194   ext_cc->AddToCommitMessage(&message);
195
196   const sync_pb::CommitMessage& commit_message = message.commit();
197   ASSERT_EQ(3, commit_message.entries_size());
198
199   sync_pb::ClientToServerResponse response;
200   for (int i = 0; i < commit_message.entries_size(); ++i) {
201     sync_pb::SyncEntity entity = commit_message.entries(i);
202     sync_pb::CommitResponse_EntryResponse* entry_response =
203         response.mutable_commit()->add_entryresponse();
204     CreateSuccessfulCommitResponse(entity, entry_response);
205   }
206
207   sessions::StatusController status;
208
209   // Process these in reverse order.  Just because we can.
210   ext_cc->ProcessCommitResponse(response, &status);
211   pref_cc->ProcessCommitResponse(response, &status);
212
213   {
214     syncable::ReadTransaction trans(FROM_HERE, dir());
215     syncable::Entry p1(&trans, syncable::GET_BY_HANDLE, pref1_handle);
216     EXPECT_TRUE(p1.GetId().ServerKnows());
217     EXPECT_FALSE(p1.GetSyncing());
218     EXPECT_LT(0, p1.GetServerVersion());
219
220     syncable::Entry p2(&trans, syncable::GET_BY_HANDLE, pref2_handle);
221     EXPECT_TRUE(p2.GetId().ServerKnows());
222     EXPECT_FALSE(p2.GetSyncing());
223     EXPECT_LT(0, p2.GetServerVersion());
224
225     syncable::Entry e1(&trans, syncable::GET_BY_HANDLE, ext1_handle);
226     EXPECT_TRUE(e1.GetId().ServerKnows());
227     EXPECT_FALSE(e1.GetSyncing());
228     EXPECT_LT(0, e1.GetServerVersion());
229   }
230
231   pref_cc->CleanUp();
232   ext_cc->CleanUp();
233 }
234
235 }  // namespace syncer