blob: ae86a4cd062e6fa654d2c87a539a5847052c916a [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/callback.h"
12#include "rtc_base/bind.h"
13#include "rtc_base/gunit.h"
14#include "rtc_base/keep_ref_until_done.h"
15#include "rtc_base/refcount.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000016
17namespace rtc {
18
19namespace {
20
21void f() {}
Yves Gerey665174f2018-06-19 15:03:05 +020022int g() {
23 return 42;
24}
25int h(int x) {
26 return x * x;
27}
28void i(int& x) {
29 x *= x;
30} // NOLINT: Testing refs
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031
32struct BindTester {
33 int a() { return 24; }
34 int b(int x) const { return x * x; }
35};
36
perkj14f41442015-11-30 22:15:45 -080037class RefCountedBindTester : public RefCountInterface {
38 public:
39 RefCountedBindTester() : count_(0) {}
Niels Möller6f72f562017-10-19 13:15:17 +020040 void AddRef() const override { ++count_; }
41 RefCountReleaseStatus Release() const override {
42 --count_;
43 return count_ == 0 ? RefCountReleaseStatus::kDroppedLastRef
44 : RefCountReleaseStatus::kOtherRefsRemained;
perkj14f41442015-11-30 22:15:45 -080045 }
46 int RefCount() const { return count_; }
47
48 private:
49 mutable int count_;
50};
51
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000052} // namespace
53
54TEST(CallbackTest, VoidReturn) {
55 Callback0<void> cb;
56 EXPECT_TRUE(cb.empty());
57 cb(); // Executing an empty callback should not crash.
58 cb = Callback0<void>(&f);
59 EXPECT_FALSE(cb.empty());
60 cb();
61}
62
63TEST(CallbackTest, IntReturn) {
64 Callback0<int> cb;
65 EXPECT_TRUE(cb.empty());
66 cb = Callback0<int>(&g);
67 EXPECT_FALSE(cb.empty());
68 EXPECT_EQ(42, cb());
69 EXPECT_EQ(42, cb());
70}
71
72TEST(CallbackTest, OneParam) {
73 Callback1<int, int> cb1(&h);
74 EXPECT_FALSE(cb1.empty());
75 EXPECT_EQ(9, cb1(-3));
76 EXPECT_EQ(100, cb1(10));
77
78 // Try clearing a callback.
79 cb1 = Callback1<int, int>();
80 EXPECT_TRUE(cb1.empty());
81
82 // Try a callback with a ref parameter.
83 Callback1<void, int&> cb2(&i);
84 int x = 3;
85 cb2(x);
86 EXPECT_EQ(9, x);
87 cb2(x);
88 EXPECT_EQ(81, x);
89}
90
91TEST(CallbackTest, WithBind) {
92 BindTester t;
93 Callback0<int> cb1 = Bind(&BindTester::a, &t);
94 EXPECT_EQ(24, cb1());
95 EXPECT_EQ(24, cb1());
96 cb1 = Bind(&BindTester::b, &t, 10);
97 EXPECT_EQ(100, cb1());
98 EXPECT_EQ(100, cb1());
99 cb1 = Bind(&BindTester::b, &t, 5);
100 EXPECT_EQ(25, cb1());
101 EXPECT_EQ(25, cb1());
102}
103
perkj14f41442015-11-30 22:15:45 -0800104TEST(KeepRefUntilDoneTest, simple) {
105 RefCountedBindTester t;
106 EXPECT_EQ(0, t.RefCount());
107 {
108 Callback0<void> cb = KeepRefUntilDone(&t);
109 EXPECT_EQ(1, t.RefCount());
110 cb();
111 EXPECT_EQ(1, t.RefCount());
112 cb();
113 EXPECT_EQ(1, t.RefCount());
114 }
115 EXPECT_EQ(0, t.RefCount());
116}
117
118TEST(KeepRefUntilDoneTest, copy) {
119 RefCountedBindTester t;
120 EXPECT_EQ(0, t.RefCount());
121 Callback0<void> cb2;
122 {
123 Callback0<void> cb = KeepRefUntilDone(&t);
124 EXPECT_EQ(1, t.RefCount());
125 cb2 = cb;
126 }
127 EXPECT_EQ(1, t.RefCount());
128 cb2 = Callback0<void>();
129 EXPECT_EQ(0, t.RefCount());
130}
131
132TEST(KeepRefUntilDoneTest, scopedref) {
133 RefCountedBindTester t;
134 EXPECT_EQ(0, t.RefCount());
135 {
136 scoped_refptr<RefCountedBindTester> t_scoped_ref(&t);
137 Callback0<void> cb = KeepRefUntilDone(t_scoped_ref);
138 t_scoped_ref = nullptr;
139 EXPECT_EQ(1, t.RefCount());
140 cb();
141 EXPECT_EQ(1, t.RefCount());
142 }
143 EXPECT_EQ(0, t.RefCount());
144}
145
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000146} // namespace rtc