Flutter Engine
 
Loading...
Searching...
No Matches
weak_ptr_unittest.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter 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#define FML_USED_ON_EMBEDDER
6
8
9#include <thread>
10#include <utility>
11
15#include "gtest/gtest.h"
16
17namespace fml {
18namespace {
19
20TEST(WeakPtrTest, Basic) {
21 int data = 0;
22 WeakPtrFactory<int> factory(&data);
23 WeakPtr<int> ptr = factory.GetWeakPtr();
24 EXPECT_EQ(&data, ptr.get());
25}
26
27TEST(WeakPtrTest, CopyConstruction) {
28 int data = 0;
29 WeakPtrFactory<int> factory(&data);
30 WeakPtr<int> ptr = factory.GetWeakPtr();
31 const WeakPtr<int>& ptr2(ptr);
32 EXPECT_EQ(&data, ptr.get());
33 EXPECT_EQ(&data, ptr2.get());
34}
35
36TEST(WeakPtrTest, MoveConstruction) {
37 int data = 0;
38 WeakPtrFactory<int> factory(&data);
39 WeakPtr<int> ptr = factory.GetWeakPtr();
40 WeakPtr<int> ptr2(std::move(ptr));
41 // The clang linter flags the method called on the moved-from reference, but
42 // this is testing the move implementation, so it is marked NOLINT.
43 EXPECT_EQ(nullptr, ptr.get()); // NOLINT
44 EXPECT_EQ(&data, ptr2.get());
45}
46
47TEST(WeakPtrTest, CopyAssignment) {
48 int data = 0;
49 WeakPtrFactory<int> factory(&data);
50 WeakPtr<int> ptr = factory.GetWeakPtr();
51 WeakPtr<int> ptr2;
52 EXPECT_EQ(nullptr, ptr2.get());
53 ptr2 = ptr;
54 EXPECT_EQ(&data, ptr.get());
55 EXPECT_EQ(&data, ptr2.get());
56}
57
58TEST(WeakPtrTest, MoveAssignment) {
59 int data = 0;
60 WeakPtrFactory<int> factory(&data);
61 WeakPtr<int> ptr = factory.GetWeakPtr();
62 WeakPtr<int> ptr2;
63 EXPECT_EQ(nullptr, ptr2.get());
64 ptr2 = std::move(ptr);
65 // The clang linter flags the method called on the moved-from reference, but
66 // this is testing the move implementation, so it is marked NOLINT.
67 EXPECT_EQ(nullptr, ptr.get()); // NOLINT
68 EXPECT_EQ(&data, ptr2.get());
69}
70
71TEST(WeakPtrTest, Testable) {
72 int data = 0;
73 WeakPtrFactory<int> factory(&data);
74 WeakPtr<int> ptr;
75 EXPECT_EQ(nullptr, ptr.get());
76 EXPECT_FALSE(ptr);
77 ptr = factory.GetWeakPtr();
78 EXPECT_EQ(&data, ptr.get());
79 EXPECT_TRUE(ptr);
80}
81
82TEST(WeakPtrTest, OutOfScope) {
83 WeakPtr<int> ptr;
84 EXPECT_EQ(nullptr, ptr.get());
85 {
86 int data = 0;
87 WeakPtrFactory<int> factory(&data);
88 ptr = factory.GetWeakPtr();
89 }
90 EXPECT_EQ(nullptr, ptr.get());
91}
92
93TEST(WeakPtrTest, Multiple) {
94 WeakPtr<int> a;
95 WeakPtr<int> b;
96 {
97 int data = 0;
98 WeakPtrFactory<int> factory(&data);
99 a = factory.GetWeakPtr();
100 b = factory.GetWeakPtr();
101 EXPECT_EQ(&data, a.get());
102 EXPECT_EQ(&data, b.get());
103 }
104 EXPECT_EQ(nullptr, a.get());
105 EXPECT_EQ(nullptr, b.get());
106}
107
108TEST(WeakPtrTest, MultipleStaged) {
109 WeakPtr<int> a;
110 {
111 int data = 0;
112 WeakPtrFactory<int> factory(&data);
113 a = factory.GetWeakPtr();
114 {
115 WeakPtr<int> b = factory.GetWeakPtr();
116 }
117 EXPECT_NE(a.get(), nullptr);
118 }
119 EXPECT_EQ(nullptr, a.get());
120}
121
122struct Base {
123 double member = 0.;
124};
125struct Derived : public Base {};
126
127TEST(WeakPtrTest, Dereference) {
128 Base data;
129 data.member = 123456.;
130 WeakPtrFactory<Base> factory(&data);
131 WeakPtr<Base> ptr = factory.GetWeakPtr();
132 EXPECT_EQ(&data, ptr.get());
133 EXPECT_EQ(data.member, (*ptr).member);
134 EXPECT_EQ(data.member, ptr->member);
135}
136
137TEST(WeakPtrTest, UpcastCopyConstruction) {
138 Derived data;
139 WeakPtrFactory<Derived> factory(&data);
140 WeakPtr<Derived> ptr = factory.GetWeakPtr();
141 WeakPtr<Base> ptr2(ptr);
142 EXPECT_EQ(&data, ptr.get());
143 EXPECT_EQ(&data, ptr2.get());
144}
145
146TEST(WeakPtrTest, UpcastMoveConstruction) {
147 Derived data;
148 WeakPtrFactory<Derived> factory(&data);
149 WeakPtr<Derived> ptr = factory.GetWeakPtr();
150 WeakPtr<Base> ptr2(std::move(ptr));
151 // The clang linter flags the method called on the moved-from reference, but
152 // this is testing the move implementation, so it is marked NOLINT.
153 EXPECT_EQ(nullptr, ptr.get()); // NOLINT
154 EXPECT_EQ(&data, ptr2.get());
155}
156
157TEST(WeakPtrTest, UpcastCopyAssignment) {
158 Derived data;
159 WeakPtrFactory<Derived> factory(&data);
160 WeakPtr<Derived> ptr = factory.GetWeakPtr();
161 WeakPtr<Base> ptr2;
162 EXPECT_EQ(nullptr, ptr2.get());
163 ptr2 = ptr;
164 EXPECT_EQ(&data, ptr.get());
165 EXPECT_EQ(&data, ptr2.get());
166}
167
168TEST(WeakPtrTest, UpcastMoveAssignment) {
169 Derived data;
170 WeakPtrFactory<Derived> factory(&data);
171 WeakPtr<Derived> ptr = factory.GetWeakPtr();
172 WeakPtr<Base> ptr2;
173 EXPECT_EQ(nullptr, ptr2.get());
174 ptr2 = std::move(ptr);
175 // The clang linter flags the method called on the moved-from reference, but
176 // this is testing the move implementation, so it is marked NOLINT.
177 EXPECT_EQ(nullptr, ptr.get()); // NOLINT
178 EXPECT_EQ(&data, ptr2.get());
179}
180
181TEST(TaskRunnerAffineWeakPtrTest, ShouldNotCrashIfRunningOnTheSameTaskRunner) {
182 fml::MessageLoop* loop1 = nullptr;
185 std::thread thread1([&loop1, &latch1, &term1]() {
188 latch1.Signal();
189 term1.Wait();
190 });
191
192 fml::MessageLoop* loop2 = nullptr;
195 fml::AutoResetWaitableEvent loop2_task_finish_latch;
196 fml::AutoResetWaitableEvent loop2_task_start_latch;
197 std::thread thread2([&loop2, &latch2, &term2, &loop2_task_finish_latch,
198 &loop2_task_start_latch]() {
200 int data = 0;
201 TaskRunnerAffineWeakPtrFactory<int> factory(&data);
203
204 loop2->GetTaskRunner()->PostTask([&]() {
205 latch2.Signal();
206 loop2_task_start_latch.Wait();
207 TaskRunnerAffineWeakPtr<int> ptr = factory.GetWeakPtr();
208 EXPECT_EQ(*ptr, data);
209 loop2_task_finish_latch.Signal();
210 });
211 loop2->Run();
212 term2.Wait();
213 });
214
215 latch1.Wait();
216 latch2.Wait();
218 fml::TaskQueueId qid2 = loop2->GetTaskRunner()->GetTaskQueueId();
219 const auto raster_thread_merger =
220 fml::MakeRefCounted<fml::RasterThreadMerger>(qid1, qid2);
221 const size_t kNumFramesMerged = 5;
222
223 raster_thread_merger->MergeWithLease(kNumFramesMerged);
224
225 loop2_task_start_latch.Signal();
226 loop2_task_finish_latch.Wait();
227
228 for (size_t i = 0; i < kNumFramesMerged; i++) {
229 ASSERT_TRUE(raster_thread_merger->IsMerged());
230 raster_thread_merger->DecrementLease();
231 }
232
233 ASSERT_FALSE(raster_thread_merger->IsMerged());
234 loop2->Terminate();
235
236 term1.Signal();
237 term2.Signal();
238 thread1.join();
239 thread2.join();
240}
241
242} // namespace
243} // namespace fml
static void EnsureInitializedForCurrentThread()
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
virtual TaskQueueId GetTaskQueueId()
TEST(MallocMapping, EmptyContructor)
std::shared_ptr< const fml::Mapping > data