diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-05 23:44:06 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-05 23:44:06 +0000 |
commit | ec140301a87ecf1ba9e70e8031ee521c002b0f32 (patch) | |
tree | 2775b581338244c0ed49633d53def838cc703755 /chrome | |
parent | 079786397d052c14a2b1886dfb494c4bd4a9335c (diff) | |
download | chromium_src-ec140301a87ecf1ba9e70e8031ee521c002b0f32.zip chromium_src-ec140301a87ecf1ba9e70e8031ee521c002b0f32.tar.gz chromium_src-ec140301a87ecf1ba9e70e8031ee521c002b0f32.tar.bz2 |
Added NetworkChangeNotifierThread interface.
Also made NetworkChange{Observer,Notifier}Proxy use it instead of
managing the source message loop and NetworkChangeNotifier themselves.
BUG=42606
TEST=unit tests
Review URL: http://codereview.chromium.org/1973001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46524 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
12 files changed, 381 insertions, 152 deletions
diff --git a/chrome/browser/sync/net/fake_network_change_notifier_thread.cc b/chrome/browser/sync/net/fake_network_change_notifier_thread.cc new file mode 100644 index 0000000..f0d9c25 --- /dev/null +++ b/chrome/browser/sync/net/fake_network_change_notifier_thread.cc @@ -0,0 +1,80 @@ +// Copyright (c) 2010 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 "chrome/browser/sync/net/fake_network_change_notifier_thread.h" + +#include "base/logging.h" +#include "base/message_loop.h" +#include "chrome/browser/sync/net/thread_blocker.h" +#include "net/base/mock_network_change_notifier.h" + +// We manage the lifetime of +// browser_sync::FakeNetworkChangeNotifierThread ourselves. +template <> +struct RunnableMethodTraits<browser_sync::FakeNetworkChangeNotifierThread> { + void RetainCallee(browser_sync::FakeNetworkChangeNotifierThread*) {} + void ReleaseCallee(browser_sync::FakeNetworkChangeNotifierThread*) {} +}; + +namespace browser_sync { + +FakeNetworkChangeNotifierThread::FakeNetworkChangeNotifierThread() + : thread_("FakeNetworkChangeNotifierThread") {} + +FakeNetworkChangeNotifierThread::~FakeNetworkChangeNotifierThread() { + CHECK(!network_change_notifier_.get()); + CHECK(!thread_blocker_.get()); + CHECK(!thread_.IsRunning()); +} + +void FakeNetworkChangeNotifierThread::Start() { + CHECK(thread_.Start()); + thread_blocker_.reset(new ThreadBlocker(&thread_)); + network_change_notifier_.reset(new net::MockNetworkChangeNotifier()); + thread_blocker_->Block(); +} + +void FakeNetworkChangeNotifierThread::Pump() { + thread_blocker_->Unblock(); + thread_blocker_->Block(); +} + +void FakeNetworkChangeNotifierThread::Stop() { + thread_blocker_->Unblock(); + network_change_notifier_.reset(); + thread_blocker_.reset(); + thread_.Stop(); +} + +void FakeNetworkChangeNotifierThread::NotifyIPAddressChange() { + CHECK(thread_.IsRunning()); + GetMessageLoop()->PostTask( + FROM_HERE, + NewRunnableMethod( + this, + &FakeNetworkChangeNotifierThread:: + NotifyIPAddressChangeOnSourceThread)); +} + +void FakeNetworkChangeNotifierThread::NotifyIPAddressChangeOnSourceThread() { + CHECK_EQ(MessageLoop::current(), GetMessageLoop()); + CHECK(network_change_notifier_.get()); + network_change_notifier_->NotifyIPAddressChange(); +} + +MessageLoop* FakeNetworkChangeNotifierThread::GetMessageLoop() const { + CHECK(thread_.IsRunning()); + MessageLoop* message_loop = thread_.message_loop(); + CHECK(message_loop); + return message_loop; +} + +net::NetworkChangeNotifier* +FakeNetworkChangeNotifierThread::GetNetworkChangeNotifier() const { + CHECK_EQ(MessageLoop::current(), GetMessageLoop()); + CHECK(network_change_notifier_.get()); + return network_change_notifier_.get(); +} + +} // namespace browser_sync diff --git a/chrome/browser/sync/net/fake_network_change_notifier_thread.h b/chrome/browser/sync/net/fake_network_change_notifier_thread.h new file mode 100644 index 0000000..ccc3225 --- /dev/null +++ b/chrome/browser/sync/net/fake_network_change_notifier_thread.h @@ -0,0 +1,64 @@ +// Copyright (c) 2010 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 CHROME_BROWSER_SYNC_NET_FAKE_NETWORK_CHANGE_NOTIFIER_THREAD_H_ +#define CHROME_BROWSER_SYNC_NET_FAKE_NETWORK_CHANGE_NOTIFIER_THREAD_H_ + +// A fake implementation of NetworkChangeNotifierThread used for +// unit-testing. + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "base/thread.h" +#include "chrome/browser/sync/net/network_change_notifier_thread.h" + +namespace net { +class MockNetworkChangeNotifier; +} // namespace net + +namespace browser_sync { + +class ThreadBlocker; + +class FakeNetworkChangeNotifierThread : public NetworkChangeNotifierThread { + public: + FakeNetworkChangeNotifierThread(); + + virtual ~FakeNetworkChangeNotifierThread(); + + // Starts the thread in a blocked state and initializes the network + // change notifier. + void Start(); + + // Runs the tasks that are currently blocked. After this call, + // thread remains in a blocked state. A call to this function is a + // memory barrier. + void Pump(); + + // Stops the thread. + void Stop(); + + // Trigger an IP address change notification on the owned network + // change notifier on the owned thread. + void NotifyIPAddressChange(); + + // Implementation of NetworkChangeNotifierThread. + + virtual MessageLoop* GetMessageLoop() const; + + virtual net::NetworkChangeNotifier* GetNetworkChangeNotifier() const; + + private: + void NotifyIPAddressChangeOnSourceThread(); + + base::Thread thread_; + scoped_ptr<ThreadBlocker> thread_blocker_; + scoped_ptr<net::MockNetworkChangeNotifier> network_change_notifier_; + + DISALLOW_COPY_AND_ASSIGN(FakeNetworkChangeNotifierThread); +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_NET_FAKE_NETWORK_CHANGE_NOTIFIER_THREAD_H_ diff --git a/chrome/browser/sync/net/fake_network_change_notifier_thread_unittest.cc b/chrome/browser/sync/net/fake_network_change_notifier_thread_unittest.cc new file mode 100644 index 0000000..02828ce --- /dev/null +++ b/chrome/browser/sync/net/fake_network_change_notifier_thread_unittest.cc @@ -0,0 +1,121 @@ +// Copyright (c) 2010 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 "chrome/browser/sync/net/fake_network_change_notifier_thread.h" + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "base/task.h" +#include "net/base/network_change_notifier.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace browser_sync { +class FlagToggler; +} // namespace browser_sync + +// We manage the lifetime of browser_sync::FlagToggler ourselves. +template <> +struct RunnableMethodTraits<browser_sync::FlagToggler> { + void RetainCallee(browser_sync::FlagToggler*) {} + void ReleaseCallee(browser_sync::FlagToggler*) {} +}; + +namespace browser_sync { + +// Utility class that toggles a flag every time it receives an IP +// address change notification. +class FlagToggler : public net::NetworkChangeNotifier::Observer { + public: + FlagToggler() : flag_(false) {} + + virtual ~FlagToggler() {} + + bool flag() const { return flag_; } + + void ToggleFlag() { + flag_ = !flag_; + } + + void Observe(NetworkChangeNotifierThread* thread) { + thread->GetNetworkChangeNotifier()->AddObserver(this); + } + + void Unobserve(NetworkChangeNotifierThread* thread) { + thread->GetNetworkChangeNotifier()->RemoveObserver(this); + } + + // net::NetworkChangeNotifier::Observer implementation. + virtual void OnIPAddressChanged() { + ToggleFlag(); + } + + private: + bool flag_; + + DISALLOW_COPY_AND_ASSIGN(FlagToggler); +}; + +namespace { + +class FakeNetworkChangeNotifierTest : public testing::Test { + protected: + FakeNetworkChangeNotifierTest() {} + + virtual ~FakeNetworkChangeNotifierTest() {} + + virtual void SetUp() { + thread_.Start(); + } + + virtual void TearDown() { + thread_.Stop(); + } + + FakeNetworkChangeNotifierThread thread_; + FlagToggler flag_toggler_; + + private: + DISALLOW_COPY_AND_ASSIGN(FakeNetworkChangeNotifierTest); +}; + +TEST_F(FakeNetworkChangeNotifierTest, Pump) { + thread_.GetMessageLoop()->PostTask( + FROM_HERE, NewRunnableMethod(&flag_toggler_, &FlagToggler::ToggleFlag)); + EXPECT_FALSE(flag_toggler_.flag()); + thread_.Pump(); + EXPECT_TRUE(flag_toggler_.flag()); +} + +TEST_F(FakeNetworkChangeNotifierTest, Basic) { + thread_.GetMessageLoop()->PostTask( + FROM_HERE, + NewRunnableMethod(&flag_toggler_, &FlagToggler::Observe, &thread_)); + thread_.NotifyIPAddressChange(); + thread_.GetMessageLoop()->PostTask( + FROM_HERE, + NewRunnableMethod(&flag_toggler_, &FlagToggler::Unobserve, &thread_)); + EXPECT_FALSE(flag_toggler_.flag()); + thread_.Pump(); + EXPECT_TRUE(flag_toggler_.flag()); +} + +TEST_F(FakeNetworkChangeNotifierTest, Multiple) { + FlagToggler observer; + thread_.GetMessageLoop()->PostTask( + FROM_HERE, + NewRunnableMethod(&flag_toggler_, &FlagToggler::Observe, &thread_)); + thread_.NotifyIPAddressChange(); + thread_.NotifyIPAddressChange(); + thread_.GetMessageLoop()->PostTask( + FROM_HERE, + NewRunnableMethod(&flag_toggler_, &FlagToggler::Unobserve, &thread_)); + EXPECT_FALSE(flag_toggler_.flag()); + thread_.Pump(); + EXPECT_FALSE(flag_toggler_.flag()); +} + +} // namespace + +} // namespace browser_sync diff --git a/chrome/browser/sync/net/network_change_notifier_proxy.cc b/chrome/browser/sync/net/network_change_notifier_proxy.cc index 7176da3..e1b3797 100644 --- a/chrome/browser/sync/net/network_change_notifier_proxy.cc +++ b/chrome/browser/sync/net/network_change_notifier_proxy.cc @@ -11,11 +11,9 @@ namespace browser_sync { NetworkChangeNotifierProxy::NetworkChangeNotifierProxy( - MessageLoop* source_message_loop, - net::NetworkChangeNotifier* source_network_change_notifier) + NetworkChangeNotifierThread* source_thread) : observer_proxy_(new NetworkChangeObserverProxy( - source_message_loop, source_network_change_notifier, - MessageLoop::current())), + source_thread, MessageLoop::current())), observer_repeater_(&observers_) { // TODO(akalin): We get this from NonThreadSafe, which // net::NetworkChangeNotifier inherits from. Interface classes diff --git a/chrome/browser/sync/net/network_change_notifier_proxy.h b/chrome/browser/sync/net/network_change_notifier_proxy.h index 517d705..2789abc 100644 --- a/chrome/browser/sync/net/network_change_notifier_proxy.h +++ b/chrome/browser/sync/net/network_change_notifier_proxy.h @@ -18,16 +18,15 @@ class MessageLoop; namespace browser_sync { +class NetworkChangeNotifierThread; class NetworkChangeObserverProxy; class NetworkChangeNotifierProxy : public net::NetworkChangeNotifier { public: - // Both source_thread and source_network_change_notifier must be - // guaranteed to outlive the current thread. Does not take - // ownership of any arguments. + // |source_thread| must be guaranteed to outlive the current thread. + // Does not take ownership of any arguments. NetworkChangeNotifierProxy( - MessageLoop* source_message_loop, - net::NetworkChangeNotifier* source_network_change_notifier); + NetworkChangeNotifierThread* source_thread); virtual ~NetworkChangeNotifierProxy(); diff --git a/chrome/browser/sync/net/network_change_notifier_proxy_unittest.cc b/chrome/browser/sync/net/network_change_notifier_proxy_unittest.cc index 5e095fd7..d92e078 100644 --- a/chrome/browser/sync/net/network_change_notifier_proxy_unittest.cc +++ b/chrome/browser/sync/net/network_change_notifier_proxy_unittest.cc @@ -6,83 +6,44 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "base/message_loop.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" -#include "base/task.h" -#include "base/thread.h" +#include "chrome/browser/sync/net/fake_network_change_notifier_thread.h" #include "chrome/browser/sync/net/mock_network_change_observer.h" -#include "chrome/browser/sync/net/thread_blocker.h" -#include "net/base/mock_network_change_notifier.h" #include "net/base/network_change_notifier.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -// We manage the lifetime of net::MockNetworkChangeNotifier ourselves. -template <> -struct RunnableMethodTraits<net::MockNetworkChangeNotifier> { - void RetainCallee(net::MockNetworkChangeNotifier*) {} - void ReleaseCallee(net::MockNetworkChangeNotifier*) {} -}; - namespace browser_sync { namespace { class NetworkChangeNotifierProxyTest : public testing::Test { protected: - NetworkChangeNotifierProxyTest() - : source_thread_("Source Thread"), - source_message_loop_(NULL) {} + NetworkChangeNotifierProxyTest() {} - virtual ~NetworkChangeNotifierProxyTest() { - CHECK(!source_thread_blocker_.get()); - CHECK(!source_message_loop_); - } + virtual ~NetworkChangeNotifierProxyTest() {} virtual void SetUp() { - CHECK(source_thread_.Start()); - source_message_loop_ = source_thread_.message_loop(); - source_thread_blocker_.reset(new ThreadBlocker(&source_thread_)); - source_thread_blocker_->Block(); - - notifier_proxy_.reset(new NetworkChangeNotifierProxy( - source_message_loop_, &source_network_change_notifier_)); + source_thread_.Start(); + notifier_proxy_.reset(new NetworkChangeNotifierProxy(&source_thread_)); } virtual void TearDown() { // Posts a task to the source thread. notifier_proxy_.reset(); - source_thread_blocker_->Unblock(); - source_thread_blocker_.reset(); - source_message_loop_ = NULL; source_thread_.Stop(); } // Trigger an "IP address changed" event on the source network // change notifier on the source thread and propagate any generated // notifications to the target thread. - void OnIPAddressChanged() { - source_message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod( - &source_network_change_notifier_, - &net::MockNetworkChangeNotifier::NotifyIPAddressChange)); - // Pump source thread. - source_thread_blocker_->Unblock(); - source_thread_blocker_->Block(); - // Pump target thread. + void NotifyIPAddressChange() { + source_thread_.NotifyIPAddressChange(); + source_thread_.Pump(); target_message_loop_.RunAllPending(); } - // This lives on |source_thread_| but is created/destroyed in the - // main thread. As long as we make sure to not modify it from the - // main thread while |source_thread_| is running, we shouldn't need - // any special synchronization. - net::MockNetworkChangeNotifier source_network_change_notifier_; - base::Thread source_thread_; - MessageLoop* source_message_loop_; - scoped_ptr<ThreadBlocker> source_thread_blocker_; + FakeNetworkChangeNotifierThread source_thread_; MessageLoop target_message_loop_; MockNetworkChangeObserver target_observer_; @@ -97,7 +58,7 @@ TEST_F(NetworkChangeNotifierProxyTest, Basic) { EXPECT_CALL(target_observer_, OnIPAddressChanged()).Times(1); notifier_proxy_->AddObserver(&target_observer_); - OnIPAddressChanged(); + NotifyIPAddressChange(); notifier_proxy_->RemoveObserver(&target_observer_); } @@ -106,13 +67,13 @@ TEST_F(NetworkChangeNotifierProxyTest, IgnoresEventAfterRemoveObserver) { notifier_proxy_->AddObserver(&target_observer_); notifier_proxy_->RemoveObserver(&target_observer_); - OnIPAddressChanged(); + NotifyIPAddressChange(); } TEST_F(NetworkChangeNotifierProxyTest, IgnoresEventBeforeRemoveObserver) { EXPECT_CALL(target_observer_, OnIPAddressChanged()).Times(0); - OnIPAddressChanged(); + NotifyIPAddressChange(); notifier_proxy_->AddObserver(&target_observer_); notifier_proxy_->RemoveObserver(&target_observer_); } @@ -129,7 +90,7 @@ TEST_F(NetworkChangeNotifierProxyTest, Multiple) { for (int i = 0; i < kNumObservers; ++i) { notifier_proxy_->AddObserver(&extra_observers[i]); } - OnIPAddressChanged(); + NotifyIPAddressChange(); for (int i = 0; i < kNumObservers; ++i) { notifier_proxy_->RemoveObserver(&extra_observers[i]); } diff --git a/chrome/browser/sync/net/network_change_notifier_thread.h b/chrome/browser/sync/net/network_change_notifier_thread.h new file mode 100644 index 0000000..e7fe375 --- /dev/null +++ b/chrome/browser/sync/net/network_change_notifier_thread.h @@ -0,0 +1,37 @@ +// Copyright (c) 2010 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 CHROME_BROWSER_SYNC_NET_NETWORK_CHANGE_NOTIFIER_THREAD_H_ +#define CHROME_BROWSER_SYNC_NET_NETWORK_CHANGE_NOTIFIER_THREAD_H_ + +// A simple interface that represents a thread which owns a +// NetworkChangeNotifier. + +class MessageLoop; + +namespace net { +class NetworkChangeNotifier; +} // namespace net + +namespace browser_sync { + +// An instance of this interface must live no longer than the thread +// it represents and its message loop and network change notifier. +class NetworkChangeNotifierThread { + public: + virtual ~NetworkChangeNotifierThread() {} + + // Returns the message loop for the thread that owns the + // NetworkChangeNotifier. Can be called on any thread. + virtual MessageLoop* GetMessageLoop() const = 0; + + // Returns the NetworkChangeNotifier of the thread. This method + // must be called only from the owning thread (i.e., by posting a + // task onto the message loop returned by GetMessageLoop()). + virtual net::NetworkChangeNotifier* GetNetworkChangeNotifier() const = 0; +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_NET_NETWORK_CHANGE_NOTIFIER_THREAD_H_ diff --git a/chrome/browser/sync/net/network_change_observer_proxy.cc b/chrome/browser/sync/net/network_change_observer_proxy.cc index b40a530..490ba5423 100644 --- a/chrome/browser/sync/net/network_change_observer_proxy.cc +++ b/chrome/browser/sync/net/network_change_observer_proxy.cc @@ -44,21 +44,22 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/task.h" +#include "chrome/browser/sync/net/network_change_notifier_thread.h" +#include "net/base/network_change_notifier.h" namespace browser_sync { NetworkChangeObserverProxy::NetworkChangeObserverProxy( - MessageLoop* source_message_loop, - net::NetworkChangeNotifier* source_network_change_notifier, + const NetworkChangeNotifierThread* source_thread, MessageLoop* target_message_loop) - : source_message_loop_(source_message_loop), - source_network_change_notifier_(source_network_change_notifier), + : source_thread_(source_thread), target_message_loop_(target_message_loop), target_observer_(NULL) { - DCHECK(source_message_loop_); - DCHECK(source_network_change_notifier_); + DCHECK(source_thread_); + MessageLoop* source_message_loop = source_thread_->GetMessageLoop(); + DCHECK(source_message_loop); DCHECK(target_message_loop_); - DCHECK_NE(source_message_loop_, target_message_loop_); + DCHECK_NE(source_message_loop, target_message_loop_); DCHECK_EQ(MessageLoop::current(), target_message_loop_); } @@ -66,7 +67,7 @@ NetworkChangeObserverProxy::~NetworkChangeObserverProxy() { MessageLoop* current_message_loop = MessageLoop::current(); // We can be deleted on either the source or target thread, so the // best we can do is check that we're on either. - DCHECK((current_message_loop == source_message_loop_) || + DCHECK((current_message_loop == source_thread_->GetMessageLoop()) || (current_message_loop == target_message_loop_)); // Even though only the target thread uses target_observer_, it // should still be unset even if we're on the source thread; posting @@ -75,15 +76,21 @@ NetworkChangeObserverProxy::~NetworkChangeObserverProxy() { } void NetworkChangeObserverProxy::Observe() { - DCHECK_EQ(MessageLoop::current(), source_message_loop_); - source_network_change_notifier_->AddObserver(this); + DCHECK_EQ(MessageLoop::current(), source_thread_->GetMessageLoop()); + net::NetworkChangeNotifier* source_network_change_notifier = + source_thread_->GetNetworkChangeNotifier(); + DCHECK(source_network_change_notifier); + source_network_change_notifier->AddObserver(this); } // The Task from which this was called may hold the last reference to // us (this is how we can get deleted on the source thread). void NetworkChangeObserverProxy::Unobserve() { - DCHECK_EQ(MessageLoop::current(), source_message_loop_); - source_network_change_notifier_->RemoveObserver(this); + DCHECK_EQ(MessageLoop::current(), source_thread_->GetMessageLoop()); + net::NetworkChangeNotifier* source_network_change_notifier = + source_thread_->GetNetworkChangeNotifier(); + DCHECK(source_network_change_notifier); + source_network_change_notifier->RemoveObserver(this); } void NetworkChangeObserverProxy::Attach( @@ -92,7 +99,7 @@ void NetworkChangeObserverProxy::Attach( DCHECK(!target_observer_); target_observer_ = target_observer; DCHECK(target_observer_); - source_message_loop_->PostTask( + source_thread_->GetMessageLoop()->PostTask( FROM_HERE, NewRunnableMethod(this, &NetworkChangeObserverProxy::Observe)); } @@ -101,7 +108,7 @@ void NetworkChangeObserverProxy::Detach() { DCHECK_EQ(MessageLoop::current(), target_message_loop_); DCHECK(target_observer_); target_observer_ = NULL; - source_message_loop_->PostTask( + source_thread_->GetMessageLoop()->PostTask( FROM_HERE, NewRunnableMethod(this, &NetworkChangeObserverProxy::Unobserve)); } @@ -111,7 +118,7 @@ void NetworkChangeObserverProxy::Detach() { // But we know that it has been posted, so it at least holds a // reference to us. void NetworkChangeObserverProxy::OnIPAddressChanged() { - DCHECK_EQ(MessageLoop::current(), source_message_loop_); + DCHECK_EQ(MessageLoop::current(), source_thread_->GetMessageLoop()); target_message_loop_->PostTask( FROM_HERE, NewRunnableMethod( diff --git a/chrome/browser/sync/net/network_change_observer_proxy.h b/chrome/browser/sync/net/network_change_observer_proxy.h index 184f5cb..34374e5 100644 --- a/chrome/browser/sync/net/network_change_observer_proxy.h +++ b/chrome/browser/sync/net/network_change_observer_proxy.h @@ -14,12 +14,12 @@ // // In the target thread, create the observer proxy: // +// NetworkChangeNotifierThread* source_thread = ...; // NetworkChangeObserverProxy* proxy = -// new NetworkChangeObserverProxy(source_thread->message_loop(), -// source_network_change_notifier, +// new NetworkChangeObserverProxy(source_thread, // MessageLoop::current()); // -// Both source_thread and source_network_change_notifier must be +// Both source_thread and its owned NetworkChangeNotifier must be // guaranteed to outlive the target (current) thread. // // Then, attach the target observer: @@ -45,6 +45,8 @@ namespace browser_sync { +class NetworkChangeNotifierThread; + // TODO(akalin): Remove use of private inheritance. class NetworkChangeObserverProxy : public base::RefCountedThreadSafe<NetworkChangeObserverProxy>, @@ -55,8 +57,7 @@ class NetworkChangeObserverProxy // Does not take ownership of any arguments. NetworkChangeObserverProxy( - MessageLoop* source_message_loop, - net::NetworkChangeNotifier* source_network_change_notifier, + const NetworkChangeNotifierThread* source_thread, MessageLoop* target_message_loop); // After this method is called, |target_observer| will start @@ -100,8 +101,7 @@ class NetworkChangeObserverProxy // |target_observer_|. void TargetObserverOnIPAddressChanged(); - MessageLoop* const source_message_loop_; - net::NetworkChangeNotifier* const source_network_change_notifier_; + const NetworkChangeNotifierThread* source_thread_; MessageLoop* const target_message_loop_; // |target_observer_| is used only by the target thread. net::NetworkChangeNotifier::Observer* target_observer_; diff --git a/chrome/browser/sync/net/network_change_observer_proxy_unittest.cc b/chrome/browser/sync/net/network_change_observer_proxy_unittest.cc index ba78e89..c39184b 100644 --- a/chrome/browser/sync/net/network_change_observer_proxy_unittest.cc +++ b/chrome/browser/sync/net/network_change_observer_proxy_unittest.cc @@ -6,25 +6,11 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "base/message_loop.h" #include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "base/task.h" -#include "base/thread.h" +#include "chrome/browser/sync/net/fake_network_change_notifier_thread.h" #include "chrome/browser/sync/net/mock_network_change_observer.h" -#include "chrome/browser/sync/net/thread_blocker.h" -#include "net/base/mock_network_change_notifier.h" -#include "net/base/network_change_notifier.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -// We manage the lifetime of net::MockNetworkChangeNotifier ourselves. -template <> -struct RunnableMethodTraits<net::MockNetworkChangeNotifier> { - void RetainCallee(net::MockNetworkChangeNotifier*) {} - void ReleaseCallee(net::MockNetworkChangeNotifier*) {} -}; - namespace browser_sync { namespace { @@ -37,13 +23,10 @@ class DeleteCheckingNetworkChangeObserverProxy // *deleting_message_loop_ must be NULL. It is set to a non-NULL // *value when this object is deleted. DeleteCheckingNetworkChangeObserverProxy( - MessageLoop* source_message_loop, - net::NetworkChangeNotifier* source_network_change_notifier, + NetworkChangeNotifierThread* source_thread, MessageLoop* target_message_loop, MessageLoop** deleting_message_loop) - : NetworkChangeObserverProxy(source_message_loop, - source_network_change_notifier, - target_message_loop), + : NetworkChangeObserverProxy(source_thread, target_message_loop), deleting_message_loop_(deleting_message_loop) { CHECK(deleting_message_loop_); EXPECT_TRUE(*deleting_message_loop_ == NULL); @@ -61,26 +44,16 @@ class DeleteCheckingNetworkChangeObserverProxy class NetworkChangeObserverProxyTest : public testing::Test { protected: - NetworkChangeObserverProxyTest() - : source_thread_("Source Thread"), - source_message_loop_(NULL), - proxy_deleting_message_loop_(NULL) {} - - virtual ~NetworkChangeObserverProxyTest() { - CHECK(!source_thread_blocker_.get()); - CHECK(!source_message_loop_); - } + NetworkChangeObserverProxyTest() : proxy_deleting_message_loop_(NULL) {} - virtual void SetUp() { - CHECK(source_thread_.Start()); - source_message_loop_ = source_thread_.message_loop(); - source_thread_blocker_.reset(new ThreadBlocker(&source_thread_)); - source_thread_blocker_->Block(); + virtual ~NetworkChangeObserverProxyTest() {} + virtual void SetUp() { + source_thread_.Start(); proxy_deleting_message_loop_ = NULL; proxy_ = new DeleteCheckingNetworkChangeObserverProxy( - source_message_loop_, &source_network_change_notifier_, - &target_message_loop_, &proxy_deleting_message_loop_); + &source_thread_, &target_message_loop_, + &proxy_deleting_message_loop_); } // On TearDown, |proxy_| must be released and both source and target @@ -88,16 +61,12 @@ class NetworkChangeObserverProxyTest : public testing::Test { virtual void TearDown() { EXPECT_TRUE(proxy_ == NULL); EXPECT_TRUE(proxy_deleting_message_loop_ != NULL); - source_thread_blocker_->Unblock(); - source_thread_blocker_.reset(); - source_message_loop_ = NULL; source_thread_.Stop(); } // Pump any events posted on the source thread. void PumpSource() { - source_thread_blocker_->Unblock(); - source_thread_blocker_->Block(); + source_thread_.Pump(); } // Pump any events posted on the target thread (which is just the @@ -108,22 +77,11 @@ class NetworkChangeObserverProxyTest : public testing::Test { // Trigger an "IP address changed" event on the source network // change notifier on the source thread. - void OnIPAddressChanged() { - source_message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod( - &source_network_change_notifier_, - &net::MockNetworkChangeNotifier::NotifyIPAddressChange)); + void NotifyIPAddressChange() { + source_thread_.NotifyIPAddressChange(); } - // This lives on |source_thread_| but is created/destroyed in the - // main thread. As long as we make sure to not modify it from the - // main thread while |source_thread_| is running, we shouldn't need - // any special synchronization. - net::MockNetworkChangeNotifier source_network_change_notifier_; - base::Thread source_thread_; - MessageLoop* source_message_loop_; - scoped_ptr<ThreadBlocker> source_thread_blocker_; + FakeNetworkChangeNotifierThread source_thread_; MessageLoop target_message_loop_; MockNetworkChangeObserver target_observer_; @@ -153,7 +111,7 @@ TEST_F(NetworkChangeObserverProxyTest, AttachDetach) { proxy_ = NULL; PumpSource(); - EXPECT_EQ(proxy_deleting_message_loop_, source_message_loop_); + EXPECT_EQ(proxy_deleting_message_loop_, source_thread_.GetMessageLoop()); } TEST_F(NetworkChangeObserverProxyTest, AttachDetachReleaseAfterPump) { @@ -171,14 +129,14 @@ TEST_F(NetworkChangeObserverProxyTest, Basic) { EXPECT_CALL(target_observer_, OnIPAddressChanged()).Times(1); proxy_->Attach(&target_observer_); - OnIPAddressChanged(); + NotifyIPAddressChange(); PumpSource(); PumpTarget(); proxy_->Detach(); proxy_ = NULL; PumpSource(); - EXPECT_EQ(proxy_deleting_message_loop_, source_message_loop_); + EXPECT_EQ(proxy_deleting_message_loop_, source_thread_.GetMessageLoop()); } TEST_F(NetworkChangeObserverProxyTest, Multiple) { @@ -187,7 +145,7 @@ TEST_F(NetworkChangeObserverProxyTest, Multiple) { proxy_->Attach(&target_observer_); for (int i = 0; i < kTimes; ++i) { - OnIPAddressChanged(); + NotifyIPAddressChange(); } PumpSource(); PumpTarget(); @@ -195,7 +153,7 @@ TEST_F(NetworkChangeObserverProxyTest, Multiple) { proxy_ = NULL; PumpSource(); - EXPECT_EQ(proxy_deleting_message_loop_, source_message_loop_); + EXPECT_EQ(proxy_deleting_message_loop_, source_thread_.GetMessageLoop()); } TEST_F(NetworkChangeObserverProxyTest, MultipleAttachDetach) { @@ -204,7 +162,7 @@ TEST_F(NetworkChangeObserverProxyTest, MultipleAttachDetach) { for (int i = 0; i < kTimes; ++i) { proxy_->Attach(&target_observer_); - OnIPAddressChanged(); + NotifyIPAddressChange(); PumpSource(); PumpTarget(); proxy_->Detach(); @@ -212,14 +170,14 @@ TEST_F(NetworkChangeObserverProxyTest, MultipleAttachDetach) { proxy_ = NULL; PumpSource(); - EXPECT_EQ(proxy_deleting_message_loop_, source_message_loop_); + EXPECT_EQ(proxy_deleting_message_loop_, source_thread_.GetMessageLoop()); } TEST_F(NetworkChangeObserverProxyTest, IgnoresEventPostedAfterDetach) { EXPECT_CALL(target_observer_, OnIPAddressChanged()).Times(0); proxy_->Attach(&target_observer_); - OnIPAddressChanged(); + NotifyIPAddressChange(); proxy_->Detach(); proxy_ = NULL; PumpSource(); @@ -232,14 +190,14 @@ TEST_F(NetworkChangeObserverProxyTest, IgnoresEventPostedBeforeDetach) { EXPECT_CALL(target_observer_, OnIPAddressChanged()).Times(0); proxy_->Attach(&target_observer_); - OnIPAddressChanged(); + NotifyIPAddressChange(); PumpSource(); proxy_->Detach(); proxy_ = NULL; PumpTarget(); PumpSource(); - EXPECT_EQ(proxy_deleting_message_loop_, source_message_loop_); + EXPECT_EQ(proxy_deleting_message_loop_, source_thread_.GetMessageLoop()); } TEST_F(NetworkChangeObserverProxyTest, IgnoresEventAfterDetach) { @@ -248,23 +206,23 @@ TEST_F(NetworkChangeObserverProxyTest, IgnoresEventAfterDetach) { proxy_->Attach(&target_observer_); proxy_->Detach(); proxy_ = NULL; - OnIPAddressChanged(); + NotifyIPAddressChange(); PumpSource(); - EXPECT_EQ(proxy_deleting_message_loop_, source_message_loop_); + EXPECT_EQ(proxy_deleting_message_loop_, source_thread_.GetMessageLoop()); } TEST_F(NetworkChangeObserverProxyTest, IgnoresEventBeforeAttach) { EXPECT_CALL(target_observer_, OnIPAddressChanged()).Times(0); - OnIPAddressChanged(); + NotifyIPAddressChange(); PumpSource(); proxy_->Attach(&target_observer_); proxy_->Detach(); proxy_ = NULL; PumpSource(); - EXPECT_EQ(proxy_deleting_message_loop_, source_message_loop_); + EXPECT_EQ(proxy_deleting_message_loop_, source_thread_.GetMessageLoop()); } } // namespace diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 48ef083..265a336 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -981,6 +981,7 @@ 'sources': [ 'browser/sync/net/network_change_notifier_proxy.cc', 'browser/sync/net/network_change_notifier_proxy.h', + 'browser/sync/net/network_change_notifier_thread.h', 'browser/sync/net/network_change_observer_proxy.cc', 'browser/sync/net/network_change_observer_proxy.h', ], diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 1f601b3..1450cce 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1841,6 +1841,9 @@ # TODO(akalin): Write our own test suite and runner. '../base/test/run_all_unittests.cc', '../base/test/test_suite.h', + 'browser/sync/net/fake_network_change_notifier_thread_unittest.cc', + 'browser/sync/net/fake_network_change_notifier_thread.cc', + 'browser/sync/net/fake_network_change_notifier_thread.h', 'browser/sync/net/mock_network_change_observer.h', 'browser/sync/net/network_change_notifier_proxy_unittest.cc', 'browser/sync/net/network_change_observer_proxy_unittest.cc', |