1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Unit tests for the SyncApi. Note that a lot of the underlying
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// functionality is provided by the Syncable layer, which has its own
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// unit tests. We'll test SyncApi specific things in this harness.
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <map>
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/basictypes.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/format_macros.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/message_loop.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/string_number_conversions.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/string_util.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/utf_string_conversions.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/values.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/http_post_provider_factory.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/http_post_provider_interface.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/sync/engine/model_safe_worker.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncapi.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_arg_list.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_backend.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_event_handler.h"
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_event_router.h"
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_test_util.h"
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/notifier/sync_notifier.h"
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/notifier/sync_notifier_observer.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/password_specifics.pb.h"
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/protocol/proto_value_conversions.h"
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/sync/sessions/sync_session.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/directory_manager.h"
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/sync/syncable/nigori_util.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/syncable.h"
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/sync/syncable/syncable_id.h"
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/sync/util/cryptographer.h"
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/test/sync/engine/test_user_share.h"
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/test/values_test_util.h"
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "testing/gmock/include/gmock/gmock.h"
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing browser_sync::Cryptographer;
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing browser_sync::HasArgsAsList;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::KeyParams;
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing browser_sync::JsArgList;
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing browser_sync::MockJsEventHandler;
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing browser_sync::MockJsEventRouter;
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing browser_sync::ModelSafeRoutingInfo;
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing browser_sync::ModelSafeWorker;
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing browser_sync::ModelSafeWorkerRegistrar;
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing browser_sync::sessions::SyncSessionSnapshot;
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing syncable::ModelType;
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing syncable::ModelTypeSet;
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing test::ExpectDictionaryValue;
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing test::ExpectStringValue;
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing testing::_;
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing testing::AtLeast;
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing testing::Invoke;
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing testing::SaveArg;
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing testing::StrictMock;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace sync_api {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace {
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExpectInt64Value(int64 expected_value,
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                      const DictionaryValue& value, const std::string& key) {
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string int64_str;
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(value.GetString(key, &int64_str));
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int64 val = 0;
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(base::StringToInt64(int64_str, &val));
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(expected_value, val);
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Makes a non-folder child of the root node.  Returns the id of the
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// newly-created node.
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint64 MakeNode(UserShare* share,
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               ModelType model_type,
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen               const std::string& client_tag) {
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  WriteTransaction trans(share);
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ReadNode root_node(&trans);
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  root_node.InitByRootLookup();
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  WriteNode node(&trans);
8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag));
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  node.SetIsFolder(false);
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return node.GetId();
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Make a folder as a child of the root node. Returns the id of the
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// newly-created node.
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint64 MakeFolder(UserShare* share,
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 syncable::ModelType model_type,
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 const std::string& client_tag) {
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WriteTransaction trans(share);
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ReadNode root_node(&trans);
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  root_node.InitByRootLookup();
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WriteNode node(&trans);
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag));
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  node.SetIsFolder(true);
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return node.GetId();
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Makes a non-folder child of a non-root node. Returns the id of the
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// newly-created node.
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint64 MakeNodeWithParent(UserShare* share,
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         ModelType model_type,
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         const std::string& client_tag,
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         int64 parent_id) {
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WriteTransaction trans(share);
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ReadNode parent_node(&trans);
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  parent_node.InitByIdLookup(parent_id);
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WriteNode node(&trans);
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(node.InitUniqueByCreation(model_type, parent_node, client_tag));
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  node.SetIsFolder(false);
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return node.GetId();
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Makes a folder child of a non-root node. Returns the id of the
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// newly-created node.
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint64 MakeFolderWithParent(UserShare* share,
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           ModelType model_type,
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           int64 parent_id,
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           BaseNode* predecessor) {
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WriteTransaction trans(share);
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ReadNode parent_node(&trans);
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  parent_node.InitByIdLookup(parent_id);
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WriteNode node(&trans);
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(node.InitByCreation(model_type, parent_node, predecessor));
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  node.SetIsFolder(true);
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return node.GetId();
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Creates the "synced" root node for a particular datatype. We use the syncable
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// methods here so that the syncer treats these nodes as if they were already
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// received from the server.
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint64 MakeServerNodeForType(UserShare* share,
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            ModelType model_type) {
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sync_pb::EntitySpecifics specifics;
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  syncable::AddDefaultExtensionValue(model_type, &specifics);
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name);
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(dir.good());
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  syncable::WriteTransaction trans(dir, syncable::UNITTEST, __FILE__, __LINE__);
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Attempt to lookup by nigori tag.
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::string type_tag = syncable::ModelTypeToRootTag(model_type);
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  syncable::Id node_id = syncable::Id::CreateFromServerId(type_tag);
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                               node_id);
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(entry.good());
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::BASE_VERSION, 1);
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::SERVER_VERSION, 1);
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::IS_UNAPPLIED_UPDATE, false);
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::SERVER_PARENT_ID, syncable::kNullId);
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::SERVER_IS_DIR, true);
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::IS_DIR, true);
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::SERVER_SPECIFICS, specifics);
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::UNIQUE_SERVER_TAG, type_tag);
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::NON_UNIQUE_NAME, type_tag);
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::IS_DEL, false);
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  entry.Put(syncable::SPECIFICS, specifics);
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return entry.Get(syncable::META_HANDLE);
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}  // namespace
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SyncApiTest : public testing::Test {
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void SetUp() {
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    test_user_share_.SetUp();
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TearDown() {
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    test_user_share_.TearDown();
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser_sync::TestUserShare test_user_share_;
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SyncApiTest, SanityCheckTest) {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(trans.GetWrappedTrans() != NULL);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(test_user_share_.user_share());
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(trans.GetWrappedTrans() != NULL);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // No entries but root should exist
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode node(&trans);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Metahandle 1 can be root, sanity check 2
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(node.InitByIdLookup(2));
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SyncApiTest, BasicTagWrite) {
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode root_node(&trans);
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    root_node.InitByRootLookup();
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(root_node.GetFirstChildId(), 0);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ignore_result(MakeNode(test_user_share_.user_share(),
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         syncable::BOOKMARKS, "testtag"));
21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode node(&trans);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS,
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "testtag"));
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode root_node(&trans);
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    root_node.InitByRootLookup();
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_NE(node.GetId(), 0);
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(node.GetId(), root_node.GetFirstChildId());
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SyncApiTest, GenerateSyncableHash) {
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("OyaXV5mEzrPS4wbogmtKvRfekAI=",
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, "tag1"));
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("iNFQtRFQb+IZcn1kKUJEZDDkLs4=",
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BaseNode::GenerateSyncableHash(syncable::PREFERENCES, "tag1"));
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("gO1cPZQXaM73sHOvSA+tKCKFs58=",
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BaseNode::GenerateSyncableHash(syncable::AUTOFILL, "tag1"));
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("A0eYIHXM1/jVwKDDp12Up20IkKY=",
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, "tag2"));
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("XYxkF7bhS4eItStFgiOIAU23swI=",
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BaseNode::GenerateSyncableHash(syncable::PREFERENCES, "tag2"));
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("GFiWzo5NGhjLlN+OyCfhy28DJTQ=",
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BaseNode::GenerateSyncableHash(syncable::AUTOFILL, "tag2"));
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SyncApiTest, ModelTypesSiloed) {
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(test_user_share_.user_share());
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode root_node(&trans);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    root_node.InitByRootLookup();
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(root_node.GetFirstChildId(), 0);
24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ignore_result(MakeNode(test_user_share_.user_share(),
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         syncable::BOOKMARKS, "collideme"));
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ignore_result(MakeNode(test_user_share_.user_share(),
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         syncable::PREFERENCES, "collideme"));
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ignore_result(MakeNode(test_user_share_.user_share(),
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         syncable::AUTOFILL, "collideme"));
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode bookmarknode(&trans);
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(bookmarknode.InitByClientTagLookup(syncable::BOOKMARKS,
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "collideme"));
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode prefnode(&trans);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(prefnode.InitByClientTagLookup(syncable::PREFERENCES,
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "collideme"));
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode autofillnode(&trans);
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(autofillnode.InitByClientTagLookup(syncable::AUTOFILL,
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "collideme"));
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_NE(bookmarknode.GetId(), prefnode.GetId());
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_NE(autofillnode.GetId(), prefnode.GetId());
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_NE(bookmarknode.GetId(), autofillnode.GetId());
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SyncApiTest, ReadMissingTagsFails) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode node(&trans);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(node.InitByClientTagLookup(syncable::BOOKMARKS,
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "testtag"));
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(test_user_share_.user_share());
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteNode node(&trans);
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(node.InitByClientTagLookup(syncable::BOOKMARKS,
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "testtag"));
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(chron): Hook this all up to the server and write full integration tests
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//              for update->undelete behavior.
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SyncApiTest, TestDeleteBehavior) {
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 node_id;
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 folder_id;
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring test_title(L"test1");
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(test_user_share_.user_share());
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode root_node(&trans);
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    root_node.InitByRootLookup();
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // we'll use this spare folder later
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteNode folder_node(&trans);
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(folder_node.InitByCreation(syncable::BOOKMARKS,
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        root_node, NULL));
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    folder_id = folder_node.GetId();
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteNode wnode(&trans);
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(wnode.InitUniqueByCreation(syncable::BOOKMARKS,
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        root_node, "testtag"));
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    wnode.SetIsFolder(false);
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    wnode.SetTitle(test_title);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node_id = wnode.GetId();
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ensure we can delete something with a tag.
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(test_user_share_.user_share());
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteNode wnode(&trans);
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(wnode.InitByClientTagLookup(syncable::BOOKMARKS,
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "testtag"));
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(wnode.GetIsFolder());
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(wnode.GetTitle(), test_title);
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    wnode.Remove();
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Lookup of a node which was deleted should return failure,
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // but have found some data about the node.
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode node(&trans);
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(node.InitByClientTagLookup(syncable::BOOKMARKS,
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "testtag"));
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Note that for proper function of this API this doesn't need to be
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // filled, we're checking just to make sure the DB worked in this test.
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(node.GetTitle(), test_title);
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(test_user_share_.user_share());
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode folder_node(&trans);
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(folder_node.InitByIdLookup(folder_id));
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteNode wnode(&trans);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This will undelete the tag.
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(wnode.InitUniqueByCreation(syncable::BOOKMARKS,
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        folder_node, "testtag"));
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(wnode.GetIsFolder(), false);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(wnode.GetParentId(), folder_node.GetId());
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(wnode.GetId(), node_id);
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_NE(wnode.GetTitle(), test_title);  // Title should be cleared
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    wnode.SetTitle(test_title);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now look up should work.
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode node(&trans);
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS,
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "testtag"));
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(node.GetTitle(), test_title);
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(node.GetModelType(), syncable::BOOKMARKS);
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SyncApiTest, WriteAndReadPassword) {
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  KeyParams params = {"localhost", "username", "passphrase"};
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    trans.GetCryptographer()->AddKey(params);
374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  {
376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(test_user_share_.user_share());
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode root_node(&trans);
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    root_node.InitByRootLookup();
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteNode password_node(&trans);
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS,
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                   root_node, "foo"));
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sync_pb::PasswordSpecificsData data;
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data.set_password_value("secret");
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    password_node.SetPasswordSpecifics(data);
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode root_node(&trans);
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    root_node.InitByRootLookup();
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReadNode password_node(&trans);
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(password_node.InitByClientTagLookup(syncable::PASSWORDS,
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                    "foo"));
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const sync_pb::PasswordSpecificsData& data =
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        password_node.GetPasswordSpecifics();
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("secret", data.password_value());
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace {
40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid CheckNodeValue(const BaseNode& node, const DictionaryValue& value) {
40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectInt64Value(node.GetId(), value, "id");
40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectInt64Value(node.GetModificationTime(), value, "modificationTime");
40672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectInt64Value(node.GetParentId(), value, "parentId");
40772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool is_folder = false;
40972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_TRUE(value.GetBoolean("isFolder", &is_folder));
41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(node.GetIsFolder(), is_folder);
41172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectStringValue(WideToUTF8(node.GetTitle()), value, "title");
41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ModelType expected_model_type = node.GetModelType();
41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string type_str;
41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_TRUE(value.GetString("type", &type_str));
41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (expected_model_type >= syncable::FIRST_REAL_MODEL_TYPE) {
418dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ModelType model_type =
41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          syncable::ModelTypeFromString(type_str);
42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_EQ(expected_model_type, model_type);
42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else if (expected_model_type == syncable::TOP_LEVEL_FOLDER) {
42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_EQ("Top-level folder", type_str);
42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else if (expected_model_type == syncable::UNSPECIFIED) {
42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_EQ("Unspecified", type_str);
42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else {
42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ADD_FAILURE();
42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectInt64Value(node.GetExternalId(), value, "externalId");
43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectInt64Value(node.GetPredecessorId(), value, "predecessorId");
43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectInt64Value(node.GetSuccessorId(), value, "successorId");
43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectInt64Value(node.GetFirstChildId(), value, "firstChildId");
433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  {
434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    scoped_ptr<DictionaryValue> expected_entry(node.GetEntry()->ToValue());
435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Value* entry = NULL;
436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_TRUE(value.Get("entry", &entry));
437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_TRUE(Value::Equals(entry, expected_entry.get()));
438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(11u, value.size());
44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}  // namespace
44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncApiTest, BaseNodeToValue) {
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ReadTransaction trans(test_user_share_.user_share());
44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ReadNode node(&trans);
44772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  node.InitByRootLookup();
44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<DictionaryValue> value(node.ToValue());
44972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (value.get()) {
45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CheckNodeValue(node, *value);
45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ADD_FAILURE();
45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
45472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace {
45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExpectChangeRecordActionValue(SyncManager::ChangeRecord::Action
45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       expected_value,
46072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   const DictionaryValue& value,
46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   const std::string& key) {
46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string str_value;
46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(value.GetString(key, &str_value));
46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  switch (expected_value) {
46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case SyncManager::ChangeRecord::ACTION_ADD:
46672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_EQ("Add", str_value);
46772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
46872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case SyncManager::ChangeRecord::ACTION_UPDATE:
46972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_EQ("Update", str_value);
47072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
47172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case SyncManager::ChangeRecord::ACTION_DELETE:
47272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      EXPECT_EQ("Delete", str_value);
47372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
47472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    default:
47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      NOTREACHED();
47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid CheckNonDeleteChangeRecordValue(const SyncManager::ChangeRecord& record,
48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                     const DictionaryValue& value,
48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                     BaseTransaction* trans) {
48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_NE(SyncManager::ChangeRecord::ACTION_DELETE, record.action);
48472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectChangeRecordActionValue(record.action, value, "action");
48572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
48672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ReadNode node(trans);
48772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_TRUE(node.InitByIdLookup(record.id));
48872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<DictionaryValue> expected_node_value(node.ToValue());
48972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ExpectDictionaryValue(*expected_node_value, value, "node");
49072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
49172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
49372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid CheckDeleteChangeRecordValue(const SyncManager::ChangeRecord& record,
49472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  const DictionaryValue& value) {
49572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(SyncManager::ChangeRecord::ACTION_DELETE, record.action);
49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExpectChangeRecordActionValue(record.action, value, "action");
49772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DictionaryValue* node_value = NULL;
49872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(value.GetDictionary("node", &node_value));
49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (node_value) {
50072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ExpectInt64Value(record.id, *node_value, "id");
50172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<DictionaryValue> expected_specifics_value(
50272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        browser_sync::EntitySpecificsToValue(record.specifics));
50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ExpectDictionaryValue(*expected_specifics_value,
50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                          *node_value, "specifics");
50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<DictionaryValue> expected_extra_value;
50672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (record.extra.get()) {
50772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      expected_extra_value.reset(record.extra->ToValue());
50872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
50972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    Value* extra_value = NULL;
51072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(record.extra.get() != NULL,
51172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              node_value->Get("extra", &extra_value));
51272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_TRUE(Value::Equals(extra_value, expected_extra_value.get()));
51372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
51472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
51572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass MockExtraChangeRecordData
517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    : public SyncManager::ExtraPasswordChangeRecordData {
51872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public:
51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MOCK_CONST_METHOD0(ToValue, DictionaryValue*());
52072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
52172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
52272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}  // namespace
52372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
52472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncApiTest, ChangeRecordToValue) {
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int64 child_id = MakeNode(test_user_share_.user_share(),
526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            syncable::BOOKMARKS, "testtag");
52772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_pb::EntitySpecifics child_specifics;
52872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ReadNode node(&trans);
53172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_TRUE(node.InitByIdLookup(child_id));
53272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    child_specifics = node.GetEntry()->Get(syncable::SPECIFICS);
53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
53472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
53572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Add
53672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
53872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SyncManager::ChangeRecord record;
53972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.action = SyncManager::ChangeRecord::ACTION_ADD;
54072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.id = 1;
54172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.specifics = child_specifics;
54272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.extra.reset(new StrictMock<MockExtraChangeRecordData>());
54372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
54472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CheckNonDeleteChangeRecordValue(record, *value, &trans);
54572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
54672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
54772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Update
54872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
55072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SyncManager::ChangeRecord record;
55172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.action = SyncManager::ChangeRecord::ACTION_UPDATE;
55272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.id = child_id;
55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.specifics = child_specifics;
55472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.extra.reset(new StrictMock<MockExtraChangeRecordData>());
55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
55672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CheckNonDeleteChangeRecordValue(record, *value, &trans);
55772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
55872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
55972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Delete (no extra)
56072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
56272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SyncManager::ChangeRecord record;
56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.action = SyncManager::ChangeRecord::ACTION_DELETE;
56472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.id = child_id + 1;
56572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.specifics = child_specifics;
56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CheckDeleteChangeRecordValue(record, *value);
56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
57072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Delete (with extra)
57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ReadTransaction trans(test_user_share_.user_share());
57372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SyncManager::ChangeRecord record;
57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.action = SyncManager::ChangeRecord::ACTION_DELETE;
57572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.id = child_id + 1;
57672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.specifics = child_specifics;
57772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
57872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DictionaryValue extra_value;
57972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    extra_value.SetString("foo", "bar");
58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<StrictMock<MockExtraChangeRecordData> > extra(
58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        new StrictMock<MockExtraChangeRecordData>());
58272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_CALL(*extra, ToValue()).Times(2).WillRepeatedly(
58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        Invoke(&extra_value, &DictionaryValue::DeepCopy));
58472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
58572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    record.extra.reset(extra.release());
58672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<DictionaryValue> value(record.ToValue(&trans));
58772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CheckDeleteChangeRecordValue(record, *value);
58872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
58972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
59072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
59172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace {
59272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
59372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass TestHttpPostProviderFactory : public HttpPostProviderFactory {
59472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public:
59572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual ~TestHttpPostProviderFactory() {}
59672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual HttpPostProviderInterface* Create() {
59772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED();
59872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return NULL;
59972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
60072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void Destroy(HttpPostProviderInterface* http) {
60172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED();
60272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
60372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
60472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass SyncManagerObserverMock : public SyncManager::Observer {
606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public:
607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD4(OnChangesApplied,
608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               void(ModelType,
609dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    const BaseTransaction*,
610dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    const SyncManager::ChangeRecord*,
611dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    int));  // NOLINT
612dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD1(OnChangesComplete, void(ModelType));  // NOLINT
613dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD1(OnSyncCycleCompleted,
614dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               void(const SyncSessionSnapshot*));  // NOLINT
615dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD0(OnInitializationComplete, void());  // NOLINT
616dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD1(OnAuthError, void(const GoogleServiceAuthError&));  // NOLINT
617dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD1(OnPassphraseRequired, void(bool));  // NOLINT
618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD0(OnPassphraseFailed, void());  // NOLINT
619dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&));  // NOLINT
620dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD0(OnStopSyncingPermanently, void());  // NOLINT
621dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD1(OnUpdatedToken, void(const std::string&));  // NOLINT
622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD1(OnMigrationNeededForTypes, void(const ModelTypeSet&));
623dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD0(OnClearServerDataFailed, void());  // NOLINT
624dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD0(OnClearServerDataSucceeded, void());  // NOLINT
625dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MOCK_METHOD1(OnEncryptionComplete, void(const ModelTypeSet&));  // NOLINT
626dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
627dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass SyncNotifierMock : public sync_notifier::SyncNotifier {
629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD1(AddObserver, void(sync_notifier::SyncNotifierObserver*));
631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD1(RemoveObserver, void(sync_notifier::SyncNotifierObserver*));
632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD1(SetState, void(const std::string&));
633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD2(UpdateCredentials,
634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               void(const std::string&, const std::string&));
635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD1(UpdateEnabledTypes,
636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               void(const syncable::ModelTypeSet&));
637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MOCK_METHOD0(SendNotification, void());
638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
640dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass SyncManagerTest : public testing::Test,
641dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                        public ModelSafeWorkerRegistrar {
64272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen protected:
643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SyncManagerTest()
644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      : ui_thread_(BrowserThread::UI, &ui_loop_),
645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        sync_notifier_observer_(NULL),
646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        update_enabled_types_call_count_(0) {}
64772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
648dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Test implementation.
64972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void SetUp() {
65072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SyncCredentials credentials;
653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    credentials.email = "foo@bar.com";
654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    credentials.sync_token = "sometoken";
655ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sync_notifier_mock_.reset(new StrictMock<SyncNotifierMock>());
657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_CALL(*sync_notifier_mock_, AddObserver(_)).
658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        WillOnce(Invoke(this, &SyncManagerTest::SyncNotifierAddObserver));
659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_CALL(*sync_notifier_mock_, SetState(""));
660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_CALL(*sync_notifier_mock_,
661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                UpdateCredentials(credentials.email, credentials.sync_token));
662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_CALL(*sync_notifier_mock_, UpdateEnabledTypes(_)).
663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        Times(AtLeast(1)).
664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        WillRepeatedly(
665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            Invoke(this, &SyncManagerTest::SyncNotifierUpdateEnabledTypes));
666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_CALL(*sync_notifier_mock_, RemoveObserver(_)).
667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        WillOnce(Invoke(this, &SyncManagerTest::SyncNotifierRemoveObserver));
668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_FALSE(sync_notifier_observer_);
670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
67172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sync_manager_.Init(temp_dir_.path(), "bogus", 0, false,
672dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       new TestHttpPostProviderFactory(), this, "bogus",
673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       credentials, sync_notifier_mock_.get(), "",
674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       true /* setup_for_test_mode */);
675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_TRUE(sync_notifier_observer_);
677dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sync_manager_.AddObserver(&observer_);
678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_EQ(1, update_enabled_types_call_count_);
680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
681dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ModelSafeRoutingInfo routes;
682dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    GetModelSafeRoutingInfo(&routes);
683dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    for (ModelSafeRoutingInfo::iterator i = routes.begin(); i != routes.end();
684dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen         ++i) {
685dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      EXPECT_CALL(observer_, OnChangesApplied(i->first, _, _, 1))
686dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          .RetiresOnSaturation();
687dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      EXPECT_CALL(observer_, OnChangesComplete(i->first))
688dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          .RetiresOnSaturation();
689dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      type_roots_[i->first] = MakeServerNodeForType(
690dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          sync_manager_.GetUserShare(), i->first);
691dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
69272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
69372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
69472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void TearDown() {
695dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sync_manager_.RemoveObserver(&observer_);
69672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sync_manager_.Shutdown();
697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_FALSE(sync_notifier_observer_);
69872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
69972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
700dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // ModelSafeWorkerRegistrar implementation.
701dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) {
702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    NOTIMPLEMENTED();
703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    out->clear();
704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
706dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    (*out)[syncable::NIGORI] = browser_sync::GROUP_PASSIVE;
707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    (*out)[syncable::BOOKMARKS] = browser_sync::GROUP_PASSIVE;
708dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    (*out)[syncable::THEMES] = browser_sync::GROUP_PASSIVE;
709dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    (*out)[syncable::SESSIONS] = browser_sync::GROUP_PASSIVE;
710dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    (*out)[syncable::PASSWORDS] = browser_sync::GROUP_PASSIVE;
711dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
712dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
713dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Helper methods.
714dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool SetUpEncryption() {
715dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We need to create the nigori node as if it were an applied server update.
716dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UserShare* share = sync_manager_.GetUserShare();
717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int64 nigori_id = GetIdForDataType(syncable::NIGORI);
718dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (nigori_id == kInvalidId)
719dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
720dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
721dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Set the nigori cryptographer information.
722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WriteTransaction trans(share);
723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Cryptographer* cryptographer = trans.GetCryptographer();
724dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!cryptographer)
725dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
726dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    KeyParams params = {"localhost", "dummy", "foobar"};
727dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    cryptographer->AddKey(params);
728dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sync_pb::NigoriSpecifics nigori;
729dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    cryptographer->GetKeys(nigori.mutable_encrypted());
730dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    WriteNode node(&trans);
731dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    node.InitByIdLookup(nigori_id);
732dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    node.SetNigoriSpecifics(nigori);
733dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return cryptographer->is_ready();
734dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
735dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
736dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int64 GetIdForDataType(ModelType type) {
737dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (type_roots_.count(type) == 0)
738dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return 0;
739dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return type_roots_[type];
740dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
741dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SyncNotifierAddObserver(
743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      sync_notifier::SyncNotifierObserver* sync_notifier_observer) {
744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_EQ(NULL, sync_notifier_observer_);
745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sync_notifier_observer_ = sync_notifier_observer;
746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SyncNotifierRemoveObserver(
749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      sync_notifier::SyncNotifierObserver* sync_notifier_observer) {
750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_EQ(sync_notifier_observer_, sync_notifier_observer);
751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sync_notifier_observer_ = NULL;
752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SyncNotifierUpdateEnabledTypes(
755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const syncable::ModelTypeSet& types) {
756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ModelSafeRoutingInfo routes;
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GetModelSafeRoutingInfo(&routes);
758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    syncable::ModelTypeSet expected_types;
759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (ModelSafeRoutingInfo::const_iterator it = routes.begin();
760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         it != routes.end(); ++it) {
761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      expected_types.insert(it->first);
762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    EXPECT_EQ(expected_types, types);
764ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ++update_enabled_types_call_count_;
765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
76772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private:
76872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Needed by |ui_thread_|.
76972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MessageLoopForUI ui_loop_;
77072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Needed by |sync_manager_|.
77172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  BrowserThread ui_thread_;
77272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Needed by |sync_manager_|.
77372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ScopedTempDir temp_dir_;
774dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Sync Id's for the roots of the enabled datatypes.
775dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::map<ModelType, int64> type_roots_;
776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<StrictMock<SyncNotifierMock> > sync_notifier_mock_;
77772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
77872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen protected:
77972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SyncManager sync_manager_;
780dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StrictMock<SyncManagerObserverMock> observer_;
781ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sync_notifier::SyncNotifierObserver* sync_notifier_observer_;
782ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int update_enabled_types_call_count_;
78372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
78472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
785ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(SyncManagerTest, UpdateEnabledTypes) {
786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(1, update_enabled_types_call_count_);
787ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Triggers SyncNotifierUpdateEnabledTypes.
788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sync_manager_.UpdateEnabledTypes();
789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(2, update_enabled_types_call_count_);
790ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
791ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
79272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncManagerTest, ParentJsEventRouter) {
79372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventRouter> event_router;
79472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
79572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter());
79672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->SetParentJsEventRouter(&event_router);
79772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(&event_router, js_backend->GetParentJsEventRouter());
79872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->RemoveParentJsEventRouter();
79972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter());
80072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
80172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
80272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncManagerTest, ProcessMessage) {
80372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const JsArgList kNoArgs;
80472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
80572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
80672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
80772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Messages sent without any parent router should be dropped.
80872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
80972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    StrictMock<MockJsEventHandler> event_handler;
81072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("unknownMessage",
81172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               kNoArgs, &event_handler);
81272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNotificationState",
81372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               kNoArgs, &event_handler);
81472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
81572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
81672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
81772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    StrictMock<MockJsEventHandler> event_handler;
81872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    StrictMock<MockJsEventRouter> event_router;
81972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
82072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue false_args;
82172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    false_args.Append(Value::CreateBooleanValue(false));
82272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
82372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_CALL(event_router,
82472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                RouteJsEvent("onGetNotificationStateFinished",
82572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             HasArgsAsList(false_args), &event_handler));
82672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
82772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->SetParentJsEventRouter(&event_router);
82872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
82972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // This message should be dropped.
83072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("unknownMessage",
83172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 kNoArgs, &event_handler);
83272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
83372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // This should trigger the reply.
83472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNotificationState",
83572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 kNoArgs, &event_handler);
83672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
83772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->RemoveParentJsEventRouter();
83872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
83972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
84072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Messages sent after a parent router has been removed should be
84172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // dropped.
84272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
84372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    StrictMock<MockJsEventHandler> event_handler;
84472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("unknownMessage",
84572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 kNoArgs, &event_handler);
84672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNotificationState",
84772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 kNoArgs, &event_handler);
84872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
84972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
85072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
85172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncManagerTest, ProcessMessageGetRootNode) {
85272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const JsArgList kNoArgs;
85372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
85472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
85572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
85672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventHandler> event_handler;
85772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventRouter> event_router;
85872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
85972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  JsArgList return_args;
86072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
86172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_CALL(event_router,
86272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              RouteJsEvent("onGetRootNodeFinished", _, &event_handler)).
86372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      WillOnce(SaveArg<1>(&return_args));
86472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
86572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->SetParentJsEventRouter(&event_router);
86672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
86772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Should trigger the reply.
86872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->ProcessMessage("getRootNode", kNoArgs, &event_handler);
86972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
87072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(1u, return_args.Get().GetSize());
87172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DictionaryValue* node_info = NULL;
87272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(return_args.Get().GetDictionary(0, &node_info));
87372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (node_info) {
87472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ReadTransaction trans(sync_manager_.GetUserShare());
87572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ReadNode node(&trans);
87672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    node.InitByRootLookup();
87772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CheckNodeValue(node, *node_info);
87872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
87972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ADD_FAILURE();
88072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
88172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
88272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->RemoveParentJsEventRouter();
88372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
88472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
88572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid CheckGetNodeByIdReturnArgs(const SyncManager& sync_manager,
88672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                const JsArgList& return_args,
88772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                int64 id) {
88872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_EQ(1u, return_args.Get().GetSize());
88972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DictionaryValue* node_info = NULL;
89072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(return_args.Get().GetDictionary(0, &node_info));
89172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (node_info) {
89272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ReadTransaction trans(sync_manager.GetUserShare());
89372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ReadNode node(&trans);
89472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    node.InitByIdLookup(id);
89572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    CheckNodeValue(node, *node_info);
89672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
89772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ADD_FAILURE();
89872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
89972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
90072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
90172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncManagerTest, ProcessMessageGetNodeById) {
90272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int64 child_id =
90372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      MakeNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, "testtag");
90472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
90572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
90672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
90772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventHandler> event_handler;
90872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventRouter> event_router;
90972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  JsArgList return_args;
91172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_CALL(event_router,
91372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              RouteJsEvent("onGetNodeByIdFinished", _, &event_handler))
91472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      .Times(2).WillRepeatedly(SaveArg<1>(&return_args));
91572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->SetParentJsEventRouter(&event_router);
91772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Should trigger the reply.
91972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
92072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue args;
92172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    args.Append(Value::CreateStringValue("1"));
92272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
92372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
92472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
92572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CheckGetNodeByIdReturnArgs(sync_manager_, return_args, 1);
92672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
92772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Should trigger another reply.
92872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
92972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue args;
93072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    args.Append(Value::CreateStringValue(base::Int64ToString(child_id)));
93172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
93272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
93372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
93472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CheckGetNodeByIdReturnArgs(sync_manager_, return_args, child_id);
93572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
93672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->RemoveParentJsEventRouter();
93772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
93872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
93972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncManagerTest, ProcessMessageGetNodeByIdFailure) {
94072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
94172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
94272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventHandler> event_handler;
94372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventRouter> event_router;
94472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
94572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ListValue null_args;
94672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  null_args.Append(Value::CreateNullValue());
94772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
94872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_CALL(event_router,
94972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              RouteJsEvent("onGetNodeByIdFinished",
95072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                           HasArgsAsList(null_args), &event_handler))
95172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      .Times(5);
95272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
95372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->SetParentJsEventRouter(&event_router);
95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
95572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
95672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue args;
95772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
95872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
95972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
96072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
96172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue args;
96272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    args.Append(Value::CreateStringValue(""));
96372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
96472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
96572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
96672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
96772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue args;
96872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    args.Append(Value::CreateStringValue("nonsense"));
96972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
97072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
97172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
97272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
97372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue args;
97472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    args.Append(Value::CreateStringValue("nonsense"));
97572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
97672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
97772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
97872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
97972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue args;
98072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    args.Append(Value::CreateStringValue("0"));
98172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    js_backend->ProcessMessage("getNodeById", JsArgList(args), &event_handler);
98272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
98372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
98472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(akalin): Figure out how to test InitByIdLookup() failure.
98572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
98672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->RemoveParentJsEventRouter();
98772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
98872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
98972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncManagerTest, OnNotificationStateChange) {
99072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventRouter> event_router;
99172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
99272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ListValue true_args;
99372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  true_args.Append(Value::CreateBooleanValue(true));
99472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ListValue false_args;
99572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  false_args.Append(Value::CreateBooleanValue(false));
99672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
99772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_CALL(event_router,
99872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              RouteJsEvent("onSyncNotificationStateChange",
99972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                           HasArgsAsList(true_args), NULL));
100072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_CALL(event_router,
100172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              RouteJsEvent("onSyncNotificationStateChange",
100272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                           HasArgsAsList(false_args), NULL));
100372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
100472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
100572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
100672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnNotificationStateChangeForTest(true);
100772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnNotificationStateChangeForTest(false);
100872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
100972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->SetParentJsEventRouter(&event_router);
101072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnNotificationStateChangeForTest(true);
101172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnNotificationStateChangeForTest(false);
101272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->RemoveParentJsEventRouter();
101372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
101472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnNotificationStateChangeForTest(true);
101572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnNotificationStateChangeForTest(false);
101672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
101772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
101872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(SyncManagerTest, OnIncomingNotification) {
101972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  StrictMock<MockJsEventRouter> event_router;
102072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
102172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const syncable::ModelTypeBitSet empty_model_types;
102272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  syncable::ModelTypeBitSet model_types;
102372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  model_types.set(syncable::BOOKMARKS);
102472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  model_types.set(syncable::THEMES);
102572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
102672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Build expected_args to have a single argument with the string
102772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // equivalents of model_types.
102872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ListValue expected_args;
102972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  {
103072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ListValue* model_type_list = new ListValue();
103172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    expected_args.Append(model_type_list);
103272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    for (int i = syncable::FIRST_REAL_MODEL_TYPE;
103372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         i < syncable::MODEL_TYPE_COUNT; ++i) {
103472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (model_types[i]) {
103572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        model_type_list->Append(
103672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            Value::CreateStringValue(
103772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                syncable::ModelTypeToString(
103872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                    syncable::ModelTypeFromInt(i))));
103972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
104072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
104172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
104272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
104372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_CALL(event_router,
104472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              RouteJsEvent("onSyncIncomingNotification",
104572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                           HasArgsAsList(expected_args), NULL));
104672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
104772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend();
104872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
104972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types);
105072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnIncomingNotificationForTest(model_types);
105172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
105272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->SetParentJsEventRouter(&event_router);
105372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnIncomingNotificationForTest(model_types);
105472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  js_backend->RemoveParentJsEventRouter();
105572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
105672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types);
105772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sync_manager_.TriggerOnIncomingNotificationForTest(model_types);
105872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
105972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1060dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(SyncManagerTest, EncryptDataTypesWithNoData) {
1061dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(SetUpEncryption());
1062dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ModelTypeSet encrypted_types;
1063dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  encrypted_types.insert(syncable::BOOKMARKS);
1064dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Even though Passwords isn't marked for encryption, it's enabled, so it
1065dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // should automatically be added to the response of OnEncryptionComplete.
1066dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ModelTypeSet expected_types = encrypted_types;
1067dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  expected_types.insert(syncable::PASSWORDS);
1068dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(observer_, OnEncryptionComplete(expected_types));
1069dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sync_manager_.EncryptDataTypes(encrypted_types);
1070dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  {
1071dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ReadTransaction trans(sync_manager_.GetUserShare());
1072dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_EQ(encrypted_types,
1073dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              GetEncryptedDataTypes(trans.GetWrappedTrans()));
1074dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1075dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1076dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1077dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(SyncManagerTest, EncryptDataTypesWithData) {
1078dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  size_t batch_size = 5;
1079dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(SetUpEncryption());
1080dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1081dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Create some unencrypted unsynced data.
1082dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(),
1083dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                      syncable::BOOKMARKS,
1084dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                      GetIdForDataType(syncable::BOOKMARKS),
1085dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                      NULL);
1086dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // First batch_size nodes are children of folder.
1087dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  size_t i;
1088dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (i = 0; i < batch_size; ++i) {
1089dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::BOOKMARKS,
1090dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       StringPrintf("%"PRIuS"", i), folder);
1091dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1092dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Next batch_size nodes are a different type and on their own.
1093dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (; i < 2*batch_size; ++i) {
1094dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::SESSIONS,
1095dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       StringPrintf("%"PRIuS"", i),
1096dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       GetIdForDataType(syncable::SESSIONS));
1097dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1098dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Last batch_size nodes are a third type that will not need encryption.
1099dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (; i < 3*batch_size; ++i) {
1100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::THEMES,
1101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       StringPrintf("%"PRIuS"", i),
1102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       GetIdForDataType(syncable::THEMES));
1103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  {
1106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ReadTransaction trans(sync_manager_.GetUserShare());
1107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(),
1108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   syncable::BOOKMARKS,
1109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   false /* not encrypted */));
1110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(),
1111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   syncable::SESSIONS,
1112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   false /* not encrypted */));
1113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(),
1114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   syncable::THEMES,
1115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   false /* not encrypted */));
1116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ModelTypeSet encrypted_types;
1119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  encrypted_types.insert(syncable::BOOKMARKS);
1120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  encrypted_types.insert(syncable::SESSIONS);
1121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  encrypted_types.insert(syncable::PASSWORDS);
1122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_CALL(observer_, OnEncryptionComplete(encrypted_types));
1123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sync_manager_.EncryptDataTypes(encrypted_types);
1124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  {
1126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ReadTransaction trans(sync_manager_.GetUserShare());
1127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    encrypted_types.erase(syncable::PASSWORDS);  // Not stored in nigori node.
1128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_EQ(encrypted_types,
1129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              GetEncryptedDataTypes(trans.GetWrappedTrans()));
1130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(),
1131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   syncable::BOOKMARKS,
1132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   true /* is encrypted */));
1133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(),
1134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   syncable::SESSIONS,
1135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   true /* is encrypted */));
1136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(),
1137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   syncable::THEMES,
1138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   false /* not encrypted */));
1139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
114272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}  // namespace
114372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace browser_sync
1145