74f5dc294483cc41ff91f370e5525a91a054365f
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WTF / WorkQueue.cpp
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 static const char* simpleTestLabel = "simpleTest";
39 static const char* longTestLabel = "longTest";
40 static const char* thirdTestLabel = "thirdTest";
41 static const char* dispatchAfterLabel = "dispatchAfter";
42     
43 TEST(WTF_WorkQueue, Simple)
44 {
45     Lock m_lock;
46     Condition m_testCompleted;
47     Vector<std::string> m_functionCallOrder;
48
49     bool calledSimpleTest = false;
50     bool calledLongTest = false;
51     bool calledThirdTest = false;
52
53     static const char* simpleTestLabel = "simpleTest";
54     static const char* longTestLabel = "longTest";
55     static const char* thirdTestLabel = "thirdTest";
56
57     auto queue = WorkQueue::create("com.apple.WebKit.Test.simple");
58     int initialRefCount = queue->refCount();
59     EXPECT_EQ(1, initialRefCount);
60
61     LockHolder locker(m_lock);
62     queue->dispatch([&](void) {
63         m_functionCallOrder.append(simpleTestLabel);
64         calledSimpleTest = true;
65     });
66
67     queue->dispatch([&](void) {
68         m_functionCallOrder.append(longTestLabel);
69         std::this_thread::sleep_for(std::chrono::nanoseconds(100));
70         calledLongTest = true;
71     });
72
73     queue->dispatch([&](void) {
74         LockHolder locker(m_lock);
75         m_functionCallOrder.append(thirdTestLabel);
76         calledThirdTest = true;
77
78         EXPECT_TRUE(calledSimpleTest);
79         EXPECT_TRUE(calledLongTest);
80         EXPECT_TRUE(calledThirdTest);
81         
82         m_testCompleted.notifyOne();
83     });
84
85     EXPECT_GT(queue->refCount(), 1);
86
87     m_testCompleted.wait(m_lock);
88
89     EXPECT_TRUE(calledSimpleTest);
90     EXPECT_TRUE(calledLongTest);
91     EXPECT_TRUE(calledThirdTest);
92
93     EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
94     EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
95     EXPECT_STREQ(longTestLabel, m_functionCallOrder[1].c_str());
96     EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[2].c_str());
97 }
98
99 TEST(WTF_WorkQueue, TwoQueues)
100 {
101     Lock m_lock;
102     Condition m_testQueue1Completed, m_testQueue2Completed;
103     Vector<std::string> m_functionCallOrder;
104
105     bool calledSimpleTest = false;
106     bool calledLongTest = false;
107     bool calledThirdTest = false;
108     
109     auto queue1 = WorkQueue::create("com.apple.WebKit.Test.twoQueues1");
110     auto queue2 = WorkQueue::create("com.apple.WebKit.Test.twoQueues2");
111
112     EXPECT_EQ(1, queue1->refCount());
113     EXPECT_EQ(1, queue2->refCount());
114
115     LockHolder locker(m_lock);
116     
117     queue1->dispatch([&](void) {
118         m_functionCallOrder.append(simpleTestLabel);
119         calledSimpleTest = true;
120     });
121
122     queue2->dispatch([&](void) {
123         std::this_thread::sleep_for(std::chrono::milliseconds(50));
124
125         LockHolder locker(m_lock);
126
127         // Will fail if queue2 took the mutex before queue1.
128         EXPECT_TRUE(calledThirdTest);
129
130         m_functionCallOrder.append(longTestLabel);
131         calledLongTest = true;
132         m_testQueue2Completed.notifyOne();
133     });
134
135     queue1->dispatch([&](void) {
136         LockHolder locker(m_lock);
137         m_functionCallOrder.append(thirdTestLabel);
138         calledThirdTest = true;
139         
140         m_testQueue1Completed.notifyOne();
141     });
142
143     m_testQueue1Completed.wait(m_lock);
144
145     EXPECT_TRUE(calledSimpleTest);
146     EXPECT_FALSE(calledLongTest);
147     EXPECT_TRUE(calledThirdTest);
148
149     m_testQueue2Completed.wait(m_lock);
150
151     EXPECT_TRUE(calledSimpleTest);
152     EXPECT_TRUE(calledLongTest);
153     EXPECT_TRUE(calledThirdTest);
154
155     EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
156     EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
157     EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[1].c_str());
158     EXPECT_STREQ(longTestLabel, m_functionCallOrder[2].c_str());
159 }
160
161 TEST(WTF_WorkQueue, DispatchAfter)
162 {
163     Lock m_lock;
164     Condition m_testCompleted, m_dispatchAfterTestCompleted;
165     Vector<std::string> m_functionCallOrder;
166
167     bool calledSimpleTest = false;
168     bool calledDispatchAfterTest = false;
169
170     auto queue = WorkQueue::create("com.apple.WebKit.Test.dispatchAfter");
171
172     LockHolder locker(m_lock);
173
174     queue->dispatch([&](void) {
175         LockHolder locker(m_lock);
176         m_functionCallOrder.append(simpleTestLabel);
177         calledSimpleTest = true;
178         m_testCompleted.notifyOne();
179     });
180
181     queue->dispatchAfter(std::chrono::milliseconds(500), [&](void) {
182         LockHolder locker(m_lock);
183         m_functionCallOrder.append(dispatchAfterLabel);
184         calledDispatchAfterTest = true;
185         m_dispatchAfterTestCompleted.notifyOne();
186     });
187
188     m_testCompleted.wait(m_lock);
189
190     EXPECT_TRUE(calledSimpleTest);
191     EXPECT_FALSE(calledDispatchAfterTest);
192     
193     m_dispatchAfterTestCompleted.wait(m_lock);
194
195     EXPECT_TRUE(calledSimpleTest);
196     EXPECT_TRUE(calledDispatchAfterTest);
197
198     EXPECT_EQ(static_cast<size_t>(2), m_functionCallOrder.size());
199     EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
200     EXPECT_STREQ(dispatchAfterLabel, m_functionCallOrder[1].c_str());
201 }
202
203 } // namespace TestWebKitAPI