#include "test.h"
#include "store_htable.h"
#include "assets/triples.h"

/** @brief Test hash table store.
 */
static int test_htstore()
{
    LSUP_HTStore *store = LSUP_htstore_new(0);
    ASSERT (store != NULL, "Error initializing store!");

    LSUP_Triple *trp = create_triples();
    LSUP_BufferTriple *ser_trp[NUM_TRP];

    for (int i = 0; i < NUM_TRP; i++)
        ser_trp[i] = LSUP_triple_serialize (trp + i);

    // Test adding.
    LSUP_HTIterator *it = LSUP_htstore_add_init (store);
    for (size_t i = 0; i < NUM_TRP; i++) {
        //printf("Insert #%lu\n", i);
        LSUP_rc rc = LSUP_htstore_add_iter (it, ser_trp[i]);
        ASSERT (
                (i < 8 && rc == LSUP_OK) || rc == LSUP_NOACTION,
                "Wrong return code on insert!");
    }

    EXPECT_INT_EQ (LSUP_htstore_size (store), 8);

    LSUP_htstore_add_done (it);

    // Test lookups.
    LSUP_Buffer *lut[12][3] = {
        {NULL, NULL, NULL},

        {ser_trp[0]->s, NULL, NULL},
        {ser_trp[2]->s, NULL, NULL},
        {NULL, ser_trp[0]->p, NULL},
        {NULL, ser_trp[0]->s, NULL},
        {NULL, NULL, ser_trp[6]->o},

        {ser_trp[4]->s, ser_trp[4]->p, NULL},
        {NULL, ser_trp[7]->p, ser_trp[7]->o},
        {ser_trp[5]->s, NULL, ser_trp[5]->o},
        {ser_trp[5]->s, NULL, ser_trp[5]->o},

        {ser_trp[4]->s, ser_trp[4]->p, ser_trp[4]->o},
        {ser_trp[4]->s, ser_trp[4]->p, ser_trp[6]->o},
    };

    size_t results[12] = {
        8,
        5, 1, 1, 0, 1,
        2, 1, 2, 2,
        1, 0,
    };

    LSUP_BufferTriple *sspo = BTRP_DUMMY;
    for (int i = 0; i < NUM_TRP; i++) {
        size_t ct, ct2 = 0;
        log_info ("Testing triple lookup #%d.", i);

        LSUP_HTIterator *it = LSUP_htstore_lookup(
                store, lut[i][0], lut[i][1], lut[i][2], &ct);
        EXPECT_INT_EQ (ct, results[i]);
        // Verify that the internal counter aligns with an external one.
        while (LSUP_htiter_next (it, sspo) != LSUP_END) ct2++;
        EXPECT_INT_EQ (ct, ct2);

        LSUP_htiter_free (it);
    }
    free (sspo);

    for (int i = 0; i < NUM_TRP; i++)
        LSUP_btriple_free (ser_trp[i]);

    LSUP_htstore_free (store);
    free_triples (trp);

    return 0;
}


int store_ht_tests()
{
    RUN(test_htstore);

    return 0;
}