#include "../Tests.hpp"
#include "core/utils/Buffer.hpp"

static constexpr size_t SIZE_TYPES =
    sizeof(int) + sizeof(long) + sizeof(float) + sizeof(double);

static void testAdd(bool light) {
    Core::Buffer buffer(10);
    size_t limit = light ? 1000 : 100000;
    for(size_t i = 0; i < limit; i++) {
        CORE_TEST_ERROR(buffer.add(5));
        CORE_TEST_ERROR(buffer.add(5L));
        CORE_TEST_ERROR(buffer.add(5.0f));
        CORE_TEST_ERROR(buffer.add(5.0));
    }
    CORE_TEST_EQUAL(SIZE_TYPES * limit, buffer.getLength());
}

static void testCopy() {
    Core::Buffer buffer(10);
    for(int i = 0; i < 10; i++) {
        CORE_TEST_ERROR(buffer.add(5));
        CORE_TEST_ERROR(buffer.add(5L));
        CORE_TEST_ERROR(buffer.add(5.0f));
        CORE_TEST_ERROR(buffer.add(5.0));
    }
    Core::Buffer buffer2;
    CORE_TEST_ERROR(buffer2.copyFrom(buffer));
    if(CORE_TEST_EQUAL(SIZE_TYPES * 10, buffer.getLength()) &&
       CORE_TEST_EQUAL(SIZE_TYPES * 10, buffer2.getLength())) {
        CORE_TEST_TRUE(memcmp(buffer, buffer2, SIZE_TYPES * 10) == 0);
    }
}

static void testMoveConstruct() {
    Core::Buffer buffer(10);
    for(int i = 0; i < 10; i++) {
        CORE_TEST_ERROR(buffer.add(5));
        CORE_TEST_ERROR(buffer.add(5L));
        CORE_TEST_ERROR(buffer.add(5.0f));
        CORE_TEST_ERROR(buffer.add(5.0));
    }
    Core::Buffer buffer2(Core::move(buffer));

    CORE_TEST_EQUAL(0, buffer.getLength());
    CORE_TEST_EQUAL(SIZE_TYPES * 10, buffer2.getLength());
}

static void testMove() {
    Core::Buffer buffer(10);
    for(int i = 0; i < 10; i++) {
        CORE_TEST_ERROR(buffer.add(5));
        CORE_TEST_ERROR(buffer.add(5L));
        CORE_TEST_ERROR(buffer.add(5.0f));
        CORE_TEST_ERROR(buffer.add(5.0));
    }
    Core::Buffer buffer2(3);
    buffer2 = Core::move(buffer);

    CORE_TEST_EQUAL(0, buffer.getLength());
    CORE_TEST_EQUAL(SIZE_TYPES * 10, buffer2.getLength());
}

void Core::testBuffer(bool light) {
    testAdd(light);
    testCopy();
    testMoveConstruct();
    testMove();
}