1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/barrier_callback.h"
7 #include "base/functional/bind.h"
8 #include "base/functional/callback.h"
9 #include "base/memory/raw_ptr.h"
10 #include "base/test/bind.h"
11 #include "base/test/gtest_util.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 TEST(BarrierCallbackTest, RunsImmediatelyForZeroCallbacks) {
19 auto barrier_callback = base::BarrierCallback<int>(
20 0, base::BindLambdaForTesting([&done](std::vector<int> results) {
21 EXPECT_THAT(results, testing::IsEmpty());
27 TEST(BarrierCallbackTest, ErrorToCallCallbackWithZeroCallbacks) {
28 auto barrier_callback =
29 base::BarrierCallback<int>(0, base::BindOnce([](std::vector<int>) {}));
30 EXPECT_FALSE(barrier_callback.is_null());
32 EXPECT_CHECK_DEATH(barrier_callback.Run(3));
35 TEST(BarrierCallbackTest, RunAfterNumCallbacks) {
37 auto barrier_callback = base::BarrierCallback<int>(
38 3, base::BindLambdaForTesting([&done](std::vector<int> results) {
39 EXPECT_THAT(results, testing::ElementsAre(1, 3, 2));
44 barrier_callback.Run(1);
47 barrier_callback.Run(3);
50 barrier_callback.Run(2);
54 TEST(BarrierCallbackTest, CopiesShareState) {
56 const auto barrier_callback = base::BarrierCallback<int>(
57 3, base::BindLambdaForTesting([&done](std::vector<int> results) {
58 EXPECT_THAT(results, testing::ElementsAre(1, 3, 2));
63 const auto barrier_copy1 = barrier_callback;
64 const auto barrier_copy2 = barrier_callback;
65 const auto barrier_copy3 = barrier_callback;
77 template <typename... Args>
78 class DestructionIndicator {
80 // Sets `*destructed` to true in destructor.
81 explicit DestructionIndicator(bool* destructed) : destructed_(destructed) {
85 ~DestructionIndicator() { *destructed_ = true; }
87 void DoNothing(Args...) {}
90 raw_ptr<bool> destructed_;
93 TEST(BarrierCallbackTest, ReleasesDoneCallbackWhenDone) {
94 bool done_destructed = false;
95 auto barrier_callback = base::BarrierCallback<bool>(
97 base::BindOnce(&DestructionIndicator<std::vector<bool>>::DoNothing,
98 std::make_unique<DestructionIndicator<std::vector<bool>>>(
100 EXPECT_FALSE(done_destructed);
101 barrier_callback.Run(true);
102 EXPECT_TRUE(done_destructed);
105 // Tests a case when `done_callback` resets the `barrier_callback`.
106 // `barrier_callback` is a RepeatingCallback holding the `done_callback`.
107 // `done_callback` holds a reference back to the `barrier_callback`. When
108 // `barrier_callback` is Run() it calls `done_callback` which erases the
109 // `barrier_callback` while still inside of its Run(). The Run() implementation
110 // (in base::BarrierCallback) must not try use itself after executing
111 // ResetBarrierCallback() or this test would crash inside Run().
112 TEST(BarrierCallbackTest, KeepingCallbackAliveUntilDone) {
113 base::RepeatingCallback<void(bool)> barrier_callback;
114 barrier_callback = base::BarrierCallback<bool>(
115 1, base::BindLambdaForTesting(
116 [&barrier_callback](std::vector<bool> results) {
117 barrier_callback = base::RepeatingCallback<void(bool)>();
118 EXPECT_THAT(results, testing::ElementsAre(true));
120 barrier_callback.Run(true);
121 EXPECT_TRUE(barrier_callback.is_null());
124 TEST(BarrierCallbackTest, SupportsMoveonlyTypes) {
127 MoveOnly() = default;
128 MoveOnly(MoveOnly&&) = default;
129 MoveOnly& operator=(MoveOnly&&) = default;
132 // No need to assert anything here, since if BarrierCallback didn't work with
133 // move-only types, this wouldn't compile.
134 auto barrier_callback = base::BarrierCallback<MoveOnly>(
135 1, base::BindOnce([](std::vector<MoveOnly>) {}));
136 barrier_callback.Run(MoveOnly());
138 auto barrier_callback2 = base::BarrierCallback<MoveOnly>(
139 1, base::BindOnce([](const std::vector<MoveOnly>&) {}));
140 barrier_callback2.Run(MoveOnly());
143 TEST(BarrierCallbackTest, SupportsConstRefResults) {
144 auto barrier_callback = base::BarrierCallback<int>(
145 1, base::BindOnce([](const std::vector<int>&) {}));
147 barrier_callback.Run(1);
150 TEST(BarrierCallbackTest, SupportsReferenceTypes) {
151 class Referenceable {
156 // No need to assert anything here, since if BarrierCallback didn't work with
157 // by-reference args, this wouldn't compile.
158 auto barrier_callback = base::BarrierCallback<const Referenceable&>(
159 1, base::BindOnce([](std::vector<Referenceable>) {}));
160 barrier_callback.Run(ref);
162 auto barrier_callback2 = base::BarrierCallback<const Referenceable&>(
163 1, base::BindOnce([](const std::vector<Referenceable>&) {}));
164 barrier_callback2.Run(ref);