1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_base/callback.h"
12
13 #include "rtc_base/bind.h"
14 #include "rtc_base/keep_ref_until_done.h"
15 #include "rtc_base/ref_count.h"
16 #include "test/gtest.h"
17
18 namespace rtc {
19
20 namespace {
21
f()22 void f() {}
g()23 int g() {
24 return 42;
25 }
h(int x)26 int h(int x) {
27 return x * x;
28 }
i(int & x)29 void i(int& x) {
30 x *= x;
31 } // NOLINT: Testing refs
32
33 struct BindTester {
artc::__anon257e24250111::BindTester34 int a() { return 24; }
brtc::__anon257e24250111::BindTester35 int b(int x) const { return x * x; }
36 };
37
38 class RefCountedBindTester : public RefCountInterface {
39 public:
RefCountedBindTester()40 RefCountedBindTester() : count_(0) {}
AddRef() const41 void AddRef() const override { ++count_; }
Release() const42 RefCountReleaseStatus Release() const override {
43 --count_;
44 return count_ == 0 ? RefCountReleaseStatus::kDroppedLastRef
45 : RefCountReleaseStatus::kOtherRefsRemained;
46 }
RefCount() const47 int RefCount() const { return count_; }
48
49 private:
50 mutable int count_;
51 };
52
53 } // namespace
54
TEST(CallbackTest,VoidReturn)55 TEST(CallbackTest, VoidReturn) {
56 Callback0<void> cb;
57 EXPECT_TRUE(cb.empty());
58 cb(); // Executing an empty callback should not crash.
59 cb = Callback0<void>(&f);
60 EXPECT_FALSE(cb.empty());
61 cb();
62 }
63
TEST(CallbackTest,IntReturn)64 TEST(CallbackTest, IntReturn) {
65 Callback0<int> cb;
66 EXPECT_TRUE(cb.empty());
67 cb = Callback0<int>(&g);
68 EXPECT_FALSE(cb.empty());
69 EXPECT_EQ(42, cb());
70 EXPECT_EQ(42, cb());
71 }
72
TEST(CallbackTest,OneParam)73 TEST(CallbackTest, OneParam) {
74 Callback1<int, int> cb1(&h);
75 EXPECT_FALSE(cb1.empty());
76 EXPECT_EQ(9, cb1(-3));
77 EXPECT_EQ(100, cb1(10));
78
79 // Try clearing a callback.
80 cb1 = Callback1<int, int>();
81 EXPECT_TRUE(cb1.empty());
82
83 // Try a callback with a ref parameter.
84 Callback1<void, int&> cb2(&i);
85 int x = 3;
86 cb2(x);
87 EXPECT_EQ(9, x);
88 cb2(x);
89 EXPECT_EQ(81, x);
90 }
91
TEST(CallbackTest,WithBind)92 TEST(CallbackTest, WithBind) {
93 BindTester t;
94 Callback0<int> cb1 = Bind(&BindTester::a, &t);
95 EXPECT_EQ(24, cb1());
96 EXPECT_EQ(24, cb1());
97 cb1 = Bind(&BindTester::b, &t, 10);
98 EXPECT_EQ(100, cb1());
99 EXPECT_EQ(100, cb1());
100 cb1 = Bind(&BindTester::b, &t, 5);
101 EXPECT_EQ(25, cb1());
102 EXPECT_EQ(25, cb1());
103 }
104
TEST(KeepRefUntilDoneTest,simple)105 TEST(KeepRefUntilDoneTest, simple) {
106 RefCountedBindTester t;
107 EXPECT_EQ(0, t.RefCount());
108 {
109 Callback0<void> cb = KeepRefUntilDone(&t);
110 EXPECT_EQ(1, t.RefCount());
111 cb();
112 EXPECT_EQ(1, t.RefCount());
113 cb();
114 EXPECT_EQ(1, t.RefCount());
115 }
116 EXPECT_EQ(0, t.RefCount());
117 }
118
TEST(KeepRefUntilDoneTest,copy)119 TEST(KeepRefUntilDoneTest, copy) {
120 RefCountedBindTester t;
121 EXPECT_EQ(0, t.RefCount());
122 Callback0<void> cb2;
123 {
124 Callback0<void> cb = KeepRefUntilDone(&t);
125 EXPECT_EQ(1, t.RefCount());
126 cb2 = cb;
127 }
128 EXPECT_EQ(1, t.RefCount());
129 cb2 = Callback0<void>();
130 EXPECT_EQ(0, t.RefCount());
131 }
132
TEST(KeepRefUntilDoneTest,scopedref)133 TEST(KeepRefUntilDoneTest, scopedref) {
134 RefCountedBindTester t;
135 EXPECT_EQ(0, t.RefCount());
136 {
137 scoped_refptr<RefCountedBindTester> t_scoped_ref(&t);
138 Callback0<void> cb = KeepRefUntilDone(t_scoped_ref);
139 t_scoped_ref = nullptr;
140 EXPECT_EQ(1, t.RefCount());
141 cb();
142 EXPECT_EQ(1, t.RefCount());
143 }
144 EXPECT_EQ(0, t.RefCount());
145 }
146
147 } // namespace rtc
148