#include "tests/BitArrayTests.h"
#include "tests/Test.h"
#include "utils/BitArray.h"
#include "utils/StringBuffer.h"

typedef StringBuffer<50> String;

static void testSetRead(Test& test) {
    BitArray<4, 3> bits;
    bits[0] = 1;
    bits[1] = 2;
    bits[2] = 3;
    bits[3] = 4;
    test.checkEqual(1, static_cast<int> (bits[0]), "set and read correct value 1");
    test.checkEqual(2, static_cast<int> (bits[1]), "set and read correct value 2");
    test.checkEqual(3, static_cast<int> (bits[2]), "set and read correct value 3");
    test.checkEqual(4, static_cast<int> (bits[3]), "set and read correct value 4");
}

static void testBigSetRead(Test& test) {
    BitArray<100, 13> bits;
    for(int i = 0; i < bits.getLength(); i++) {
        bits[i] = i;
    }
    for(int i = 0; i < bits.getLength(); i++) {
        test.checkEqual(i, static_cast<int> (bits[i]), "set and read correct value over long array");
    }
}

static void testRandomSetRead(Test& test) {
    const int length = 100;
    int data[length];
    BitArray<100, 13> bits;
    int seed = 534;
    for(int k = 0; k < 20; k++) {
        for(int i = 0; i < bits.getLength(); i++) {
            seed = seed * 636455 + 53453;
            bits[i] = seed & (0x1FFF);
            data[i] = seed & (0x1FFF);
        }
    }
    for(int i = 0; i < bits.getLength(); i++) {
        test.checkEqual(data[i], static_cast<int> (bits[i]), "set and read correct value with random input");
    }
}

static void testReadOnly(Test& test) {
    BitArray<4, 3> bits;
    bits[0] = 1;
    bits[1] = 2;
    bits[2] = 3;
    bits[3] = 4;
    const BitArray<4, 3> bits2 = bits;
    test.checkEqual(1, bits2[0], "can read from const 1");
    test.checkEqual(2, bits2[1], "can read from const 2");
    test.checkEqual(3, bits2[2], "can read from const 3");
    test.checkEqual(4, bits2[3], "can read from const 4");
}

static void testChainedSet(Test& test) {
    BitArray<4, 3> bits;
    bits[0] = bits[2] = bits[3] = 2;
    bits[3] = bits[1] = 7;
    test.checkEqual(2, static_cast<int> (bits[0]), "chained set sets correct value 1");
    test.checkEqual(7, static_cast<int> (bits[1]), "chained set sets correct value 2");
    test.checkEqual(2, static_cast<int> (bits[2]), "chained set sets correct value 3");
    test.checkEqual(7, static_cast<int> (bits[3]), "chained set sets correct value 4");
}

static void testToString1(Test& test) {
    BitArray<4, 3> bits;
    bits[0] = 1;
    bits[1] = 2;
    bits[2] = 3;
    bits[3] = 4;
    test.checkEqual(String("[1, 2, 3, 4]"), String(bits), "bit array to string 1");
}

static void testToString2(Test& test) {
    BitArray<1, 3> a;
    a[0] = 1;
    test.checkEqual(String("[1]"), String(a), "bit array to string 1");
}

void BitArrayTests::test() {
    Test test("BitArray");
    testSetRead(test);
    testBigSetRead(test);
    testRandomSetRead(test);
    testReadOnly(test);
    testChainedSet(test);
    testToString1(test);
    testToString2(test);
    test.finalize();
}