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