1 | /* |
2 | * Copyright (C) 2015 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 "Test.h" |
29 | #include <wtf/Condition.h> |
30 | #include <wtf/Lock.h> |
31 | #include <wtf/Vector.h> |
32 | #include <wtf/WorkQueue.h> |
33 | #include <string> |
34 | #include <thread> |
35 | |
36 | namespace TestWebKitAPI { |
37 | |
38 | using namespace std::literals::chrono_literals; |
39 | |
40 | static const char* simpleTestLabel = "simpleTest" ; |
41 | static const char* longTestLabel = "longTest" ; |
42 | static const char* thirdTestLabel = "thirdTest" ; |
43 | static const char* dispatchAfterLabel = "dispatchAfter" ; |
44 | |
45 | TEST(WTF_WorkQueue, Simple) |
46 | { |
47 | Lock m_lock; |
48 | Condition m_testCompleted; |
49 | Vector<std::string> m_functionCallOrder; |
50 | |
51 | bool calledSimpleTest = false; |
52 | bool calledLongTest = false; |
53 | bool calledThirdTest = false; |
54 | |
55 | static const char* simpleTestLabel = "simpleTest" ; |
56 | static const char* longTestLabel = "longTest" ; |
57 | static const char* thirdTestLabel = "thirdTest" ; |
58 | |
59 | auto queue = WorkQueue::create("com.apple.WebKit.Test.simple" ); |
60 | int initialRefCount = queue->refCount(); |
61 | EXPECT_EQ(1, initialRefCount); |
62 | |
63 | LockHolder locker(m_lock); |
64 | queue->dispatch([&](void) { |
65 | m_functionCallOrder.append(simpleTestLabel); |
66 | calledSimpleTest = true; |
67 | }); |
68 | |
69 | queue->dispatch([&](void) { |
70 | m_functionCallOrder.append(longTestLabel); |
71 | std::this_thread::sleep_for(100ns); |
72 | calledLongTest = true; |
73 | }); |
74 | |
75 | queue->dispatch([&](void) { |
76 | LockHolder locker(m_lock); |
77 | m_functionCallOrder.append(thirdTestLabel); |
78 | calledThirdTest = true; |
79 | |
80 | EXPECT_TRUE(calledSimpleTest); |
81 | EXPECT_TRUE(calledLongTest); |
82 | EXPECT_TRUE(calledThirdTest); |
83 | |
84 | m_testCompleted.notifyOne(); |
85 | }); |
86 | |
87 | EXPECT_GT(queue->refCount(), 1); |
88 | |
89 | m_testCompleted.wait(m_lock); |
90 | |
91 | EXPECT_TRUE(calledSimpleTest); |
92 | EXPECT_TRUE(calledLongTest); |
93 | EXPECT_TRUE(calledThirdTest); |
94 | |
95 | EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size()); |
96 | EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str()); |
97 | EXPECT_STREQ(longTestLabel, m_functionCallOrder[1].c_str()); |
98 | EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[2].c_str()); |
99 | } |
100 | |
101 | TEST(WTF_WorkQueue, TwoQueues) |
102 | { |
103 | Lock m_lock; |
104 | Condition m_testQueue1Completed, m_testQueue2Completed; |
105 | Vector<std::string> m_functionCallOrder; |
106 | |
107 | bool calledSimpleTest = false; |
108 | bool calledLongTest = false; |
109 | bool calledThirdTest = false; |
110 | |
111 | auto queue1 = WorkQueue::create("com.apple.WebKit.Test.twoQueues1" ); |
112 | auto queue2 = WorkQueue::create("com.apple.WebKit.Test.twoQueues2" ); |
113 | |
114 | EXPECT_EQ(1, queue1->refCount()); |
115 | EXPECT_EQ(1, queue2->refCount()); |
116 | |
117 | LockHolder locker(m_lock); |
118 | |
119 | queue1->dispatch([&](void) { |
120 | m_functionCallOrder.append(simpleTestLabel); |
121 | calledSimpleTest = true; |
122 | }); |
123 | |
124 | queue2->dispatch([&](void) { |
125 | std::this_thread::sleep_for(50ms); |
126 | |
127 | LockHolder locker(m_lock); |
128 | |
129 | // Will fail if queue2 took the mutex before queue1. |
130 | EXPECT_TRUE(calledThirdTest); |
131 | |
132 | m_functionCallOrder.append(longTestLabel); |
133 | calledLongTest = true; |
134 | m_testQueue2Completed.notifyOne(); |
135 | }); |
136 | |
137 | queue1->dispatch([&](void) { |
138 | LockHolder locker(m_lock); |
139 | m_functionCallOrder.append(thirdTestLabel); |
140 | calledThirdTest = true; |
141 | |
142 | m_testQueue1Completed.notifyOne(); |
143 | }); |
144 | |
145 | m_testQueue1Completed.wait(m_lock); |
146 | |
147 | EXPECT_TRUE(calledSimpleTest); |
148 | EXPECT_FALSE(calledLongTest); |
149 | EXPECT_TRUE(calledThirdTest); |
150 | |
151 | m_testQueue2Completed.wait(m_lock); |
152 | |
153 | EXPECT_TRUE(calledSimpleTest); |
154 | EXPECT_TRUE(calledLongTest); |
155 | EXPECT_TRUE(calledThirdTest); |
156 | |
157 | EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size()); |
158 | EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str()); |
159 | EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[1].c_str()); |
160 | EXPECT_STREQ(longTestLabel, m_functionCallOrder[2].c_str()); |
161 | } |
162 | |
163 | TEST(WTF_WorkQueue, DispatchAfter) |
164 | { |
165 | Lock m_lock; |
166 | Condition m_testCompleted, m_dispatchAfterTestCompleted; |
167 | Vector<std::string> m_functionCallOrder; |
168 | |
169 | bool calledSimpleTest = false; |
170 | bool calledDispatchAfterTest = false; |
171 | |
172 | auto queue = WorkQueue::create("com.apple.WebKit.Test.dispatchAfter" ); |
173 | |
174 | LockHolder locker(m_lock); |
175 | |
176 | queue->dispatch([&](void) { |
177 | LockHolder locker(m_lock); |
178 | m_functionCallOrder.append(simpleTestLabel); |
179 | calledSimpleTest = true; |
180 | m_testCompleted.notifyOne(); |
181 | }); |
182 | |
183 | queue->dispatchAfter(500_ms, [&](void) { |
184 | LockHolder locker(m_lock); |
185 | m_functionCallOrder.append(dispatchAfterLabel); |
186 | calledDispatchAfterTest = true; |
187 | m_dispatchAfterTestCompleted.notifyOne(); |
188 | }); |
189 | |
190 | m_testCompleted.wait(m_lock); |
191 | |
192 | EXPECT_TRUE(calledSimpleTest); |
193 | EXPECT_FALSE(calledDispatchAfterTest); |
194 | |
195 | m_dispatchAfterTestCompleted.wait(m_lock); |
196 | |
197 | EXPECT_TRUE(calledSimpleTest); |
198 | EXPECT_TRUE(calledDispatchAfterTest); |
199 | |
200 | EXPECT_EQ(static_cast<size_t>(2), m_functionCallOrder.size()); |
201 | EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str()); |
202 | EXPECT_STREQ(dispatchAfterLabel, m_functionCallOrder[1].c_str()); |
203 | } |
204 | |
205 | TEST(WTF_WorkQueue, DestroyOnSelf) |
206 | { |
207 | Lock lock; |
208 | Condition dispatchAfterTestStarted; |
209 | Condition dispatchAfterTestCompleted; |
210 | bool started = false; |
211 | bool completed = false; |
212 | |
213 | { |
214 | LockHolder locker(lock); |
215 | { |
216 | auto queue = WorkQueue::create("com.apple.WebKit.Test.dispatchAfter" ); |
217 | queue->dispatchAfter(500_ms, [&](void) { |
218 | LockHolder locker(lock); |
219 | dispatchAfterTestStarted.wait(lock, [&] { |
220 | return started; |
221 | }); |
222 | completed = true; |
223 | dispatchAfterTestCompleted.notifyOne(); |
224 | }); |
225 | } |
226 | started = true; |
227 | dispatchAfterTestStarted.notifyOne(); |
228 | } |
229 | { |
230 | LockHolder locker(lock); |
231 | dispatchAfterTestCompleted.wait(lock, [&] { |
232 | return completed; |
233 | }); |
234 | WTF::sleep(100_ms); |
235 | } |
236 | } |
237 | |
238 | } // namespace TestWebKitAPI |
239 | |