ocarina/tests/core/database.cpp

223 lines
4.2 KiB
C++

/*
* Copyright 2014 (c) Anna Schumaker.
* Test a Database
*/
#include <core/database.h>
#include <tests/test.h>
#include <sstream>
#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
{
std::stringstream ss;
ss << val;
return ss.str();
}
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 void test_insertion()
{
std::vector<IntEntry *> pointers;
std::vector<IntEntry *>::iterator p_it;
/*
* Check initial sizes.
*/
test_equal(DB->size(), (unsigned)0);
test_equal(DB->actual_size(), (unsigned)0);
test :: begin();
for (unsigned int i = 0; i < N; i++) {
IntEntry *it = DB->insert(IntEntry(i));
check_not_equal(it, (IntEntry *)NULL);
check_equal(it->index(), i);
check_equal(it->val, i);
pointers.push_back(it);
it = DB->insert(IntEntry(i));
check_equal(it, (IntEntry *)NULL);
}
test :: success();
/*
* Size should change
*/
test_equal(DB->size(), N);
test_equal(DB->actual_size(), N);
/*
* Pointers should still be valid
*/
test :: begin();
for (unsigned int i = 0; i < N; i++)
check_equal(pointers[i], DB->at(i));
test :: success();
}
static void test_removal()
{
test :: begin();
for (unsigned int i = 0; i < N; i+=2) {
/*
* Database size should only decrease once.
*/
DB->remove(i);
DB->remove(i);
}
test :: success();
/*
* Size should change
*/
test_equal(DB->size(), N / 2);
test_equal(DB->actual_size(), N);
/*
* Test out-of-bounds removal
*/
test :: begin();
for (unsigned int i = 0; i < 10; i++)
DB->remove(N + i);
test :: success();
/*
* Size should not change
*/
test_equal(DB->size(), N / 2);
test_equal(DB->actual_size(), N);
}
static void test_access()
{
Database<IntEntry>::iterator it;
test :: begin();
for (unsigned int i = 0; i < N; i+=2)
check_equal(DB->at(i), (IntEntry *)NULL);
test :: success();
test :: begin();
it = DB->begin();
for (unsigned int i = 1; i < N; i+=2) {
IntEntry *ie = DB->at(i);
check_not_equal(ie, (IntEntry *)NULL);
check_equal(*it, ie);
check_equal(ie->val, i);
check_equal(ie->index(), i);
it = DB->next(it);
}
test :: success();
test :: begin();
for (unsigned int i = 0; i < 10; i++)
check_equal(DB->at(N + i), (IntEntry *)NULL);
test :: success();
}
static void test_reinsert()
{
test :: begin();
for (unsigned int i = 0; i < N; i+=2) {
IntEntry *it = DB->insert(IntEntry(i));
check_equal(it->index(), N + (i / 2));
}
test :: success();
/*
* Size should change
*/
test_equal(DB->size(), N);
test_equal(DB->actual_size(), N + (N / 2));
}
static void test_save_load()
{
Database<IntEntry> db2("database.db", false);
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());
Database<IntEntry>::iterator it1;
Database<IntEntry>::iterator it2 = db2.begin();
test :: begin();
for (it1 = DB->begin(); it1 != DB->end(); it1++) {
if (*it1 == (IntEntry *)NULL)
check_equal(*it2, (IntEntry *)NULL);
else {
check_not_equal(*it2, (IntEntry *)NULL);
check_equal((*it1)->index(), (*it2)->index());
check_equal((*it1)->val, (*it2)->val);
}
it2++;
}
test :: success();
}
static void db_test(unsigned int n, bool autosave)
{
test :: rm_data_dir();
std::stringstream ss;
ss << " (n = " << n << ")";
const std::string n_str = ss.str();
Database<IntEntry> db("database.db", autosave);
N = n;
DB = &db;
AUTOSAVE = autosave;
run_test("Database Insertion Test" + n_str, test_insertion);
run_test("Database Removal Test" + n_str, test_removal);
run_test("Database Access Test" + n_str, test_access);
run_test("Database Reinsertion Test" + n_str, test_reinsert);
run_test("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;
}