1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sync/internal_api/public/util/weak_handle.h"
8 #include "base/compiler_specific.h"
9 #include "base/location.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/threading/thread.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
19 using ::testing::SaveArg
;
20 using ::testing::StrictMock
;
24 Base() : weak_ptr_factory_(this) {}
26 WeakHandle
<Base
> AsWeakHandle() {
27 return MakeWeakHandle(weak_ptr_factory_
.GetWeakPtr());
31 weak_ptr_factory_
.InvalidateWeakPtrs();
34 MOCK_METHOD0(Test
, void());
35 MOCK_METHOD1(Test1
, void(const int&));
36 MOCK_METHOD2(Test2
, void(const int&, Base
*));
37 MOCK_METHOD3(Test3
, void(const int&, Base
*, float));
38 MOCK_METHOD4(Test4
, void(const int&, Base
*, float, const char*));
40 MOCK_METHOD1(TestWithSelf
, void(const WeakHandle
<Base
>&));
43 base::WeakPtrFactory
<Base
> weak_ptr_factory_
;
46 class Derived
: public Base
, public base::SupportsWeakPtr
<Derived
> {};
48 class WeakHandleTest
: public ::testing::Test
{
50 void TearDown() override
{
51 // Process any last-minute posted tasks.
56 base::RunLoop().RunUntilIdle();
59 static void CallTestFromOtherThread(tracked_objects::Location from_here
,
60 const WeakHandle
<Base
>& h
) {
61 base::Thread
t("Test thread");
62 ASSERT_TRUE(t
.Start());
63 t
.message_loop()->PostTask(
64 from_here
, base::Bind(&WeakHandleTest::CallTest
, from_here
, h
));
68 static void CallTest(tracked_objects::Location from_here
,
69 const WeakHandle
<Base
>& h
) {
70 h
.Call(from_here
, &Base::Test
);
73 base::MessageLoop message_loop_
;
76 TEST_F(WeakHandleTest
, Uninitialized
) {
79 EXPECT_FALSE(h
.IsInitialized());
82 WeakHandle
<int> h2(h
);
83 EXPECT_FALSE(h2
.IsInitialized());
89 EXPECT_FALSE(h
.IsInitialized());
93 TEST_F(WeakHandleTest
, InitializedAfterDestroy
) {
99 EXPECT_TRUE(h
.IsInitialized());
100 EXPECT_FALSE(h
.Get());
103 TEST_F(WeakHandleTest
, InitializedAfterInvalidate
) {
105 WeakHandle
<Base
> h
= b
.AsWeakHandle();
107 EXPECT_TRUE(h
.IsInitialized());
108 EXPECT_FALSE(h
.Get());
111 TEST_F(WeakHandleTest
, Call
) {
113 const char test_str
[] = "test";
114 EXPECT_CALL(b
, Test());
115 EXPECT_CALL(b
, Test1(5));
116 EXPECT_CALL(b
, Test2(5, &b
));
117 EXPECT_CALL(b
, Test3(5, &b
, 5));
118 EXPECT_CALL(b
, Test4(5, &b
, 5, test_str
));
120 WeakHandle
<Base
> h
= b
.AsWeakHandle();
121 EXPECT_TRUE(h
.IsInitialized());
124 h
.Call(FROM_HERE
, &Base::Test
);
125 h
.Call(FROM_HERE
, &Base::Test1
, 5);
126 h
.Call(FROM_HERE
, &Base::Test2
, 5, &b
);
127 h
.Call(FROM_HERE
, &Base::Test3
, 5, &b
, 5);
128 h
.Call(FROM_HERE
, &Base::Test4
, 5, &b
, 5, test_str
);
132 TEST_F(WeakHandleTest
, CallAfterDestroy
) {
135 EXPECT_CALL(b
, Test()).Times(0);
137 WeakHandle
<Base
> h
= b
.AsWeakHandle();
138 EXPECT_TRUE(h
.IsInitialized());
141 h
.Call(FROM_HERE
, &Base::Test
);
146 TEST_F(WeakHandleTest
, CallAfterInvalidate
) {
148 EXPECT_CALL(b
, Test()).Times(0);
150 WeakHandle
<Base
> h
= b
.AsWeakHandle();
151 EXPECT_TRUE(h
.IsInitialized());
154 h
.Call(FROM_HERE
, &Base::Test
);
160 TEST_F(WeakHandleTest
, CallThreaded
) {
162 EXPECT_CALL(b
, Test());
164 WeakHandle
<Base
> h
= b
.AsWeakHandle();
166 CallTestFromOtherThread(FROM_HERE
, h
);
170 TEST_F(WeakHandleTest
, CallAfterDestroyThreaded
) {
174 EXPECT_CALL(b
, Test()).Times(0);
175 h
= b
.AsWeakHandle();
179 CallTestFromOtherThread(FROM_HERE
, h
);
183 TEST_F(WeakHandleTest
, CallAfterInvalidateThreaded
) {
185 EXPECT_CALL(b
, Test()).Times(0);
187 WeakHandle
<Base
> h
= b
.AsWeakHandle();
190 CallTestFromOtherThread(FROM_HERE
, h
);
194 TEST_F(WeakHandleTest
, DeleteOnOtherThread
) {
196 EXPECT_CALL(b
, Test()).Times(0);
198 WeakHandle
<Base
>* h
= new WeakHandle
<Base
>(b
.AsWeakHandle());
201 base::Thread
t("Test thread");
202 ASSERT_TRUE(t
.Start());
203 t
.message_loop()->DeleteSoon(FROM_HERE
, h
);
209 void CallTestWithSelf(const WeakHandle
<Base
>& b1
) {
211 b1
.Call(FROM_HERE
, &Base::TestWithSelf
, b2
.AsWeakHandle());
214 TEST_F(WeakHandleTest
, WithDestroyedThread
) {
217 EXPECT_CALL(b1
, TestWithSelf(_
)).WillOnce(SaveArg
<0>(&b2
));
220 base::Thread
t("Test thread");
221 ASSERT_TRUE(t
.Start());
222 t
.message_loop()->PostTask(FROM_HERE
,
223 base::Bind(&CallTestWithSelf
,
227 // Calls b1.TestWithSelf().
230 // Shouldn't do anything, since the thread is gone.
231 b2
.Call(FROM_HERE
, &Base::Test
);
233 // |b2| shouldn't leak when it's destroyed, even if the original
237 TEST_F(WeakHandleTest
, InitializedAcrossCopyAssign
) {
239 EXPECT_CALL(b
, Test()).Times(3);
241 EXPECT_TRUE(b
.AsWeakHandle().IsInitialized());
242 b
.AsWeakHandle().Call(FROM_HERE
, &Base::Test
);
245 WeakHandle
<Base
> h(b
.AsWeakHandle());
246 EXPECT_TRUE(h
.IsInitialized());
247 h
.Call(FROM_HERE
, &Base::Test
);
249 EXPECT_FALSE(h
.IsInitialized());
254 h
= b
.AsWeakHandle();
255 EXPECT_TRUE(h
.IsInitialized());
256 h
.Call(FROM_HERE
, &Base::Test
);
258 EXPECT_FALSE(h
.IsInitialized());
264 TEST_F(WeakHandleTest
, TypeConversionConstructor
) {
265 StrictMock
<Derived
> d
;
266 EXPECT_CALL(d
, Test()).Times(2);
268 const WeakHandle
<Derived
> weak_handle
= MakeWeakHandle(d
.AsWeakPtr());
270 // Should trigger type conversion constructor.
271 const WeakHandle
<Base
> base_weak_handle(weak_handle
);
272 // Should trigger regular copy constructor.
273 const WeakHandle
<Derived
> derived_weak_handle(weak_handle
);
275 EXPECT_TRUE(base_weak_handle
.IsInitialized());
276 base_weak_handle
.Call(FROM_HERE
, &Base::Test
);
278 EXPECT_TRUE(derived_weak_handle
.IsInitialized());
279 // Copy constructor shouldn't construct a new |core_|.
280 EXPECT_EQ(weak_handle
.core_
.get(), derived_weak_handle
.core_
.get());
281 derived_weak_handle
.Call(FROM_HERE
, &Base::Test
);
286 TEST_F(WeakHandleTest
, TypeConversionConstructorMakeWeakHandle
) {
287 const base::WeakPtr
<Derived
> weak_ptr
;
289 // Should trigger type conversion constructor after MakeWeakHandle.
290 WeakHandle
<Base
> base_weak_handle(MakeWeakHandle(weak_ptr
));
291 // Should trigger regular copy constructor after MakeWeakHandle.
292 const WeakHandle
<Derived
> derived_weak_handle(MakeWeakHandle(weak_ptr
));
294 EXPECT_TRUE(base_weak_handle
.IsInitialized());
295 EXPECT_TRUE(derived_weak_handle
.IsInitialized());
298 TEST_F(WeakHandleTest
, TypeConversionConstructorAssignment
) {
299 const WeakHandle
<Derived
> weak_handle
=
300 MakeWeakHandle(Derived().AsWeakPtr());
302 // Should trigger type conversion constructor before the assignment.
303 WeakHandle
<Base
> base_weak_handle
;
304 base_weak_handle
= weak_handle
;
305 // Should trigger regular copy constructor before the assignment.
306 WeakHandle
<Derived
> derived_weak_handle
;
307 derived_weak_handle
= weak_handle
;
309 EXPECT_TRUE(base_weak_handle
.IsInitialized());
310 EXPECT_TRUE(derived_weak_handle
.IsInitialized());
311 // Copy constructor shouldn't construct a new |core_|.
312 EXPECT_EQ(weak_handle
.core_
.get(), derived_weak_handle
.core_
.get());
315 TEST_F(WeakHandleTest
, TypeConversionConstructorUninitialized
) {
316 const WeakHandle
<Base
> base_weak_handle
= WeakHandle
<Derived
>();
317 EXPECT_FALSE(base_weak_handle
.IsInitialized());
320 TEST_F(WeakHandleTest
, TypeConversionConstructorUninitializedAssignment
) {
321 WeakHandle
<Base
> base_weak_handle
;
322 base_weak_handle
= WeakHandle
<Derived
>();
323 EXPECT_FALSE(base_weak_handle
.IsInitialized());
326 } // namespace syncer