summaryrefslogtreecommitdiffstats
path: root/sync/internal_api/public/util/weak_handle_unittest.cc
diff options
context:
space:
mode:
authortim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-17 01:07:19 +0000
committertim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-17 01:07:19 +0000
commit406203d804cfd1c0ff1b74bced465700df5a531b (patch)
treedbb0c78215287dd9215eb69411493bff8ae4d3f4 /sync/internal_api/public/util/weak_handle_unittest.cc
parenta263538270e30269c67e914fa67542e5d6da2be2 (diff)
downloadchromium_src-406203d804cfd1c0ff1b74bced465700df5a531b.zip
chromium_src-406203d804cfd1c0ff1b74bced465700df5a531b.tar.gz
chromium_src-406203d804cfd1c0ff1b74bced465700df5a531b.tar.bz2
sync: move internal_api components used by chrome/browser into internal_api/public
TBR=jhawkins@chromium.org BUG=131130 TEST= Review URL: https://chromiumcodereview.appspot.com/10534080 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@142626 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/internal_api/public/util/weak_handle_unittest.cc')
-rw-r--r--sync/internal_api/public/util/weak_handle_unittest.cc326
1 files changed, 326 insertions, 0 deletions
diff --git a/sync/internal_api/public/util/weak_handle_unittest.cc b/sync/internal_api/public/util/weak_handle_unittest.cc
new file mode 100644
index 0000000..af919ad
--- /dev/null
+++ b/sync/internal_api/public/util/weak_handle_unittest.cc
@@ -0,0 +1,326 @@
+// 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/internal_api/public/util/weak_handle.h"
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/location.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
+#include "base/threading/thread.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+
+using ::testing::_;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
+
+class Base {
+ public:
+ Base() : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
+
+ WeakHandle<Base> AsWeakHandle() {
+ return MakeWeakHandle(weak_ptr_factory_.GetWeakPtr());
+ }
+
+ void Kill() {
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ }
+
+ MOCK_METHOD0(Test, void());
+ MOCK_METHOD1(Test1, void(const int&));
+ MOCK_METHOD2(Test2, void(const int&, Base*));
+ MOCK_METHOD3(Test3, void(const int&, Base*, float));
+ MOCK_METHOD4(Test4, void(const int&, Base*, float, const char*));
+
+ MOCK_METHOD1(TestWithSelf, void(const WeakHandle<Base>&));
+
+ private:
+ base::WeakPtrFactory<Base> weak_ptr_factory_;
+};
+
+class Derived : public Base, public base::SupportsWeakPtr<Derived> {};
+
+class WeakHandleTest : public ::testing::Test {
+ protected:
+ virtual void TearDown() {
+ // Process any last-minute posted tasks.
+ PumpLoop();
+ }
+
+ void PumpLoop() {
+ message_loop_.RunAllPending();
+ }
+
+ static void CallTestFromOtherThread(tracked_objects::Location from_here,
+ const WeakHandle<Base>& h) {
+ base::Thread t("Test thread");
+ ASSERT_TRUE(t.Start());
+ t.message_loop()->PostTask(
+ from_here, base::Bind(&WeakHandleTest::CallTest, from_here, h));
+ }
+
+ private:
+ static void CallTest(tracked_objects::Location from_here,
+ const WeakHandle<Base>& h) {
+ h.Call(from_here, &Base::Test);
+ }
+
+ MessageLoop message_loop_;
+};
+
+TEST_F(WeakHandleTest, Uninitialized) {
+ // Default.
+ WeakHandle<int> h;
+ EXPECT_FALSE(h.IsInitialized());
+ // Copy.
+ {
+ WeakHandle<int> h2(h);
+ EXPECT_FALSE(h2.IsInitialized());
+ }
+ // Assign.
+ {
+ WeakHandle<int> h2;
+ h2 = h;
+ EXPECT_FALSE(h.IsInitialized());
+ }
+}
+
+TEST_F(WeakHandleTest, InitializedAfterDestroy) {
+ WeakHandle<Base> h;
+ {
+ StrictMock<Base> b;
+ h = b.AsWeakHandle();
+ }
+ EXPECT_TRUE(h.IsInitialized());
+ EXPECT_FALSE(h.Get());
+}
+
+TEST_F(WeakHandleTest, InitializedAfterInvalidate) {
+ StrictMock<Base> b;
+ WeakHandle<Base> h = b.AsWeakHandle();
+ b.Kill();
+ EXPECT_TRUE(h.IsInitialized());
+ EXPECT_FALSE(h.Get());
+}
+
+TEST_F(WeakHandleTest, Call) {
+ StrictMock<Base> b;
+ const char test_str[] = "test";
+ EXPECT_CALL(b, Test());
+ EXPECT_CALL(b, Test1(5));
+ EXPECT_CALL(b, Test2(5, &b));
+ EXPECT_CALL(b, Test3(5, &b, 5));
+ EXPECT_CALL(b, Test4(5, &b, 5, test_str));
+
+ WeakHandle<Base> h = b.AsWeakHandle();
+ EXPECT_TRUE(h.IsInitialized());
+
+ // Should run.
+ h.Call(FROM_HERE, &Base::Test);
+ h.Call(FROM_HERE, &Base::Test1, 5);
+ h.Call(FROM_HERE, &Base::Test2, 5, &b);
+ h.Call(FROM_HERE, &Base::Test3, 5, &b, 5);
+ h.Call(FROM_HERE, &Base::Test4, 5, &b, 5, test_str);
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, CallAfterDestroy) {
+ {
+ StrictMock<Base> b;
+ EXPECT_CALL(b, Test()).Times(0);
+
+ WeakHandle<Base> h = b.AsWeakHandle();
+ EXPECT_TRUE(h.IsInitialized());
+
+ // Should not run.
+ h.Call(FROM_HERE, &Base::Test);
+ }
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, CallAfterInvalidate) {
+ StrictMock<Base> b;
+ EXPECT_CALL(b, Test()).Times(0);
+
+ WeakHandle<Base> h = b.AsWeakHandle();
+ EXPECT_TRUE(h.IsInitialized());
+
+ // Should not run.
+ h.Call(FROM_HERE, &Base::Test);
+
+ b.Kill();
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, CallThreaded) {
+ StrictMock<Base> b;
+ EXPECT_CALL(b, Test());
+
+ WeakHandle<Base> h = b.AsWeakHandle();
+ // Should run.
+ CallTestFromOtherThread(FROM_HERE, h);
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, CallAfterDestroyThreaded) {
+ WeakHandle<Base> h;
+ {
+ StrictMock<Base> b;
+ EXPECT_CALL(b, Test()).Times(0);
+ h = b.AsWeakHandle();
+ }
+
+ // Should not run.
+ CallTestFromOtherThread(FROM_HERE, h);
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, CallAfterInvalidateThreaded) {
+ StrictMock<Base> b;
+ EXPECT_CALL(b, Test()).Times(0);
+
+ WeakHandle<Base> h = b.AsWeakHandle();
+ b.Kill();
+ // Should not run.
+ CallTestFromOtherThread(FROM_HERE, h);
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, DeleteOnOtherThread) {
+ StrictMock<Base> b;
+ EXPECT_CALL(b, Test()).Times(0);
+
+ WeakHandle<Base>* h = new WeakHandle<Base>(b.AsWeakHandle());
+
+ {
+ base::Thread t("Test thread");
+ ASSERT_TRUE(t.Start());
+ t.message_loop()->DeleteSoon(FROM_HERE, h);
+ }
+
+ PumpLoop();
+}
+
+void CallTestWithSelf(const WeakHandle<Base>& b1) {
+ StrictMock<Base> b2;
+ b1.Call(FROM_HERE, &Base::TestWithSelf, b2.AsWeakHandle());
+}
+
+TEST_F(WeakHandleTest, WithDestroyedThread) {
+ StrictMock<Base> b1;
+ WeakHandle<Base> b2;
+ EXPECT_CALL(b1, TestWithSelf(_)).WillOnce(SaveArg<0>(&b2));
+
+ {
+ base::Thread t("Test thread");
+ ASSERT_TRUE(t.Start());
+ t.message_loop()->PostTask(FROM_HERE,
+ base::Bind(&CallTestWithSelf,
+ b1.AsWeakHandle()));
+ }
+
+ // Calls b1.TestWithSelf().
+ PumpLoop();
+
+ // Shouldn't do anything, since the thread is gone.
+ b2.Call(FROM_HERE, &Base::Test);
+
+ // |b2| shouldn't leak when it's destroyed, even if the original
+ // thread is gone.
+}
+
+TEST_F(WeakHandleTest, InitializedAcrossCopyAssign) {
+ StrictMock<Base> b;
+ EXPECT_CALL(b, Test()).Times(3);
+
+ EXPECT_TRUE(b.AsWeakHandle().IsInitialized());
+ b.AsWeakHandle().Call(FROM_HERE, &Base::Test);
+
+ {
+ WeakHandle<Base> h(b.AsWeakHandle());
+ EXPECT_TRUE(h.IsInitialized());
+ h.Call(FROM_HERE, &Base::Test);
+ h.Reset();
+ EXPECT_FALSE(h.IsInitialized());
+ }
+
+ {
+ WeakHandle<Base> h;
+ h = b.AsWeakHandle();
+ EXPECT_TRUE(h.IsInitialized());
+ h.Call(FROM_HERE, &Base::Test);
+ h.Reset();
+ EXPECT_FALSE(h.IsInitialized());
+ }
+
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, TypeConversionConstructor) {
+ StrictMock<Derived> d;
+ EXPECT_CALL(d, Test()).Times(2);
+
+ const WeakHandle<Derived> weak_handle = MakeWeakHandle(d.AsWeakPtr());
+
+ // Should trigger type conversion constructor.
+ const WeakHandle<Base> base_weak_handle(weak_handle);
+ // Should trigger regular copy constructor.
+ const WeakHandle<Derived> derived_weak_handle(weak_handle);
+
+ EXPECT_TRUE(base_weak_handle.IsInitialized());
+ base_weak_handle.Call(FROM_HERE, &Base::Test);
+
+ EXPECT_TRUE(derived_weak_handle.IsInitialized());
+ // Copy constructor shouldn't construct a new |core_|.
+ EXPECT_EQ(weak_handle.core_.get(), derived_weak_handle.core_.get());
+ derived_weak_handle.Call(FROM_HERE, &Base::Test);
+
+ PumpLoop();
+}
+
+TEST_F(WeakHandleTest, TypeConversionConstructorMakeWeakHandle) {
+ const base::WeakPtr<Derived> weak_ptr;
+
+ // Should trigger type conversion constructor after MakeWeakHandle.
+ WeakHandle<Base> base_weak_handle(MakeWeakHandle(weak_ptr));
+ // Should trigger regular copy constructor after MakeWeakHandle.
+ const WeakHandle<Derived> derived_weak_handle(MakeWeakHandle(weak_ptr));
+
+ EXPECT_TRUE(base_weak_handle.IsInitialized());
+ EXPECT_TRUE(derived_weak_handle.IsInitialized());
+}
+
+TEST_F(WeakHandleTest, TypeConversionConstructorAssignment) {
+ const WeakHandle<Derived> weak_handle =
+ MakeWeakHandle(Derived().AsWeakPtr());
+
+ // Should trigger type conversion constructor before the assignment.
+ WeakHandle<Base> base_weak_handle;
+ base_weak_handle = weak_handle;
+ // Should trigger regular copy constructor before the assignment.
+ WeakHandle<Derived> derived_weak_handle;
+ derived_weak_handle = weak_handle;
+
+ EXPECT_TRUE(base_weak_handle.IsInitialized());
+ EXPECT_TRUE(derived_weak_handle.IsInitialized());
+ // Copy constructor shouldn't construct a new |core_|.
+ EXPECT_EQ(weak_handle.core_.get(), derived_weak_handle.core_.get());
+}
+
+TEST_F(WeakHandleTest, TypeConversionConstructorUninitialized) {
+ const WeakHandle<Base> base_weak_handle = WeakHandle<Derived>();
+ EXPECT_FALSE(base_weak_handle.IsInitialized());
+}
+
+TEST_F(WeakHandleTest, TypeConversionConstructorUninitializedAssignment) {
+ WeakHandle<Base> base_weak_handle;
+ base_weak_handle = WeakHandle<Derived>();
+ EXPECT_FALSE(base_weak_handle.IsInitialized());
+}
+
+} // namespace browser_sync