Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Unified Diff: chrome/browser/notifier/chrome_notifier_service_unittest.cc

Issue 11745024: Synced Notification Sync Change Processor (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/notifier/chrome_notifier_service_unittest.cc
diff --git a/chrome/browser/notifier/chrome_notifier_service_unittest.cc b/chrome/browser/notifier/chrome_notifier_service_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a718ad10b71f5282ab9778091290b3360a721a80
--- /dev/null
+++ b/chrome/browser/notifier/chrome_notifier_service_unittest.cc
@@ -0,0 +1,306 @@
+// 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 <map>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/notifier/chrome_notifier_service.h"
+#include "chrome/browser/notifier/synced_notification.h"
+#include "sync/api/sync_change.h"
+#include "sync/api/sync_change_processor.h"
+#include "sync/api/sync_error_factory.h"
+#include "sync/api/sync_error_factory_mock.h"
+#include "sync/protocol/sync.pb.h"
+#include "sync/protocol/synced_notification_specifics.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using namespace sync_pb;
+using namespace syncer;
+
+namespace {
+
+
dcheng 2013/01/07 20:42:10 Extra newline. Please remove.
Pete Williamson 2013/01/18 18:58:39 Done.
+const char MY_APP_ID[] = "fboilmbenheemaomgaeehigklolhkhnf";
dcheng 2013/01/07 20:42:10 Wrong naming convention.
Pete Williamson 2013/01/18 18:58:39 Done.
+const char COALESCING_KEY[] = "foo";
+const unsigned long long FAKE_CREATION_TIME = 42;
+
+// Extract notification id from syncer::SyncData.
+std::string GetId(const SyncData& sync_data) {
+ SyncedNotificationSpecifics specifics = sync_data.GetSpecifics().
+ synced_notification();
+ return specifics.coalesced_notification().notification(0).external_id();
+}
+
+// Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
+// back up to Sync.
+class TestChangeProcessor : public SyncChangeProcessor {
+ public:
+ TestChangeProcessor() { }
+ virtual ~TestChangeProcessor() { }
+
+ // Store a copy of all the changes passed in so we can examine them later.
+ virtual SyncError ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const SyncChangeList& change_list) {
+ change_map_.erase(change_map_.begin(), change_map_.end());
+ for (SyncChangeList::const_iterator iter = change_list.begin();
+ iter != change_list.end(); ++iter) {
+ // Put the data into the change tracking map.
+ change_map_[GetId(iter->sync_data())] = *iter;
+ }
+
+ return SyncError();
+ }
+
+ size_t change_list_size() { return change_map_.size(); }
+
+ bool ContainsId(const std::string& id) {
+ return change_map_.find(id) != change_map_.end();
+ }
+
+ SyncChange GetChangeById(const std::string& id) {
+ DCHECK(ContainsId(id));
+ return change_map_[id];
+ }
+
+ private:
+ // Track the changes received in ProcessSyncChanges.
+ std::map<std::string, SyncChange> change_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
+};
+
+class SyncChangeProcessorDelegate : public SyncChangeProcessor {
+ public:
+ explicit SyncChangeProcessorDelegate(SyncChangeProcessor* recipient)
+ : recipient_(recipient) {
+ DCHECK(recipient_);
+ }
+ virtual ~SyncChangeProcessorDelegate() {}
+
+ // syncer::SyncChangeProcessor implementation.
+ virtual SyncError ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const SyncChangeList& change_list) OVERRIDE {
+ return recipient_->ProcessSyncChanges(from_here, change_list);
+ }
+
+ private:
+ // The recipient of all sync changes.
+ SyncChangeProcessor* recipient_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
+};
+
+} // namespace
+
+class ChromeNotifierServiceTest : public testing::Test {
+
+ public:
+ ChromeNotifierServiceTest()
+ : sync_processor_(new TestChangeProcessor),
+ sync_processor_delegate_(new SyncChangeProcessorDelegate(
+ sync_processor_.get())) {}
+ ~ChromeNotifierServiceTest() {}
+
+ // Methods from testing::Test.
+
+ virtual void SetUp() {
+ }
+
+ virtual void TearDown() {
+ }
+
+ TestChangeProcessor* processor() { return sync_processor_.get(); }
+
+ scoped_ptr<SyncChangeProcessor> PassProcessor() {
+ return sync_processor_delegate_.PassAs<SyncChangeProcessor>();
+ }
+
+ SyncedNotification* CreateNotification(const std::string& message,
+ const std::string& external_id) {
+ SyncData sync_data = CreateSyncData(message, external_id);
+ // Set enough fields in sync_data, including specifics, for our tests
+ // to pass.
+ return new SyncedNotification(sync_data);
+ }
+
+ // Helper to create syncer::SyncChange.
+ static SyncChange CreateSyncChange(
+ SyncChange::SyncChangeType type,
+ SyncedNotification* notification) {
+ // Take control of the notification to clean it up after we create data
+ // out of it.
+ scoped_ptr<SyncedNotification> scoped_notif(notification);
+ return SyncChange(
+ FROM_HERE,
+ type,
+ ChromeNotifierService::CreateSyncDataFromNotification(*notification));
+ }
+
+ // Helper to create syncer::SyncData.
+ static SyncData CreateSyncData(const std::string& message,
+ const std::string& external_id) {
+
+ // CreateLocalData makes a copy of this, so this can safely live
+ // on the stack.
+ EntitySpecifics entity_specifics;
+
+ // Get a writeable pointer to the sync notifications specifics inside the
+ // entity specifics.
+ SyncedNotificationSpecifics* specifics =
+ entity_specifics.mutable_synced_notification();
+
+ // Fill out as much of SyncedNotificationSpecifics as the tests need.
+
+ // Set the layout type to Title and Subtext.
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_layout()->
+ set_layout_type(RenderInfo_Layout_LayoutType_TITLE_AND_SUBTEXT);
+ // Set the APP_ID field in the ID.
+ specifics->mutable_coalesced_notification()->
+ mutable_id()->
+ set_app_id(MY_APP_ID);
+ // Set the coalescing key in the ID.
+ specifics->mutable_coalesced_notification()->
+ mutable_id()->
+ set_coalescing_key(COALESCING_KEY);
+ // Set the title (of a title and subtext).
+ specifics->mutable_coalesced_notification()->
+ mutable_render_info()->
+ mutable_layout()->
+ mutable_title_and_subtext_data()->
+ set_title(message);
+ // Set the creation time.
+ specifics->mutable_coalesced_notification()->
+ set_creation_time_msec(FAKE_CREATION_TIME);
+ // Set the first notification, including external ID.
+ specifics->mutable_coalesced_notification()->
+ add_notification();
+ specifics->mutable_coalesced_notification()->
+ mutable_notification(0)->set_external_id(external_id);
+
+
+ SyncData sync_data = SyncData::CreateLocalData(
+ "syncer::SYNCED_NOTIFICATIONS",
+ "ChromeNotifierServiceUnitTest",
+ entity_specifics);
+
+ return sync_data;
+ }
+
+ private:
+ scoped_ptr<TestChangeProcessor> sync_processor_;
+ scoped_ptr<SyncChangeProcessorDelegate> sync_processor_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeNotifierServiceTest);
+};
+
+// Create a Notification, convert it to SyncData and convert it back.
+TEST_F(ChromeNotifierServiceTest, NotificationToSyncDataToNotification) {
+ // TODO(petewil): Make this more robust when I add more properties to
+ // the notification.
+ scoped_ptr<SyncedNotification> notif1(CreateNotification("1", "11"));
+ SyncData sync_data =
+ ChromeNotifierService::CreateSyncDataFromNotification(*notif1);
+ scoped_ptr<SyncedNotification> notif2(
+ ChromeNotifierService::CreateNotificationFromSyncData(sync_data));
+ EXPECT_TRUE(notif2.get());
+ EXPECT_TRUE(notif1->Equals(*notif2));
+}
+
+
+// Model assocation: We have no local data, and no remote data.
+TEST_F(ChromeNotifierServiceTest, ModelAssocBothEmpty) {
+ ChromeNotifierService notifier;
+
+ notifier.MergeDataAndStartSyncing(
+ SYNCED_NOTIFICATIONS,
+ SyncDataList(), // Empty.
+ PassProcessor(),
+ scoped_ptr<SyncErrorFactory>(new SyncErrorFactoryMock()));
+
+ EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
+ EXPECT_EQ(0U, processor()->change_list_size());}
+
+// Process sync changes when there is no local data.
+TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesEmptyModel) {
+ // We initially have no data.
+ ChromeNotifierService notifier;
+
+ notifier.MergeDataAndStartSyncing(
+ SYNCED_NOTIFICATIONS,
+ SyncDataList(),
+ PassProcessor(),
+ scoped_ptr<SyncErrorFactory>(new SyncErrorFactoryMock()));
+
+ // Set up a bunch of ADDs.
+ SyncChangeList changes;
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_ADD, CreateNotification("1", "11")));
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_ADD, CreateNotification("2", "22")));
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_ADD, CreateNotification("3", "33")));
+
+ notifier.ProcessSyncChanges(FROM_HERE, changes);
+
+ EXPECT_EQ(3U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
+}
+
+// Model has some notifications, some of them are local only. Sync has some
+// notifications. No items match up.
+TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
+ ChromeNotifierService notifier;
+
+ // Create some local fake data.
+ SyncedNotification* n1 = CreateNotification("1", "11");
+ notifier.Add(n1);
+ SyncedNotification* n2 = CreateNotification("2", "22");
+ notifier.Add(n2);
+ SyncedNotification* n3 = CreateNotification("3", "33");
+ notifier.Add(n3);
+
+ // Create some remote fake data.
+ SyncDataList initial_data;
+ SyncData s1 = CreateSyncData("4", "44");
+ initial_data.push_back(s1);
+ initial_data.push_back(CreateSyncData("5", "55"));
+ initial_data.push_back(CreateSyncData("6", "66"));
+ initial_data.push_back(CreateSyncData("7", "77"));
+
+ // Merge the local and remote data.
+ notifier.MergeDataAndStartSyncing(
+ SYNCED_NOTIFICATIONS,
+ initial_data,
+ PassProcessor(),
+ scoped_ptr<SyncErrorFactory>(new SyncErrorFactoryMock()));
+
+ // Ensure the array now has all local and remote notifications.
+ EXPECT_EQ(7U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
+ for (SyncDataList::const_iterator iter = initial_data.begin();
+ iter != initial_data.end(); ++iter) {
+ scoped_ptr<SyncedNotification> notif1(
+ ChromeNotifierService::CreateNotificationFromSyncData(*iter));
+ // TODO(petewil): Revisit this when we expand the protobuf more.
+ const std::string& value = notif1->title();
+ const SyncedNotification* notif2 = notifier.GetNotification(value);
+ EXPECT_TRUE(NULL != notif2);
+ EXPECT_TRUE(notif1->Equals(*notif2));
+ }
+ EXPECT_TRUE(notifier.GetNotification(n1->title()));
+ EXPECT_TRUE(notifier.GetNotification(n2->title()));
+ EXPECT_TRUE(notifier.GetNotification(n3->title()));
+
+ // Verify the changes made it up to the remote service.
+ EXPECT_EQ(3U, processor()->change_list_size());
+ EXPECT_TRUE(processor()->ContainsId(n1->get_first_external_id()));
+ EXPECT_EQ(SyncChange::ACTION_ADD, processor()->GetChangeById(
+ n1->get_first_external_id()).change_type());
+ EXPECT_FALSE(processor()->ContainsId("44"));
+ EXPECT_TRUE(processor()->ContainsId(n3->get_first_external_id()));
+ EXPECT_EQ(SyncChange::ACTION_ADD, processor()->GetChangeById(
+ n3->get_first_external_id()).change_type());
+}

Powered by Google App Engine
This is Rietveld 408576698