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. 4 5 #include "sync/internal_api/public/util/weak_handle.h" 6 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/message_loop/message_loop.h" 12 #include "base/threading/thread.h" 13 #include "testing/gmock/include/gmock/gmock.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace syncer { 17 18 using ::testing::_; 19 using ::testing::SaveArg; 20 using ::testing::StrictMock; 21 22 class Base { 23 public: 24 Base() : weak_ptr_factory_(this) {} 25 26 WeakHandle<Base> AsWeakHandle() { 27 return MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()); 28 } 29 30 void Kill() { 31 weak_ptr_factory_.InvalidateWeakPtrs(); 32 } 33 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*)); 39 40 MOCK_METHOD1(TestWithSelf, void(const WeakHandle<Base>&)); 41 42 private: 43 base::WeakPtrFactory<Base> weak_ptr_factory_; 44 }; 45 46 class Derived : public Base, public base::SupportsWeakPtr<Derived> {}; 47 48 class WeakHandleTest : public ::testing::Test { 49 protected: 50 virtual void TearDown() { 51 // Process any last-minute posted tasks. 52 PumpLoop(); 53 } 54 55 void PumpLoop() { 56 message_loop_.RunUntilIdle(); 57 } 58 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)); 65 } 66 67 private: 68 static void CallTest(tracked_objects::Location from_here, 69 const WeakHandle<Base>& h) { 70 h.Call(from_here, &Base::Test); 71 } 72 73 base::MessageLoop message_loop_; 74 }; 75 76 TEST_F(WeakHandleTest, Uninitialized) { 77 // Default. 78 WeakHandle<int> h; 79 EXPECT_FALSE(h.IsInitialized()); 80 // Copy. 81 { 82 WeakHandle<int> h2(h); 83 EXPECT_FALSE(h2.IsInitialized()); 84 } 85 // Assign. 86 { 87 WeakHandle<int> h2; 88 h2 = h; 89 EXPECT_FALSE(h.IsInitialized()); 90 } 91 } 92 93 TEST_F(WeakHandleTest, InitializedAfterDestroy) { 94 WeakHandle<Base> h; 95 { 96 StrictMock<Base> b; 97 h = b.AsWeakHandle(); 98 } 99 EXPECT_TRUE(h.IsInitialized()); 100 EXPECT_FALSE(h.Get()); 101 } 102 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()); 109 } 110 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)); 119 120 WeakHandle<Base> h = b.AsWeakHandle(); 121 EXPECT_TRUE(h.IsInitialized()); 122 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(); 130 } 131 132 TEST_F(WeakHandleTest, CallAfterDestroy) { 133 { 134 StrictMock<Base> b; 135 EXPECT_CALL(b, Test()).Times(0); 136 137 WeakHandle<Base> h = b.AsWeakHandle(); 138 EXPECT_TRUE(h.IsInitialized()); 139 140 // Should not run. 141 h.Call(FROM_HERE, &Base::Test); 142 } 143 PumpLoop(); 144 } 145 146 TEST_F(WeakHandleTest, CallAfterInvalidate) { 147 StrictMock<Base> b; 148 EXPECT_CALL(b, Test()).Times(0); 149 150 WeakHandle<Base> h = b.AsWeakHandle(); 151 EXPECT_TRUE(h.IsInitialized()); 152 153 // Should not run. 154 h.Call(FROM_HERE, &Base::Test); 155 156 b.Kill(); 157 PumpLoop(); 158 } 159 160 TEST_F(WeakHandleTest, CallThreaded) { 161 StrictMock<Base> b; 162 EXPECT_CALL(b, Test()); 163 164 WeakHandle<Base> h = b.AsWeakHandle(); 165 // Should run. 166 CallTestFromOtherThread(FROM_HERE, h); 167 PumpLoop(); 168 } 169 170 TEST_F(WeakHandleTest, CallAfterDestroyThreaded) { 171 WeakHandle<Base> h; 172 { 173 StrictMock<Base> b; 174 EXPECT_CALL(b, Test()).Times(0); 175 h = b.AsWeakHandle(); 176 } 177 178 // Should not run. 179 CallTestFromOtherThread(FROM_HERE, h); 180 PumpLoop(); 181 } 182 183 TEST_F(WeakHandleTest, CallAfterInvalidateThreaded) { 184 StrictMock<Base> b; 185 EXPECT_CALL(b, Test()).Times(0); 186 187 WeakHandle<Base> h = b.AsWeakHandle(); 188 b.Kill(); 189 // Should not run. 190 CallTestFromOtherThread(FROM_HERE, h); 191 PumpLoop(); 192 } 193 194 TEST_F(WeakHandleTest, DeleteOnOtherThread) { 195 StrictMock<Base> b; 196 EXPECT_CALL(b, Test()).Times(0); 197 198 WeakHandle<Base>* h = new WeakHandle<Base>(b.AsWeakHandle()); 199 200 { 201 base::Thread t("Test thread"); 202 ASSERT_TRUE(t.Start()); 203 t.message_loop()->DeleteSoon(FROM_HERE, h); 204 } 205 206 PumpLoop(); 207 } 208 209 void CallTestWithSelf(const WeakHandle<Base>& b1) { 210 StrictMock<Base> b2; 211 b1.Call(FROM_HERE, &Base::TestWithSelf, b2.AsWeakHandle()); 212 } 213 214 TEST_F(WeakHandleTest, WithDestroyedThread) { 215 StrictMock<Base> b1; 216 WeakHandle<Base> b2; 217 EXPECT_CALL(b1, TestWithSelf(_)).WillOnce(SaveArg<0>(&b2)); 218 219 { 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())); 225 } 226 227 // Calls b1.TestWithSelf(). 228 PumpLoop(); 229 230 // Shouldn't do anything, since the thread is gone. 231 b2.Call(FROM_HERE, &Base::Test); 232 233 // |b2| shouldn't leak when it's destroyed, even if the original 234 // thread is gone. 235 } 236 237 TEST_F(WeakHandleTest, InitializedAcrossCopyAssign) { 238 StrictMock<Base> b; 239 EXPECT_CALL(b, Test()).Times(3); 240 241 EXPECT_TRUE(b.AsWeakHandle().IsInitialized()); 242 b.AsWeakHandle().Call(FROM_HERE, &Base::Test); 243 244 { 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()); 250 } 251 252 { 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()); 259 } 260 261 PumpLoop(); 262 } 263 264 TEST_F(WeakHandleTest, TypeConversionConstructor) { 265 StrictMock<Derived> d; 266 EXPECT_CALL(d, Test()).Times(2); 267 268 const WeakHandle<Derived> weak_handle = MakeWeakHandle(d.AsWeakPtr()); 269 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); 274 275 EXPECT_TRUE(base_weak_handle.IsInitialized()); 276 base_weak_handle.Call(FROM_HERE, &Base::Test); 277 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); 282 283 PumpLoop(); 284 } 285 286 TEST_F(WeakHandleTest, TypeConversionConstructorMakeWeakHandle) { 287 const base::WeakPtr<Derived> weak_ptr; 288 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)); 293 294 EXPECT_TRUE(base_weak_handle.IsInitialized()); 295 EXPECT_TRUE(derived_weak_handle.IsInitialized()); 296 } 297 298 TEST_F(WeakHandleTest, TypeConversionConstructorAssignment) { 299 const WeakHandle<Derived> weak_handle = 300 MakeWeakHandle(Derived().AsWeakPtr()); 301 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; 308 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()); 313 } 314 315 TEST_F(WeakHandleTest, TypeConversionConstructorUninitialized) { 316 const WeakHandle<Base> base_weak_handle = WeakHandle<Derived>(); 317 EXPECT_FALSE(base_weak_handle.IsInitialized()); 318 } 319 320 TEST_F(WeakHandleTest, TypeConversionConstructorUninitializedAssignment) { 321 WeakHandle<Base> base_weak_handle; 322 base_weak_handle = WeakHandle<Derived>(); 323 EXPECT_FALSE(base_weak_handle.IsInitialized()); 324 } 325 326 } // namespace syncer 327