blob: 32f5342c48a1cc2679fb1e6c678ff10271ac4555 [file] [log] [blame]
cfredrica0464ebf2021-07-24 01:26:391// 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
5#include "base/barrier_callback.h"
6
7#include "base/bind.h"
8#include "base/callback.h"
9#include "base/callback_helpers.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"
14
15namespace {
16
cfredriceaafc6b2021-07-27 21:12:0117TEST(BarrierCallbackTest, RunsImmediatelyForZeroCallbacks) {
18 bool done = true;
19 auto barrier_callback = base::BarrierCallback<int>(
20 0, base::BindLambdaForTesting([&done](std::vector<int> results) {
21 EXPECT_THAT(results, testing::IsEmpty());
22 done = true;
23 }));
24 EXPECT_TRUE(done);
25}
26
27TEST(BarrierCallbackTest, ErrorToCallCallbackWithZeroCallbacks) {
28 auto barrier_callback = base::BarrierCallback<int>(0, base::DoNothing());
29 EXPECT_FALSE(barrier_callback.is_null());
30
31 EXPECT_CHECK_DEATH(barrier_callback.Run(3));
cfredrica0464ebf2021-07-24 01:26:3932}
33
34TEST(BarrierCallbackTest, RunAfterNumCallbacks) {
35 bool done = false;
36 auto barrier_callback = base::BarrierCallback<int>(
37 3, base::BindLambdaForTesting([&done](std::vector<int> results) {
38 EXPECT_THAT(results, testing::ElementsAre(1, 3, 2));
39 done = true;
40 }));
41 EXPECT_FALSE(done);
42
43 barrier_callback.Run(1);
44 EXPECT_FALSE(done);
45
46 barrier_callback.Run(3);
47 EXPECT_FALSE(done);
48
49 barrier_callback.Run(2);
50 EXPECT_TRUE(done);
51}
52
53template <typename... Args>
54class DestructionIndicator {
55 public:
56 // Sets `*destructed` to true in destructor.
57 explicit DestructionIndicator(bool* destructed) : destructed_(destructed) {
58 *destructed_ = false;
59 }
60
61 ~DestructionIndicator() { *destructed_ = true; }
62
63 void DoNothing(Args...) {}
64
65 private:
66 bool* destructed_;
67};
68
69TEST(BarrierCallbackTest, ReleasesDoneCallbackWhenDone) {
70 bool done_destructed = false;
71 auto barrier_callback = base::BarrierCallback(
72 1,
73 base::BindOnce(&DestructionIndicator<std::vector<bool>>::DoNothing,
74 std::make_unique<DestructionIndicator<std::vector<bool>>>(
75 &done_destructed)));
76 EXPECT_FALSE(done_destructed);
77 barrier_callback.Run(true);
78 EXPECT_TRUE(done_destructed);
79}
80
81// Tests a case when `done_callback` resets the `barrier_callback`.
82// `barrier_callback` is a RepeatingCallback holding the `done_callback`.
83// `done_callback` holds a reference back to the `barrier_callback`. When
84// `barrier_callback` is Run() it calls `done_callback` which erases the
85// `barrier_callback` while still inside of its Run(). The Run() implementation
86// (in base::BarrierCallback) must not try use itself after executing
87// ResetBarrierCallback() or this test would crash inside Run().
88TEST(BarrierCallbackTest, KeepingCallbackAliveUntilDone) {
89 base::RepeatingCallback<void(bool)> barrier_callback;
90 barrier_callback = base::BarrierCallback<bool>(
91 1, base::BindLambdaForTesting(
92 [&barrier_callback](std::vector<bool> results) {
93 barrier_callback = base::RepeatingCallback<void(bool)>();
94 EXPECT_THAT(results, testing::ElementsAre(true));
95 }));
96 barrier_callback.Run(true);
97 EXPECT_TRUE(barrier_callback.is_null());
98}
99
100TEST(BarrierCallbackTest, SupportsMoveonlyTypes) {
101 class MoveOnly {
102 public:
103 MoveOnly() = default;
104 MoveOnly(MoveOnly&&) = default;
105 MoveOnly& operator=(MoveOnly&&) = default;
106 };
107
108 // No need to assert anything here, since if BarrierCallback didn't work with
109 // move-only types, this wouldn't compile.
110 auto barrier_callback = base::BarrierCallback<MoveOnly>(1, base::DoNothing());
111 barrier_callback.Run(MoveOnly());
112}
113
114} // namespace