blob: 75a202bccd8381c94260f996d83348ec15fd0c05 [file] [log] [blame]
Danil Chapovalovba916b72019-11-12 10:24:43 +01001/*
2 * Copyright 2019 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 "api/scoped_refptr.h"
12
13#include <utility>
14#include <vector>
15
16#include "test/gtest.h"
17
18namespace rtc {
19namespace {
20
21struct FunctionsCalled {
22 int addref = 0;
23 int release = 0;
24};
25
26class ScopedRefCounted {
27 public:
28 explicit ScopedRefCounted(FunctionsCalled* called) : called_(*called) {}
29 ScopedRefCounted(const ScopedRefCounted&) = delete;
30 ScopedRefCounted& operator=(const ScopedRefCounted&) = delete;
31
32 void AddRef() {
33 ++called_.addref;
34 ++ref_count_;
35 }
36 void Release() {
37 ++called_.release;
38 if (0 == --ref_count_)
39 delete this;
40 }
41
42 private:
43 ~ScopedRefCounted() = default;
44
45 FunctionsCalled& called_;
46 int ref_count_ = 0;
47};
48
49TEST(ScopedRefptrTest, IsCopyConstructable) {
50 FunctionsCalled called;
51 scoped_refptr<ScopedRefCounted> ptr = new ScopedRefCounted(&called);
52 scoped_refptr<ScopedRefCounted> another_ptr = ptr;
53
54 EXPECT_TRUE(ptr);
55 EXPECT_TRUE(another_ptr);
56 EXPECT_EQ(called.addref, 2);
57}
58
59TEST(ScopedRefptrTest, IsCopyAssignable) {
60 FunctionsCalled called;
61 scoped_refptr<ScopedRefCounted> another_ptr;
62 scoped_refptr<ScopedRefCounted> ptr = new ScopedRefCounted(&called);
63 another_ptr = ptr;
64
65 EXPECT_TRUE(ptr);
66 EXPECT_TRUE(another_ptr);
67 EXPECT_EQ(called.addref, 2);
68}
69
70TEST(ScopedRefptrTest, IsMoveConstructableWithoutExtraAddRefRelease) {
71 FunctionsCalled called;
72 scoped_refptr<ScopedRefCounted> ptr = new ScopedRefCounted(&called);
73 scoped_refptr<ScopedRefCounted> another_ptr = std::move(ptr);
74
75 EXPECT_FALSE(ptr);
76 EXPECT_TRUE(another_ptr);
77 EXPECT_EQ(called.addref, 1);
78 EXPECT_EQ(called.release, 0);
79}
80
81TEST(ScopedRefptrTest, IsMoveAssignableWithoutExtraAddRefRelease) {
82 FunctionsCalled called;
83 scoped_refptr<ScopedRefCounted> another_ptr;
84 scoped_refptr<ScopedRefCounted> ptr = new ScopedRefCounted(&called);
85 another_ptr = std::move(ptr);
86
87 EXPECT_FALSE(ptr);
88 EXPECT_TRUE(another_ptr);
89 EXPECT_EQ(called.addref, 1);
90 EXPECT_EQ(called.release, 0);
91}
92
93TEST(ScopedRefptrTest, MovableDuringVectorReallocation) {
94 static_assert(
95 std::is_nothrow_move_constructible<scoped_refptr<ScopedRefCounted>>(),
96 "");
97 // Test below describes a scenario where it is helpful for move constructor
98 // to be noexcept.
99 FunctionsCalled called;
100 std::vector<scoped_refptr<ScopedRefCounted>> ptrs;
101 ptrs.reserve(1);
102 // Insert more elements than reserved to provoke reallocation.
103 ptrs.push_back(new ScopedRefCounted(&called));
104 ptrs.push_back(new ScopedRefCounted(&called));
105
106 EXPECT_EQ(called.addref, 2);
107 EXPECT_EQ(called.release, 0);
108}
109
110} // namespace
111} // namespace rtc