/* * 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 #include #include #include #include #include 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 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(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 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(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 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(2), m_functionCallOrder.size()); EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str()); EXPECT_STREQ(dispatchAfterLabel, m_functionCallOrder[1].c_str()); } } // namespace TestWebKitAPI