barrier_callback_unittest.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2021 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 "base/barrier_callback.h"
  5. #include "base/bind.h"
  6. #include "base/callback.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/test/bind.h"
  9. #include "base/test/gtest_util.h"
  10. #include "testing/gmock/include/gmock/gmock.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace {
  13. TEST(BarrierCallbackTest, RunsImmediatelyForZeroCallbacks) {
  14. bool done = false;
  15. auto barrier_callback = base::BarrierCallback<int>(
  16. 0, base::BindLambdaForTesting([&done](std::vector<int> results) {
  17. EXPECT_THAT(results, testing::IsEmpty());
  18. done = true;
  19. }));
  20. EXPECT_TRUE(done);
  21. }
  22. TEST(BarrierCallbackTest, ErrorToCallCallbackWithZeroCallbacks) {
  23. auto barrier_callback =
  24. base::BarrierCallback<int>(0, base::BindOnce([](std::vector<int>) {}));
  25. EXPECT_FALSE(barrier_callback.is_null());
  26. EXPECT_CHECK_DEATH(barrier_callback.Run(3));
  27. }
  28. TEST(BarrierCallbackTest, RunAfterNumCallbacks) {
  29. bool done = false;
  30. auto barrier_callback = base::BarrierCallback<int>(
  31. 3, base::BindLambdaForTesting([&done](std::vector<int> results) {
  32. EXPECT_THAT(results, testing::ElementsAre(1, 3, 2));
  33. done = true;
  34. }));
  35. EXPECT_FALSE(done);
  36. barrier_callback.Run(1);
  37. EXPECT_FALSE(done);
  38. barrier_callback.Run(3);
  39. EXPECT_FALSE(done);
  40. barrier_callback.Run(2);
  41. EXPECT_TRUE(done);
  42. }
  43. TEST(BarrierCallbackTest, CopiesShareState) {
  44. bool done = false;
  45. const auto barrier_callback = base::BarrierCallback<int>(
  46. 3, base::BindLambdaForTesting([&done](std::vector<int> results) {
  47. EXPECT_THAT(results, testing::ElementsAre(1, 3, 2));
  48. done = true;
  49. }));
  50. EXPECT_FALSE(done);
  51. const auto barrier_copy1 = barrier_callback;
  52. const auto barrier_copy2 = barrier_callback;
  53. const auto barrier_copy3 = barrier_callback;
  54. barrier_copy1.Run(1);
  55. EXPECT_FALSE(done);
  56. barrier_copy2.Run(3);
  57. EXPECT_FALSE(done);
  58. barrier_copy3.Run(2);
  59. EXPECT_TRUE(done);
  60. }
  61. template <typename... Args>
  62. class DestructionIndicator {
  63. public:
  64. // Sets `*destructed` to true in destructor.
  65. explicit DestructionIndicator(bool* destructed) : destructed_(destructed) {
  66. *destructed_ = false;
  67. }
  68. ~DestructionIndicator() { *destructed_ = true; }
  69. void DoNothing(Args...) {}
  70. private:
  71. raw_ptr<bool> destructed_;
  72. };
  73. TEST(BarrierCallbackTest, ReleasesDoneCallbackWhenDone) {
  74. bool done_destructed = false;
  75. auto barrier_callback = base::BarrierCallback<bool>(
  76. 1,
  77. base::BindOnce(&DestructionIndicator<std::vector<bool>>::DoNothing,
  78. std::make_unique<DestructionIndicator<std::vector<bool>>>(
  79. &done_destructed)));
  80. EXPECT_FALSE(done_destructed);
  81. barrier_callback.Run(true);
  82. EXPECT_TRUE(done_destructed);
  83. }
  84. // Tests a case when `done_callback` resets the `barrier_callback`.
  85. // `barrier_callback` is a RepeatingCallback holding the `done_callback`.
  86. // `done_callback` holds a reference back to the `barrier_callback`. When
  87. // `barrier_callback` is Run() it calls `done_callback` which erases the
  88. // `barrier_callback` while still inside of its Run(). The Run() implementation
  89. // (in base::BarrierCallback) must not try use itself after executing
  90. // ResetBarrierCallback() or this test would crash inside Run().
  91. TEST(BarrierCallbackTest, KeepingCallbackAliveUntilDone) {
  92. base::RepeatingCallback<void(bool)> barrier_callback;
  93. barrier_callback = base::BarrierCallback<bool>(
  94. 1, base::BindLambdaForTesting(
  95. [&barrier_callback](std::vector<bool> results) {
  96. barrier_callback = base::RepeatingCallback<void(bool)>();
  97. EXPECT_THAT(results, testing::ElementsAre(true));
  98. }));
  99. barrier_callback.Run(true);
  100. EXPECT_TRUE(barrier_callback.is_null());
  101. }
  102. TEST(BarrierCallbackTest, SupportsMoveonlyTypes) {
  103. class MoveOnly {
  104. public:
  105. MoveOnly() = default;
  106. MoveOnly(MoveOnly&&) = default;
  107. MoveOnly& operator=(MoveOnly&&) = default;
  108. };
  109. // No need to assert anything here, since if BarrierCallback didn't work with
  110. // move-only types, this wouldn't compile.
  111. auto barrier_callback = base::BarrierCallback<MoveOnly>(
  112. 1, base::BindOnce([](std::vector<MoveOnly>) {}));
  113. barrier_callback.Run(MoveOnly());
  114. auto barrier_callback2 = base::BarrierCallback<MoveOnly>(
  115. 1, base::BindOnce([](const std::vector<MoveOnly>&) {}));
  116. barrier_callback2.Run(MoveOnly());
  117. }
  118. TEST(BarrierCallbackTest, SupportsConstRefResults) {
  119. auto barrier_callback = base::BarrierCallback<int>(
  120. 1, base::BindOnce([](const std::vector<int>&) {}));
  121. barrier_callback.Run(1);
  122. }
  123. TEST(BarrierCallbackTest, SupportsReferenceTypes) {
  124. class Referenceable {
  125. // Must be copyable.
  126. };
  127. Referenceable ref;
  128. // No need to assert anything here, since if BarrierCallback didn't work with
  129. // by-reference args, this wouldn't compile.
  130. auto barrier_callback = base::BarrierCallback<const Referenceable&>(
  131. 1, base::BindOnce([](std::vector<Referenceable>) {}));
  132. barrier_callback.Run(ref);
  133. auto barrier_callback2 = base::BarrierCallback<const Referenceable&>(
  134. 1, base::BindOnce([](const std::vector<Referenceable>&) {}));
  135. barrier_callback2.Run(ref);
  136. }
  137. } // namespace