[M85 Dev][EFL] Fix crashes at webview launch
[platform/framework/web/chromium-efl.git] / base / callback_unittest.cc
1 // Copyright (c) 2012 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/callback.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/callback_internal.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/notreached.h"
14 #include "base/test/test_timeouts.h"
15 #include "base/threading/thread.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19
20 void NopInvokeFunc() {}
21
22 // White-box testpoints to inject into a callback object for checking
23 // comparators and emptiness APIs. Use a BindState that is specialized based on
24 // a type we declared in the anonymous namespace above to remove any chance of
25 // colliding with another instantiation and breaking the one-definition-rule.
26 struct FakeBindState : internal::BindStateBase {
27   FakeBindState() : BindStateBase(&NopInvokeFunc, &Destroy, &IsCancelled) {}
28
29  private:
30   ~FakeBindState() = default;
31   static void Destroy(const internal::BindStateBase* self) {
32     delete static_cast<const FakeBindState*>(self);
33   }
34   static bool IsCancelled(const internal::BindStateBase*,
35                           internal::BindStateBase::CancellationQueryMode mode) {
36     switch (mode) {
37       case internal::BindStateBase::IS_CANCELLED:
38         return false;
39       case internal::BindStateBase::MAYBE_VALID:
40         return true;
41     }
42     NOTREACHED();
43   }
44 };
45
46 namespace {
47
48 class CallbackTest : public ::testing::Test {
49  public:
50   CallbackTest()
51       : callback_a_(new FakeBindState()), callback_b_(new FakeBindState()) {}
52
53   ~CallbackTest() override = default;
54
55  protected:
56   RepeatingCallback<void()> callback_a_;
57   const RepeatingCallback<void()> callback_b_;  // Ensure APIs work with const.
58   RepeatingCallback<void()> null_callback_;
59 };
60
61 // Ensure we can create unbound callbacks. We need this to be able to store
62 // them in class members that can be initialized later.
63 TEST_F(CallbackTest, DefaultConstruction) {
64   RepeatingCallback<void()> c0;
65   RepeatingCallback<void(int)> c1;
66   RepeatingCallback<void(int, int)> c2;
67   RepeatingCallback<void(int, int, int)> c3;
68   RepeatingCallback<void(int, int, int, int)> c4;
69   RepeatingCallback<void(int, int, int, int, int)> c5;
70   RepeatingCallback<void(int, int, int, int, int, int)> c6;
71
72   EXPECT_TRUE(c0.is_null());
73   EXPECT_TRUE(c1.is_null());
74   EXPECT_TRUE(c2.is_null());
75   EXPECT_TRUE(c3.is_null());
76   EXPECT_TRUE(c4.is_null());
77   EXPECT_TRUE(c5.is_null());
78   EXPECT_TRUE(c6.is_null());
79 }
80
81 TEST_F(CallbackTest, IsNull) {
82   EXPECT_TRUE(null_callback_.is_null());
83   EXPECT_FALSE(callback_a_.is_null());
84   EXPECT_FALSE(callback_b_.is_null());
85 }
86
87 TEST_F(CallbackTest, Equals) {
88   EXPECT_EQ(callback_a_, callback_a_);
89   EXPECT_NE(callback_a_, callback_b_);
90   EXPECT_NE(callback_b_, callback_a_);
91
92   // We should compare based on instance, not type.
93   RepeatingCallback<void()> callback_c(new FakeBindState());
94   RepeatingCallback<void()> callback_a2 = callback_a_;
95   EXPECT_EQ(callback_a_, callback_a2);
96   EXPECT_NE(callback_a_, callback_c);
97
98   // Empty, however, is always equal to empty.
99   RepeatingCallback<void()> empty2;
100   EXPECT_EQ(null_callback_, empty2);
101 }
102
103 TEST_F(CallbackTest, Reset) {
104   // Resetting should bring us back to empty.
105   ASSERT_FALSE(callback_a_.is_null());
106   EXPECT_NE(callback_a_, null_callback_);
107
108   callback_a_.Reset();
109
110   EXPECT_TRUE(callback_a_.is_null());
111   EXPECT_EQ(callback_a_, null_callback_);
112 }
113
114 TEST_F(CallbackTest, Move) {
115   // Moving should reset the callback.
116   ASSERT_FALSE(callback_a_.is_null());
117   EXPECT_NE(callback_a_, null_callback_);
118
119   auto tmp = std::move(callback_a_);
120
121   EXPECT_TRUE(callback_a_.is_null());
122   EXPECT_EQ(callback_a_, null_callback_);
123 }
124
125 TEST_F(CallbackTest, NullAfterMoveRun) {
126   RepeatingCallback<void(void*)> cb = BindRepeating([](void* param) {
127     EXPECT_TRUE(static_cast<RepeatingCallback<void(void*)>*>(param)->is_null());
128   });
129   ASSERT_TRUE(cb);
130   std::move(cb).Run(&cb);
131   EXPECT_FALSE(cb);
132
133   const RepeatingClosure cb2 = BindRepeating([] {});
134   ASSERT_TRUE(cb2);
135   std::move(cb2).Run();
136   EXPECT_TRUE(cb2);
137
138   OnceCallback<void(void*)> cb3 = BindOnce([](void* param) {
139     EXPECT_TRUE(static_cast<OnceCallback<void(void*)>*>(param)->is_null());
140   });
141   ASSERT_TRUE(cb3);
142   std::move(cb3).Run(&cb3);
143   EXPECT_FALSE(cb3);
144 }
145
146 TEST_F(CallbackTest, MaybeValidReturnsTrue) {
147   RepeatingCallback<void()> cb = BindRepeating([]() {});
148   // By default, MaybeValid() just returns true all the time.
149   EXPECT_TRUE(cb.MaybeValid());
150   cb.Run();
151   EXPECT_TRUE(cb.MaybeValid());
152 }
153
154 // WeakPtr detection in BindRepeating() requires a method, not just any
155 // function.
156 class ClassWithAMethod {
157  public:
158   void TheMethod() {}
159 };
160
161 TEST_F(CallbackTest, MaybeValidInvalidateWeakPtrsOnSameSequence) {
162   ClassWithAMethod obj;
163   WeakPtrFactory<ClassWithAMethod> factory(&obj);
164   WeakPtr<ClassWithAMethod> ptr = factory.GetWeakPtr();
165
166   RepeatingCallback<void()> cb =
167       BindRepeating(&ClassWithAMethod::TheMethod, ptr);
168   EXPECT_TRUE(cb.MaybeValid());
169   EXPECT_FALSE(cb.IsCancelled());
170
171   factory.InvalidateWeakPtrs();
172   // MaybeValid() should be false and IsCancelled() should become true because
173   // InvalidateWeakPtrs() was called on the same thread.
174   EXPECT_FALSE(cb.MaybeValid());
175   EXPECT_TRUE(cb.IsCancelled());
176   // is_null() is not affected by the invalidated WeakPtr.
177   EXPECT_FALSE(cb.is_null());
178 }
179
180 TEST_F(CallbackTest, MaybeValidInvalidateWeakPtrsOnOtherSequence) {
181   ClassWithAMethod obj;
182   WeakPtrFactory<ClassWithAMethod> factory(&obj);
183   WeakPtr<ClassWithAMethod> ptr = factory.GetWeakPtr();
184
185   RepeatingCallback<void()> cb =
186       BindRepeating(&ClassWithAMethod::TheMethod, ptr);
187   EXPECT_TRUE(cb.MaybeValid());
188
189   Thread other_thread("other_thread");
190   other_thread.StartAndWaitForTesting();
191   other_thread.task_runner()->PostTask(
192       FROM_HERE,
193       BindOnce(
194           [](RepeatingCallback<void()> cb) {
195             // Check that MaybeValid() _eventually_ returns false.
196             const TimeDelta timeout = TestTimeouts::tiny_timeout();
197             const TimeTicks begin = TimeTicks::Now();
198             while (cb.MaybeValid() && (TimeTicks::Now() - begin) < timeout)
199               PlatformThread::YieldCurrentThread();
200             EXPECT_FALSE(cb.MaybeValid());
201           },
202           cb));
203   factory.InvalidateWeakPtrs();
204   // |other_thread|'s destructor will join, ensuring we wait for the task to be
205   // run.
206 }
207
208 class CallbackOwner : public base::RefCounted<CallbackOwner> {
209  public:
210   explicit CallbackOwner(bool* deleted) {
211     // WrapRefCounted() here is needed to avoid the check failure in the
212     // BindRepeating implementation, that refuses to create the first reference
213     // to ref-counted objects.
214     callback_ = BindRepeating(&CallbackOwner::Unused, WrapRefCounted(this));
215     deleted_ = deleted;
216   }
217   void Reset() {
218     callback_.Reset();
219     // We are deleted here if no-one else had a ref to us.
220   }
221
222  private:
223   friend class base::RefCounted<CallbackOwner>;
224   virtual ~CallbackOwner() {
225     *deleted_ = true;
226   }
227   void Unused() {
228     FAIL() << "Should never be called";
229   }
230
231   RepeatingClosure callback_;
232   bool* deleted_;
233 };
234
235 TEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) {
236   bool deleted = false;
237   CallbackOwner* owner = new CallbackOwner(&deleted);
238   owner->Reset();
239   ASSERT_TRUE(deleted);
240 }
241
242 }  // namespace
243 }  // namespace base