#include "tests/StackTests.h"

#include "data/Stack.h"
#include "test/Test.h"

template<typename T>
static void testPushPopPeek() {
    T stack;
    CORE_TEST_ERROR(stack.push(1));
    CORE_TEST_ERROR(stack.push(2));
    CORE_TEST_ERROR(stack.push(3));
    CORE_TEST_EQUAL(3, stack.peek());
    CORE_TEST_ERROR(stack.pop());
    CORE_TEST_EQUAL(2, stack.peek());
    CORE_TEST_ERROR(stack.pop());
    CORE_TEST_EQUAL(1, stack.peek());
    CORE_TEST_ERROR(stack.pop());
    CORE_TEST_TRUE(stack.isEmpty());
}

template<typename T>
static void testBigPushPop(int amount) {
    T stack;
    for(int i = 0; i < amount; i++) {
        CORE_TEST_ERROR(stack.push(i));
    }
    for(int i = 0; i < amount; i++) {
        CORE_TEST_ERROR(stack.pop());
    }
    CORE_TEST_TRUE(stack.isEmpty());
}

template<typename T>
static void testToString1() {
    T stack;
    CORE_TEST_ERROR(stack.push(1));
    CORE_TEST_ERROR(stack.push(243));
    CORE_TEST_ERROR(stack.push(-423));
    CORE_TEST_STRING("[1, 243, -423]", stack);
}

template<typename T>
static void testToString2() {
    T stack;
    CORE_TEST_ERROR(stack.push(1));
    CORE_TEST_STRING("[1]", stack);
}

template<typename T>
static void testToString3() {
    T stack;
    CORE_TEST_STRING("[]", stack);
}

template<typename T>
static void testPop() {
    T stack;
    for(int i = 0; i < 100000; i++) {
        CORE_TEST_EQUAL(Core::Error::INVALID_INDEX, stack.pop());
    }
}

template<typename T>
static void testType(int amount) {
    testPushPopPeek<T>();
    testBigPushPop<T>(amount);
    testToString1<T>();
    testToString2<T>();
    testToString3<T>();
    testPop<T>();
}

void Core::StackTests::test() {
    testType<Core::ListStack<int>>(100000);
    testType<Core::ArrayStack<int, 100>>(100);
}