1 | /* |
2 | * Copyright (C) 2013-2017 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | |
28 | #include "RefLogger.h" |
29 | #include "Utilities.h" |
30 | #include <wtf/MainThread.h> |
31 | #include <wtf/NeverDestroyed.h> |
32 | #include <wtf/RefCounted.h> |
33 | #include <wtf/RefPtr.h> |
34 | #include <wtf/RunLoop.h> |
35 | #include <wtf/ThreadSafeRefCounted.h> |
36 | #include <wtf/Threading.h> |
37 | |
38 | namespace TestWebKitAPI { |
39 | |
40 | TEST(WTF_RefPtr, Basic) |
41 | { |
42 | DerivedRefLogger a("a" ); |
43 | |
44 | RefPtr<RefLogger> empty; |
45 | EXPECT_EQ(nullptr, empty.get()); |
46 | |
47 | { |
48 | RefPtr<RefLogger> ptr(&a); |
49 | EXPECT_EQ(&a, ptr.get()); |
50 | EXPECT_EQ(&a, &*ptr); |
51 | EXPECT_EQ(&a.name, &ptr->name); |
52 | } |
53 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
54 | |
55 | { |
56 | RefPtr<RefLogger> ptr = &a; |
57 | EXPECT_EQ(&a, ptr.get()); |
58 | } |
59 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
60 | |
61 | { |
62 | RefPtr<RefLogger> p1 = &a; |
63 | RefPtr<RefLogger> p2(p1); |
64 | EXPECT_EQ(&a, p1.get()); |
65 | EXPECT_EQ(&a, p2.get()); |
66 | } |
67 | EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) " , takeLogStr().c_str()); |
68 | |
69 | { |
70 | RefPtr<RefLogger> p1 = &a; |
71 | RefPtr<RefLogger> p2 = p1; |
72 | EXPECT_EQ(&a, p1.get()); |
73 | EXPECT_EQ(&a, p2.get()); |
74 | } |
75 | EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) " , takeLogStr().c_str()); |
76 | |
77 | { |
78 | RefPtr<RefLogger> p1 = &a; |
79 | RefPtr<RefLogger> p2 = WTFMove(p1); |
80 | EXPECT_EQ(nullptr, p1.get()); |
81 | EXPECT_EQ(&a, p2.get()); |
82 | } |
83 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
84 | |
85 | { |
86 | RefPtr<RefLogger> p1 = &a; |
87 | RefPtr<RefLogger> p2(WTFMove(p1)); |
88 | EXPECT_EQ(nullptr, p1.get()); |
89 | EXPECT_EQ(&a, p2.get()); |
90 | } |
91 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
92 | |
93 | { |
94 | RefPtr<DerivedRefLogger> p1 = &a; |
95 | RefPtr<RefLogger> p2 = p1; |
96 | EXPECT_EQ(&a, p1.get()); |
97 | EXPECT_EQ(&a, p2.get()); |
98 | } |
99 | EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) " , takeLogStr().c_str()); |
100 | |
101 | { |
102 | RefPtr<DerivedRefLogger> p1 = &a; |
103 | RefPtr<RefLogger> p2 = WTFMove(p1); |
104 | EXPECT_EQ(nullptr, p1.get()); |
105 | EXPECT_EQ(&a, p2.get()); |
106 | } |
107 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
108 | |
109 | { |
110 | RefPtr<RefLogger> ptr(&a); |
111 | EXPECT_EQ(&a, ptr.get()); |
112 | ptr = nullptr; |
113 | EXPECT_EQ(nullptr, ptr.get()); |
114 | } |
115 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
116 | } |
117 | |
118 | TEST(WTF_RefPtr, AssignPassRefToRefPtr) |
119 | { |
120 | DerivedRefLogger a("a" ); |
121 | { |
122 | Ref<RefLogger> passRef(a); |
123 | RefPtr<RefLogger> ptr = WTFMove(passRef); |
124 | EXPECT_EQ(&a, ptr.get()); |
125 | } |
126 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
127 | } |
128 | |
129 | TEST(WTF_RefPtr, Adopt) |
130 | { |
131 | DerivedRefLogger a("a" ); |
132 | |
133 | RefPtr<RefLogger> empty; |
134 | EXPECT_EQ(nullptr, empty.get()); |
135 | |
136 | { |
137 | RefPtr<RefLogger> ptr(adoptRef(&a)); |
138 | EXPECT_EQ(&a, ptr.get()); |
139 | EXPECT_EQ(&a, &*ptr); |
140 | EXPECT_EQ(&a.name, &ptr->name); |
141 | } |
142 | EXPECT_STREQ("deref(a) " , takeLogStr().c_str()); |
143 | |
144 | { |
145 | RefPtr<RefLogger> ptr = adoptRef(&a); |
146 | EXPECT_EQ(&a, ptr.get()); |
147 | } |
148 | EXPECT_STREQ("deref(a) " , takeLogStr().c_str()); |
149 | } |
150 | |
151 | TEST(WTF_RefPtr, Assignment) |
152 | { |
153 | DerivedRefLogger a("a" ); |
154 | RefLogger b("b" ); |
155 | DerivedRefLogger c("c" ); |
156 | |
157 | { |
158 | RefPtr<RefLogger> p1(&a); |
159 | RefPtr<RefLogger> p2(&b); |
160 | EXPECT_EQ(&a, p1.get()); |
161 | EXPECT_EQ(&b, p2.get()); |
162 | log() << "| " ; |
163 | p1 = p2; |
164 | EXPECT_EQ(&b, p1.get()); |
165 | EXPECT_EQ(&b, p2.get()); |
166 | log() << "| " ; |
167 | } |
168 | EXPECT_STREQ("ref(a) ref(b) | ref(b) deref(a) | deref(b) deref(b) " , takeLogStr().c_str()); |
169 | |
170 | { |
171 | RefPtr<RefLogger> ptr(&a); |
172 | EXPECT_EQ(&a, ptr.get()); |
173 | log() << "| " ; |
174 | ptr = &b; |
175 | EXPECT_EQ(&b, ptr.get()); |
176 | log() << "| " ; |
177 | } |
178 | EXPECT_STREQ("ref(a) | ref(b) deref(a) | deref(b) " , takeLogStr().c_str()); |
179 | |
180 | { |
181 | RefPtr<RefLogger> ptr(&a); |
182 | EXPECT_EQ(&a, ptr.get()); |
183 | log() << "| " ; |
184 | ptr = adoptRef(&b); |
185 | EXPECT_EQ(&b, ptr.get()); |
186 | log() << "| " ; |
187 | } |
188 | EXPECT_STREQ("ref(a) | deref(a) | deref(b) " , takeLogStr().c_str()); |
189 | |
190 | { |
191 | RefPtr<RefLogger> ptr(&a); |
192 | EXPECT_EQ(&a, ptr.get()); |
193 | ptr = nullptr; |
194 | EXPECT_EQ(nullptr, ptr.get()); |
195 | } |
196 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
197 | |
198 | { |
199 | RefPtr<RefLogger> p1(&a); |
200 | RefPtr<RefLogger> p2(&b); |
201 | EXPECT_EQ(&a, p1.get()); |
202 | EXPECT_EQ(&b, p2.get()); |
203 | log() << "| " ; |
204 | p1 = WTFMove(p2); |
205 | EXPECT_EQ(&b, p1.get()); |
206 | EXPECT_EQ(nullptr, p2.get()); |
207 | log() << "| " ; |
208 | } |
209 | EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) " , takeLogStr().c_str()); |
210 | |
211 | { |
212 | RefPtr<RefLogger> p1(&a); |
213 | RefPtr<DerivedRefLogger> p2(&c); |
214 | EXPECT_EQ(&a, p1.get()); |
215 | EXPECT_EQ(&c, p2.get()); |
216 | log() << "| " ; |
217 | p1 = p2; |
218 | EXPECT_EQ(&c, p1.get()); |
219 | EXPECT_EQ(&c, p2.get()); |
220 | log() << "| " ; |
221 | } |
222 | EXPECT_STREQ("ref(a) ref(c) | ref(c) deref(a) | deref(c) deref(c) " , takeLogStr().c_str()); |
223 | |
224 | { |
225 | RefPtr<RefLogger> ptr(&a); |
226 | EXPECT_EQ(&a, ptr.get()); |
227 | log() << "| " ; |
228 | ptr = &c; |
229 | EXPECT_EQ(&c, ptr.get()); |
230 | log() << "| " ; |
231 | } |
232 | EXPECT_STREQ("ref(a) | ref(c) deref(a) | deref(c) " , takeLogStr().c_str()); |
233 | |
234 | { |
235 | RefPtr<RefLogger> ptr(&a); |
236 | EXPECT_EQ(&a, ptr.get()); |
237 | log() << "| " ; |
238 | ptr = adoptRef(&c); |
239 | EXPECT_EQ(&c, ptr.get()); |
240 | log() << "| " ; |
241 | } |
242 | EXPECT_STREQ("ref(a) | deref(a) | deref(c) " , takeLogStr().c_str()); |
243 | |
244 | { |
245 | RefPtr<RefLogger> p1(&a); |
246 | RefPtr<DerivedRefLogger> p2(&c); |
247 | EXPECT_EQ(&a, p1.get()); |
248 | EXPECT_EQ(&c, p2.get()); |
249 | log() << "| " ; |
250 | p1 = WTFMove(p2); |
251 | EXPECT_EQ(&c, p1.get()); |
252 | EXPECT_EQ(nullptr, p2.get()); |
253 | log() << "| " ; |
254 | } |
255 | EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) " , takeLogStr().c_str()); |
256 | |
257 | { |
258 | RefPtr<RefLogger> ptr(&a); |
259 | EXPECT_EQ(&a, ptr.get()); |
260 | log() << "| " ; |
261 | #if COMPILER(CLANG) |
262 | #pragma clang diagnostic push |
263 | #pragma clang diagnostic ignored "-Wunknown-pragmas" |
264 | #pragma clang diagnostic ignored "-Wunknown-warning-option" |
265 | #pragma clang diagnostic ignored "-Wself-assign-overloaded" |
266 | #endif |
267 | ptr = ptr; |
268 | #if COMPILER(CLANG) |
269 | #pragma clang diagnostic pop |
270 | #endif |
271 | EXPECT_EQ(&a, ptr.get()); |
272 | log() << "| " ; |
273 | } |
274 | EXPECT_STREQ("ref(a) | ref(a) deref(a) | deref(a) " , takeLogStr().c_str()); |
275 | |
276 | { |
277 | RefPtr<RefLogger> ptr(&a); |
278 | EXPECT_EQ(&a, ptr.get()); |
279 | #if COMPILER(CLANG) |
280 | #pragma clang diagnostic push |
281 | #pragma clang diagnostic ignored "-Wunknown-pragmas" |
282 | #pragma clang diagnostic ignored "-Wself-move" |
283 | #endif |
284 | ptr = WTFMove(ptr); |
285 | #if COMPILER(CLANG) |
286 | #pragma clang diagnostic pop |
287 | #endif |
288 | EXPECT_EQ(&a, ptr.get()); |
289 | } |
290 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
291 | } |
292 | |
293 | TEST(WTF_RefPtr, Swap) |
294 | { |
295 | RefLogger a("a" ); |
296 | RefLogger b("b" ); |
297 | |
298 | { |
299 | RefPtr<RefLogger> p1(&a); |
300 | RefPtr<RefLogger> p2(&b); |
301 | log() << "| " ; |
302 | EXPECT_EQ(&a, p1.get()); |
303 | EXPECT_EQ(&b, p2.get()); |
304 | p1.swap(p2); |
305 | EXPECT_EQ(&b, p1.get()); |
306 | EXPECT_EQ(&a, p2.get()); |
307 | log() << "| " ; |
308 | } |
309 | EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) " , takeLogStr().c_str()); |
310 | |
311 | { |
312 | RefPtr<RefLogger> p1(&a); |
313 | RefPtr<RefLogger> p2(&b); |
314 | log() << "| " ; |
315 | EXPECT_EQ(&a, p1.get()); |
316 | EXPECT_EQ(&b, p2.get()); |
317 | std::swap(p1, p2); |
318 | EXPECT_EQ(&b, p1.get()); |
319 | EXPECT_EQ(&a, p2.get()); |
320 | log() << "| " ; |
321 | } |
322 | EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) " , takeLogStr().c_str()); |
323 | } |
324 | |
325 | TEST(WTF_RefPtr, ReleaseNonNull) |
326 | { |
327 | RefLogger a("a" ); |
328 | |
329 | { |
330 | RefPtr<RefLogger> refPtr = &a; |
331 | RefPtr<RefLogger> ref = refPtr.releaseNonNull(); |
332 | } |
333 | |
334 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
335 | } |
336 | |
337 | TEST(WTF_RefPtr, Release) |
338 | { |
339 | DerivedRefLogger a("a" ); |
340 | RefLogger b("b" ); |
341 | DerivedRefLogger c("c" ); |
342 | |
343 | { |
344 | RefPtr<RefLogger> p1 = &a; |
345 | RefPtr<RefLogger> p2 = WTFMove(p1); |
346 | EXPECT_EQ(nullptr, p1.get()); |
347 | EXPECT_EQ(&a, p2.get()); |
348 | } |
349 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
350 | |
351 | { |
352 | RefPtr<RefLogger> p1 = &a; |
353 | RefPtr<RefLogger> p2(WTFMove(p1)); |
354 | EXPECT_EQ(nullptr, p1.get()); |
355 | EXPECT_EQ(&a, p2.get()); |
356 | } |
357 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
358 | |
359 | { |
360 | RefPtr<DerivedRefLogger> p1 = &a; |
361 | RefPtr<RefLogger> p2 = WTFMove(p1); |
362 | EXPECT_EQ(nullptr, p1.get()); |
363 | EXPECT_EQ(&a, p2.get()); |
364 | } |
365 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
366 | |
367 | { |
368 | RefPtr<RefLogger> p1(&a); |
369 | RefPtr<RefLogger> p2(&b); |
370 | EXPECT_EQ(&a, p1.get()); |
371 | EXPECT_EQ(&b, p2.get()); |
372 | log() << "| " ; |
373 | p1 = WTFMove(p2); |
374 | EXPECT_EQ(&b, p1.get()); |
375 | EXPECT_EQ(nullptr, p2.get()); |
376 | log() << "| " ; |
377 | } |
378 | EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) " , takeLogStr().c_str()); |
379 | |
380 | { |
381 | RefPtr<RefLogger> p1(&a); |
382 | RefPtr<DerivedRefLogger> p2(&c); |
383 | EXPECT_EQ(&a, p1.get()); |
384 | EXPECT_EQ(&c, p2.get()); |
385 | log() << "| " ; |
386 | p1 = WTFMove(p2); |
387 | EXPECT_EQ(&c, p1.get()); |
388 | EXPECT_EQ(nullptr, p2.get()); |
389 | log() << "| " ; |
390 | } |
391 | EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) " , takeLogStr().c_str()); |
392 | } |
393 | |
394 | RefPtr<RefLogger> f1(RefLogger& logger) |
395 | { |
396 | return RefPtr<RefLogger>(&logger); |
397 | } |
398 | |
399 | TEST(WTF_RefPtr, ReturnValue) |
400 | { |
401 | DerivedRefLogger a("a" ); |
402 | |
403 | { |
404 | f1(a); |
405 | } |
406 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
407 | |
408 | { |
409 | auto ptr = f1(a); |
410 | } |
411 | EXPECT_STREQ("ref(a) deref(a) " , takeLogStr().c_str()); |
412 | } |
413 | |
414 | struct ConstRefCounted : RefCounted<ConstRefCounted> { |
415 | static Ref<ConstRefCounted> create() { return adoptRef(*new ConstRefCounted); } |
416 | }; |
417 | |
418 | const ConstRefCounted& returnConstRefCountedRef() |
419 | { |
420 | static NeverDestroyed<ConstRefCounted> instance; |
421 | return instance.get(); |
422 | } |
423 | ConstRefCounted& returnRefCountedRef() |
424 | { |
425 | static NeverDestroyed<ConstRefCounted> instance; |
426 | return instance.get(); |
427 | } |
428 | |
429 | TEST(WTF_RefPtr, Const) |
430 | { |
431 | // This test passes if it compiles without an error. |
432 | auto a = ConstRefCounted::create(); |
433 | Ref<const ConstRefCounted> b = WTFMove(a); |
434 | RefPtr<const ConstRefCounted> c = b.ptr(); |
435 | Ref<const ConstRefCounted> d = returnConstRefCountedRef(); |
436 | RefPtr<const ConstRefCounted> e = &returnConstRefCountedRef(); |
437 | RefPtr<ConstRefCounted> f = ConstRefCounted::create(); |
438 | RefPtr<const ConstRefCounted> g = f; |
439 | RefPtr<const ConstRefCounted> h(f); |
440 | Ref<const ConstRefCounted> i(returnRefCountedRef()); |
441 | } |
442 | |
443 | struct RefPtrCheckingRefLogger : RefLogger { |
444 | RefPtrCheckingRefLogger(const char* name); |
445 | void ref(); |
446 | void deref(); |
447 | const RefPtr<RefPtrCheckingRefLogger>* slotToCheck { nullptr }; |
448 | }; |
449 | |
450 | RefPtrCheckingRefLogger::RefPtrCheckingRefLogger(const char* name) |
451 | : RefLogger { name } |
452 | { |
453 | } |
454 | |
455 | static const char* loggerName(const RefPtr<RefPtrCheckingRefLogger>& pointer) |
456 | { |
457 | return pointer ? &pointer->name : "null" ; |
458 | } |
459 | |
460 | void RefPtrCheckingRefLogger::ref() |
461 | { |
462 | if (slotToCheck) |
463 | log() << "slot=" << loggerName(*slotToCheck) << " " ; |
464 | RefLogger::ref(); |
465 | } |
466 | |
467 | void RefPtrCheckingRefLogger::deref() |
468 | { |
469 | if (slotToCheck) |
470 | log() << "slot=" << loggerName(*slotToCheck) << " " ; |
471 | RefLogger::deref(); |
472 | } |
473 | |
474 | TEST(WTF_RefPtr, AssignBeforeDeref) |
475 | { |
476 | RefPtrCheckingRefLogger a("a" ); |
477 | RefPtrCheckingRefLogger b("b" ); |
478 | |
479 | { |
480 | RefPtr<RefPtrCheckingRefLogger> p1(&a); |
481 | RefPtr<RefPtrCheckingRefLogger> p2(&b); |
482 | EXPECT_EQ(&a, p1.get()); |
483 | EXPECT_EQ(&b, p2.get()); |
484 | log() << "| " ; |
485 | a.slotToCheck = &p1; |
486 | b.slotToCheck = &p1; |
487 | p1 = p2; |
488 | a.slotToCheck = nullptr; |
489 | b.slotToCheck = nullptr; |
490 | EXPECT_EQ(&b, p1.get()); |
491 | EXPECT_EQ(&b, p2.get()); |
492 | log() << "| " ; |
493 | } |
494 | EXPECT_STREQ("ref(a) ref(b) | slot=a ref(b) slot=b deref(a) | deref(b) deref(b) " , takeLogStr().c_str()); |
495 | |
496 | { |
497 | RefPtr<RefPtrCheckingRefLogger> ptr(&a); |
498 | EXPECT_EQ(&a, ptr.get()); |
499 | log() << "| " ; |
500 | a.slotToCheck = &ptr; |
501 | b.slotToCheck = &ptr; |
502 | ptr = &b; |
503 | a.slotToCheck = nullptr; |
504 | b.slotToCheck = nullptr; |
505 | EXPECT_EQ(&b, ptr.get()); |
506 | log() << "| " ; |
507 | } |
508 | EXPECT_STREQ("ref(a) | slot=a ref(b) slot=b deref(a) | deref(b) " , takeLogStr().c_str()); |
509 | |
510 | { |
511 | RefPtr<RefPtrCheckingRefLogger> ptr(&a); |
512 | EXPECT_EQ(&a, ptr.get()); |
513 | a.slotToCheck = &ptr; |
514 | ptr = nullptr; |
515 | a.slotToCheck = nullptr; |
516 | EXPECT_EQ(nullptr, ptr.get()); |
517 | } |
518 | EXPECT_STREQ("ref(a) slot=null deref(a) " , takeLogStr().c_str()); |
519 | |
520 | { |
521 | RefPtr<RefPtrCheckingRefLogger> p1(&a); |
522 | RefPtr<RefPtrCheckingRefLogger> p2(&b); |
523 | EXPECT_EQ(&a, p1.get()); |
524 | EXPECT_EQ(&b, p2.get()); |
525 | log() << "| " ; |
526 | a.slotToCheck = &p1; |
527 | b.slotToCheck = &p1; |
528 | p1 = WTFMove(p2); |
529 | a.slotToCheck = nullptr; |
530 | b.slotToCheck = nullptr; |
531 | EXPECT_EQ(&b, p1.get()); |
532 | EXPECT_EQ(nullptr, p2.get()); |
533 | log() << "| " ; |
534 | } |
535 | EXPECT_STREQ("ref(a) ref(b) | slot=b deref(a) | deref(b) " , takeLogStr().c_str()); |
536 | } |
537 | |
538 | TEST(WTF_RefPtr, ReleaseNonNullBeforeDeref) |
539 | { |
540 | RefPtrCheckingRefLogger a("a" ); |
541 | |
542 | { |
543 | RefPtr<RefPtrCheckingRefLogger> refPtr = &a; |
544 | a.slotToCheck = &refPtr; |
545 | refPtr.releaseNonNull(); |
546 | a.slotToCheck = nullptr; |
547 | } |
548 | |
549 | EXPECT_STREQ("ref(a) slot=null deref(a) " , takeLogStr().c_str()); |
550 | } |
551 | |
552 | // FIXME: Enable these tests once Win platform supports TestWebKitAPI::Util::run |
553 | #if! PLATFORM(WIN) |
554 | |
555 | static bool done; |
556 | static bool isDestroyedInMainThread; |
557 | struct ThreadSafeRefCountedObject : ThreadSafeRefCounted<ThreadSafeRefCountedObject> { |
558 | static Ref<ThreadSafeRefCountedObject> create() { return adoptRef(*new ThreadSafeRefCountedObject); } |
559 | |
560 | ~ThreadSafeRefCountedObject() |
561 | { |
562 | isDestroyedInMainThread = isMainThread(); |
563 | done = true; |
564 | } |
565 | }; |
566 | |
567 | struct MainThreadSafeRefCountedObject : ThreadSafeRefCounted<MainThreadSafeRefCountedObject, WTF::DestructionThread::Main> { |
568 | static Ref<MainThreadSafeRefCountedObject> create() { return adoptRef(*new MainThreadSafeRefCountedObject); } |
569 | |
570 | ~MainThreadSafeRefCountedObject() |
571 | { |
572 | isDestroyedInMainThread = isMainThread(); |
573 | done = true; |
574 | } |
575 | }; |
576 | |
577 | TEST(WTF_RefPtr, ReleaseInNonMainThread) |
578 | { |
579 | done = false; |
580 | Thread::create("" , [object = ThreadSafeRefCountedObject::create()] { }); |
581 | TestWebKitAPI::Util::run(&done); |
582 | |
583 | EXPECT_FALSE(isDestroyedInMainThread); |
584 | } |
585 | |
586 | TEST(WTF_RefPtr, ReleaseInNonMainThreadDestroyInMainThread) |
587 | { |
588 | RunLoop::initializeMainRunLoop(); |
589 | done = false; |
590 | Thread::create("" , [object = MainThreadSafeRefCountedObject::create()] { }); |
591 | TestWebKitAPI::Util::run(&done); |
592 | |
593 | EXPECT_TRUE(isDestroyedInMainThread); |
594 | } |
595 | |
596 | #endif |
597 | |
598 | } // namespace TestWebKitAPI |
599 | |