blob: 74f5dc294483cc41ff91f370e5525a91a054365f [file] [log] [blame]
/*
* Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "Test.h"
#include <wtf/Condition.h>
#include <wtf/Lock.h>
#include <wtf/Vector.h>
#include <wtf/WorkQueue.h>
#include <string>
#include <thread>
namespace TestWebKitAPI {
static const char* simpleTestLabel = "simpleTest";
static const char* longTestLabel = "longTest";
static const char* thirdTestLabel = "thirdTest";
static const char* dispatchAfterLabel = "dispatchAfter";
TEST(WTF_WorkQueue, Simple)
{
Lock m_lock;
Condition m_testCompleted;
Vector<std::string> m_functionCallOrder;
bool calledSimpleTest = false;
bool calledLongTest = false;
bool calledThirdTest = false;
static const char* simpleTestLabel = "simpleTest";
static const char* longTestLabel = "longTest";
static const char* thirdTestLabel = "thirdTest";
auto queue = WorkQueue::create("com.apple.WebKit.Test.simple");
int initialRefCount = queue->refCount();
EXPECT_EQ(1, initialRefCount);
LockHolder locker(m_lock);
queue->dispatch([&](void) {
m_functionCallOrder.append(simpleTestLabel);
calledSimpleTest = true;
});
queue->dispatch([&](void) {
m_functionCallOrder.append(longTestLabel);
std::this_thread::sleep_for(std::chrono::nanoseconds(100));
calledLongTest = true;
});
queue->dispatch([&](void) {
LockHolder locker(m_lock);
m_functionCallOrder.append(thirdTestLabel);
calledThirdTest = true;
EXPECT_TRUE(calledSimpleTest);
EXPECT_TRUE(calledLongTest);
EXPECT_TRUE(calledThirdTest);
m_testCompleted.notifyOne();
});
EXPECT_GT(queue->refCount(), 1);
m_testCompleted.wait(m_lock);
EXPECT_TRUE(calledSimpleTest);
EXPECT_TRUE(calledLongTest);
EXPECT_TRUE(calledThirdTest);
EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
EXPECT_STREQ(longTestLabel, m_functionCallOrder[1].c_str());
EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[2].c_str());
}
TEST(WTF_WorkQueue, TwoQueues)
{
Lock m_lock;
Condition m_testQueue1Completed, m_testQueue2Completed;
Vector<std::string> m_functionCallOrder;
bool calledSimpleTest = false;
bool calledLongTest = false;
bool calledThirdTest = false;
auto queue1 = WorkQueue::create("com.apple.WebKit.Test.twoQueues1");
auto queue2 = WorkQueue::create("com.apple.WebKit.Test.twoQueues2");
EXPECT_EQ(1, queue1->refCount());
EXPECT_EQ(1, queue2->refCount());
LockHolder locker(m_lock);
queue1->dispatch([&](void) {
m_functionCallOrder.append(simpleTestLabel);
calledSimpleTest = true;
});
queue2->dispatch([&](void) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
LockHolder locker(m_lock);
// Will fail if queue2 took the mutex before queue1.
EXPECT_TRUE(calledThirdTest);
m_functionCallOrder.append(longTestLabel);
calledLongTest = true;
m_testQueue2Completed.notifyOne();
});
queue1->dispatch([&](void) {
LockHolder locker(m_lock);
m_functionCallOrder.append(thirdTestLabel);
calledThirdTest = true;
m_testQueue1Completed.notifyOne();
});
m_testQueue1Completed.wait(m_lock);
EXPECT_TRUE(calledSimpleTest);
EXPECT_FALSE(calledLongTest);
EXPECT_TRUE(calledThirdTest);
m_testQueue2Completed.wait(m_lock);
EXPECT_TRUE(calledSimpleTest);
EXPECT_TRUE(calledLongTest);
EXPECT_TRUE(calledThirdTest);
EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[1].c_str());
EXPECT_STREQ(longTestLabel, m_functionCallOrder[2].c_str());
}
TEST(WTF_WorkQueue, DispatchAfter)
{
Lock m_lock;
Condition m_testCompleted, m_dispatchAfterTestCompleted;
Vector<std::string> m_functionCallOrder;
bool calledSimpleTest = false;
bool calledDispatchAfterTest = false;
auto queue = WorkQueue::create("com.apple.WebKit.Test.dispatchAfter");
LockHolder locker(m_lock);
queue->dispatch([&](void) {
LockHolder locker(m_lock);
m_functionCallOrder.append(simpleTestLabel);
calledSimpleTest = true;
m_testCompleted.notifyOne();
});
queue->dispatchAfter(std::chrono::milliseconds(500), [&](void) {
LockHolder locker(m_lock);
m_functionCallOrder.append(dispatchAfterLabel);
calledDispatchAfterTest = true;
m_dispatchAfterTestCompleted.notifyOne();
});
m_testCompleted.wait(m_lock);
EXPECT_TRUE(calledSimpleTest);
EXPECT_FALSE(calledDispatchAfterTest);
m_dispatchAfterTestCompleted.wait(m_lock);
EXPECT_TRUE(calledSimpleTest);
EXPECT_TRUE(calledDispatchAfterTest);
EXPECT_EQ(static_cast<size_t>(2), m_functionCallOrder.size());
EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
EXPECT_STREQ(dispatchAfterLabel, m_functionCallOrder[1].c_str());
}
} // namespace TestWebKitAPI