| Index: base/cancelable_callback_unittest.cc
|
| diff --git a/base/cancelable_callback_unittest.cc b/base/cancelable_callback_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..980359b963cb42fe81e0611bc2007b57419b0641
|
| --- /dev/null
|
| +++ b/base/cancelable_callback_unittest.cc
|
| @@ -0,0 +1,182 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/cancelable_callback.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/message_loop.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace base {
|
| +namespace {
|
| +
|
| +class TestRefCounted : public RefCountedThreadSafe<TestRefCounted> {
|
| + private:
|
| + friend class RefCountedThreadSafe<TestRefCounted>;
|
| + ~TestRefCounted() {};
|
| +};
|
| +
|
| +void Increment(int* count) { (*count)++; }
|
| +void IncrementBy(int* count, int n) { (*count) += n; }
|
| +void RefCountedParam(const scoped_refptr<TestRefCounted>& ref_counted) {}
|
| +
|
| +// Cancel().
|
| +// - Callback can be run multiple times.
|
| +// - After Cancel(), Run() completes but has no effect.
|
| +TEST(CancelableCallbackTest, Cancel) {
|
| + int count = 0;
|
| + CancelableCallback cancelable(
|
| + base::Bind(&Increment, base::Unretained(&count)));
|
| +
|
| + base::Closure callback = cancelable.callback();
|
| + callback.Run();
|
| + EXPECT_EQ(1, count);
|
| +
|
| + callback.Run();
|
| + EXPECT_EQ(2, count);
|
| +
|
| + cancelable.Cancel();
|
| + callback.Run();
|
| + EXPECT_EQ(2, count);
|
| +}
|
| +
|
| +// Cancel() called multiple times.
|
| +// - Cancel() cancels all copies of the wrapped callback.
|
| +TEST(CancelableCallbackTest, MultipleCancel) {
|
| + int count = 0;
|
| + CancelableCallback cancelable(
|
| + base::Bind(&Increment, base::Unretained(&count)));
|
| +
|
| + base::Closure callback1 = cancelable.callback();
|
| + cancelable.Cancel();
|
| +
|
| + callback1.Run();
|
| + EXPECT_EQ(0, count);
|
| +
|
| + base::Closure callback2 = cancelable.callback();
|
| + callback2.Run();
|
| + EXPECT_EQ(0, count);
|
| +
|
| + // Cancel() should have no effect, but callback() is still runnable.
|
| + base::Closure callback3 = cancelable.callback();
|
| + cancelable.Cancel();
|
| + callback3.Run();
|
| + EXPECT_EQ(0, count);
|
| +}
|
| +
|
| +// CancelableCallback destroyed before callback is run.
|
| +// - Destruction of CancelableCallback cancels outstanding callbacks.
|
| +TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) {
|
| + int count = 0;
|
| + base::Closure callback;
|
| +
|
| + {
|
| + CancelableCallback cancelable(
|
| + base::Bind(&Increment, base::Unretained(&count)));
|
| +
|
| + callback = cancelable.callback();
|
| + callback.Run();
|
| + EXPECT_EQ(1, count);
|
| + }
|
| +
|
| + callback.Run();
|
| + EXPECT_EQ(1, count);
|
| +}
|
| +
|
| +// Cancel() called on bound closure with a RefCounted parameter.
|
| +// - Cancel drops wrapped callback (and, implicitly, its bound arguments).
|
| +TEST(CancelableCallbackTest, CancelDropsCallback) {
|
| + scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted;
|
| + EXPECT_TRUE(ref_counted->HasOneRef());
|
| +
|
| + CancelableCallback cancelable(base::Bind(RefCountedParam, ref_counted));
|
| + EXPECT_FALSE(cancelable.IsCancelled());
|
| + EXPECT_TRUE(ref_counted.get());
|
| + EXPECT_FALSE(ref_counted->HasOneRef());
|
| +
|
| + // There is only one reference to |ref_counted| after the Cancel().
|
| + cancelable.Cancel();
|
| + EXPECT_TRUE(cancelable.IsCancelled());
|
| + EXPECT_TRUE(ref_counted.get());
|
| + EXPECT_TRUE(ref_counted->HasOneRef());
|
| +}
|
| +
|
| +// Reset().
|
| +// - Reset() replaces the existing wrapped callback with a new callback.
|
| +// - Reset() deactivates outstanding callbacks.
|
| +TEST(CancelableCallbackTest, Reset) {
|
| + int count = 0;
|
| + CancelableCallback cancelable(
|
| + base::Bind(&Increment, base::Unretained(&count)));
|
| +
|
| + base::Closure callback = cancelable.callback();
|
| + callback.Run();
|
| + EXPECT_EQ(1, count);
|
| +
|
| + callback.Run();
|
| + EXPECT_EQ(2, count);
|
| +
|
| + cancelable.Reset(
|
| + base::Bind(&IncrementBy, base::Unretained(&count), 3));
|
| + EXPECT_FALSE(cancelable.IsCancelled());
|
| +
|
| + // The stale copy of the cancelable callback is non-null.
|
| + ASSERT_FALSE(callback.is_null());
|
| +
|
| + // The stale copy of the cancelable callback is no longer active.
|
| + callback.Run();
|
| + EXPECT_EQ(2, count);
|
| +
|
| + base::Closure callback2 = cancelable.callback();
|
| + ASSERT_FALSE(callback2.is_null());
|
| +
|
| + callback2.Run();
|
| + EXPECT_EQ(5, count);
|
| +}
|
| +
|
| +// IsCanceled().
|
| +// - Cancel() transforms the CancelableCallback into a cancelled state.
|
| +TEST(CancelableCallbackTest, IsNull) {
|
| + CancelableCallback cancelable;
|
| + EXPECT_TRUE(cancelable.IsCancelled());
|
| +
|
| + int count = 0;
|
| + cancelable.Reset(base::Bind(&Increment,
|
| + base::Unretained(&count)));
|
| + EXPECT_FALSE(cancelable.IsCancelled());
|
| +
|
| + cancelable.Cancel();
|
| + EXPECT_TRUE(cancelable.IsCancelled());
|
| +}
|
| +
|
| +// CancelableCallback posted to a MessageLoop with PostTask.
|
| +// - Callbacks posted to a MessageLoop can be cancelled.
|
| +TEST(CancelableCallbackTest, PostTask) {
|
| + MessageLoop loop(MessageLoop::TYPE_DEFAULT);
|
| +
|
| + int count = 0;
|
| + CancelableCallback cancelable(base::Bind(&Increment,
|
| + base::Unretained(&count)));
|
| +
|
| + MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback());
|
| + MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
|
| + MessageLoop::current()->Run();
|
| +
|
| + EXPECT_EQ(1, count);
|
| +
|
| + MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback());
|
| + MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
|
| +
|
| + // Cancel before running the message loop.
|
| + cancelable.Cancel();
|
| + MessageLoop::current()->Run();
|
| +
|
| + // Callback never ran due to cancellation; count is the same.
|
| + EXPECT_EQ(1, count);
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace base
|
|
|