#include "gtest/gtest.h"
#include "pithreadpoolexecutor.h"
#include "pimutex.h"

const int WAIT_THREAD_TIME_MS = 30;

TEST(ExcutorIntegrationTest, execute_is_runnable_invoke) {
    PIMutex m;
    int invokedRunnables = 0;
    PIThreadPoolExecutor executorService(1);
    executorService.execute([&]() {
        m.lock();
        invokedRunnables++;
        m.unlock();
    });
    piMSleep(WAIT_THREAD_TIME_MS);
    ASSERT_EQ(invokedRunnables, 1);
}

TEST(ExcutorIntegrationTest, execute_is_not_execute_after_shutdown) {
    bool isRunnableInvoke = false;
    PIThreadPoolExecutor executorService(1);
    executorService.shutdown();
    executorService.execute([&]() {
        isRunnableInvoke = true;
    });
    piMSleep(WAIT_THREAD_TIME_MS);
    ASSERT_FALSE(isRunnableInvoke);
}

TEST(ExcutorIntegrationTest, execute_is_execute_before_shutdown) {
    bool isRunnableInvoke = false;
    PIThreadPoolExecutor executorService(1);
    executorService.execute([&]() {
        piMSleep(WAIT_THREAD_TIME_MS);
        isRunnableInvoke = true;
    });
    executorService.shutdown();
    piMSleep(2 * WAIT_THREAD_TIME_MS);
    ASSERT_TRUE(isRunnableInvoke);
}

TEST(ExcutorIntegrationTest, execute_is_awaitTermination_wait) {
    PIThreadPoolExecutor executorService(1);
    executorService.execute([&]() {
        piMSleep(2 * WAIT_THREAD_TIME_MS);
    });
    executorService.shutdown();
    PITimeMeasurer measurer;
    ASSERT_TRUE(executorService.awaitTermination(3 * WAIT_THREAD_TIME_MS));
    double waitTime = measurer.elapsed_m();
    ASSERT_GE(waitTime, WAIT_THREAD_TIME_MS);
    ASSERT_LE(waitTime, 4 * WAIT_THREAD_TIME_MS);
}
