summaryrefslogtreecommitdiffstats
path: root/sync
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 02:50:12 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 02:50:12 +0000
commit895a1e5bb93fa9a86fac22f5492598cf99636e47 (patch)
tree0f2e965b0014a64656ef378930710a16ad8c79d8 /sync
parent49f47568522c5a83c851f4333592521a1dae86dd (diff)
downloadchromium_src-895a1e5bb93fa9a86fac22f5492598cf99636e47.zip
chromium_src-895a1e5bb93fa9a86fac22f5492598cf99636e47.tar.gz
chromium_src-895a1e5bb93fa9a86fac22f5492598cf99636e47.tar.bz2
[Sync] Move chrome/browser/sync/api to sync/api
Update all references. BUG=128061 TEST= TBR=sky@chromium.org Review URL: https://chromiumcodereview.appspot.com/10389134 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137062 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync')
-rw-r--r--sync/api/DEPS6
-rw-r--r--sync/api/fake_syncable_service.cc58
-rw-r--r--sync/api/fake_syncable_service.h48
-rw-r--r--sync/api/sync_change.cc73
-rw-r--r--sync/api/sync_change.h67
-rw-r--r--sync/api/sync_change_processor.cc9
-rw-r--r--sync/api/sync_change_processor.h40
-rw-r--r--sync/api/sync_change_unittest.cc130
-rw-r--r--sync/api/sync_data.cc140
-rw-r--r--sync/api/sync_data.h121
-rw-r--r--sync/api/sync_error.cc108
-rw-r--r--sync/api/sync_error.h85
-rw-r--r--sync/api/sync_error_factory.cc11
-rw-r--r--sync/api/sync_error_factory.h26
-rw-r--r--sync/api/sync_error_factory_mock.cc12
-rw-r--r--sync/api/sync_error_factory_mock.h23
-rw-r--r--sync/api/sync_error_unittest.cc132
-rw-r--r--sync/api/syncable_service.cc7
-rw-r--r--sync/api/syncable_service.h65
-rw-r--r--sync/sync.gyp96
20 files changed, 1257 insertions, 0 deletions
diff --git a/sync/api/DEPS b/sync/api/DEPS
new file mode 100644
index 0000000..157d02f
--- /dev/null
+++ b/sync/api/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+sync/internal_api/base_node.h",
+ "+sync/protocol",
+ "+sync/syncable/model_type.h",
+ "+sync/util/immutable.h",
+]
diff --git a/sync/api/fake_syncable_service.cc b/sync/api/fake_syncable_service.cc
new file mode 100644
index 0000000..f5738eb
--- /dev/null
+++ b/sync/api/fake_syncable_service.cc
@@ -0,0 +1,58 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/fake_syncable_service.h"
+
+#include "base/location.h"
+#include "sync/api/sync_error_factory.h"
+
+FakeSyncableService::FakeSyncableService()
+ : syncing_(false),
+ type_(syncable::UNSPECIFIED) {}
+
+FakeSyncableService::~FakeSyncableService() {}
+
+void FakeSyncableService::set_merge_data_and_start_syncing_error(
+ const SyncError& error) {
+ merge_data_and_start_syncing_error_ = error;
+}
+
+void FakeSyncableService::set_process_sync_changes_error(
+ const SyncError& error) {
+ process_sync_changes_error_ = error;
+}
+
+bool FakeSyncableService::syncing() const {
+ return syncing_;
+}
+
+// SyncableService implementation.
+SyncError FakeSyncableService::MergeDataAndStartSyncing(
+ syncable::ModelType type,
+ const SyncDataList& initial_sync_data,
+ scoped_ptr<SyncChangeProcessor> sync_processor,
+ scoped_ptr<SyncErrorFactory> sync_error_factory) {
+ sync_processor_ = sync_processor.Pass();
+ type_ = type;
+ if (!merge_data_and_start_syncing_error_.IsSet()) {
+ syncing_ = true;
+ }
+ return merge_data_and_start_syncing_error_;
+}
+
+void FakeSyncableService::StopSyncing(syncable::ModelType type) {
+ syncing_ = false;
+ sync_processor_.reset();
+}
+
+SyncDataList FakeSyncableService::GetAllSyncData(
+ syncable::ModelType type) const {
+ return SyncDataList();
+}
+
+SyncError FakeSyncableService::ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const SyncChangeList& change_list) {
+ return process_sync_changes_error_;
+}
diff --git a/sync/api/fake_syncable_service.h b/sync/api/fake_syncable_service.h
new file mode 100644
index 0000000..9f10a65
--- /dev/null
+++ b/sync/api/fake_syncable_service.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_FAKE_SYNCABLE_SERVICE_H_
+#define SYNC_API_FAKE_SYNCABLE_SERVICE_H_
+#pragma once
+
+#include "sync/api/syncable_service.h"
+
+class SyncErrorFactory;
+
+// A fake SyncableService that can return arbitrary values and maintains the
+// syncing status.
+class FakeSyncableService : public SyncableService {
+ public:
+ FakeSyncableService();
+ virtual ~FakeSyncableService();
+
+ // Setters for SyncableService implementation results.
+ void set_merge_data_and_start_syncing_error(const SyncError& error);
+ void set_process_sync_changes_error(const SyncError& error);
+
+ // Whether we're syncing or not. Set on a successful MergeDataAndStartSyncing,
+ // unset on StopSyncing. False by default.
+ bool syncing() const;
+
+ // SyncableService implementation.
+ virtual SyncError MergeDataAndStartSyncing(
+ syncable::ModelType type,
+ const SyncDataList& initial_sync_data,
+ scoped_ptr<SyncChangeProcessor> sync_processor,
+ scoped_ptr<SyncErrorFactory> sync_error_factory) OVERRIDE;
+ virtual void StopSyncing(syncable::ModelType type) OVERRIDE;
+ virtual SyncDataList GetAllSyncData(syncable::ModelType type) const OVERRIDE;
+ virtual SyncError ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const SyncChangeList& change_list) OVERRIDE;
+
+ private:
+ scoped_ptr<SyncChangeProcessor> sync_processor_;
+ SyncError merge_data_and_start_syncing_error_;
+ SyncError process_sync_changes_error_;
+ bool syncing_;
+ syncable::ModelType type_;
+};
+
+#endif // SYNC_API_FAKE_SYNCABLE_SERVICE_H_
diff --git a/sync/api/sync_change.cc b/sync/api/sync_change.cc
new file mode 100644
index 0000000..627c19b
--- /dev/null
+++ b/sync/api/sync_change.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_change.h"
+
+#include <ostream>
+
+SyncChange::SyncChange() : change_type_(ACTION_INVALID) {
+}
+
+SyncChange::SyncChange(SyncChangeType change_type, const SyncData& sync_data)
+ : change_type_(change_type),
+ sync_data_(sync_data) {
+ DCHECK(IsValid());
+}
+
+SyncChange::~SyncChange() {}
+
+bool SyncChange::IsValid() const {
+ if (change_type_ == ACTION_INVALID || !sync_data_.IsValid())
+ return false;
+
+ // Data from the syncer must always have valid specifics.
+ if (!sync_data_.IsLocal())
+ return syncable::IsRealDataType(sync_data_.GetDataType());
+
+ // Local changes must always have a tag and specify a valid datatype.
+ if (sync_data_.GetTag().empty() ||
+ !syncable::IsRealDataType(sync_data_.GetDataType())) {
+ return false;
+ }
+
+ // Adds and updates must have a non-unique-title.
+ if (change_type_ == ACTION_ADD || change_type_ == ACTION_UPDATE)
+ return (!sync_data_.GetTitle().empty());
+
+ return true;
+}
+
+SyncChange::SyncChangeType SyncChange::change_type() const {
+ return change_type_;
+}
+
+SyncData SyncChange::sync_data() const {
+ return sync_data_;
+}
+
+// static
+std::string SyncChange::ChangeTypeToString(SyncChangeType change_type) {
+ switch (change_type) {
+ case ACTION_INVALID:
+ return "ACTION_INVALID";
+ case ACTION_ADD:
+ return "ACTION_ADD";
+ case ACTION_UPDATE:
+ return "ACTION_UPDATE";
+ case ACTION_DELETE:
+ return "ACTION_DELETE";
+ default:
+ NOTREACHED();
+ }
+ return std::string();
+}
+
+std::string SyncChange::ToString() const {
+ return "{ changeType: " + ChangeTypeToString(change_type_) +
+ ", syncData: " + sync_data_.ToString() + "}";
+}
+
+void PrintTo(const SyncChange& sync_change, std::ostream* os) {
+ *os << sync_change.ToString();
+}
diff --git a/sync/api/sync_change.h b/sync/api/sync_change.h
new file mode 100644
index 0000000..19218f5
--- /dev/null
+++ b/sync/api/sync_change.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_SYNC_CHANGE_H_
+#define SYNC_API_SYNC_CHANGE_H_
+#pragma once
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "sync/api/sync_data.h"
+
+// A SyncChange object reflects a change to a piece of synced data. The change
+// can be either a delete, add, or an update. All data relevant to the change
+// is encapsulated within the SyncChange, which, once created, is immutable.
+// Note: it is safe and cheap to pass these by value or make copies, as they do
+// not create deep copies of their internal data.
+class SyncChange {
+ public:
+ enum SyncChangeType {
+ ACTION_INVALID,
+ ACTION_ADD,
+ ACTION_UPDATE,
+ ACTION_DELETE
+ };
+
+ // Default constructor creates an invalid change.
+ SyncChange();
+ // Create a new change with the specified sync data.
+ SyncChange(SyncChangeType change_type, const SyncData& sync_data);
+ ~SyncChange();
+
+ // Copy constructor and assignment operator welcome.
+
+ // Whether this change is valid. This must be true before attempting to access
+ // the data.
+ // Deletes: Requires valid tag when going to the syncer. Requires valid
+ // specifics when coming from the syncer.
+ // Adds, Updates: Require valid tag and specifics when going to the syncer.
+ // Require only valid specifics when coming from the syncer.
+ bool IsValid() const;
+
+ // Getters.
+ SyncChangeType change_type() const;
+ SyncData sync_data() const;
+
+ // Returns a string representation of |change_type|.
+ static std::string ChangeTypeToString(SyncChangeType change_type);
+
+ // Returns a string representation of the entire object. Used for gmock
+ // printing method, PrintTo.
+ std::string ToString() const;
+
+ private:
+ SyncChangeType change_type_;
+
+ // An immutable container for the data of this SyncChange. Whenever
+ // SyncChanges are copied, they copy references to this data.
+ SyncData sync_data_;
+};
+
+// gmock printer helper.
+void PrintTo(const SyncChange& sync_change, std::ostream* os);
+
+#endif // SYNC_API_SYNC_CHANGE_H_
diff --git a/sync/api/sync_change_processor.cc b/sync/api/sync_change_processor.cc
new file mode 100644
index 0000000..74e6401
--- /dev/null
+++ b/sync/api/sync_change_processor.cc
@@ -0,0 +1,9 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_change_processor.h"
+
+SyncChangeProcessor::SyncChangeProcessor() {}
+
+SyncChangeProcessor::~SyncChangeProcessor() {}
diff --git a/sync/api/sync_change_processor.h b/sync/api/sync_change_processor.h
new file mode 100644
index 0000000..1eed159
--- /dev/null
+++ b/sync/api/sync_change_processor.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_SYNC_CHANGE_PROCESSOR_H_
+#define SYNC_API_SYNC_CHANGE_PROCESSOR_H_
+#pragma once
+
+#include <vector>
+
+#include "sync/api/sync_error.h"
+
+class SyncChange;
+
+namespace tracked_objects {
+class Location;
+} // namespace tracked_objects
+
+typedef std::vector<SyncChange> SyncChangeList;
+
+// An interface for services that handle receiving SyncChanges.
+class SyncChangeProcessor {
+ public:
+ SyncChangeProcessor();
+ virtual ~SyncChangeProcessor();
+
+ // Process a list of SyncChanges.
+ // Returns: A default SyncError (IsSet() == false) if no errors were
+ // encountered, and a filled SyncError (IsSet() == true)
+ // otherwise.
+ // Inputs:
+ // |from_here|: allows tracking of where sync changes originate.
+ // |change_list|: is the list of sync changes in need of processing.
+ virtual SyncError ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const SyncChangeList& change_list) = 0;
+ protected:
+};
+
+#endif // SYNC_API_SYNC_CHANGE_PROCESSOR_H_
diff --git a/sync/api/sync_change_unittest.cc b/sync/api/sync_change_unittest.cc
new file mode 100644
index 0000000..263abdd
--- /dev/null
+++ b/sync/api/sync_change_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_change.h"
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "sync/protocol/preference_specifics.pb.h"
+#include "sync/protocol/proto_value_conversions.h"
+#include "sync/protocol/sync.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using browser_sync::EntitySpecificsToValue;
+
+// Ordered list of SyncChange's.
+typedef std::vector<SyncChange> SyncChangeList;
+
+namespace {
+
+typedef testing::Test SyncChangeTest;
+
+TEST_F(SyncChangeTest, LocalDelete) {
+ SyncChange::SyncChangeType change_type = SyncChange::ACTION_DELETE;
+ std::string tag = "client_tag";
+ SyncChange e(change_type,
+ SyncData::CreateLocalDelete(tag, syncable::PREFERENCES));
+ EXPECT_EQ(change_type, e.change_type());
+ EXPECT_EQ(tag, e.sync_data().GetTag());
+ EXPECT_EQ(syncable::PREFERENCES, e.sync_data().GetDataType());
+}
+
+TEST_F(SyncChangeTest, LocalUpdate) {
+ SyncChange::SyncChangeType change_type = SyncChange::ACTION_UPDATE;
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::PreferenceSpecifics* pref_specifics = specifics.mutable_preference();
+ pref_specifics->set_name("test");
+ std::string tag = "client_tag";
+ std::string title = "client_title";
+ SyncChange e(change_type,
+ SyncData::CreateLocalData(tag, title, specifics));
+ EXPECT_EQ(change_type, e.change_type());
+ EXPECT_EQ(tag, e.sync_data().GetTag());
+ EXPECT_EQ(title, e.sync_data().GetTitle());
+ EXPECT_EQ(syncable::PREFERENCES, e.sync_data().GetDataType());
+ scoped_ptr<DictionaryValue> ref_spec(EntitySpecificsToValue(specifics));
+ scoped_ptr<DictionaryValue> e_spec(EntitySpecificsToValue(
+ e.sync_data().GetSpecifics()));
+ EXPECT_TRUE(ref_spec->Equals(e_spec.get()));
+}
+
+TEST_F(SyncChangeTest, LocalAdd) {
+ SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD;
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::PreferenceSpecifics* pref_specifics = specifics.mutable_preference();
+ pref_specifics->set_name("test");
+ std::string tag = "client_tag";
+ std::string title = "client_title";
+ SyncChange e(change_type,
+ SyncData::CreateLocalData(tag, title, specifics));
+ EXPECT_EQ(change_type, e.change_type());
+ EXPECT_EQ(tag, e.sync_data().GetTag());
+ EXPECT_EQ(title, e.sync_data().GetTitle());
+ EXPECT_EQ(syncable::PREFERENCES, e.sync_data().GetDataType());
+ scoped_ptr<DictionaryValue> ref_spec(EntitySpecificsToValue(specifics));
+ scoped_ptr<DictionaryValue> e_spec(EntitySpecificsToValue(
+ e.sync_data().GetSpecifics()));
+ EXPECT_TRUE(ref_spec->Equals(e_spec.get()));
+}
+
+TEST_F(SyncChangeTest, SyncerChanges) {
+ SyncChangeList change_list;
+
+ // Create an update.
+ sync_pb::EntitySpecifics update_specifics;
+ sync_pb::PreferenceSpecifics* pref_specifics =
+ update_specifics.mutable_preference();
+ pref_specifics->set_name("update");
+ change_list.push_back(SyncChange(
+ SyncChange::ACTION_UPDATE,
+ SyncData::CreateRemoteData(1, update_specifics)));
+
+ // Create an add.
+ sync_pb::EntitySpecifics add_specifics;
+ pref_specifics = add_specifics.mutable_preference();
+ pref_specifics->set_name("add");
+ change_list.push_back(SyncChange(
+ SyncChange::ACTION_ADD,
+ SyncData::CreateRemoteData(2, add_specifics)));
+
+ // Create a delete.
+ sync_pb::EntitySpecifics delete_specifics;
+ pref_specifics = delete_specifics.mutable_preference();
+ pref_specifics->set_name("add");
+ change_list.push_back(SyncChange(
+ SyncChange::ACTION_DELETE,
+ SyncData::CreateRemoteData(3, delete_specifics)));
+
+ ASSERT_EQ(3U, change_list.size());
+
+ // Verify update.
+ SyncChange e = change_list[0];
+ EXPECT_EQ(SyncChange::ACTION_UPDATE, e.change_type());
+ EXPECT_EQ(syncable::PREFERENCES, e.sync_data().GetDataType());
+ scoped_ptr<DictionaryValue> ref_spec(EntitySpecificsToValue(
+ update_specifics));
+ scoped_ptr<DictionaryValue> e_spec(EntitySpecificsToValue(
+ e.sync_data().GetSpecifics()));
+ EXPECT_TRUE(ref_spec->Equals(e_spec.get()));
+
+ // Verify add.
+ e = change_list[1];
+ EXPECT_EQ(SyncChange::ACTION_ADD, e.change_type());
+ EXPECT_EQ(syncable::PREFERENCES, e.sync_data().GetDataType());
+ ref_spec.reset(EntitySpecificsToValue(add_specifics));
+ e_spec.reset(EntitySpecificsToValue(e.sync_data().GetSpecifics()));
+ EXPECT_TRUE(ref_spec->Equals(e_spec.get()));
+
+ // Verify delete.
+ e = change_list[2];
+ EXPECT_EQ(SyncChange::ACTION_DELETE, e.change_type());
+ EXPECT_EQ(syncable::PREFERENCES, e.sync_data().GetDataType());
+ ref_spec.reset(EntitySpecificsToValue(delete_specifics));
+ e_spec.reset(EntitySpecificsToValue(e.sync_data().GetSpecifics()));
+ EXPECT_TRUE(ref_spec->Equals(e_spec.get()));
+}
+
+} // namespace
diff --git a/sync/api/sync_data.cc b/sync/api/sync_data.cc
new file mode 100644
index 0000000..679c547
--- /dev/null
+++ b/sync/api/sync_data.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_data.h"
+
+#include <ostream>
+
+#include "base/json/json_writer.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/values.h"
+#include "sync/internal_api/base_node.h"
+#include "sync/protocol/proto_value_conversions.h"
+#include "sync/protocol/sync.pb.h"
+#include "sync/syncable/model_type.h"
+
+void SyncData::ImmutableSyncEntityTraits::InitializeWrapper(
+ Wrapper* wrapper) {
+ *wrapper = new sync_pb::SyncEntity();
+}
+
+void SyncData::ImmutableSyncEntityTraits::DestroyWrapper(
+ Wrapper* wrapper) {
+ delete *wrapper;
+}
+
+const sync_pb::SyncEntity& SyncData::ImmutableSyncEntityTraits::Unwrap(
+ const Wrapper& wrapper) {
+ return *wrapper;
+}
+
+sync_pb::SyncEntity* SyncData::ImmutableSyncEntityTraits::UnwrapMutable(
+ Wrapper* wrapper) {
+ return *wrapper;
+}
+
+void SyncData::ImmutableSyncEntityTraits::Swap(sync_pb::SyncEntity* t1,
+ sync_pb::SyncEntity* t2) {
+ t1->Swap(t2);
+}
+
+SyncData::SyncData()
+ : is_valid_(false),
+ id_(sync_api::kInvalidId) {}
+
+SyncData::SyncData(int64 id, sync_pb::SyncEntity* entity)
+ : is_valid_(true),
+ id_(id),
+ immutable_entity_(entity) {}
+
+SyncData::~SyncData() {}
+
+// Static.
+SyncData SyncData::CreateLocalDelete(
+ const std::string& sync_tag,
+ syncable::ModelType datatype) {
+ sync_pb::EntitySpecifics specifics;
+ syncable::AddDefaultFieldValue(datatype, &specifics);
+ return CreateLocalData(sync_tag, "", specifics);
+}
+
+// Static.
+SyncData SyncData::CreateLocalData(
+ const std::string& sync_tag,
+ const std::string& non_unique_title,
+ const sync_pb::EntitySpecifics& specifics) {
+ sync_pb::SyncEntity entity;
+ entity.set_client_defined_unique_tag(sync_tag);
+ entity.set_non_unique_name(non_unique_title);
+ entity.mutable_specifics()->CopyFrom(specifics);
+ return SyncData(sync_api::kInvalidId, &entity);
+}
+
+// Static.
+SyncData SyncData::CreateRemoteData(
+ int64 id, const sync_pb::EntitySpecifics& specifics) {
+ DCHECK_NE(id, sync_api::kInvalidId);
+ sync_pb::SyncEntity entity;
+ entity.mutable_specifics()->CopyFrom(specifics);
+ return SyncData(id, &entity);
+}
+
+bool SyncData::IsValid() const {
+ return is_valid_;
+}
+
+const sync_pb::EntitySpecifics& SyncData::GetSpecifics() const {
+ return immutable_entity_.Get().specifics();
+}
+
+syncable::ModelType SyncData::GetDataType() const {
+ return syncable::GetModelTypeFromSpecifics(GetSpecifics());
+}
+
+const std::string& SyncData::GetTag() const {
+ DCHECK(IsLocal());
+ return immutable_entity_.Get().client_defined_unique_tag();
+}
+
+const std::string& SyncData::GetTitle() const {
+ // TODO(zea): set this for data coming from the syncer too.
+ DCHECK(immutable_entity_.Get().has_non_unique_name());
+ return immutable_entity_.Get().non_unique_name();
+}
+
+int64 SyncData::GetRemoteId() const {
+ DCHECK(!IsLocal());
+ return id_;
+}
+
+bool SyncData::IsLocal() const {
+ return id_ == sync_api::kInvalidId;
+}
+
+std::string SyncData::ToString() const {
+ if (!IsValid())
+ return "<Invalid SyncData>";
+
+ std::string type = syncable::ModelTypeToString(GetDataType());
+ std::string specifics;
+ scoped_ptr<DictionaryValue> value(
+ browser_sync::EntitySpecificsToValue(GetSpecifics()));
+ base::JSONWriter::WriteWithOptions(value.get(),
+ base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ &specifics);
+
+ if (IsLocal()) {
+ return "{ isLocal: true, type: " + type + ", tag: " + GetTag() +
+ ", title: " + GetTitle() + ", specifics: " + specifics + "}";
+ }
+
+ std::string id = base::Int64ToString(GetRemoteId());
+ return "{ isLocal: false, type: " + type + ", specifics: " + specifics +
+ ", id: " + id + "}";
+}
+
+void PrintTo(const SyncData& sync_data, std::ostream* os) {
+ *os << sync_data.ToString();
+}
diff --git a/sync/api/sync_data.h b/sync/api/sync_data.h
new file mode 100644
index 0000000..cef132b
--- /dev/null
+++ b/sync/api/sync_data.h
@@ -0,0 +1,121 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_SYNC_DATA_H_
+#define SYNC_API_SYNC_DATA_H_
+#pragma once
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "sync/syncable/model_type.h"
+#include "sync/util/immutable.h"
+
+namespace sync_pb {
+class EntitySpecifics;
+class SyncEntity;
+} // namespace sync_pb
+
+typedef syncable::ModelType SyncDataType;
+
+// A light-weight container for immutable sync data. Pass-by-value and storage
+// in STL containers are supported and encouraged if helpful.
+class SyncData {
+ public:
+ // Creates an empty and invalid SyncData.
+ SyncData();
+ ~SyncData();
+
+ // Default copy and assign welcome.
+
+ // Helper methods for creating SyncData objects for local data.
+ // The sync tag must be a string unique to this datatype and is used as a node
+ // identifier server-side.
+ // For deletes: |datatype| must specify the datatype who node is being
+ // deleted.
+ // For adds/updates: the specifics must be valid and the non-unique title (can
+ // be the same as sync tag) must be specfied.
+ // Note: the non_unique_title is primarily for debug purposes, and will be
+ // overwritten if the datatype is encrypted.
+ static SyncData CreateLocalDelete(
+ const std::string& sync_tag,
+ syncable::ModelType datatype);
+ static SyncData CreateLocalData(
+ const std::string& sync_tag,
+ const std::string& non_unique_title,
+ const sync_pb::EntitySpecifics& specifics);
+
+ // Helper method for creating SyncData objects originating from the syncer.
+ static SyncData CreateRemoteData(
+ int64 id, const sync_pb::EntitySpecifics& specifics);
+
+ // Whether this SyncData holds valid data. The only way to have a SyncData
+ // without valid data is to use the default constructor.
+ bool IsValid() const;
+
+ // Return the datatype we're holding information about. Derived from the sync
+ // datatype specifics.
+ SyncDataType GetDataType() const;
+
+ // Return the current sync datatype specifics.
+ const sync_pb::EntitySpecifics& GetSpecifics() const;
+
+ // Returns the value of the unique client tag. This is only set for data going
+ // TO the syncer, not coming from.
+ const std::string& GetTag() const;
+
+ // Returns the non unique title (for debugging). Currently only set for data
+ // going TO the syncer, not from.
+ const std::string& GetTitle() const;
+
+ // Should only be called by sync code when IsLocal() is false.
+ int64 GetRemoteId() const;
+
+ // Whether this sync data is for local data or data coming from the syncer.
+ bool IsLocal() const;
+
+ std::string ToString() const;
+
+ // TODO(zea): Query methods for other sync properties: parent, successor, etc.
+
+ private:
+ // Necessary since we forward-declare sync_pb::SyncEntity; see
+ // comments in immutable.h.
+ struct ImmutableSyncEntityTraits {
+ typedef sync_pb::SyncEntity* Wrapper;
+
+ static void InitializeWrapper(Wrapper* wrapper);
+
+ static void DestroyWrapper(Wrapper* wrapper);
+
+ static const sync_pb::SyncEntity& Unwrap(const Wrapper& wrapper);
+
+ static sync_pb::SyncEntity* UnwrapMutable(Wrapper* wrapper);
+
+ static void Swap(sync_pb::SyncEntity* t1, sync_pb::SyncEntity* t2);
+ };
+
+ typedef browser_sync::Immutable<
+ sync_pb::SyncEntity, ImmutableSyncEntityTraits>
+ ImmutableSyncEntity;
+
+ // Clears |entity|.
+ SyncData(int64 id, sync_pb::SyncEntity* entity);
+
+ // Whether this SyncData holds valid data.
+ bool is_valid_;
+
+ // Equal to sync_api::kInvalidId iff this is local.
+ int64 id_;
+
+ // The actual shared sync entity being held.
+ ImmutableSyncEntity immutable_entity_;
+};
+
+// gmock printer helper.
+void PrintTo(const SyncData& sync_data, std::ostream* os);
+
+#endif // SYNC_API_SYNC_DATA_H_
diff --git a/sync/api/sync_error.cc b/sync/api/sync_error.cc
new file mode 100644
index 0000000..49bf74b
--- /dev/null
+++ b/sync/api/sync_error.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_error.h"
+
+#include <ostream>
+
+#include "base/location.h"
+#include "base/logging.h"
+#include "sync/syncable/model_type.h"
+
+SyncError::SyncError() {
+ Clear();
+}
+
+SyncError::SyncError(const tracked_objects::Location& location,
+ const std::string& message,
+ syncable::ModelType type) {
+ Init(location, message, type);
+ PrintLogError();
+}
+
+SyncError::SyncError(const SyncError& other) {
+ Copy(other);
+}
+
+SyncError::~SyncError() {
+}
+
+SyncError& SyncError::operator=(const SyncError& other) {
+ if (this == &other) {
+ return *this;
+ }
+ Copy(other);
+ return *this;
+}
+
+void SyncError::Copy(const SyncError& other) {
+ if (other.IsSet()) {
+ Init(other.location(),
+ other.message(),
+ other.type());
+ } else {
+ Clear();
+ }
+}
+
+void SyncError::Clear() {
+ location_.reset();
+ message_ = std::string();
+ type_ = syncable::UNSPECIFIED;
+}
+
+void SyncError::Reset(const tracked_objects::Location& location,
+ const std::string& message,
+ syncable::ModelType type) {
+ Init(location, message, type);
+ PrintLogError();
+}
+
+void SyncError::Init(const tracked_objects::Location& location,
+ const std::string& message,
+ syncable::ModelType type) {
+ location_.reset(new tracked_objects::Location(location));
+ message_ = message;
+ type_ = type;
+}
+
+bool SyncError::IsSet() const {
+ return location_.get() != NULL;
+}
+
+
+const tracked_objects::Location& SyncError::location() const {
+ CHECK(IsSet());
+ return *location_;
+}
+
+const std::string& SyncError::message() const {
+ CHECK(IsSet());
+ return message_;
+}
+
+syncable::ModelType SyncError::type() const {
+ CHECK(IsSet());
+ return type_;
+}
+
+std::string SyncError::ToString() const {
+ if (!IsSet()) {
+ return std::string();
+ }
+ return location_->ToString() + ", " + syncable::ModelTypeToString(type_) +
+ ", Sync Error: " + message_;
+}
+
+void SyncError::PrintLogError() const {
+ LAZY_STREAM(logging::LogMessage(location_->file_name(),
+ location_->line_number(),
+ logging::LOG_ERROR).stream(),
+ LOG_IS_ON(ERROR))
+ << syncable::ModelTypeToString(type_) << ", Sync Error: " << message_;
+}
+
+void PrintTo(const SyncError& sync_error, std::ostream* os) {
+ *os << sync_error.ToString();
+}
diff --git a/sync/api/sync_error.h b/sync/api/sync_error.h
new file mode 100644
index 0000000..2b6dc93
--- /dev/null
+++ b/sync/api/sync_error.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_SYNC_ERROR_H_
+#define SYNC_API_SYNC_ERROR_H_
+#pragma once
+
+#include <iosfwd>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "sync/syncable/model_type.h"
+
+namespace tracked_objects {
+class Location;
+} // namespace tracked_objects
+
+// Sync errors are used for debug purposes and handled internally and/or
+// exposed through Chrome's "about:sync" internal page. They are considered
+// unrecoverable for the datatype creating them, and should only be used as
+// such.
+// This class is copy-friendly and thread-safe.
+class SyncError {
+ public:
+ // Default constructor refers to "no error", and IsSet() will return false.
+ SyncError();
+
+ // Create a new Sync error triggered by datatype |type| with debug message
+ // |message| from the specified location. IsSet() will return true.
+ // Will print the new error to LOG(ERROR).
+ SyncError(const tracked_objects::Location& location,
+ const std::string& message,
+ syncable::ModelType type);
+
+ // Copy and assign via deep copy.
+ SyncError(const SyncError& other);
+ SyncError& operator=(const SyncError& other);
+
+ ~SyncError();
+
+ // Reset the current error to a new error. May be called irrespective of
+ // whether IsSet() is true. After this is called, IsSet() will return true.
+ // Will print the new error to LOG(ERROR).
+ void Reset(const tracked_objects::Location& location,
+ const std::string& message,
+ syncable::ModelType type);
+
+ // Whether this is a valid error or not.
+ bool IsSet() const;
+
+ // These must only be called if IsSet() is true.
+ const tracked_objects::Location& location() const;
+ const std::string& message() const;
+ syncable::ModelType type() const;
+
+ // Returns empty string is IsSet() is false.
+ std::string ToString() const;
+ private:
+ // Print error information to log.
+ void PrintLogError() const;
+
+ // Make a copy of a SyncError. If other.IsSet() == false, this->IsSet() will
+ // now return false.
+ void Copy(const SyncError& other);
+
+ // Initialize the local error data with the specified error data. After this
+ // is called, IsSet() will return true.
+ void Init(const tracked_objects::Location& location,
+ const std::string& message,
+ syncable::ModelType type);
+
+ // Reset the error to it's default (unset) values.
+ void Clear();
+
+ // scoped_ptr is necessary because Location objects aren't assignable.
+ scoped_ptr<tracked_objects::Location> location_;
+ std::string message_;
+ syncable::ModelType type_;
+};
+
+// gmock printer helper.
+void PrintTo(const SyncError& sync_error, std::ostream* os);
+
+#endif // SYNC_API_SYNC_ERROR_H_
diff --git a/sync/api/sync_error_factory.cc b/sync/api/sync_error_factory.cc
new file mode 100644
index 0000000..0e9b451
--- /dev/null
+++ b/sync/api/sync_error_factory.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_error_factory.h"
+
+SyncErrorFactory::SyncErrorFactory() {
+}
+
+SyncErrorFactory::~SyncErrorFactory() {
+}
diff --git a/sync/api/sync_error_factory.h b/sync/api/sync_error_factory.h
new file mode 100644
index 0000000..72f317e
--- /dev/null
+++ b/sync/api/sync_error_factory.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_SYNC_ERROR_FACTORY_H_
+#define SYNC_API_SYNC_ERROR_FACTORY_H_
+#pragma once
+
+#include <string>
+
+#include "base/location.h"
+#include "sync/api/sync_error.h"
+
+class SyncErrorFactory {
+ public:
+ SyncErrorFactory();
+ virtual ~SyncErrorFactory();
+
+ // Creates a SyncError object and uploads this call stack to breakpad.
+ virtual SyncError CreateAndUploadError(
+ const tracked_objects::Location& location,
+ const std::string& message) = 0;
+};
+
+#endif // SYNC_API_SYNC_ERROR_FACTORY_H_
+
diff --git a/sync/api/sync_error_factory_mock.cc b/sync/api/sync_error_factory_mock.cc
new file mode 100644
index 0000000..e730b88
--- /dev/null
+++ b/sync/api/sync_error_factory_mock.cc
@@ -0,0 +1,12 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_error_factory_mock.h"
+
+SyncErrorFactoryMock::SyncErrorFactoryMock() {
+}
+
+SyncErrorFactoryMock::~SyncErrorFactoryMock() {
+}
+
diff --git a/sync/api/sync_error_factory_mock.h b/sync/api/sync_error_factory_mock.h
new file mode 100644
index 0000000..6fc58074
--- /dev/null
+++ b/sync/api/sync_error_factory_mock.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_SYNC_ERROR_FACTORY_MOCK_H_
+#define SYNC_API_SYNC_ERROR_FACTORY_MOCK_H_
+#pragma once
+
+#include "sync/api/sync_error_factory.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+
+class SyncErrorFactoryMock : public SyncErrorFactory {
+ public:
+ SyncErrorFactoryMock();
+ virtual ~SyncErrorFactoryMock();
+
+ MOCK_METHOD2(CreateAndUploadError, SyncError(
+ const tracked_objects::Location& location,
+ const std::string& message));
+};
+
+#endif // SYNC_API_SYNC_ERROR_FACTORY_MOCK_H_
diff --git a/sync/api/sync_error_unittest.cc b/sync/api/sync_error_unittest.cc
new file mode 100644
index 0000000..c700db55
--- /dev/null
+++ b/sync/api/sync_error_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/sync_error.h"
+
+#include <string>
+
+#include "base/location.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+using syncable::ModelType;
+
+namespace {
+
+typedef testing::Test SyncErrorTest;
+
+TEST_F(SyncErrorTest, Unset) {
+ SyncError error;
+ EXPECT_FALSE(error.IsSet());
+}
+
+TEST_F(SyncErrorTest, Default) {
+ tracked_objects::Location location = FROM_HERE;
+ std::string msg = "test";
+ ModelType type = syncable::PREFERENCES;
+ SyncError error(location, msg, type);
+ ASSERT_TRUE(error.IsSet());
+ EXPECT_EQ(location.line_number(), error.location().line_number());
+ EXPECT_EQ(msg, error.message());
+ EXPECT_EQ(type, error.type());
+}
+
+TEST_F(SyncErrorTest, Reset) {
+ tracked_objects::Location location = FROM_HERE;
+ std::string msg = "test";
+ ModelType type = syncable::PREFERENCES;
+
+ SyncError error;
+ EXPECT_FALSE(error.IsSet());
+
+ error.Reset(location, msg, type);
+ ASSERT_TRUE(error.IsSet());
+ EXPECT_EQ(location.line_number(), error.location().line_number());
+ EXPECT_EQ(msg, error.message());
+ EXPECT_EQ(type, error.type());
+
+ tracked_objects::Location location2 = FROM_HERE;
+ std::string msg2 = "test";
+ ModelType type2 = syncable::PREFERENCES;
+ error.Reset(location2, msg2, type2);
+ ASSERT_TRUE(error.IsSet());
+ EXPECT_EQ(location2.line_number(), error.location().line_number());
+ EXPECT_EQ(msg2, error.message());
+ EXPECT_EQ(type2, error.type());
+}
+
+TEST_F(SyncErrorTest, Copy) {
+ tracked_objects::Location location = FROM_HERE;
+ std::string msg = "test";
+ ModelType type = syncable::PREFERENCES;
+
+ SyncError error1;
+ EXPECT_FALSE(error1.IsSet());
+ SyncError error2(error1);
+ EXPECT_FALSE(error2.IsSet());
+
+ error1.Reset(location, msg, type);
+ ASSERT_TRUE(error1.IsSet());
+ EXPECT_EQ(location.line_number(), error1.location().line_number());
+ EXPECT_EQ(msg, error1.message());
+ EXPECT_EQ(type, error1.type());
+
+ SyncError error3(error1);
+ ASSERT_TRUE(error3.IsSet());
+ EXPECT_EQ(error1.location().line_number(), error3.location().line_number());
+ EXPECT_EQ(error1.message(), error3.message());
+ EXPECT_EQ(error1.type(), error3.type());
+
+ SyncError error4;
+ EXPECT_FALSE(error4.IsSet());
+ SyncError error5(error4);
+ EXPECT_FALSE(error5.IsSet());
+}
+
+TEST_F(SyncErrorTest, Assign) {
+ tracked_objects::Location location = FROM_HERE;
+ std::string msg = "test";
+ ModelType type = syncable::PREFERENCES;
+
+ SyncError error1;
+ EXPECT_FALSE(error1.IsSet());
+ SyncError error2;
+ error2 = error1;
+ EXPECT_FALSE(error2.IsSet());
+
+ error1.Reset(location, msg, type);
+ ASSERT_TRUE(error1.IsSet());
+ EXPECT_EQ(location.line_number(), error1.location().line_number());
+ EXPECT_EQ(msg, error1.message());
+ EXPECT_EQ(type, error1.type());
+
+ error2 = error1;
+ ASSERT_TRUE(error2.IsSet());
+ EXPECT_EQ(error1.location().line_number(), error2.location().line_number());
+ EXPECT_EQ(error1.message(), error2.message());
+ EXPECT_EQ(error1.type(), error2.type());
+
+ error2 = SyncError();
+ EXPECT_FALSE(error2.IsSet());
+}
+
+TEST_F(SyncErrorTest, ToString) {
+ tracked_objects::Location location = FROM_HERE;
+ std::string msg = "test";
+ ModelType type = syncable::PREFERENCES;
+ std::string expected = "Preferences, Sync Error: test";
+ SyncError error(location, msg, type);
+ EXPECT_TRUE(error.IsSet());
+ EXPECT_NE(string::npos, error.ToString().find(expected));
+
+ SyncError error2;
+ EXPECT_FALSE(error2.IsSet());
+ EXPECT_EQ(std::string(), error2.ToString());
+
+ error2 = error;
+ EXPECT_TRUE(error2.IsSet());
+ EXPECT_NE(string::npos, error.ToString().find(expected));
+}
+
+} // namespace
diff --git a/sync/api/syncable_service.cc b/sync/api/syncable_service.cc
new file mode 100644
index 0000000..198173a
--- /dev/null
+++ b/sync/api/syncable_service.cc
@@ -0,0 +1,7 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/api/syncable_service.h"
+
+SyncableService::~SyncableService() {}
diff --git a/sync/api/syncable_service.h b/sync/api/syncable_service.h
new file mode 100644
index 0000000..bfcab3a
--- /dev/null
+++ b/sync/api/syncable_service.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_API_SYNCABLE_SERVICE_H_
+#define SYNC_API_SYNCABLE_SERVICE_H_
+#pragma once
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "sync/api/sync_change_processor.h"
+#include "sync/api/sync_data.h"
+#include "sync/api/sync_error.h"
+#include "sync/syncable/model_type.h"
+
+class SyncErrorFactory;
+
+typedef std::vector<SyncData> SyncDataList;
+
+// TODO(zea): remove SupportsWeakPtr in favor of having all SyncableService
+// implementers provide a way of getting a weak pointer to themselves.
+// See crbug.com/100114.
+class SyncableService : public SyncChangeProcessor,
+ public base::SupportsWeakPtr<SyncableService> {
+ public:
+ // Informs the service to begin syncing the specified synced datatype |type|.
+ // The service should then merge |initial_sync_data| into it's local data,
+ // calling |sync_processor|'s ProcessSyncChanges as necessary to reconcile the
+ // two. After this, the SyncableService's local data should match the server
+ // data, and the service should be ready to receive and process any further
+ // SyncChange's as they occur.
+ // Returns: A default SyncError (IsSet() == false) if no errors were
+ // encountered, and a filled SyncError (IsSet() == true)
+ // otherwise.
+ virtual SyncError MergeDataAndStartSyncing(
+ syncable::ModelType type,
+ const SyncDataList& initial_sync_data,
+ scoped_ptr<SyncChangeProcessor> sync_processor,
+ scoped_ptr<SyncErrorFactory> error_handler) = 0;
+
+ // Stop syncing the specified type and reset state.
+ virtual void StopSyncing(syncable::ModelType type) = 0;
+
+ // Fills a list of SyncData from the local data. This should create an up
+ // to date representation of the SyncableService's view of that datatype, and
+ // should match/be a subset of the server's view of that datatype.
+ virtual SyncDataList GetAllSyncData(syncable::ModelType type) const = 0;
+
+ // SyncChangeProcessor interface.
+ // Process a list of new SyncChanges and update the local data as necessary.
+ // Returns: A default SyncError (IsSet() == false) if no errors were
+ // encountered, and a filled SyncError (IsSet() == true)
+ // otherwise.
+ virtual SyncError ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const SyncChangeList& change_list) OVERRIDE = 0;
+
+ protected:
+ virtual ~SyncableService();
+};
+
+#endif // SYNC_API_SYNCABLE_SERVICE_H_
diff --git a/sync/sync.gyp b/sync/sync.gyp
index 97d493e..ba97a47 100644
--- a/sync/sync.gyp
+++ b/sync/sync.gyp
@@ -299,6 +299,39 @@
],
},
+ # The sync external API library.
+ {
+ 'target_name': 'syncapi_service',
+ 'type': 'static_library',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ 'protocol/sync_proto.gyp:sync_proto',
+ 'sync',
+ ],
+ # Even though this target depends on sync_proto, it doesn't
+ # need to export a hard dependency since we explicitly avoid
+ # including the generated proto header files from this target's
+ # header files.
+ 'sources': [
+ 'api/syncable_service.cc',
+ 'api/syncable_service.h',
+ 'api/sync_data.h',
+ 'api/sync_data.cc',
+ 'api/sync_change.h',
+ 'api/sync_change.cc',
+ 'api/sync_change_processor.h',
+ 'api/sync_change_processor.cc',
+ 'api/sync_error.h',
+ 'api/sync_error.cc',
+ 'api/sync_error_factory.h',
+ 'api/sync_error_factory.cc',
+ ],
+ },
+
# Test support files for the 'sync' target.
{
'target_name': 'test_support_sync',
@@ -405,6 +438,29 @@
],
},
+ # Test support files for the 'syncapi_service' target.
+ {
+ 'target_name': 'test_support_syncapi_service',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ '../testing/gmock.gyp:gmock',
+ 'syncapi_service',
+ ],
+ 'export_dependent_settings': [
+ '../testing/gmock.gyp:gmock',
+ 'syncapi_service',
+ ],
+ 'sources': [
+ 'api/fake_syncable_service.cc',
+ 'api/fake_syncable_service.h',
+ 'api/sync_error_factory_mock.cc',
+ 'api/sync_error_factory_mock.h',
+ ],
+ },
+
# Unit tests for the 'sync' target. This cannot be a static
# library because the unit test files have to be compiled directly
# into the executable, so we push the target files to the
@@ -593,6 +649,45 @@
},
},
+ # Unit tests for the 'syncapi_service' target. This cannot be a static
+ # library because the unit test files have to be compiled directly
+ # into the executable, so we push the target files to the
+ # depending executable target via direct_dependent_settings.
+ {
+ 'target_name': 'syncapi_service_tests',
+ 'type': 'none',
+ # We only want unit test executables to include this target.
+ 'suppress_wildcard': 1,
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../testing/gtest.gyp:gtest',
+ 'protocol/sync_proto.gyp:sync_proto',
+ 'sync',
+ 'syncapi_service',
+ 'test_support_syncapi_service',
+ ],
+ # Propagate all dependencies since the actual compilation
+ # happens in the dependents.
+ 'export_dependent_settings': [
+ '../base/base.gyp:base',
+ '../testing/gtest.gyp:gtest',
+ 'protocol/sync_proto.gyp:sync_proto',
+ 'sync',
+ 'syncapi_service',
+ 'test_support_syncapi_service',
+ ],
+ 'direct_dependent_settings': {
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'api/sync_change_unittest.cc',
+ 'api/sync_error_unittest.cc',
+ ],
+ },
+ },
+
# The unit test executable for sync tests.
{
'target_name': 'sync_unit_tests',
@@ -602,6 +697,7 @@
'sync_tests',
'sync_notifier_tests',
'syncapi_core_tests',
+ 'syncapi_service_tests',
],
# TODO(akalin): This is needed because histogram.cc uses
# leak_annotations.h, which pulls this in. Make 'base'