15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/cancelable_callback.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestRefCounted : public RefCountedThreadSafe<TestRefCounted> { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class RefCountedThreadSafe<TestRefCounted>; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~TestRefCounted() {}; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Increment(int* count) { (*count)++; } 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IncrementBy(int* count, int n) { (*count) += n; } 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RefCountedParam(const scoped_refptr<TestRefCounted>& ref_counted) {} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cancel(). 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Callback can be run multiple times. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - After Cancel(), Run() completes but has no effect. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(CancelableCallbackTest, Cancel) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableClosure cancelable( 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Increment, base::Unretained(&count))); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure callback = cancelable.callback(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, count); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, count); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Cancel(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, count); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cancel() called multiple times. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Cancel() cancels all copies of the wrapped callback. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Calling Cancel() more than once has no effect. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - After Cancel(), callback() returns a null callback. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(CancelableCallbackTest, MultipleCancel) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableClosure cancelable( 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Increment, base::Unretained(&count))); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure callback1 = cancelable.callback(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure callback2 = cancelable.callback(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Cancel(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback1.Run(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, count); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback2.Run(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, count); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calling Cancel() again has no effect. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Cancel(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callback() of a cancelled callback is null. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure callback3 = cancelable.callback(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(callback3.is_null()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CancelableCallback destroyed before callback is run. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Destruction of CancelableCallback cancels outstanding callbacks. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure callback; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableClosure cancelable( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Increment, base::Unretained(&count))); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback = cancelable.callback(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, count); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, count); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cancel() called on bound closure with a RefCounted parameter. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Cancel drops wrapped callback (and, implicitly, its bound arguments). 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(CancelableCallbackTest, CancelDropsCallback) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ref_counted->HasOneRef()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableClosure cancelable(base::Bind(RefCountedParam, ref_counted)); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(cancelable.IsCancelled()); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ref_counted.get()); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(ref_counted->HasOneRef()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is only one reference to |ref_counted| after the Cancel(). 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Cancel(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cancelable.IsCancelled()); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ref_counted.get()); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(ref_counted->HasOneRef()); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reset(). 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Reset() replaces the existing wrapped callback with a new callback. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Reset() deactivates outstanding callbacks. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(CancelableCallbackTest, Reset) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableClosure cancelable( 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Increment, base::Unretained(&count))); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure callback = cancelable.callback(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, count); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, count); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Reset( 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&IncrementBy, base::Unretained(&count), 3)); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(cancelable.IsCancelled()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The stale copy of the cancelable callback is non-null. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(callback.is_null()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The stale copy of the cancelable callback is no longer active. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, count); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure callback2 = cancelable.callback(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(callback2.is_null()); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback2.Run(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(5, count); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IsCanceled(). 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Cancel() transforms the CancelableCallback into a cancelled state. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(CancelableCallbackTest, IsNull) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableClosure cancelable; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cancelable.IsCancelled()); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Reset(base::Bind(&Increment, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(&count))); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(cancelable.IsCancelled()); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Cancel(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(cancelable.IsCancelled()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CancelableCallback posted to a MessageLoop with PostTask. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Callbacks posted to a MessageLoop can be cancelled. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(CancelableCallbackTest, PostTask) { 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MessageLoop loop; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableClosure cancelable(base::Bind(&Increment, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(&count))); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunLoop().RunUntilIdle(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, count); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel before running the message loop. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelable.Cancel(); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunLoop().RunUntilIdle(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback never ran due to cancellation; count is the same. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, count); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 185