1 // Copyright 2019 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 "util/weak_ptr.h"
6 
7 #include "gtest/gtest.h"
8 
9 namespace openscreen {
10 namespace {
11 
12 class SomeClass {
13  public:
14   virtual ~SomeClass() = default;
GetValue() const15   virtual int GetValue() const { return 42; }
16 };
17 
18 struct SomeSubclass final : public SomeClass {
19  public:
20   ~SomeSubclass() final = default;
GetValueopenscreen::__anoncc6e1aef0111::SomeSubclass21   int GetValue() const override { return 999; }
22 };
23 
TEST(WeakPtrTest,InteractsWithNullptr)24 TEST(WeakPtrTest, InteractsWithNullptr) {
25   WeakPtr<const int> default_constructed;  // Invoke default constructor.
26   EXPECT_TRUE(default_constructed == nullptr);
27   EXPECT_TRUE(nullptr == default_constructed);
28   EXPECT_FALSE(default_constructed != nullptr);
29   EXPECT_FALSE(nullptr != default_constructed);
30 
31   WeakPtr<const int> null_constructed = nullptr;  // Invoke construct-from-null.
32   EXPECT_TRUE(null_constructed == nullptr);
33   EXPECT_TRUE(nullptr == null_constructed);
34   EXPECT_FALSE(null_constructed != nullptr);
35   EXPECT_FALSE(nullptr != null_constructed);
36 
37   const int foo = 42;
38   WeakPtrFactory<const int> factory(&foo);
39   WeakPtr<const int> not_null = factory.GetWeakPtr();
40   EXPECT_TRUE(not_null != nullptr);
41   EXPECT_TRUE(nullptr != not_null);
42   EXPECT_FALSE(not_null == nullptr);
43   EXPECT_FALSE(nullptr == not_null);
44 }
45 
TEST(WeakPtrTest,CopyConstructsAndAssigns)46 TEST(WeakPtrTest, CopyConstructsAndAssigns) {
47   SomeSubclass foo;
48   WeakPtrFactory<SomeSubclass> factory(&foo);
49 
50   WeakPtr<SomeSubclass> weak_ptr = factory.GetWeakPtr();
51   EXPECT_TRUE(weak_ptr);
52   EXPECT_EQ(&foo, weak_ptr.get());
53 
54   // Normal copy constructor.
55   WeakPtr<SomeSubclass> copied0 = weak_ptr;
56   EXPECT_EQ(&foo, weak_ptr.get());  // Did not mutate original.
57   EXPECT_TRUE(copied0);
58   EXPECT_EQ(&foo, copied0.get());
59 
60   // Copy constructor, adding const qualifier.
61   WeakPtr<const SomeSubclass> copied1 = weak_ptr;
62   EXPECT_EQ(&foo, weak_ptr.get());  // Did not mutate original.
63   EXPECT_TRUE(copied1);
64   EXPECT_EQ(&foo, copied1.get());
65 
66   // Normal copy assignment.
67   WeakPtr<SomeSubclass> assigned0;
68   EXPECT_FALSE(assigned0);
69   assigned0 = copied0;
70   EXPECT_EQ(&foo, copied0.get());  // Did not mutate original.
71   EXPECT_TRUE(assigned0);
72   EXPECT_EQ(&foo, assigned0.get());
73 
74   // Copy assignment, adding const qualifier.
75   WeakPtr<const SomeSubclass> assigned1;
76   EXPECT_FALSE(assigned1);
77   assigned1 = copied0;
78   EXPECT_EQ(&foo, copied0.get());  // Did not mutate original.
79   EXPECT_TRUE(assigned1);
80   EXPECT_EQ(&foo, assigned1.get());
81 
82   // Upcast copy constructor.
83   WeakPtr<SomeClass> copied2 = weak_ptr;
84   EXPECT_EQ(&foo, weak_ptr.get());  // Did not mutate original.
85   EXPECT_TRUE(copied2);
86   EXPECT_EQ(&foo, copied2.get());
87   EXPECT_EQ(999, (*copied2).GetValue());
88   EXPECT_EQ(999, copied2->GetValue());
89 
90   // Upcast copy assignment.
91   WeakPtr<SomeClass> assigned2;
92   EXPECT_FALSE(assigned2);
93   assigned2 = weak_ptr;
94   EXPECT_EQ(&foo, weak_ptr.get());  // Did not mutate original.
95   EXPECT_TRUE(assigned2);
96   EXPECT_EQ(&foo, assigned2.get());
97   EXPECT_EQ(999, (*assigned2).GetValue());
98   EXPECT_EQ(999, assigned2->GetValue());
99 }
100 
TEST(WeakPtrTest,MoveConstructsAndAssigns)101 TEST(WeakPtrTest, MoveConstructsAndAssigns) {
102   SomeSubclass foo;
103   WeakPtrFactory<SomeSubclass> factory(&foo);
104 
105   // Normal move constructor.
106   WeakPtr<SomeSubclass> weak_ptr = factory.GetWeakPtr();
107   WeakPtr<SomeSubclass> moved0 = std::move(weak_ptr);
108   EXPECT_FALSE(weak_ptr);  // Original becomes null.
109   EXPECT_TRUE(moved0);
110   EXPECT_EQ(&foo, moved0.get());
111 
112   // Move constructor, adding const qualifier.
113   weak_ptr = factory.GetWeakPtr();
114   WeakPtr<const SomeSubclass> moved1 = std::move(weak_ptr);
115   EXPECT_FALSE(weak_ptr);  // Original becomes null.
116   EXPECT_TRUE(moved1);
117   EXPECT_EQ(&foo, moved1.get());
118 
119   // Normal move assignment.
120   weak_ptr = factory.GetWeakPtr();
121   WeakPtr<SomeSubclass> assigned0;
122   EXPECT_FALSE(assigned0);
123   assigned0 = std::move(weak_ptr);
124   EXPECT_FALSE(weak_ptr);  // Original becomes null.
125   EXPECT_TRUE(assigned0);
126   EXPECT_EQ(&foo, assigned0.get());
127 
128   // Move assignment, adding const qualifier.
129   weak_ptr = factory.GetWeakPtr();
130   WeakPtr<const SomeSubclass> assigned1;
131   EXPECT_FALSE(assigned1);
132   assigned1 = std::move(weak_ptr);
133   EXPECT_FALSE(weak_ptr);  // Original becomes null.
134   EXPECT_TRUE(assigned1);
135   EXPECT_EQ(&foo, assigned1.get());
136 
137   // Upcast move constructor.
138   weak_ptr = factory.GetWeakPtr();
139   WeakPtr<SomeClass> moved2 = std::move(weak_ptr);
140   EXPECT_FALSE(weak_ptr);  // Original becomes null.
141   EXPECT_TRUE(moved2);
142   EXPECT_EQ(&foo, moved2.get());
143   EXPECT_EQ(999, (*moved2).GetValue());  // Result from subclass's GetValue().
144   EXPECT_EQ(999, moved2->GetValue());    // Result from subclass's GetValue().
145 
146   // Upcast move assignment.
147   weak_ptr = factory.GetWeakPtr();
148   WeakPtr<SomeClass> assigned2;
149   EXPECT_FALSE(assigned2);
150   assigned2 = std::move(weak_ptr);
151   EXPECT_FALSE(weak_ptr);  // Original becomes null.
152   EXPECT_TRUE(assigned2);
153   EXPECT_EQ(&foo, assigned2.get());
154   EXPECT_EQ(999,
155             (*assigned2).GetValue());     // Result from subclass's GetValue().
156   EXPECT_EQ(999, assigned2->GetValue());  // Result from subclass's GetValue().
157 }
158 
TEST(WeakPtrTest,InvalidatesWeakPtrs)159 TEST(WeakPtrTest, InvalidatesWeakPtrs) {
160   const int foo = 1337;
161   WeakPtrFactory<const int> factory(&foo);
162 
163   // Thrice: Create weak pointers and invalidate them. This is done more than
164   // once to confirm the factory can create valid WeakPtrs again after each
165   // InvalidateWeakPtrs() call.
166   for (int i = 0; i < 3; ++i) {
167     // Create three WeakPtrs, two from the factory, one as a copy of another
168     // WeakPtr.
169     WeakPtr<const int> ptr0 = factory.GetWeakPtr();
170     WeakPtr<const int> ptr1 = factory.GetWeakPtr();
171     WeakPtr<const int> ptr2 = ptr1;
172     EXPECT_EQ(&foo, ptr0.get());
173     EXPECT_EQ(&foo, ptr1.get());
174     EXPECT_EQ(&foo, ptr2.get());
175 
176     // Invalidate all outstanding WeakPtrs from the factory, and confirm all
177     // outstanding WeakPtrs become null.
178     factory.InvalidateWeakPtrs();
179     EXPECT_FALSE(ptr0);
180     EXPECT_FALSE(ptr1);
181     EXPECT_FALSE(ptr2);
182   }
183 }
184 
185 }  // namespace
186 }  // namespace openscreen
187