Reland r216808, underlying lldb bug has been fixed.
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WTF / ThreadMessages.cpp
1 /*
2  * Copyright (C) 2017 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 <type_traits>
29 #include <wtf/DataLog.h>
30 #include <wtf/HashSet.h>
31 #include <wtf/Ref.h>
32 #include <wtf/ThreadMessage.h>
33 #include <wtf/Vector.h>
34 #include <wtf/threads/Signals.h>
35
36 static void runThreadMessageTest(unsigned numSenders, unsigned numMessages)
37 {
38     Atomic<bool> receiverShouldKeepRunning(true);
39     RefPtr<Thread> receiverThread = Thread::create("ThreadMessage receiver", [&receiverShouldKeepRunning] () {
40         while (receiverShouldKeepRunning.load()) { }
41     });
42     ASSERT_TRUE(receiverThread);
43
44     Vector<RefPtr<Thread>> senderThreads(numSenders);
45     Vector<unsigned> messagesRun(numSenders);
46     Vector<unsigned> handlersRun(numSenders);
47     messagesRun.fill(0);
48     handlersRun.fill(0);
49
50     for (unsigned senderID = 0; senderID < numSenders; ++senderID) {
51         senderThreads[senderID] = Thread::create("ThreadMessage sender", [senderID, numMessages, receiverThread, &messagesRun, &handlersRun] () {
52             for (unsigned i = 0; i < numMessages; ++i) {
53                 auto result = sendMessage(*receiverThread.get(), [senderID, &handlersRun] (PlatformRegisters&) {
54                     handlersRun[senderID]++;
55                 });
56                 EXPECT_TRUE(result == WTF::MessageStatus::MessageRan);
57                 messagesRun[senderID]++;
58             }
59         });
60         ASSERT_TRUE(senderThreads[senderID]);
61     }
62
63     for (unsigned i = 0; i < numSenders; ++i)
64         senderThreads[i]->waitForCompletion();
65
66     receiverShouldKeepRunning.store(false);
67     receiverThread->waitForCompletion();
68
69     for (unsigned i = 0; i < numSenders; ++i) {
70         EXPECT_EQ(numMessages, messagesRun[i]);
71         EXPECT_EQ(numMessages, handlersRun[i]);
72     }
73 }
74
75 TEST(ThreadMessage, Basic)
76 {
77     runThreadMessageTest(1, 1);
78     runThreadMessageTest(1, 100);
79 }
80
81 TEST(ThreadMessage, MultipleSenders)
82 {
83     runThreadMessageTest(10, 1);
84     runThreadMessageTest(10, 100);
85     runThreadMessageTest(10, 10000);
86 }
87
88 class ReflectedThread : public Thread {
89 public:
90     using Thread::m_mutex;
91     using Thread::m_handle;
92     using Thread::hasExited;
93 };
94
95 TEST(ThreadMessage, SignalsWorkOnExit)
96 {
97     static bool handlerRan = false;
98     installSignalHandler(Signal::Usr, [] (Signal, SigInfo&, PlatformRegisters&) -> SignalAction {
99         dataLogLn("here");
100         handlerRan = true;
101         return SignalAction::Handled;
102     });
103
104     Atomic<bool> receiverShouldKeepRunning(true);
105     RefPtr<Thread> receiverThread = (Thread::create("ThreadMessage receiver",
106         [&receiverShouldKeepRunning] () {
107             while (receiverShouldKeepRunning.load()) { }
108     }));
109     ASSERT_TRUE(receiverThread);
110
111     bool signalFired;
112     {
113         std::unique_lock<std::mutex> locker(static_cast<ReflectedThread*>(receiverThread.get())->m_mutex);
114         receiverShouldKeepRunning.store(false);
115         EXPECT_FALSE(static_cast<ReflectedThread*>(receiverThread.get())->hasExited());
116         sleep(1);
117         signalFired = !pthread_kill(static_cast<ReflectedThread*>(receiverThread.get())->m_handle, toSystemSignal(Signal::Usr));
118     }
119
120     receiverThread->waitForCompletion();
121     EXPECT_TRUE(handlerRan || !signalFired);
122 }
123