ocarina/tests/core/database.cpp

194 lines
4.2 KiB
C++
Raw Normal View History

/*
* Copyright 2014 (c) Anna Schumaker.
* Test a Database
*/
#include <core/database.h>
#include <core/string.h>
#include <tests/test.h>
#include <vector>
/*
* Derive a DatabaseEntry for storing integerss
*/
class IntEntry : public DatabaseEntry {
public:
unsigned int val;
IntEntry() : val(0) {};
IntEntry(unsigned int v) : val(v) {};
const std::string primary_key() const
{
return string :: utos(val);
}
void write(File &f) { f << val; }
void read(File &f) { f >> val; }
};
static unsigned int N = 0;
static bool AUTOSAVE = false;
static Database<IntEntry> *DB = NULL;
static Database<IntEntry>::iterator IT;
static std::vector<IntEntry *> *POINTERS;
static unsigned int _test_insertion_check(unsigned int i)
{
IntEntry *it = DB->insert(IntEntry(i));
if ((it == NULL) || (it->index() != i) || (it->val != i))
return LOOP_FAILED;
POINTERS->push_back(it);
return (DB->insert(IntEntry(i)) == NULL) ? LOOP_PASSED : LOOP_FAILED;
}
static unsigned int _test_insertion_pointer_check(unsigned int i)
{
return (POINTERS->at(i) == DB->at(i)) ? LOOP_PASSED : LOOP_FAILED;
}
static void test_insertion()
{
/* Check initial sizes. */
test_equal(DB->size(), (unsigned)0);
test_equal(DB->actual_size(), (unsigned)0);
test_for_each(0, N, 1, _test_insertion_check);
test_equal(DB->size(), N);
test_equal(DB->actual_size(), N);
/* Pointers should still be valid. */
test_for_each(0, N, 1, _test_insertion_pointer_check);
}
static void test_removal()
{
/* Size should have only changed once each iteration. */
for (unsigned int i = 0; i < N; i+=2) {
DB->remove(i);
DB->remove(i);
}
test_equal(DB->size(), N / 2);
test_equal(DB->actual_size(), N);
/* Test out-of-bounds removal. */
for (unsigned int i = 0; i < 10; i++)
DB->remove(N + i);
test_equal(DB->size(), N / 2);
test_equal(DB->actual_size(), N);
}
static unsigned int _test_access_null(unsigned int i)
{
return (DB->at(i) == NULL) ? LOOP_PASSED : LOOP_FAILED;
}
static unsigned int _test_access_valid(unsigned int i)
{
IntEntry *ie = DB->at(i);
if ((ie == NULL) || (*IT != ie) ||
(ie->val != i) || (ie->index() != i))
return LOOP_FAILED;
IT = DB->next(IT);
return LOOP_PASSED;
}
static void test_access()
{
IT = DB->begin();
test_for_each(0, N, 2, _test_access_null);
test_for_each(1, N, 2, _test_access_valid);
test_for_each(N, N + 10, 1, _test_access_null);
}
static unsigned int _test_reinsert_check(unsigned int i)
{
IntEntry *it = DB->insert(IntEntry(i));
return (it->index() == (N + (i / 2))) ? LOOP_PASSED : LOOP_FAILED;
}
static void test_reinsert()
{
test_for_each(0, N, 2, _test_reinsert_check);
test_equal(DB->size(), N);
test_equal(DB->actual_size(), N + (N / 2));
}
static Database<IntEntry> *DB2;
static unsigned int _test_save_load_check(unsigned int i)
{
IntEntry *ie1 = DB->at(i);
IntEntry *ie2 = DB2->at(i);
if (ie1 == NULL)
return (ie2 == NULL) ? LOOP_PASSED : LOOP_FAILED;
else {
if ((ie2 == NULL) || (ie1->index() != ie2->index()) ||
(ie1->val != ie2->val))
return LOOP_FAILED;
}
return LOOP_PASSED;
}
static void test_save_load()
{
Database<IntEntry> db2("database.db", false);
db2.load();
DB2 = &db2;
if (AUTOSAVE == false) {
test_equal(db2.size(), (unsigned)0);
test_equal(db2.actual_size(), (unsigned)0);
DB->save();
db2.load();
}
test_equal(db2.size(), DB->size());
test_equal(db2.actual_size(), DB->actual_size());
test_for_each(0, DB->actual_size(), 1, _test_save_load_check);
}
static void db_test(unsigned int n, bool autosave)
{
std::string n_str = " (n = " + string :: utos(n) + ")";
Database<IntEntry> db("database.db", autosave);
std::vector<IntEntry *> pointers;
N = n;
DB = &db;
AUTOSAVE = autosave;
POINTERS = &pointers;
test :: rm_data_dir();
test :: run("Database Insertion Test" + n_str, test_insertion);
test :: run("Database Removal Test" + n_str, test_removal);
test :: run("Database Access Test" + n_str, test_access);
test :: run("Database Reinsertion Test" + n_str, test_reinsert);
test :: run("Database Save and Load Test" + n_str, test_save_load);
}
int main(int argc, char **argv)
{
db_test(0, true);
db_test(10, true);
db_test(100, true);
db_test(1000, true);
db_test(10000, false);
db_test(100000, false);
return 0;
}