/*
 * 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()
        : m_lowerQueue(SynchronizedFixedQueue<CString, BufferSize>::create())
        , m_upperQueue(SynchronizedFixedQueue<CString, BufferSize>::create())
    {
    }

    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++));
#if PLATFORM(WIN)
                auto sleepAmount = std::chrono::milliseconds(20);
#else
                auto sleepAmount = std::chrono::milliseconds(10);
#endif
                std::this_thread::sleep_for(sleepAmount);
            }
            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:
    Ref<SynchronizedFixedQueue<CString, BufferSize>> m_lowerQueue;
    Ref<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);
}

}
