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