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