fixup! [M120 Migration] Notify media device state to webbrowser
[platform/framework/web/chromium-efl.git] / base / barrier_callback_unittest.cc
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.
4
5 #include "base/barrier_callback.h"
6
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"
14
15 namespace {
16
17 TEST(BarrierCallbackTest, RunsImmediatelyForZeroCallbacks) {
18   bool done = false;
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
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());
31
32   EXPECT_CHECK_DEATH(barrier_callback.Run(3));
33 }
34
35 TEST(BarrierCallbackTest, RunAfterNumCallbacks) {
36   bool done = false;
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));
40         done = true;
41       }));
42   EXPECT_FALSE(done);
43
44   barrier_callback.Run(1);
45   EXPECT_FALSE(done);
46
47   barrier_callback.Run(3);
48   EXPECT_FALSE(done);
49
50   barrier_callback.Run(2);
51   EXPECT_TRUE(done);
52 }
53
54 TEST(BarrierCallbackTest, CopiesShareState) {
55   bool done = false;
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));
59         done = true;
60       }));
61   EXPECT_FALSE(done);
62
63   const auto barrier_copy1 = barrier_callback;
64   const auto barrier_copy2 = barrier_callback;
65   const auto barrier_copy3 = barrier_callback;
66
67   barrier_copy1.Run(1);
68   EXPECT_FALSE(done);
69
70   barrier_copy2.Run(3);
71   EXPECT_FALSE(done);
72
73   barrier_copy3.Run(2);
74   EXPECT_TRUE(done);
75 }
76
77 template <typename... Args>
78 class DestructionIndicator {
79  public:
80   // Sets `*destructed` to true in destructor.
81   explicit DestructionIndicator(bool* destructed) : destructed_(destructed) {
82     *destructed_ = false;
83   }
84
85   ~DestructionIndicator() { *destructed_ = true; }
86
87   void DoNothing(Args...) {}
88
89  private:
90   raw_ptr<bool> destructed_;
91 };
92
93 TEST(BarrierCallbackTest, ReleasesDoneCallbackWhenDone) {
94   bool done_destructed = false;
95   auto barrier_callback = base::BarrierCallback<bool>(
96       1,
97       base::BindOnce(&DestructionIndicator<std::vector<bool>>::DoNothing,
98                      std::make_unique<DestructionIndicator<std::vector<bool>>>(
99                          &done_destructed)));
100   EXPECT_FALSE(done_destructed);
101   barrier_callback.Run(true);
102   EXPECT_TRUE(done_destructed);
103 }
104
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));
119              }));
120   barrier_callback.Run(true);
121   EXPECT_TRUE(barrier_callback.is_null());
122 }
123
124 TEST(BarrierCallbackTest, SupportsMoveonlyTypes) {
125   class MoveOnly {
126    public:
127     MoveOnly() = default;
128     MoveOnly(MoveOnly&&) = default;
129     MoveOnly& operator=(MoveOnly&&) = default;
130   };
131
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());
137
138   auto barrier_callback2 = base::BarrierCallback<MoveOnly>(
139       1, base::BindOnce([](const std::vector<MoveOnly>&) {}));
140   barrier_callback2.Run(MoveOnly());
141 }
142
143 TEST(BarrierCallbackTest, SupportsConstRefResults) {
144   auto barrier_callback = base::BarrierCallback<int>(
145       1, base::BindOnce([](const std::vector<int>&) {}));
146
147   barrier_callback.Run(1);
148 }
149
150 TEST(BarrierCallbackTest, SupportsReferenceTypes) {
151   class Referenceable {
152     // Must be copyable.
153   };
154   Referenceable ref;
155
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);
161
162   auto barrier_callback2 = base::BarrierCallback<const Referenceable&>(
163       1, base::BindOnce([](const std::vector<Referenceable>&) {}));
164   barrier_callback2.Run(ref);
165 }
166
167 }  // namespace