ocarina/tests/src/database.cpp

221 lines
4.0 KiB
C++

/*
* Copyright 2014 (c) Anna Schumaker.
* Test a Database
*/
#include <database.h>
#include <print.h>
#include <sstream>
#include <stdlib.h>
#include <unistd.h>
unsigned int test_num = 0;
class IntEntry : public DatabaseEntry {
public:
unsigned int val;
IntEntry();
IntEntry(unsigned int);
const std::string primary_key();
void write(File &);
void read(File &);
void print();
};
IntEntry :: IntEntry() : val(0) {}
IntEntry :: IntEntry(unsigned int v) : val(v) {}
const std::string IntEntry :: primary_key()
{
std::stringstream ss;
ss << val;
return ss.str();
}
void IntEntry :: write(File &f) { f << val; }
void IntEntry :: read(File &f) { f >> val; }
void IntEntry :: print() { :: print(primary_key().c_str()); }
void test_results(bool success, unsigned int line)
{
print(" %u: ", test_num);
if (success)
print("Success!\n");
else {
print("FAILED (%u) =(\n", line);
exit(1);
}
test_num++;
}
void test_size(Database<IntEntry> &db, unsigned int size,
unsigned int actual, unsigned int line)
{
test_results( (db.size() == size) || (db.actual_size() == actual), line );
}
int main(int argc, char **argv)
{
bool autosave = false;
unsigned int n = 0, size = 0, actual = 0;
char c;
while ((c = getopt(argc, argv, "a")) != -1) {
switch (c) {
case 'a':
autosave = true;
break;
}
}
n = atoi(argv[optind]);
Database<IntEntry> db("database.db", autosave);
/**
* 0: Test initial size
*/
test_size(db, size, actual, __LINE__);
/**
* 1: Test insertion
*/
for (unsigned int i = 0; i < n; i++) {
if (db.insert(IntEntry(i)) != i)
test_results(false, __LINE__);
}
test_results(true, __LINE__);
size += n;
actual += n;
/**
* 2: Test that size changes
*/
test_size(db, size, actual, __LINE__);
/**
* 3: Test inserting ... again.
*/
for (unsigned int i = 0; i < n; i++) {
if (db.insert(IntEntry(i)) != i)
test_results(false, __LINE__);
}
test_results(true, __LINE__);
/**
* 4: Test that size didn't change
*/
test_size(db, size, actual, __LINE__);
/**
* 5: Test that size changes when removing
* Also test out-of-bounds removal
*
* Note: This test removes all even-index entries
*/
for (unsigned int i = 0; i < n + 10; i+=2) {
db.remove(i);
size--;
}
test_size(db, size, actual, __LINE__);
/**
* 6: Test that removing again doesn't change anything
*/
for (unsigned int i = 0; i < n; i+=2)
db.remove(i);
test_size(db, size, actual, __LINE__);
/**
* 7: Test iterating
*/
Database<IntEntry>::iterator it;
unsigned int index = 1;
for (it = db.begin(); it != db.end(); it = db.next(it)) {
if ((*it).val != index)
test_results(false, __LINE__);
index+=2;
};
test_results(true, __LINE__);
/**
* 8. Test access by id
*/
for (unsigned int i = 0; i < n + 10; i++) {
Database<IntEntry>::iterator it = db.at(i);
if (((i % 2) == 0) && (it != db.end()))
test_results(false, __LINE__);
if ((i >= n) && (it != db.end()))
test_results(false, __LINE__);
}
test_results(true, __LINE__);
/**
* 9. Test inserting once again
*/
for (unsigned int i = 0; i < n; i++) {
index = db.insert(i);
if ((i % 2) == 0) {
size++;
actual++;
if (index != (n + (i / 2)))
test_results(false, __LINE__);
} else {
if (index != i)
test_results(false, __LINE__);
}
}
test_results(true, __LINE__);
/**
* 10. Test that size changed for every other insert
*/
test_size(db, size, actual, __LINE__);
/**
* Everything after this point tests loading from a file
*/
if (autosave == false)
return 0;
Database<IntEntry> db2("database.db", autosave);
db2.load();
/**
* 11. Sizes should match
*/
test_size(db2, db.size(), db.actual_size(), __LINE__);
/**
* 12. Values should match
*/
Database<IntEntry>::iterator it2 = db2.begin();
for (it = db.begin(); it != db.end(); it++) {
if (it->valid != it2->valid)
test_results(false, __LINE__);
if (it->valid == true) {
if (it->val != it2->val)
test_results(false, __LINE__);
}
it2++;
}
test_results(true, __LINE__);
return 0;
}