summaryrefslogtreecommitdiff
path: root/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp')
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp b/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp
new file mode 100644
index 000000000..31436bc22
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2016 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 <chrono>
+#include <thread>
+
+#include <wtf/ASCIICType.h>
+#include <wtf/SynchronizedFixedQueue.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/text/CString.h>
+#include <wtf/threads/BinarySemaphore.h>
+
+namespace TestWebKitAPI {
+
+static char const* textItem(size_t index)
+{
+ static char const* items[] = { "first", "second", "third", "fourth", "fifth", "sixth" };
+ return index < sizeof(items) / sizeof(items[0]) ? items[index] : nullptr;
+}
+
+static CString toUpper(const CString& lower)
+{
+ CString upper = lower;
+
+ for (char* buffer = upper.mutableData(); *buffer; ++buffer)
+ *buffer = toASCIIUpper(*buffer);
+
+ return upper;
+}
+
+template <size_t BufferSize>
+class ToUpperConverter {
+public:
+ ToUpperConverter()
+ {
+ }
+
+ WorkQueue* produceQueue()
+ {
+ if (!m_produceQueue)
+ m_produceQueue = WorkQueue::create("org.webkit.Produce");
+ return m_produceQueue.get();
+ }
+
+ WorkQueue* consumeQueue()
+ {
+ if (!m_consumeQueue)
+ m_consumeQueue = WorkQueue::create("org.webkit.Consume");
+ return m_consumeQueue.get();
+ }
+
+ void startProducing()
+ {
+ if (isProducing())
+ return;
+
+ produceQueue()->dispatch([this] {
+ CString lower;
+ while (m_lowerQueue.dequeue(lower)) {
+ m_upperQueue.enqueue(toUpper(lower));
+ EXPECT_TRUE(lower == textItem(m_produceCount++));
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ m_produceCloseSemaphore.signal();
+ });
+ }
+
+ void startConsuming()
+ {
+ if (isConsuming())
+ return;
+
+ consumeQueue()->dispatch([this] {
+ CString upper;
+ while (m_upperQueue.dequeue(upper)) {
+ EXPECT_TRUE(upper == toUpper(textItem(m_consumeCount++)));
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+ m_consumeCloseSemaphore.signal();
+ });
+ }
+
+ void start()
+ {
+ startProducing();
+ startConsuming();
+ }
+
+ void stopProducing()
+ {
+ if (!isProducing())
+ return;
+
+ m_lowerQueue.close();
+ m_produceCloseSemaphore.wait(WallTime::infinity());
+ m_produceQueue = nullptr;
+ }
+
+ void stopConsuming()
+ {
+ if (!isConsuming())
+ return;
+
+ m_upperQueue.close();
+ m_consumeCloseSemaphore.wait(WallTime::infinity());
+ m_consumeQueue = nullptr;
+ }
+
+ void stop()
+ {
+ stopProducing();
+ stopConsuming();
+ }
+
+ void enqueueLower(const CString& lower)
+ {
+ m_lowerQueue.enqueue(lower);
+ }
+
+ bool isProducing() { return m_produceQueue; }
+ bool isConsuming() { return m_consumeQueue; }
+
+ size_t produceCount() const { return m_produceCount; }
+ size_t consumeCount() const { return m_consumeCount; }
+
+private:
+ SynchronizedFixedQueue<CString, BufferSize> m_lowerQueue;
+ SynchronizedFixedQueue<CString, BufferSize> m_upperQueue;
+ RefPtr<WorkQueue> m_produceQueue;
+ RefPtr<WorkQueue> m_consumeQueue;
+ BinarySemaphore m_produceCloseSemaphore;
+ BinarySemaphore m_consumeCloseSemaphore;
+ size_t m_produceCount { 0 };
+ size_t m_consumeCount { 0 };
+};
+
+TEST(WTF_SynchronizedFixedQueue, Basic)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.start();
+ EXPECT_TRUE(converter.isProducing() && converter.isConsuming());
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+
+ EXPECT_EQ(converter.produceCount(), 0U);
+ EXPECT_EQ(converter.consumeCount(), 0U);
+}
+
+TEST(WTF_SynchronizedFixedQueue, ProduceOnly)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.startProducing();
+ EXPECT_TRUE(converter.isProducing() && !converter.isConsuming());
+
+ size_t count = 0;
+ while (char const* item = textItem(count)) {
+ converter.enqueueLower(item);
+ ++count;
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+}
+
+TEST(WTF_SynchronizedFixedQueue, ConsumeOnly)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.startConsuming();
+ EXPECT_TRUE(!converter.isProducing() && converter.isConsuming());
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+}
+
+TEST(WTF_SynchronizedFixedQueue, Limits)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.start();
+ EXPECT_TRUE(converter.isProducing() && converter.isConsuming());
+
+ size_t count = 0;
+ while (char const* item = textItem(count)) {
+ converter.enqueueLower(item);
+ ++count;
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(400));
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+
+ EXPECT_EQ(converter.produceCount(), count);
+ EXPECT_EQ(converter.consumeCount(), count);
+}
+
+}