/* * Copyright 2014 (c) Anna Schumaker. * Test a Database */ #include #include #include #include #include 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 &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 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::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::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 db2("database.db", autosave); db2.load(); /** * 11. Sizes should match */ test_size(db2, db.size(), db.actual_size(), __LINE__); /** * 12. Values should match */ Database::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; }