cancelable_callback_unittest.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright (c) 2011 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. #include "butil/cancelable_callback.h"
  5. #include "butil/bind.h"
  6. #include "butil/bind_helpers.h"
  7. #include "butil/memory/ref_counted.h"
  8. #include <gtest/gtest.h>
  9. namespace butil {
  10. namespace {
  11. class TestRefCounted : public RefCountedThreadSafe<TestRefCounted> {
  12. private:
  13. friend class RefCountedThreadSafe<TestRefCounted>;
  14. ~TestRefCounted() {};
  15. };
  16. void Increment(int* count) { (*count)++; }
  17. void IncrementBy(int* count, int n) { (*count) += n; }
  18. void RefCountedParam(const scoped_refptr<TestRefCounted>& ref_counted) {}
  19. // Cancel().
  20. // - Callback can be run multiple times.
  21. // - After Cancel(), Run() completes but has no effect.
  22. TEST(CancelableCallbackTest, Cancel) {
  23. int count = 0;
  24. CancelableClosure cancelable(
  25. butil::Bind(&Increment, butil::Unretained(&count)));
  26. butil::Closure callback = cancelable.callback();
  27. callback.Run();
  28. EXPECT_EQ(1, count);
  29. callback.Run();
  30. EXPECT_EQ(2, count);
  31. cancelable.Cancel();
  32. callback.Run();
  33. EXPECT_EQ(2, count);
  34. }
  35. // Cancel() called multiple times.
  36. // - Cancel() cancels all copies of the wrapped callback.
  37. // - Calling Cancel() more than once has no effect.
  38. // - After Cancel(), callback() returns a null callback.
  39. TEST(CancelableCallbackTest, MultipleCancel) {
  40. int count = 0;
  41. CancelableClosure cancelable(
  42. butil::Bind(&Increment, butil::Unretained(&count)));
  43. butil::Closure callback1 = cancelable.callback();
  44. butil::Closure callback2 = cancelable.callback();
  45. cancelable.Cancel();
  46. callback1.Run();
  47. EXPECT_EQ(0, count);
  48. callback2.Run();
  49. EXPECT_EQ(0, count);
  50. // Calling Cancel() again has no effect.
  51. cancelable.Cancel();
  52. // callback() of a cancelled callback is null.
  53. butil::Closure callback3 = cancelable.callback();
  54. EXPECT_TRUE(callback3.is_null());
  55. }
  56. // CancelableCallback destroyed before callback is run.
  57. // - Destruction of CancelableCallback cancels outstanding callbacks.
  58. TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) {
  59. int count = 0;
  60. butil::Closure callback;
  61. {
  62. CancelableClosure cancelable(
  63. butil::Bind(&Increment, butil::Unretained(&count)));
  64. callback = cancelable.callback();
  65. callback.Run();
  66. EXPECT_EQ(1, count);
  67. }
  68. callback.Run();
  69. EXPECT_EQ(1, count);
  70. }
  71. // Cancel() called on bound closure with a RefCounted parameter.
  72. // - Cancel drops wrapped callback (and, implicitly, its bound arguments).
  73. TEST(CancelableCallbackTest, CancelDropsCallback) {
  74. scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted;
  75. EXPECT_TRUE(ref_counted->HasOneRef());
  76. CancelableClosure cancelable(butil::Bind(RefCountedParam, ref_counted));
  77. EXPECT_FALSE(cancelable.IsCancelled());
  78. EXPECT_TRUE(ref_counted.get());
  79. EXPECT_FALSE(ref_counted->HasOneRef());
  80. // There is only one reference to |ref_counted| after the Cancel().
  81. cancelable.Cancel();
  82. EXPECT_TRUE(cancelable.IsCancelled());
  83. EXPECT_TRUE(ref_counted.get());
  84. EXPECT_TRUE(ref_counted->HasOneRef());
  85. }
  86. // Reset().
  87. // - Reset() replaces the existing wrapped callback with a new callback.
  88. // - Reset() deactivates outstanding callbacks.
  89. TEST(CancelableCallbackTest, Reset) {
  90. int count = 0;
  91. CancelableClosure cancelable(
  92. butil::Bind(&Increment, butil::Unretained(&count)));
  93. butil::Closure callback = cancelable.callback();
  94. callback.Run();
  95. EXPECT_EQ(1, count);
  96. callback.Run();
  97. EXPECT_EQ(2, count);
  98. cancelable.Reset(
  99. butil::Bind(&IncrementBy, butil::Unretained(&count), 3));
  100. EXPECT_FALSE(cancelable.IsCancelled());
  101. // The stale copy of the cancelable callback is non-null.
  102. ASSERT_FALSE(callback.is_null());
  103. // The stale copy of the cancelable callback is no longer active.
  104. callback.Run();
  105. EXPECT_EQ(2, count);
  106. butil::Closure callback2 = cancelable.callback();
  107. ASSERT_FALSE(callback2.is_null());
  108. callback2.Run();
  109. EXPECT_EQ(5, count);
  110. }
  111. // IsCanceled().
  112. // - Cancel() transforms the CancelableCallback into a cancelled state.
  113. TEST(CancelableCallbackTest, IsNull) {
  114. CancelableClosure cancelable;
  115. EXPECT_TRUE(cancelable.IsCancelled());
  116. int count = 0;
  117. cancelable.Reset(butil::Bind(&Increment,
  118. butil::Unretained(&count)));
  119. EXPECT_FALSE(cancelable.IsCancelled());
  120. cancelable.Cancel();
  121. EXPECT_TRUE(cancelable.IsCancelled());
  122. }
  123. } // namespace
  124. } // namespace butil