| Index: chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc
|
| diff --git a/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc b/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc
|
| index ffd42fd6eea1e76ee1bbe028c166f802de0ecf31..a2054c2131732040062aaff821bf8fdfbae8578d 100644
|
| --- a/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc
|
| +++ b/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc
|
| @@ -5,8 +5,11 @@
|
| #include "chrome/browser/sync/glue/chrome_sync_notification_bridge.h"
|
|
|
| #include "base/compiler_specific.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/memory/ref_counted.h"
|
| #include "base/memory/weak_ptr.h"
|
| #include "base/message_loop.h"
|
| +#include "base/sequenced_task_runner.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/test/test_timeouts.h"
|
| #include "base/threading/thread.h"
|
| @@ -17,7 +20,6 @@
|
| #include "content/public/test/test_browser_thread.h"
|
| #include "sync/internal_api/public/base/model_type.h"
|
| #include "sync/internal_api/public/base/model_type_payload_map.h"
|
| -#include "sync/notifier/mock_sync_notifier_observer.h"
|
| #include "sync/notifier/sync_notifier_observer.h"
|
| #include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| @@ -34,24 +36,28 @@ using content::BrowserThread;
|
| // ModelTypePayloadMap. ReceivedProperNotification() will return true only
|
| // if the observer has received a notification with the proper source and
|
| // payload.
|
| -// Note: Because this object lives on the IO thread, we use a fake (vs a mock)
|
| -// so we don't have to worry about possible thread safety issues within
|
| -// GTest/GMock.
|
| -class FakeSyncNotifierObserverIO
|
| - : public syncer::SyncNotifierObserver {
|
| +// Note: Because this object lives on the sync thread, we use a fake
|
| +// (vs a mock) so we don't have to worry about possible thread safety
|
| +// issues within GTest/GMock.
|
| +class FakeSyncNotifierObserver : public syncer::SyncNotifierObserver {
|
| public:
|
| - FakeSyncNotifierObserverIO(
|
| + FakeSyncNotifierObserver(
|
| + const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner,
|
| ChromeSyncNotificationBridge* bridge,
|
| - const syncer::ModelTypePayloadMap& expected_payloads)
|
| - : bridge_(bridge),
|
| + const syncer::ModelTypePayloadMap& expected_payloads,
|
| + syncer::IncomingNotificationSource expected_source)
|
| + : sync_task_runner_(sync_task_runner),
|
| + bridge_(bridge),
|
| received_improper_notification_(false),
|
| notification_count_(0),
|
| - expected_payloads_(expected_payloads) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + expected_payloads_(expected_payloads),
|
| + expected_source_(expected_source) {
|
| + DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
|
| bridge_->AddObserver(this);
|
| }
|
| - virtual ~FakeSyncNotifierObserverIO() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + virtual ~FakeSyncNotifierObserver() {
|
| + DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
|
| bridge_->RemoveObserver(this);
|
| }
|
|
|
| @@ -59,14 +65,14 @@ class FakeSyncNotifierObserverIO
|
| virtual void OnIncomingNotification(
|
| const syncer::ModelTypePayloadMap& type_payloads,
|
| syncer::IncomingNotificationSource source) OVERRIDE {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
|
| notification_count_++;
|
| - if (source != syncer::LOCAL_NOTIFICATION) {
|
| - LOG(ERROR) << "Received notification with wrong source.";
|
| + if (source != expected_source_) {
|
| + LOG(ERROR) << "Received notification with wrong source";
|
| received_improper_notification_ = true;
|
| }
|
| if (expected_payloads_ != type_payloads) {
|
| - LOG(ERROR) << "Received wrong payload.";
|
| + LOG(ERROR) << "Received wrong payload";
|
| received_improper_notification_ = true;
|
| }
|
| }
|
| @@ -79,89 +85,103 @@ class FakeSyncNotifierObserverIO
|
| }
|
|
|
| bool ReceivedProperNotification() const {
|
| + DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
|
| return (notification_count_ == 1) && !received_improper_notification_;
|
| }
|
|
|
| private:
|
| - ChromeSyncNotificationBridge* bridge_;
|
| + const scoped_refptr<base::SequencedTaskRunner> sync_task_runner_;
|
| + ChromeSyncNotificationBridge* const bridge_;
|
| bool received_improper_notification_;
|
| size_t notification_count_;
|
| - syncer::ModelTypePayloadMap expected_payloads_;
|
| + const syncer::ModelTypePayloadMap expected_payloads_;
|
| + const syncer::IncomingNotificationSource expected_source_;
|
| };
|
|
|
| class ChromeSyncNotificationBridgeTest : public testing::Test {
|
| public:
|
| ChromeSyncNotificationBridgeTest()
|
| - : ui_thread_(BrowserThread::UI, &ui_loop_),
|
| - io_thread_(BrowserThread::IO),
|
| - io_observer_(NULL),
|
| - io_observer_notification_failure_(false),
|
| - bridge_(&mock_profile_),
|
| - done_(true, false) {
|
| - io_thread_.StartIOThread();
|
| - }
|
| + : ui_thread_(BrowserThread::UI),
|
| + sync_thread_("Sync thread"),
|
| + sync_observer_(NULL),
|
| + sync_observer_notification_failure_(false),
|
| + done_(true, false) {}
|
| +
|
| virtual ~ChromeSyncNotificationBridgeTest() {}
|
|
|
| protected:
|
| + virtual void SetUp() OVERRIDE {
|
| + ASSERT_TRUE(sync_thread_.Start());
|
| + bridge_.reset(
|
| + new ChromeSyncNotificationBridge(
|
| + &mock_profile_, sync_thread_.message_loop_proxy()));
|
| + }
|
| +
|
| virtual void TearDown() OVERRIDE {
|
| - io_thread_.Stop();
|
| - ui_loop_.RunAllPending();
|
| - EXPECT_EQ(NULL, io_observer_);
|
| - if (io_observer_notification_failure_)
|
| - ADD_FAILURE() << "IO Observer did not receive proper notification.";
|
| + sync_thread_.Stop();
|
| + // Must be reset only after the sync thread is stopped.
|
| + bridge_.reset();
|
| + EXPECT_EQ(NULL, sync_observer_);
|
| + if (sync_observer_notification_failure_)
|
| + ADD_FAILURE() << "Sync Observer did not receive proper notification.";
|
| }
|
|
|
| - void VerifyAndDestroyObserverOnIOThread() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (!io_observer_) {
|
| - io_observer_notification_failure_ = true;
|
| + void VerifyAndDestroyObserverOnSyncThread() {
|
| + DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
|
| + if (!sync_observer_) {
|
| + sync_observer_notification_failure_ = true;
|
| } else {
|
| - io_observer_notification_failure_ =
|
| - !io_observer_->ReceivedProperNotification();
|
| - delete io_observer_;
|
| - io_observer_ = NULL;
|
| + sync_observer_notification_failure_ =
|
| + !sync_observer_->ReceivedProperNotification();
|
| + delete sync_observer_;
|
| + sync_observer_ = NULL;
|
| }
|
| }
|
|
|
| void VerifyAndDestroyObserver() {
|
| - ASSERT_TRUE(BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| + ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
|
| FROM_HERE,
|
| base::Bind(&ChromeSyncNotificationBridgeTest::
|
| - VerifyAndDestroyObserverOnIOThread,
|
| + VerifyAndDestroyObserverOnSyncThread,
|
| base::Unretained(this))));
|
| + BlockForSyncThread();
|
| }
|
|
|
| - void CreateObserverOnIOThread(
|
| - syncer::ModelTypePayloadMap expected_payloads) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - io_observer_ = new FakeSyncNotifierObserverIO(&bridge_,
|
| - expected_payloads);
|
| + void CreateObserverOnSyncThread(
|
| + syncer::ModelTypePayloadMap expected_payloads,
|
| + syncer::IncomingNotificationSource expected_source) {
|
| + DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
|
| + sync_observer_ = new FakeSyncNotifierObserver(
|
| + sync_thread_.message_loop_proxy(),
|
| + bridge_.get(),
|
| + expected_payloads,
|
| + expected_source);
|
| }
|
|
|
| - void CreateObserverWithExpectedPayload(
|
| - syncer::ModelTypePayloadMap expected_payloads) {
|
| - ASSERT_TRUE(BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| + void CreateObserverWithExpectations(
|
| + syncer::ModelTypePayloadMap expected_payloads,
|
| + syncer::IncomingNotificationSource expected_source) {
|
| + ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ChromeSyncNotificationBridgeTest::CreateObserverOnIOThread,
|
| - base::Unretained(this),
|
| - expected_payloads)));
|
| - BlockForIOThread();
|
| + base::Bind(
|
| + &ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread,
|
| + base::Unretained(this),
|
| + expected_payloads,
|
| + expected_source)));
|
| + BlockForSyncThread();
|
| }
|
|
|
| - void SignalOnIOThread() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + void SignalOnSyncThread() {
|
| + DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
|
| done_.Signal();
|
| }
|
|
|
| - void BlockForIOThread() {
|
| + void BlockForSyncThread() {
|
| done_.Reset();
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| + ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ChromeSyncNotificationBridgeTest::SignalOnIOThread,
|
| - base::Unretained(this)));
|
| + base::Bind(&ChromeSyncNotificationBridgeTest::SignalOnSyncThread,
|
| + base::Unretained(this))));
|
| done_.TimedWait(TestTimeouts::action_timeout());
|
| if (!done_.IsSignaled())
|
| ADD_FAILURE() << "Timed out waiting for IO thread.";
|
| @@ -176,103 +196,68 @@ class ChromeSyncNotificationBridgeTest : public testing::Test {
|
| content::Details<const syncer::ModelTypePayloadMap>(&payload_map));
|
| }
|
|
|
| - MessageLoop ui_loop_;
|
| + private:
|
| content::TestBrowserThread ui_thread_;
|
| - content::TestBrowserThread io_thread_;
|
| + base::Thread sync_thread_;
|
| NiceMock<ProfileMock> mock_profile_;
|
| - // Created/used/destroyed on I/O thread.
|
| - FakeSyncNotifierObserverIO* io_observer_;
|
| - bool io_observer_notification_failure_;
|
| - ChromeSyncNotificationBridge bridge_;
|
| + // Created/used/destroyed on sync thread.
|
| + FakeSyncNotifierObserver* sync_observer_;
|
| + bool sync_observer_notification_failure_;
|
| + scoped_ptr<ChromeSyncNotificationBridge> bridge_;
|
| base::WaitableEvent done_;
|
| };
|
|
|
| -// Adds an observer on the UI thread, triggers a local refresh notification, and
|
| -// ensures the bridge posts a LOCAL_NOTIFICATION with the proper payload to it.
|
| +// Adds an observer on the sync thread, triggers a local refresh
|
| +// notification, and ensures the bridge posts a LOCAL_NOTIFICATION
|
| +// with the proper payload to it.
|
| TEST_F(ChromeSyncNotificationBridgeTest, LocalNotification) {
|
| syncer::ModelTypePayloadMap payload_map;
|
| payload_map[syncer::SESSIONS] = "";
|
| - StrictMock<syncer::MockSyncNotifierObserver> observer;
|
| - EXPECT_CALL(observer,
|
| - OnIncomingNotification(payload_map,
|
| - syncer::LOCAL_NOTIFICATION));
|
| - bridge_.AddObserver(&observer);
|
| + CreateObserverWithExpectations(payload_map, syncer::LOCAL_NOTIFICATION);
|
| TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
|
| payload_map);
|
| - ui_loop_.RunAllPending();
|
| - Mock::VerifyAndClearExpectations(&observer);
|
| + VerifyAndDestroyObserver();
|
| }
|
|
|
| -// Adds an observer on the UI thread, triggers a remote refresh notification,
|
| -// and ensures the bridge posts a REMOTE_NOTIFICATION with the proper payload
|
| -// to it.
|
| +// Adds an observer on the sync thread, triggers a remote refresh
|
| +// notification, and ensures the bridge posts a REMOTE_NOTIFICATION
|
| +// with the proper payload to it.
|
| TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotification) {
|
| syncer::ModelTypePayloadMap payload_map;
|
| - payload_map[syncer::BOOKMARKS] = "";
|
| - StrictMock<syncer::MockSyncNotifierObserver> observer;
|
| - EXPECT_CALL(observer,
|
| - OnIncomingNotification(payload_map,
|
| - syncer::REMOTE_NOTIFICATION));
|
| - bridge_.AddObserver(&observer);
|
| + payload_map[syncer::SESSIONS] = "";
|
| + CreateObserverWithExpectations(payload_map, syncer::REMOTE_NOTIFICATION);
|
| TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
|
| payload_map);
|
| - ui_loop_.RunAllPending();
|
| - Mock::VerifyAndClearExpectations(&observer);
|
| + VerifyAndDestroyObserver();
|
| }
|
|
|
| -// Adds an observer on the UI thread, triggers a local refresh notification
|
| -// with empty payload map and ensures the bridge posts a
|
| +// Adds an observer on the sync thread, triggers a local refresh
|
| +// notification with empty payload map and ensures the bridge posts a
|
| // LOCAL_NOTIFICATION with the proper payload to it.
|
| TEST_F(ChromeSyncNotificationBridgeTest, LocalNotificationEmptyPayloadMap) {
|
| const syncer::ModelTypeSet enabled_types(
|
| syncer::BOOKMARKS, syncer::PASSWORDS);
|
| const syncer::ModelTypePayloadMap enabled_types_payload_map =
|
| syncer::ModelTypePayloadMapFromEnumSet(enabled_types, std::string());
|
| -
|
| - StrictMock<syncer::MockSyncNotifierObserver> observer;
|
| - EXPECT_CALL(observer,
|
| - OnIncomingNotification(enabled_types_payload_map,
|
| - syncer::LOCAL_NOTIFICATION));
|
| - bridge_.AddObserver(&observer);
|
| - // Set enabled types on the bridge.
|
| - bridge_.UpdateEnabledTypes(enabled_types);
|
| + CreateObserverWithExpectations(
|
| + enabled_types_payload_map, syncer::LOCAL_NOTIFICATION);
|
| TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
|
| - syncer::ModelTypePayloadMap());
|
| - ui_loop_.RunAllPending();
|
| - Mock::VerifyAndClearExpectations(&observer);
|
| + enabled_types_payload_map);
|
| + VerifyAndDestroyObserver();
|
| }
|
|
|
| -// Adds an observer on the UI thread, triggers a remote refresh notification
|
| -// with empty payload map and ensures the bridge posts a
|
| +// Adds an observer on the sync thread, triggers a remote refresh
|
| +// notification with empty payload map and ensures the bridge posts a
|
| // REMOTE_NOTIFICATION with the proper payload to it.
|
| TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotificationEmptyPayloadMap) {
|
| const syncer::ModelTypeSet enabled_types(
|
| syncer::BOOKMARKS, syncer::TYPED_URLS);
|
| const syncer::ModelTypePayloadMap enabled_types_payload_map =
|
| syncer::ModelTypePayloadMapFromEnumSet(enabled_types, std::string());
|
| -
|
| - StrictMock<syncer::MockSyncNotifierObserver> observer;
|
| - EXPECT_CALL(observer,
|
| - OnIncomingNotification(enabled_types_payload_map,
|
| - syncer::REMOTE_NOTIFICATION));
|
| - bridge_.AddObserver(&observer);
|
| - // Set enabled types on the bridge.
|
| - bridge_.UpdateEnabledTypes(enabled_types);
|
| + CreateObserverWithExpectations(
|
| + enabled_types_payload_map, syncer::REMOTE_NOTIFICATION);
|
| TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
|
| - syncer::ModelTypePayloadMap());
|
| - ui_loop_.RunAllPending();
|
| - Mock::VerifyAndClearExpectations(&observer);
|
| -}
|
| -
|
| -// Adds an observer on the I/O thread. Then triggers a refresh notification on
|
| -// the UI thread. We finally verify the proper notification was received by the
|
| -// observer and destroy it on the I/O thread.
|
| -TEST_F(ChromeSyncNotificationBridgeTest, BasicThreaded) {
|
| - syncer::ModelTypePayloadMap payload_map;
|
| - payload_map[syncer::SESSIONS] = "";
|
| - CreateObserverWithExpectedPayload(payload_map);
|
| - TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
|
| - payload_map);
|
| + enabled_types_payload_map);
|
| VerifyAndDestroyObserver();
|
| }
|
|
|
|
|