183 lines
4.3 KiB
C++
183 lines
4.3 KiB
C++
/*
|
|
* Copyright 2014 (c) Anna Schumaker.
|
|
* Test a Database
|
|
*/
|
|
#include <core/database.h>
|
|
#include <core/string.h>
|
|
#include "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 Database<IntEntry> *DB = NULL;
|
|
|
|
|
|
static void test_insertion(unsigned int n, bool autosave)
|
|
{
|
|
test_rm_data_dir();
|
|
DB = new Database<IntEntry>("database.db", autosave);
|
|
std::vector<IntEntry *> pointers;
|
|
|
|
/* Check initial sizes. */
|
|
test_equal(DB->size(), (unsigned)0);
|
|
test_equal(DB->actual_size(), (unsigned)0);
|
|
|
|
for (unsigned int i = 0; i < n; i++) {
|
|
IntEntry *it = DB->insert(IntEntry(i));
|
|
test_loop_not_equal(it, NULL, i);
|
|
test_loop_equal(it->index(), i, i);
|
|
test_loop_equal(it->val, i, i);
|
|
test_loop_equal(DB->insert(IntEntry(i)), NULL, i);
|
|
pointers.push_back(it);
|
|
} test_loop_passed();
|
|
|
|
test_equal(DB->size(), n);
|
|
test_equal(DB->actual_size(), n);
|
|
|
|
/* Pointers should still be valid. */
|
|
for (unsigned int i = 0; i < n; i++)
|
|
test_loop_equal(pointers.at(i), DB->at(i), i);
|
|
test_loop_passed();
|
|
}
|
|
|
|
static void test_removal(unsigned int n, bool autosave)
|
|
{
|
|
/* 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 void test_access(unsigned int n, bool autosave)
|
|
{
|
|
Database<IntEntry>::iterator it;
|
|
IntEntry *ie;
|
|
|
|
for (unsigned int i = 0; i < n; i += 2)
|
|
test_loop_equal(DB->at(i), NULL, i);
|
|
test_loop_passed();
|
|
|
|
it = DB->begin();
|
|
for (unsigned int i = 1; i < n; i += 2) {
|
|
ie = DB->at(i);
|
|
test_loop_not_equal(ie, NULL, i);
|
|
test_loop_equal(ie->val, i, i);
|
|
test_loop_equal(ie->index(), i, i);
|
|
test_loop_equal(*it, ie, i);
|
|
it = DB->next(it);
|
|
} test_loop_passed();
|
|
|
|
for (unsigned int i = n; i < n + 10; i++)
|
|
test_loop_equal(DB->at(i), NULL, i);
|
|
test_loop_passed();
|
|
}
|
|
|
|
|
|
static void test_reinsertion(unsigned int n, bool autosave)
|
|
{
|
|
IntEntry *it;
|
|
|
|
for (unsigned int i = 0; i < n; i += 2) {
|
|
it = DB->insert(IntEntry(i));
|
|
test_loop_equal(it->index(), (n + (i / 2)), i);
|
|
} test_loop_passed();
|
|
|
|
test_equal(DB->size(), n);
|
|
test_equal(DB->actual_size(), n + (n / 2));
|
|
}
|
|
|
|
|
|
static void test_save_load(unsigned int n, bool autosave)
|
|
{
|
|
Database<IntEntry> db2("database.db", false);
|
|
IntEntry *ie1, *ie2;
|
|
db2.load();
|
|
|
|
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());
|
|
|
|
for (unsigned int i = 0; i < DB->actual_size(); i++) {
|
|
ie1 = DB->at(i);
|
|
ie2 = db2.at(i);
|
|
if (ie1) {
|
|
test_loop_equal(ie2->index(), ie1->index(), i);
|
|
test_loop_equal(ie2->val, ie1->val, i);
|
|
} else
|
|
test_loop_equal(ie2, NULL, i);
|
|
} test_loop_passed();
|
|
delete DB;
|
|
}
|
|
|
|
|
|
#define DB_TEST_FUNCS(n, autosave) \
|
|
static void test_insertion_##n( ) { test_insertion(n, autosave); } \
|
|
static void test_removal_##n() { test_removal(n, autosave); } \
|
|
static void test_access_##n() { test_access(n, autosave); } \
|
|
static void test_reinsertion_##n() { test_reinsertion(n, autosave); } \
|
|
static void test_save_load_##n() { test_save_load(n, autosave); }
|
|
|
|
|
|
DB_TEST_FUNCS(0, true)
|
|
DB_TEST_FUNCS(10, true)
|
|
DB_TEST_FUNCS(100, true)
|
|
DB_TEST_FUNCS(1000, true)
|
|
DB_TEST_FUNCS(10000, false)
|
|
DB_TEST_FUNCS(100000, false)
|
|
|
|
|
|
#define DB_UNIT_TESTS(n) \
|
|
UNIT_TEST("Database Insertion (n = " #n ")", test_insertion_##n), \
|
|
UNIT_TEST("Database Removal (n = " #n ")", test_removal_##n), \
|
|
UNIT_TEST("Database Access (n = " #n ")", test_access_##n), \
|
|
UNIT_TEST("Database Reinsertion (n = " #n ")", test_reinsertion_##n), \
|
|
UNIT_TEST("Database Save and Load (n = " #n ")", test_save_load_##n)
|
|
|
|
|
|
DECLARE_UNIT_TESTS(
|
|
DB_UNIT_TESTS(0),
|
|
DB_UNIT_TESTS(10),
|
|
DB_UNIT_TESTS(100),
|
|
DB_UNIT_TESTS(1000),
|
|
DB_UNIT_TESTS(10000),
|
|
DB_UNIT_TESTS(100000),
|
|
);
|