Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / sync / internal_api / public / util / weak_handle_unittest.cc
blob44b579563867611dee0cad4cc959ad59e556cb4c
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"
7 #include "base/bind.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"
16 namespace syncer {
18 using ::testing::_;
19 using ::testing::SaveArg;
20 using ::testing::StrictMock;
22 class Base {
23 public:
24 Base() : weak_ptr_factory_(this) {}
26 WeakHandle<Base> AsWeakHandle() {
27 return MakeWeakHandle(weak_ptr_factory_.GetWeakPtr());
30 void Kill() {
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>&));
42 private:
43 base::WeakPtrFactory<Base> weak_ptr_factory_;
46 class Derived : public Base, public base::SupportsWeakPtr<Derived> {};
48 class WeakHandleTest : public ::testing::Test {
49 protected:
50 void TearDown() override {
51 // Process any last-minute posted tasks.
52 PumpLoop();
55 void PumpLoop() {
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));
67 private:
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) {
77 // Default.
78 WeakHandle<int> h;
79 EXPECT_FALSE(h.IsInitialized());
80 // Copy.
82 WeakHandle<int> h2(h);
83 EXPECT_FALSE(h2.IsInitialized());
85 // Assign.
87 WeakHandle<int> h2;
88 h2 = h;
89 EXPECT_FALSE(h.IsInitialized());
93 TEST_F(WeakHandleTest, InitializedAfterDestroy) {
94 WeakHandle<Base> h;
96 StrictMock<Base> b;
97 h = b.AsWeakHandle();
99 EXPECT_TRUE(h.IsInitialized());
100 EXPECT_FALSE(h.Get());
103 TEST_F(WeakHandleTest, InitializedAfterInvalidate) {
104 StrictMock<Base> b;
105 WeakHandle<Base> h = b.AsWeakHandle();
106 b.Kill();
107 EXPECT_TRUE(h.IsInitialized());
108 EXPECT_FALSE(h.Get());
111 TEST_F(WeakHandleTest, Call) {
112 StrictMock<Base> b;
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());
123 // Should run.
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);
129 PumpLoop();
132 TEST_F(WeakHandleTest, CallAfterDestroy) {
134 StrictMock<Base> b;
135 EXPECT_CALL(b, Test()).Times(0);
137 WeakHandle<Base> h = b.AsWeakHandle();
138 EXPECT_TRUE(h.IsInitialized());
140 // Should not run.
141 h.Call(FROM_HERE, &Base::Test);
143 PumpLoop();
146 TEST_F(WeakHandleTest, CallAfterInvalidate) {
147 StrictMock<Base> b;
148 EXPECT_CALL(b, Test()).Times(0);
150 WeakHandle<Base> h = b.AsWeakHandle();
151 EXPECT_TRUE(h.IsInitialized());
153 // Should not run.
154 h.Call(FROM_HERE, &Base::Test);
156 b.Kill();
157 PumpLoop();
160 TEST_F(WeakHandleTest, CallThreaded) {
161 StrictMock<Base> b;
162 EXPECT_CALL(b, Test());
164 WeakHandle<Base> h = b.AsWeakHandle();
165 // Should run.
166 CallTestFromOtherThread(FROM_HERE, h);
167 PumpLoop();
170 TEST_F(WeakHandleTest, CallAfterDestroyThreaded) {
171 WeakHandle<Base> h;
173 StrictMock<Base> b;
174 EXPECT_CALL(b, Test()).Times(0);
175 h = b.AsWeakHandle();
178 // Should not run.
179 CallTestFromOtherThread(FROM_HERE, h);
180 PumpLoop();
183 TEST_F(WeakHandleTest, CallAfterInvalidateThreaded) {
184 StrictMock<Base> b;
185 EXPECT_CALL(b, Test()).Times(0);
187 WeakHandle<Base> h = b.AsWeakHandle();
188 b.Kill();
189 // Should not run.
190 CallTestFromOtherThread(FROM_HERE, h);
191 PumpLoop();
194 TEST_F(WeakHandleTest, DeleteOnOtherThread) {
195 StrictMock<Base> b;
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);
206 PumpLoop();
209 void CallTestWithSelf(const WeakHandle<Base>& b1) {
210 StrictMock<Base> b2;
211 b1.Call(FROM_HERE, &Base::TestWithSelf, b2.AsWeakHandle());
214 TEST_F(WeakHandleTest, WithDestroyedThread) {
215 StrictMock<Base> b1;
216 WeakHandle<Base> b2;
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,
224 b1.AsWeakHandle()));
227 // Calls b1.TestWithSelf().
228 PumpLoop();
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
234 // thread is gone.
237 TEST_F(WeakHandleTest, InitializedAcrossCopyAssign) {
238 StrictMock<Base> b;
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);
248 h.Reset();
249 EXPECT_FALSE(h.IsInitialized());
253 WeakHandle<Base> h;
254 h = b.AsWeakHandle();
255 EXPECT_TRUE(h.IsInitialized());
256 h.Call(FROM_HERE, &Base::Test);
257 h.Reset();
258 EXPECT_FALSE(h.IsInitialized());
261 PumpLoop();
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);
283 PumpLoop();
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