The table head of test freshness page should not scroll with the page.
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WTF / PoisonedUniquePtrForNonTriviallyDestructibleArrays.cpp
1 /*
2  * Copyright (C) 2017-2018 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include <mutex>
29 #include <wtf/PoisonedUniquePtr.h>
30
31 namespace TestWebKitAPI {
32
33 namespace {
34
35 uintptr_t g_poisonA;
36 uintptr_t g_poisonB;
37
38 using PoisonA = Poison<g_poisonA>;
39 using PoisonB = Poison<g_poisonB>;
40
41 static void initializePoisons()
42 {
43     static std::once_flag initializeOnceFlag;
44     std::call_once(initializeOnceFlag, [] {
45         // Make sure we get 2 different poison values.
46         g_poisonA = makePoison();
47         while (!g_poisonB || g_poisonB == g_poisonA)
48             g_poisonB = makePoison();
49     });
50 }
51
52 struct Logger {
53     Logger() { }
54     Logger(const char* name, int& destructCount)
55         : name(name)
56         , destructCount(&destructCount)
57     { }
58
59     ~Logger() { ++(*destructCount); }
60
61     const char* name;
62     int* destructCount;
63 };
64     
65 template<typename T, typename... Arguments>
66 T* makeArray(size_t count, Arguments&&... arguments)
67 {
68     T* result = new T[count];
69     while (count--)
70         new (result + count) T(std::forward<Arguments>(arguments)...);
71     return result;
72 }
73
74 const int arraySize = 5;
75
76 } // anonymous namespace
77
78 TEST(WTF_PoisonedUniquePtrForNonTriviallyDestructibleArrays, DISABLED_Basic)
79 {
80     initializePoisons();
81
82     {
83         PoisonedUniquePtr<PoisonA, Logger[]> empty;
84         ASSERT_EQ(nullptr, empty.unpoisoned());
85         ASSERT_EQ(0u, empty.bits());
86     }
87
88     {
89         int aDestructCount = 0;
90         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
91         {
92             PoisonedUniquePtr<PoisonA, Logger[]> ptr(a);
93             ASSERT_EQ(0, aDestructCount);
94             ASSERT_EQ(a, ptr.unpoisoned());
95             ASSERT_EQ(a, &*ptr);
96             for (auto i = 0; i < arraySize; ++i)
97                 ASSERT_EQ(a[i].name, ptr[i].name);
98
99 #if ENABLE(POISON)
100             uintptr_t ptrBits;
101             std::memcpy(&ptrBits, &ptr, sizeof(ptrBits));
102             ASSERT_TRUE(ptrBits != bitwise_cast<uintptr_t>(a));
103 #if ENABLE(POISON_ASSERTS)
104             ASSERT_TRUE((PoisonedUniquePtr<PoisonA, Logger[]>::isPoisoned(ptrBits)));
105 #endif
106 #endif // ENABLE(POISON)
107         }
108         ASSERT_EQ(arraySize, aDestructCount);
109     }
110
111     {
112         int aDestructCount = 0;
113         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
114         {
115             PoisonedUniquePtr<PoisonA, Logger[]> ptr = a;
116             ASSERT_EQ(0, aDestructCount);
117             ASSERT_EQ(a, ptr.unpoisoned());
118             for (auto i = 0; i < arraySize; ++i)
119                 ASSERT_EQ(a[i].name, ptr[i].name);
120         }
121         ASSERT_EQ(arraySize, aDestructCount);
122     }
123
124     {
125         int aDestructCount = 0;
126         const char* aName = "a";
127         {
128             PoisonedUniquePtr<PoisonA, Logger[]> ptr = PoisonedUniquePtr<PoisonA, Logger[]>::create(arraySize, aName, aDestructCount);
129             ASSERT_EQ(0, aDestructCount);
130             ASSERT_TRUE(nullptr != ptr.unpoisoned());
131             for (auto i = 0; i < arraySize; ++i)
132                 ASSERT_EQ(aName, ptr[i].name);
133         }
134         ASSERT_EQ(arraySize, aDestructCount);
135     }
136
137     {
138         int aDestructCount = 0;
139         int bDestructCount = 0;
140         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
141         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
142         {
143             PoisonedUniquePtr<PoisonA, Logger[]> p1 = a;
144             PoisonedUniquePtr<PoisonA, Logger[]> p2 = WTFMove(p1);
145             ASSERT_EQ(aDestructCount, 0);
146             ASSERT_EQ(nullptr, p1.unpoisoned());
147             ASSERT_EQ(0u, p1.bits());
148             ASSERT_EQ(a, p2.unpoisoned());
149
150             PoisonedUniquePtr<PoisonA, Logger[]> p3 = b;
151             PoisonedUniquePtr<PoisonB, Logger[]> p4 = WTFMove(p3);
152             ASSERT_EQ(0, bDestructCount);
153             ASSERT_EQ(nullptr, p3.unpoisoned());
154             ASSERT_EQ(0u, p3.bits());
155             ASSERT_EQ(b, p4.unpoisoned());
156         }
157         ASSERT_EQ(arraySize, aDestructCount);
158         ASSERT_EQ(arraySize, bDestructCount);
159     }
160
161     {
162         int aDestructCount = 0;
163         int bDestructCount = 0;
164         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
165         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
166         {
167             PoisonedUniquePtr<PoisonA, Logger[]> p1 = a;
168             PoisonedUniquePtr<PoisonA, Logger[]> p2(WTFMove(p1));
169             ASSERT_EQ(0, aDestructCount);
170             ASSERT_EQ(nullptr, p1.unpoisoned());
171             ASSERT_EQ(0u, p1.bits());
172             ASSERT_EQ(a, p2.unpoisoned());
173
174             PoisonedUniquePtr<PoisonA, Logger[]> p3 = b;
175             PoisonedUniquePtr<PoisonB, Logger[]> p4(WTFMove(p3));
176             ASSERT_EQ(0, bDestructCount);
177             ASSERT_EQ(nullptr, p3.unpoisoned());
178             ASSERT_EQ(0u, p3.bits());
179             ASSERT_EQ(b, p4.unpoisoned());
180         }
181         ASSERT_EQ(arraySize, aDestructCount);
182         ASSERT_EQ(arraySize, bDestructCount);
183     }
184
185     {
186         int aDestructCount = 0;
187         int bDestructCount = 0;
188         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
189         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
190         {
191             PoisonedUniquePtr<PoisonA, Logger[]> p1 = a;
192             PoisonedUniquePtr<PoisonA, Logger[]> p2 = WTFMove(p1);
193             ASSERT_EQ(aDestructCount, 0);
194             ASSERT_TRUE(!p1.unpoisoned());
195             ASSERT_TRUE(!p1.bits());
196             ASSERT_EQ(a, p2.unpoisoned());
197
198             PoisonedUniquePtr<PoisonA, Logger[]> p3 = b;
199             PoisonedUniquePtr<PoisonB, Logger[]> p4 = WTFMove(p3);
200             ASSERT_EQ(bDestructCount, 0);
201             ASSERT_TRUE(!p3.unpoisoned());
202             ASSERT_TRUE(!p3.bits());
203             ASSERT_EQ(b, p4.unpoisoned());
204         }
205         ASSERT_EQ(arraySize, aDestructCount);
206         ASSERT_EQ(arraySize, bDestructCount);
207     }
208
209     {
210         int aDestructCount = 0;
211         int bDestructCount = 0;
212         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
213         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
214         {
215             PoisonedUniquePtr<PoisonA, Logger[]> p1 = a;
216             PoisonedUniquePtr<PoisonA, Logger[]> p2(WTFMove(p1));
217             ASSERT_EQ(aDestructCount, 0);
218             ASSERT_TRUE(!p1.unpoisoned());
219             ASSERT_TRUE(!p1.bits());
220             ASSERT_EQ(a, p2.unpoisoned());
221
222             PoisonedUniquePtr<PoisonA, Logger[]> p3 = b;
223             PoisonedUniquePtr<PoisonB, Logger[]> p4(WTFMove(p3));
224             ASSERT_EQ(bDestructCount, 0);
225             ASSERT_TRUE(!p3.unpoisoned());
226             ASSERT_TRUE(!p3.bits());
227             ASSERT_EQ(b, p4.unpoisoned());
228         }
229         ASSERT_EQ(arraySize, aDestructCount);
230         ASSERT_EQ(arraySize, bDestructCount);
231     }
232
233     {
234         int aDestructCount = 0;
235         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
236         {
237             PoisonedUniquePtr<PoisonA, Logger[]> ptr(a);
238             ASSERT_EQ(a, ptr.unpoisoned());
239             ptr.clear();
240             ASSERT_TRUE(!ptr.unpoisoned());
241             ASSERT_TRUE(!ptr.bits());
242             ASSERT_EQ(arraySize, aDestructCount);
243         }
244         ASSERT_EQ(arraySize, aDestructCount);
245     }
246 }
247
248 TEST(WTF_PoisonedUniquePtrForNonTriviallyDestructibleArrays, DISABLED_Assignment)
249 {
250     initializePoisons();
251
252     {
253         int aDestructCount = 0;
254         int bDestructCount = 0;
255         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
256         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
257         {
258             PoisonedUniquePtr<PoisonA, Logger[]> ptr(a);
259             ASSERT_EQ(0, aDestructCount);
260             ASSERT_EQ(0, bDestructCount);
261             ASSERT_EQ(a, ptr.unpoisoned());
262             ptr = b;
263             ASSERT_EQ(arraySize, aDestructCount);
264             ASSERT_EQ(0, bDestructCount);
265             ASSERT_EQ(b, ptr.unpoisoned());
266         }
267         ASSERT_EQ(arraySize, aDestructCount);
268         ASSERT_EQ(arraySize, bDestructCount);
269     }
270
271     {
272         int aDestructCount = 0;
273         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
274         {
275             PoisonedUniquePtr<PoisonA, Logger[]> ptr(a);
276             ASSERT_EQ(0, aDestructCount);
277             ASSERT_EQ(a, ptr.unpoisoned());
278             ptr = nullptr;
279             ASSERT_EQ(arraySize, aDestructCount);
280             ASSERT_EQ(nullptr, ptr.unpoisoned());
281         }
282         ASSERT_EQ(arraySize, aDestructCount);
283     }
284
285     {
286         int aDestructCount = 0;
287         int bDestructCount = 0;
288         int cDestructCount = 0;
289         int dDestructCount = 0;
290         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
291         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
292         Logger* c = makeArray<Logger>(arraySize, "c", cDestructCount);
293         Logger* d = makeArray<Logger>(arraySize, "d", dDestructCount);
294         {
295             PoisonedUniquePtr<PoisonA, Logger[]> p1(a);
296             PoisonedUniquePtr<PoisonA, Logger[]> p2(b);
297             ASSERT_EQ(0, aDestructCount);
298             ASSERT_EQ(0, bDestructCount);
299             ASSERT_EQ(a, p1.unpoisoned());
300             ASSERT_EQ(b, p2.unpoisoned());
301             p1 = WTFMove(p2);
302             ASSERT_EQ(arraySize, aDestructCount);
303             ASSERT_EQ(0, bDestructCount);
304             ASSERT_EQ(b, p1.unpoisoned());
305             ASSERT_EQ(nullptr, p2.unpoisoned());
306
307             PoisonedUniquePtr<PoisonA, Logger[]> p3(c);
308             PoisonedUniquePtr<PoisonB, Logger[]> p4(d);
309             ASSERT_EQ(0, cDestructCount);
310             ASSERT_EQ(0, dDestructCount);
311             ASSERT_EQ(c, p3.unpoisoned());
312             ASSERT_EQ(d, p4.unpoisoned());
313             p3 = WTFMove(p4);
314             ASSERT_EQ(arraySize, cDestructCount);
315             ASSERT_EQ(0, dDestructCount);
316             ASSERT_EQ(d, p3.unpoisoned());
317             ASSERT_EQ(nullptr, p4.unpoisoned());
318         }
319         ASSERT_EQ(arraySize, aDestructCount);
320         ASSERT_EQ(arraySize, bDestructCount);
321         ASSERT_EQ(arraySize, cDestructCount);
322         ASSERT_EQ(arraySize, dDestructCount);
323     }
324
325     {
326         int aDestructCount = 0;
327         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
328         {
329             PoisonedUniquePtr<PoisonA, Logger[]> ptr(a);
330             ASSERT_EQ(0, aDestructCount);
331             ASSERT_EQ(a, ptr.unpoisoned());
332             ptr = a;
333             ASSERT_EQ(0, aDestructCount);
334             ASSERT_EQ(a, ptr.unpoisoned());
335         }
336         ASSERT_EQ(arraySize, aDestructCount);
337     }
338
339     {
340         int aDestructCount = 0;
341         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
342         {
343             PoisonedUniquePtr<PoisonA, Logger[]> ptr(a);
344             ASSERT_EQ(0, aDestructCount);
345             ASSERT_EQ(a, ptr.unpoisoned());
346 #if COMPILER(CLANG)
347 #pragma clang diagnostic push
348 #pragma clang diagnostic ignored "-Wunknown-pragmas"
349 #pragma clang diagnostic ignored "-Wself-move"
350 #endif
351             ptr = WTFMove(ptr);
352 #if COMPILER(CLANG)
353 #pragma clang diagnostic pop
354 #endif
355             ASSERT_EQ(0, aDestructCount);
356             ASSERT_EQ(a, ptr.unpoisoned());
357         }
358         ASSERT_EQ(arraySize, aDestructCount);
359     }
360 }
361
362 TEST(WTF_PoisonedUniquePtrForNonTriviallyDestructibleArrays, DISABLED_Swap)
363 {
364     initializePoisons();
365
366     {
367         int aDestructCount = 0;
368         int bDestructCount = 0;
369         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
370         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
371         {
372             PoisonedUniquePtr<PoisonA, Logger[]> p1 = a;
373             PoisonedUniquePtr<PoisonA, Logger[]> p2;
374             ASSERT_EQ(a, p1.unpoisoned());
375             ASSERT_TRUE(!p2.bits());
376             ASSERT_TRUE(!p2.unpoisoned());
377             p2.swap(p1);
378             ASSERT_EQ(aDestructCount, 0);
379             ASSERT_TRUE(!p1.bits());
380             ASSERT_TRUE(!p1.unpoisoned());
381             ASSERT_EQ(a, p2.unpoisoned());
382
383             PoisonedUniquePtr<PoisonA, Logger[]> p3 = b;
384             PoisonedUniquePtr<PoisonB, Logger[]> p4;
385             ASSERT_EQ(b, p3.unpoisoned());
386             ASSERT_TRUE(!p4.bits());
387             ASSERT_TRUE(!p4.unpoisoned());
388             p4.swap(p3);
389             ASSERT_EQ(0, bDestructCount);
390             ASSERT_TRUE(!p3.bits());
391             ASSERT_TRUE(!p3.unpoisoned());
392             ASSERT_EQ(b, p4.unpoisoned());
393         }
394         ASSERT_EQ(arraySize, aDestructCount);
395         ASSERT_EQ(arraySize, bDestructCount);
396     }
397
398     {
399         int aDestructCount = 0;
400         int bDestructCount = 0;
401         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
402         Logger* b = makeArray<Logger>(arraySize, "b", bDestructCount);
403         {
404             PoisonedUniquePtr<PoisonA, Logger[]> p1 = a;
405             PoisonedUniquePtr<PoisonA, Logger[]> p2;
406             ASSERT_EQ(a, p1.unpoisoned());
407             ASSERT_TRUE(!p2.bits());
408             ASSERT_TRUE(!p2.unpoisoned());
409             swap(p1, p2);
410             ASSERT_EQ(0, aDestructCount);
411             ASSERT_TRUE(!p1.bits());
412             ASSERT_TRUE(!p1.unpoisoned());
413             ASSERT_EQ(a, p2.unpoisoned());
414
415             PoisonedUniquePtr<PoisonA, Logger[]> p3 = b;
416             PoisonedUniquePtr<PoisonB, Logger[]> p4;
417             ASSERT_EQ(b, p3.unpoisoned());
418             ASSERT_TRUE(!p4.bits());
419             ASSERT_TRUE(!p4.unpoisoned());
420             swap(p3, p4);
421             ASSERT_EQ(0, bDestructCount);
422             ASSERT_TRUE(!p3.bits());
423             ASSERT_TRUE(!p3.unpoisoned());
424             ASSERT_EQ(b, p4.unpoisoned());
425         }
426         ASSERT_EQ(arraySize, aDestructCount);
427         ASSERT_EQ(arraySize, bDestructCount);
428     }
429 }
430
431 static PoisonedUniquePtr<PoisonA, Logger[]> poisonedPtrFoo(Logger* array)
432 {
433     return PoisonedUniquePtr<PoisonA, Logger[]>(array);
434 }
435
436 TEST(WTF_PoisonedUniquePtrForNonTriviallyDestructibleArrays, DISABLED_ReturnValue)
437 {
438     initializePoisons();
439
440     {
441         int aDestructCount = 0;
442         Logger* a = makeArray<Logger>(arraySize, "a", aDestructCount);
443         {
444             auto ptr = poisonedPtrFoo(a);
445             ASSERT_EQ(0, aDestructCount);
446             ASSERT_EQ(a, ptr.unpoisoned());
447             ASSERT_EQ(a, &*ptr);
448             for (auto i = 0; i < arraySize; ++i)
449                 ASSERT_EQ(a[i].name, ptr[i].name);
450         }
451         ASSERT_EQ(arraySize, aDestructCount);
452     }
453 }
454
455 } // namespace TestWebKitAPI
456