2
* Copyright (C) 2019 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
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.
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.
28
#include "RefLogger.h"
29
#include "Utilities.h"
30
#include <wtf/MainThread.h>
31
#include <wtf/NeverDestroyed.h>
32
#include <wtf/PackedRef.h>
33
#include <wtf/PackedRefPtr.h>
34
#include <wtf/RefCounted.h>
35
#include <wtf/RunLoop.h>
36
#include <wtf/ThreadSafeRefCounted.h>
37
#include <wtf/Threading.h>
39
namespace TestWebKitAPI {
41
TEST(WTF_PackedRefPtr, Basic)
43
DerivedRefLogger a("a");
45
PackedRefPtr<RefLogger> empty;
46
EXPECT_EQ(nullptr, empty.get());
49
PackedRefPtr<RefLogger> ptr(&a);
50
EXPECT_EQ(&a, ptr.get());
52
EXPECT_EQ(&a.name, &ptr->name);
54
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
57
PackedRefPtr<RefLogger> ptr = &a;
58
EXPECT_EQ(&a, ptr.get());
60
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
63
PackedRefPtr<RefLogger> p1 = &a;
64
PackedRefPtr<RefLogger> p2(p1);
65
EXPECT_EQ(&a, p1.get());
66
EXPECT_EQ(&a, p2.get());
68
EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
71
PackedRefPtr<RefLogger> p1 = &a;
72
PackedRefPtr<RefLogger> p2 = p1;
73
EXPECT_EQ(&a, p1.get());
74
EXPECT_EQ(&a, p2.get());
76
EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
79
PackedRefPtr<RefLogger> p1 = &a;
80
PackedRefPtr<RefLogger> p2 = WTFMove(p1);
81
EXPECT_EQ(nullptr, p1.get());
82
EXPECT_EQ(&a, p2.get());
84
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
87
PackedRefPtr<RefLogger> p1 = &a;
88
PackedRefPtr<RefLogger> p2(WTFMove(p1));
89
EXPECT_EQ(nullptr, p1.get());
90
EXPECT_EQ(&a, p2.get());
92
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
95
PackedRefPtr<DerivedRefLogger> p1 = &a;
96
PackedRefPtr<RefLogger> p2 = p1;
97
EXPECT_EQ(&a, p1.get());
98
EXPECT_EQ(&a, p2.get());
100
EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
103
PackedRefPtr<DerivedRefLogger> p1 = &a;
104
PackedRefPtr<RefLogger> p2 = WTFMove(p1);
105
EXPECT_EQ(nullptr, p1.get());
106
EXPECT_EQ(&a, p2.get());
108
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
111
PackedRefPtr<RefLogger> ptr(&a);
112
EXPECT_EQ(&a, ptr.get());
114
EXPECT_EQ(nullptr, ptr.get());
116
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
119
TEST(WTF_PackedRefPtr, AssignPassRefToRefPtr)
121
DerivedRefLogger a("a");
123
PackedRef<RefLogger> passRef(a);
124
PackedRefPtr<RefLogger> ptr = WTFMove(passRef);
125
EXPECT_EQ(&a, ptr.get());
127
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
130
TEST(WTF_PackedRefPtr, Adopt)
132
DerivedRefLogger a("a");
134
PackedRefPtr<RefLogger> empty;
135
EXPECT_EQ(nullptr, empty.get());
138
PackedRefPtr<RefLogger> ptr(adoptRef(&a));
139
EXPECT_EQ(&a, ptr.get());
140
EXPECT_EQ(&a, &*ptr);
141
EXPECT_EQ(&a.name, &ptr->name);
143
EXPECT_STREQ("deref(a) ", takeLogStr().c_str());
146
PackedRefPtr<RefLogger> ptr = adoptRef(&a);
147
EXPECT_EQ(&a, ptr.get());
149
EXPECT_STREQ("deref(a) ", takeLogStr().c_str());
152
TEST(WTF_PackedRefPtr, Assignment)
154
DerivedRefLogger a("a");
156
DerivedRefLogger c("c");
159
PackedRefPtr<RefLogger> p1(&a);
160
PackedRefPtr<RefLogger> p2(&b);
161
EXPECT_EQ(&a, p1.get());
162
EXPECT_EQ(&b, p2.get());
165
EXPECT_EQ(&b, p1.get());
166
EXPECT_EQ(&b, p2.get());
169
EXPECT_STREQ("ref(a) ref(b) | ref(b) deref(a) | deref(b) deref(b) ", takeLogStr().c_str());
172
PackedRefPtr<RefLogger> ptr(&a);
173
EXPECT_EQ(&a, ptr.get());
176
EXPECT_EQ(&b, ptr.get());
179
EXPECT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
182
PackedRefPtr<RefLogger> ptr(&a);
183
EXPECT_EQ(&a, ptr.get());
186
EXPECT_EQ(&b, ptr.get());
189
EXPECT_STREQ("ref(a) | deref(a) | deref(b) ", takeLogStr().c_str());
192
PackedRefPtr<RefLogger> ptr(&a);
193
EXPECT_EQ(&a, ptr.get());
195
EXPECT_EQ(nullptr, ptr.get());
197
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
200
PackedRefPtr<RefLogger> p1(&a);
201
PackedRefPtr<RefLogger> p2(&b);
202
EXPECT_EQ(&a, p1.get());
203
EXPECT_EQ(&b, p2.get());
206
EXPECT_EQ(&b, p1.get());
207
EXPECT_EQ(nullptr, p2.get());
210
EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) ", takeLogStr().c_str());
213
PackedRefPtr<RefLogger> p1(&a);
214
PackedRefPtr<DerivedRefLogger> p2(&c);
215
EXPECT_EQ(&a, p1.get());
216
EXPECT_EQ(&c, p2.get());
219
EXPECT_EQ(&c, p1.get());
220
EXPECT_EQ(&c, p2.get());
223
EXPECT_STREQ("ref(a) ref(c) | ref(c) deref(a) | deref(c) deref(c) ", takeLogStr().c_str());
226
PackedRefPtr<RefLogger> ptr(&a);
227
EXPECT_EQ(&a, ptr.get());
230
EXPECT_EQ(&c, ptr.get());
233
EXPECT_STREQ("ref(a) | ref(c) deref(a) | deref(c) ", takeLogStr().c_str());
236
PackedRefPtr<RefLogger> ptr(&a);
237
EXPECT_EQ(&a, ptr.get());
240
EXPECT_EQ(&c, ptr.get());
243
EXPECT_STREQ("ref(a) | deref(a) | deref(c) ", takeLogStr().c_str());
246
PackedRefPtr<RefLogger> p1(&a);
247
PackedRefPtr<DerivedRefLogger> p2(&c);
248
EXPECT_EQ(&a, p1.get());
249
EXPECT_EQ(&c, p2.get());
252
EXPECT_EQ(&c, p1.get());
253
EXPECT_EQ(nullptr, p2.get());
256
EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) ", takeLogStr().c_str());
259
PackedRefPtr<RefLogger> ptr(&a);
260
EXPECT_EQ(&a, ptr.get());
263
#pragma clang diagnostic push
264
#pragma clang diagnostic ignored "-Wunknown-pragmas"
265
#pragma clang diagnostic ignored "-Wunknown-warning-option"
266
#pragma clang diagnostic ignored "-Wself-assign-overloaded"
270
#pragma clang diagnostic pop
272
EXPECT_EQ(&a, ptr.get());
275
EXPECT_STREQ("ref(a) | ref(a) deref(a) | deref(a) ", takeLogStr().c_str());
278
PackedRefPtr<RefLogger> ptr(&a);
279
EXPECT_EQ(&a, ptr.get());
281
#pragma clang diagnostic push
282
#pragma clang diagnostic ignored "-Wunknown-pragmas"
283
#pragma clang diagnostic ignored "-Wself-move"
287
#pragma clang diagnostic pop
289
EXPECT_EQ(&a, ptr.get());
291
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
294
TEST(WTF_PackedRefPtr, Swap)
300
PackedRefPtr<RefLogger> p1(&a);
301
PackedRefPtr<RefLogger> p2(&b);
303
EXPECT_EQ(&a, p1.get());
304
EXPECT_EQ(&b, p2.get());
306
EXPECT_EQ(&b, p1.get());
307
EXPECT_EQ(&a, p2.get());
310
EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
313
PackedRefPtr<RefLogger> p1(&a);
314
PackedRefPtr<RefLogger> p2(&b);
316
EXPECT_EQ(&a, p1.get());
317
EXPECT_EQ(&b, p2.get());
319
EXPECT_EQ(&b, p1.get());
320
EXPECT_EQ(&a, p2.get());
323
EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
326
TEST(WTF_PackedRefPtr, ReleaseNonNull)
331
PackedRefPtr<RefLogger> refPtr = &a;
332
PackedRefPtr<RefLogger> ref = refPtr.releaseNonNull();
335
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
338
TEST(WTF_PackedRefPtr, Release)
340
DerivedRefLogger a("a");
342
DerivedRefLogger c("c");
345
PackedRefPtr<RefLogger> p1 = &a;
346
PackedRefPtr<RefLogger> p2 = WTFMove(p1);
347
EXPECT_EQ(nullptr, p1.get());
348
EXPECT_EQ(&a, p2.get());
350
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
353
PackedRefPtr<RefLogger> p1 = &a;
354
PackedRefPtr<RefLogger> p2(WTFMove(p1));
355
EXPECT_EQ(nullptr, p1.get());
356
EXPECT_EQ(&a, p2.get());
358
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
361
PackedRefPtr<DerivedRefLogger> p1 = &a;
362
PackedRefPtr<RefLogger> p2 = WTFMove(p1);
363
EXPECT_EQ(nullptr, p1.get());
364
EXPECT_EQ(&a, p2.get());
366
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
369
PackedRefPtr<RefLogger> p1(&a);
370
PackedRefPtr<RefLogger> p2(&b);
371
EXPECT_EQ(&a, p1.get());
372
EXPECT_EQ(&b, p2.get());
375
EXPECT_EQ(&b, p1.get());
376
EXPECT_EQ(nullptr, p2.get());
379
EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) ", takeLogStr().c_str());
382
PackedRefPtr<RefLogger> p1(&a);
383
PackedRefPtr<DerivedRefLogger> p2(&c);
384
EXPECT_EQ(&a, p1.get());
385
EXPECT_EQ(&c, p2.get());
388
EXPECT_EQ(&c, p1.get());
389
EXPECT_EQ(nullptr, p2.get());
392
EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) ", takeLogStr().c_str());
395
static RefPtr<RefLogger> f1(RefLogger& logger)
397
return PackedRefPtr<RefLogger>(&logger);
400
TEST(WTF_PackedRefPtr, ReturnValue)
402
DerivedRefLogger a("a");
407
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
412
EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
415
struct ConstRefCounted : RefCounted<ConstRefCounted> {
416
static Ref<ConstRefCounted> create() { return adoptRef(*new ConstRefCounted); }
419
static const ConstRefCounted& returnConstRefCountedRef()
421
static NeverDestroyed<ConstRefCounted> instance;
422
return instance.get();
424
static ConstRefCounted& returnRefCountedRef()
426
static NeverDestroyed<ConstRefCounted> instance;
427
return instance.get();
430
TEST(WTF_PackedRefPtr, Const)
432
// This test passes if it compiles without an error.
433
auto a = ConstRefCounted::create();
434
PackedRef<const ConstRefCounted> b = WTFMove(a);
435
PackedRefPtr<const ConstRefCounted> c = b.ptr();
436
PackedRef<const ConstRefCounted> d = returnConstRefCountedRef();
437
PackedRefPtr<const ConstRefCounted> e = &returnConstRefCountedRef();
438
PackedRefPtr<ConstRefCounted> f = ConstRefCounted::create();
439
PackedRefPtr<const ConstRefCounted> g = f;
440
PackedRefPtr<const ConstRefCounted> h(f);
441
PackedRef<const ConstRefCounted> i(returnRefCountedRef());
444
struct PackedRefPtrCheckingRefLogger : RefLogger {
445
PackedRefPtrCheckingRefLogger(const char* name);
448
const PackedRefPtr<PackedRefPtrCheckingRefLogger>* slotToCheck { nullptr };
451
PackedRefPtrCheckingRefLogger::PackedRefPtrCheckingRefLogger(const char* name)
456
static const char* loggerName(const PackedRefPtr<PackedRefPtrCheckingRefLogger>& pointer)
458
return pointer ? &pointer->name : "null";
461
void PackedRefPtrCheckingRefLogger::ref()
464
log() << "slot=" << loggerName(*slotToCheck) << " ";
468
void PackedRefPtrCheckingRefLogger::deref()
471
log() << "slot=" << loggerName(*slotToCheck) << " ";
475
TEST(WTF_PackedRefPtr, AssignBeforeDeref)
477
PackedRefPtrCheckingRefLogger a("a");
478
PackedRefPtrCheckingRefLogger b("b");
481
PackedRefPtr<PackedRefPtrCheckingRefLogger> p1(&a);
482
PackedRefPtr<PackedRefPtrCheckingRefLogger> p2(&b);
483
EXPECT_EQ(&a, p1.get());
484
EXPECT_EQ(&b, p2.get());
489
a.slotToCheck = nullptr;
490
b.slotToCheck = nullptr;
491
EXPECT_EQ(&b, p1.get());
492
EXPECT_EQ(&b, p2.get());
495
EXPECT_STREQ("ref(a) ref(b) | slot=a ref(b) slot=b deref(a) | deref(b) deref(b) ", takeLogStr().c_str());
498
PackedRefPtr<PackedRefPtrCheckingRefLogger> ptr(&a);
499
EXPECT_EQ(&a, ptr.get());
501
a.slotToCheck = &ptr;
502
b.slotToCheck = &ptr;
504
a.slotToCheck = nullptr;
505
b.slotToCheck = nullptr;
506
EXPECT_EQ(&b, ptr.get());
509
EXPECT_STREQ("ref(a) | slot=a ref(b) slot=b deref(a) | deref(b) ", takeLogStr().c_str());
512
PackedRefPtr<PackedRefPtrCheckingRefLogger> ptr(&a);
513
EXPECT_EQ(&a, ptr.get());
514
a.slotToCheck = &ptr;
516
a.slotToCheck = nullptr;
517
EXPECT_EQ(nullptr, ptr.get());
519
EXPECT_STREQ("ref(a) slot=null deref(a) ", takeLogStr().c_str());
522
PackedRefPtr<PackedRefPtrCheckingRefLogger> p1(&a);
523
PackedRefPtr<PackedRefPtrCheckingRefLogger> p2(&b);
524
EXPECT_EQ(&a, p1.get());
525
EXPECT_EQ(&b, p2.get());
530
a.slotToCheck = nullptr;
531
b.slotToCheck = nullptr;
532
EXPECT_EQ(&b, p1.get());
533
EXPECT_EQ(nullptr, p2.get());
536
EXPECT_STREQ("ref(a) ref(b) | slot=b deref(a) | deref(b) ", takeLogStr().c_str());
539
TEST(WTF_PackedRefPtr, ReleaseNonNullBeforeDeref)
541
PackedRefPtrCheckingRefLogger a("a");
544
PackedRefPtr<PackedRefPtrCheckingRefLogger> refPtr = &a;
545
a.slotToCheck = &refPtr;
546
refPtr.releaseNonNull();
547
a.slotToCheck = nullptr;
550
EXPECT_STREQ("ref(a) slot=null deref(a) ", takeLogStr().c_str());
553
} // namespace TestWebKitAPI