1 | /* |
2 | * Copyright (C) 2016 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 <wtf/CrossThreadTask.h> |
29 | #include <wtf/HashCountedSet.h> |
30 | #include <wtf/text/StringBuilder.h> |
31 | #include <wtf/text/StringHash.h> |
32 | |
33 | namespace TestWebKitAPI { |
34 | |
35 | static size_t totalDestructorCalls; |
36 | static size_t totalIsolatedCopyCalls; |
37 | |
38 | static HashCountedSet<String> defaultConstructorSet; |
39 | static HashCountedSet<String> nameConstructorSet; |
40 | static HashCountedSet<String> copyConstructorSet; |
41 | static HashCountedSet<String> moveConstructorSet; |
42 | |
43 | struct LifetimeLogger { |
44 | LifetimeLogger() |
45 | { |
46 | defaultConstructorSet.add(fullName()); |
47 | } |
48 | |
49 | LifetimeLogger(const char* inputName) |
50 | : name(*inputName) |
51 | { |
52 | nameConstructorSet.add(fullName()); |
53 | } |
54 | |
55 | LifetimeLogger(const LifetimeLogger& other) |
56 | : name(other.name) |
57 | , copyGeneration(other.copyGeneration + 1) |
58 | , moveGeneration(other.moveGeneration) |
59 | { |
60 | copyConstructorSet.add(fullName()); |
61 | } |
62 | |
63 | LifetimeLogger(LifetimeLogger&& other) |
64 | : name(other.name) |
65 | , copyGeneration(other.copyGeneration) |
66 | , moveGeneration(other.moveGeneration + 1) |
67 | { |
68 | moveConstructorSet.add(fullName()); |
69 | } |
70 | |
71 | ~LifetimeLogger() |
72 | { |
73 | ++totalDestructorCalls; |
74 | } |
75 | |
76 | LifetimeLogger isolatedCopy() const |
77 | { |
78 | ++totalIsolatedCopyCalls; |
79 | return LifetimeLogger(*this); |
80 | } |
81 | |
82 | String fullName() |
83 | { |
84 | StringBuilder builder; |
85 | builder.append(&name); |
86 | builder.append("-" ); |
87 | builder.append(String::number(copyGeneration)); |
88 | builder.append("-" ); |
89 | builder.append(String::number(moveGeneration)); |
90 | |
91 | return builder.toString(); |
92 | } |
93 | |
94 | const char& name { *"<default>" }; |
95 | int copyGeneration { 0 }; |
96 | int moveGeneration { 0 }; |
97 | }; |
98 | |
99 | void testFunction(const LifetimeLogger&, const LifetimeLogger&, const LifetimeLogger&) |
100 | { |
101 | // Do nothing - Just need to check the side effects of the arguments getting in here. |
102 | } |
103 | |
104 | TEST(WTF_CrossThreadTask, Basic) |
105 | { |
106 | { |
107 | LifetimeLogger logger1; |
108 | LifetimeLogger logger2(logger1); |
109 | LifetimeLogger logger3("logger" ); |
110 | |
111 | auto task = createCrossThreadTask(testFunction, logger1, logger2, logger3); |
112 | task.performTask(); |
113 | } |
114 | |
115 | ASSERT_EQ(1u, defaultConstructorSet.size()); |
116 | ASSERT_EQ(1u, defaultConstructorSet.count("<default>-0-0" )); |
117 | |
118 | ASSERT_EQ(1u, nameConstructorSet.size()); |
119 | ASSERT_EQ(1u, nameConstructorSet.count("logger-0-0" )); |
120 | |
121 | ASSERT_EQ(3u, copyConstructorSet.size()); |
122 | ASSERT_EQ(1u, copyConstructorSet.count("logger-1-0" )); |
123 | ASSERT_EQ(2u, copyConstructorSet.count("<default>-1-0" )); |
124 | ASSERT_EQ(1u, copyConstructorSet.count("<default>-2-0" )); |
125 | |
126 | #if !COMPILER(MSVC) |
127 | ASSERT_EQ(6u, moveConstructorSet.size()); |
128 | #else |
129 | // The number of times the move constructor is called is different on Windows in this test. |
130 | // This seems to be caused by differences in MSVC's implementation of lambdas or std functions like std::make_tuple. |
131 | ASSERT_EQ(9u, moveConstructorSet.size()); |
132 | #endif |
133 | ASSERT_EQ(1u, moveConstructorSet.count("logger-1-1" )); |
134 | ASSERT_EQ(1u, moveConstructorSet.count("logger-1-2" )); |
135 | ASSERT_EQ(1u, moveConstructorSet.count("<default>-2-1" )); |
136 | ASSERT_EQ(1u, moveConstructorSet.count("<default>-2-2" )); |
137 | ASSERT_EQ(1u, moveConstructorSet.count("<default>-1-1" )); |
138 | ASSERT_EQ(1u, moveConstructorSet.count("<default>-1-2" )); |
139 | |
140 | #if !COMPILER(MSVC) |
141 | ASSERT_EQ(12u, totalDestructorCalls); |
142 | #else |
143 | // Since the move constructor is called 3 more times on Windows (see above), we will have 3 more destructor calls. |
144 | ASSERT_EQ(15u, totalDestructorCalls); |
145 | #endif |
146 | ASSERT_EQ(3u, totalIsolatedCopyCalls); |
147 | |
148 | } |
149 | |
150 | } // namespace TestWebKitAPI |
151 | |