tests: Rework much of the testing library

I move the code into a new cpp file, so it is no longer a header-only
library.  I also take the chance to add a for-each function for testing
iterators.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-01-04 17:56:54 -05:00
parent 8d3010a31e
commit 6cfd0d5c51
23 changed files with 620 additions and 533 deletions

View File

@ -4,167 +4,46 @@
#ifndef OCARINA_TESTS_TEST_H
#define OCARINA_TESTS_TEST_H
#include <iostream>
#include <stdlib.h>
#include <glib.h>
#include <string>
namespace test
{
extern unsigned int failed;
void run(const std::string &, void (*)());
static unsigned int test_num;
static unsigned int failed;
void equal(const int, const int, unsigned int);
void equal(const std::string &, const std::string &, unsigned int);
void equal(const void *, const void *, unsigned int);
void new_test(const std::string &name)
{
std::cout << name << std::endl;
test_num = 0;
failed = 0;
}
void not_equal(const int, const int, unsigned int);
void not_equal(const std::string &, const std::string &, unsigned int);
void not_equal(const void *, const void *, unsigned int);
void begin()
{
std::cout << " " << test_num << ": ";
test_num++;
}
void for_each(unsigned int, unsigned int, unsigned int,
unsigned int (*)(unsigned int), unsigned int);
void end()
{
std::cout << std::endl;
if (failed > 0) {
std::cout << failed << " tests failed =(" << std::endl;
std::cout << std::endl;
exit(failed);
}
}
void success()
{
std::cout << "Success!" << std::endl;
}
template <class T>
void failure(const T &lhs, const T &rhs, unsigned int line)
{
std::cout << "Failed at line " << line << ":" << std::endl;
std::cout << " Actual: " << lhs << std::endl;
std::cout << " Expected: " << rhs << std::endl;
failed++;
}
template <class T>
void check_equal(const T &lhs, const T &rhs, unsigned int line)
{
if (lhs == rhs)
success();
else
failure(lhs, rhs, line);
}
template <class T>
void check_not_equal(const T &lhs, const T &rhs, unsigned int line)
{
if (lhs != rhs)
success();
else
failure(lhs, rhs, line);
}
template <class T>
void equal(const T &lhs, const T &rhs, unsigned int line)
{
begin();
check_equal(lhs, rhs, line);
}
template <class T>
void not_equal(const T &lhs, const T &rhs, unsigned int line)
{
begin();
check_not_equal(lhs, rhs, line);
}
std::string data_dir()
{
std::string res = g_get_user_data_dir();
res += "/ocarina-test";
return res;
}
std::string data_file(const std::string &name)
{
return data_dir() + "/" + name;
}
bool data_dir_exists()
{
return g_file_test(data_dir().c_str(), G_FILE_TEST_IS_DIR);
}
bool data_file_exists(const std::string &name)
{
return g_file_test(data_file(name).c_str(), G_FILE_TEST_EXISTS);
}
void rm_data_dir()
{
std::string cmd = "rm -r " + data_dir() + " 2>/dev/null";
if (data_dir_exists())
system(cmd.c_str());
}
void reset_data_dir()
{
std::string cmd = "mkdir -p " + data_dir();
rm_data_dir();
system(cmd.c_str());
}
void cp_data_dir()
{
reset_data_dir();
std::string cmd = "cp -r tests/Data/* " + data_dir();
system(cmd.c_str());
}
void gen_library()
{
system("tests/gen_library.sh");
}
void rm_library_dirs()
{
system("rm -r /tmp/ocarina/dir2 /tmp/ocarina/dir4");
}
std::string data_dir();
std::string data_file(const std::string &name);
bool data_dir_exists();
bool data_file_exists(const std::string &name);
void rm_data_dir();
void reset_data_dir();
void cp_data_dir();
void gen_library();
void rm_library_dirs();
}
#define run_test(name, func, ...) \
do { \
test :: new_test(name); \
func( __VA_ARGS__ ); \
test :: end(); \
} while (0)
#define test_equal(lhs, rhs) \
test :: equal(lhs, rhs, __LINE__)
#define test_equal(lhs, rhs) \
do { \
test :: equal(lhs, rhs, __LINE__); \
} while (0)
#define test_not_equal(lhs, rhs) \
test :: not_equal(lhs, rhs, __LINE__)
#define test_not_equal(lhs, rhs) \
do { \
test :: not_equal(lhs, rhs, __LINE__); \
} while (0)
#define test_for_each(init, max, inc, func) \
test :: for_each(init, max, inc, func, __LINE__)
#define check_equal(lhs, rhs) \
do { \
if (lhs != rhs) \
test :: failure(lhs, rhs, __LINE__); \
} while (0)
#define check_not_equal(lhs, rhs) \
do { \
if (lhs == rhs) \
test :: failure(lhs, rhs, __LINE__); \
} while (0)
#define LOOP_PASSED 0
#define LOOP_FAILED __LINE__
#endif /* OCARINA_TESTS_TEST_H */

1
tests/.gitignore vendored
View File

@ -1,2 +1,3 @@
*-core
*-lib
sanity

View File

@ -26,14 +26,17 @@ def get_test_obj(name, dir):
return test_env.Object("%s.cpp-%s" % (name, dir), src)
return None
test_lib = test_env.Object("test.cpp");
def generic_test(name, dir, objs, extra):
global test_obj;
obj = get_test_obj(name, dir)
test_objs = extra
if obj != None:
objs += [ obj ]
test_objs = extra + objs
exe = test_env.Program(name, [ "%s.cpp" % name ] + test_objs)
exe = test_env.Program(name, [ "%s.cpp" % name, test_lib ] + test_objs)
test = Command("%s.fake" % name, [], "tests/%s/%s" % (dir, name))
Alias("tests/%s/%s" % (dir, name), test)
@ -44,7 +47,15 @@ def generic_test(name, dir, objs, extra):
Export("get_test_obj", "generic_test")
test_env.UsePackage("glib-2.0")
exe = test_env.Program("sanity", [ "sanity.cpp", test_lib ])
test = Command("sanity.fake", [], "tests/sanity")
Alias("tests/sanity", test)
Depends(test, exe)
add_test(test, "")
SConscript("core/Sconscript")
SConscript("lib/Sconscript")
#SConscript("lib/Sconscript")
Return("res")

View File

@ -189,10 +189,10 @@ void test_autopause()
int main(int argc, char **argv)
{
TestDriver driver;
run_test("Test Audio Pre-Init", test_pre_init);
run_test("Test Audio Init", test_init);
run_test("Test Audio Playback Controls", test_playback_controls);
run_test("Test Audio Track Controls", test_track_controls);
run_test("Test Audio Automatic Pausing", test_autopause);
test :: run("Test Audio Pre-Init", test_pre_init);
test :: run("Test Audio Init", test_init);
test :: run("Test Audio Playback Controls", test_playback_controls);
test :: run("Test Audio Track Controls", test_track_controls);
test :: run("Test Audio Automatic Pausing", test_autopause);
return 0;
}

View File

@ -35,130 +35,122 @@ public:
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()
{
std::vector<IntEntry *> pointers;
std::vector<IntEntry *>::iterator p_it;
/*
* Check initial sizes.
*/
/* 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_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 :: begin();
for (unsigned int i = 0; i < N; i++)
check_equal(pointers[i], DB->at(i));
test :: success();
/* Pointers should still be valid. */
test_for_each(0, N, 1, _test_insertion_pointer_check);
}
static void test_removal()
{
test :: begin();
/* Size should have only changed once each iteration. */
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();
/* Test out-of-bounds removal. */
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 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()
{
Database<IntEntry>::iterator it;
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);
}
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 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 :: 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_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);
@ -170,43 +162,30 @@ static void test_save_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();
test_for_each(0, DB->actual_size(), 1, _test_save_load_check);
}
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);
std::vector<IntEntry *> pointers;
std::stringstream ss;
std::string n_str;
ss << " (n = " << n << ")";
n_str = ss.str();
N = n;
DB = &db;
AUTOSAVE = autosave;
POINTERS = &pointers;
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);
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)
@ -217,6 +196,5 @@ int main(int argc, char **argv)
db_test(1000, true);
db_test(10000, false);
db_test(100000, false);
return 0;
}

View File

@ -156,8 +156,8 @@ int main(int argc, char **argv)
{
test :: rm_data_dir();
run_test("Deck Init Test", test_init);
run_test("Deck Create, Move and Destroy Test", test_create_mv_destroy);
run_test("Deck Next and Prev Test", test_next_prev);
test :: run("Deck Init Test", test_init);
test :: run("Deck Create, Move and Destroy Test", test_create_mv_destroy);
test :: run("Deck Next and Prev Test", test_next_prev);
return 0;
}

View File

@ -64,8 +64,8 @@ int main(int argc, char **argv)
{
test :: rm_data_dir();
run_test("File Constructor Test", test_filepath);
run_test("File Open Test", test_open);
run_test("File I/O Test", test_io);
test :: run("File Constructor Test", test_filepath);
test :: run("File Open Test", test_open);
test :: run("File I/O Test", test_io);
return 0;
}

View File

@ -61,23 +61,27 @@ static void test_add()
"well excuse me princess");
}
static std::set<unsigned int>::iterator IT;
static unsigned int *IDS = NULL;
static unsigned int _do_test_search_compare(unsigned int i)
{
return (*IT++ == IDS[i]) ? LOOP_PASSED : LOOP_FAILED;
}
static void do_test_search(const std::string &text, unsigned int len,
unsigned int *ids)
{
int init_values[] = { 1, 2, 3, 4, 5 };
std::set<unsigned int> res(init_values, init_values + 5);
std::set<unsigned int>::iterator it;
filter :: search(text, res);
test_equal(res.size(), (size_t)len);
test :: begin();
it = res.begin();
for (unsigned int i = 0; i < len; i++) {
check_equal(*it, ids[i]);
it++;
}
test :: success();
IDS = ids;
IT = res.begin();
test_for_each(0, len, 1, _do_test_search_compare);
}
static void test_search()
@ -102,8 +106,8 @@ static void test_search()
int main(int argc, char **argv)
{
run_test("Filter Lowercase Test", test_lowercase);
run_test("Filter Add Test", test_add);
run_test("Filter Search Test", test_search);
test :: run("Filter Lowercase Test", test_lowercase);
test :: run("Filter Add Test", test_add);
test :: run("Filter Search Test", test_search);
return 0;
}

View File

@ -10,11 +10,22 @@
static float N = 0;
static float cur = -1;
static bool func_passed = false;
static void inc_cur(float &expected)
{
cur++;
check_equal(cur, expected);
func_passed = (cur == expected);
}
static unsigned int _test_idle_queue_step(unsigned int i)
{
if (idle :: run_task() == false)
return LOOP_FAILED;
if (idle :: get_progress() != ((i + 1) / N))
return LOOP_FAILED;
return func_passed ? LOOP_PASSED : LOOP_FAILED;
}
static void test_idle_queue()
@ -26,12 +37,7 @@ static void test_idle_queue()
idle :: schedule(inc_cur, i);
test_equal(idle :: get_progress(), (float)0.0);
test :: begin();
for (float i = 0; i < (N - 1); i++) {
check_equal(idle :: run_task(), true);
check_equal(idle :: get_progress(), (i + 1) / N);
}
test :: success();
test_for_each(0, N - 1, 1, _test_idle_queue_step);
test_equal(idle :: run_task(), false);
test_equal(idle :: get_progress(), (float)1.0);
@ -45,7 +51,7 @@ static void do_test(unsigned int n)
N = n;
cur = -1;
run_test("Idle Queue Test" + n_str, test_idle_queue);
test :: run("Idle Queue Test" + n_str, test_idle_queue);
}
int main(int argc, char **argv)

View File

@ -2,8 +2,8 @@
* Copyright 2014 (c) Anna Schumaker.
* Test a Database
*/
#include <core/index.h>
#include <core/print.h>
#include <tests/test.h>
#include <sstream>
@ -30,69 +30,78 @@ static void test_single_item()
test_equal(it->size(), (size_t)0);
}
static void test_insertion()
static unsigned int _test_insertion_check(unsigned int i)
{
std::string key;
IndexEntry *it;
test :: begin();
for (char c = 'a'; c <= 'z'; c++) {
key = c;
for (unsigned int i = 0; i < N; i++)
INDEX->insert(key, i);
}
test :: success();
std::string key(1, (char)i);
IndexEntry *it = INDEX->find(std::string(1, (char)i));
if (N == 0)
test_equal(INDEX->size(), (unsigned int)0);
else
test_equal(INDEX->size(), (unsigned int)26);
return (it == NULL) ? LOOP_PASSED : LOOP_FAILED;
if (it == NULL)
return LOOP_FAILED;
if (it->size() != N)
return LOOP_FAILED;
return LOOP_PASSED;
}
test :: begin();
static void test_insertion()
{
for (char c = 'a'; c <= 'z'; c++) {
key = c;
it = INDEX->find(key);
if (N == 0)
check_equal(it, (IndexEntry *)NULL);
else {
check_not_equal(it, (IndexEntry *)NULL);
check_equal(it->size(), (size_t)N);
}
for (unsigned int i = 0; i < N; i++)
INDEX->insert(std::string(1, c), i);
}
test :: success();
test_equal(INDEX->size(), (N == 0) ? 0 : 26);
test_for_each('a', 'z' + 1, 1, _test_insertion_check);
}
static unsigned int _test_removal_check(unsigned int i)
{
IndexEntry *it;
std::string key(1, (char)i);
for (unsigned int i = 0; i < N; i++)
INDEX->remove(key, i);
it = INDEX->find(key);
if (N == 0)
return (it == NULL) ? LOOP_PASSED : LOOP_FAILED;
if ((it == NULL) || (it->size() != 0))
return LOOP_FAILED;
return LOOP_PASSED;
}
static void test_removal()
{
std::string key;
IndexEntry *it;
test_for_each('a', 'z' + 1, 1, _test_removal_check);
}
test :: begin();
for (char c = 'a'; c <= 'z'; c++) {
key = c;
for (unsigned int i = 0; i < N; i++)
INDEX->remove(key, i);
it = INDEX->find(key);
if (N == 0)
check_equal(it, (IndexEntry *)NULL);
else {
check_not_equal(it, (IndexEntry *)NULL);
check_equal(it->size(), (size_t)0);
}
static Index *INDEX2 = NULL;
static unsigned int _test_saving_check(unsigned int i)
{
std::string key(1, (char)i);
IndexEntry *it1 = INDEX->find(key);
IndexEntry *it2 = INDEX2->find(key);
if (N == 0) {
if ((it1 != NULL) || (it2 != NULL))
return LOOP_FAILED;
} else {
if ((it1 == NULL) || (it2 == NULL) ||
(it1->size() != it2->size()))
return LOOP_FAILED;
}
test :: success();
return LOOP_PASSED;
}
static void test_saving()
{
std::string key;
IndexEntry *it1, *it2;
Index idx2("index.idx", false);
idx2.load();
INDEX2 = &idx2;
test_equal(idx2.size(), (unsigned)0);
INDEX->save();
@ -101,42 +110,27 @@ static void test_saving()
test_equal(idx2.size(), INDEX->size());
test_equal(idx2.actual_size(), INDEX->actual_size());
test :: begin();
for (char c = 'a'; c <= 'z'; c++) {
key = c;
it1 = INDEX->find(key);
it2 = idx2.find(key);
if (N == 0) {
check_equal(it1, (IndexEntry *)NULL);
check_equal(it2, (IndexEntry *)NULL);
} else {
check_not_equal(it1, (IndexEntry *)NULL);
check_not_equal(it2, (IndexEntry *)NULL);
check_equal(it1->size(), it2->size());
}
}
test :: success();
test_for_each('a', 'z' + 1, 1, _test_saving_check);
}
static void index_test(unsigned int n)
{
test :: rm_data_dir();
std::stringstream ss;
ss << " (n = " << n << ")";
const std::string n_str = ss.str();
Index index("index.idx", false);
std::stringstream ss;
std::string n_str;
ss << " (n = " << n << ")";
n_str = ss.str();
N = n;
INDEX = &index;
test :: rm_data_dir();
if (n == 0)
run_test("Index Single Item Test", test_single_item);
run_test("Index Insertion Test" + n_str, test_insertion);
run_test("Index Removal Test" + n_str, test_removal);
run_test("Index Save and Load Test" + n_str, test_saving);
test :: run("Index Single Item Test", test_single_item);
test :: run("Index Insertion Test" + n_str, test_insertion);
test :: run("Index Removal Test" + n_str, test_removal);
test :: run("Index Save and Load Test" + n_str, test_saving);
}
int main(int argc, char **argv)

View File

@ -108,9 +108,9 @@ int main(int argc, char **argv)
{
test :: cp_data_dir();
run_test("Library Init Test", test_init);
run_test("Library Enable and Disable Test", test_enable);
run_test("Library Delete Path Test", test_remove);
run_test("Library Add Path Test", test_add);
run_test("Library Update Path Test", test_update);
test :: run("Library Init Test", test_init);
test :: run("Library Enable and Disable Test", test_enable);
test :: run("Library Delete Path Test", test_remove);
test :: run("Library Add Path Test", test_add);
test :: run("Library Update Path Test", test_update);
}

View File

@ -90,37 +90,39 @@ static void test_delete()
test_equal(playlist :: get_tracks("No Playlist"), IDX_NULL);
}
static unsigned int _test_has_loop_banned(unsigned int i)
{
Track *track = tags :: get_track(i);
bool has = playlist :: has(track, "Banned");
if (i <= 3)
return has ? LOOP_PASSED : LOOP_FAILED;
return has ? LOOP_FAILED : LOOP_PASSED;
}
static unsigned int _test_has_loop_favorites(unsigned int i)
{
Track *track = tags :: get_track(i);
bool has = playlist :: has(track, "Favorites");
if (i >= 16)
return has ? LOOP_PASSED : LOOP_FAILED;
return has ? LOOP_FAILED : LOOP_PASSED;
}
static void test_has()
{
test :: begin();
for (unsigned int i = 0; i < 24; i++) {
Track *track = tags :: get_track(i);
if (i <= 3)
check_equal(playlist :: has(track, "Banned"), true);
else
check_equal(playlist :: has(track, "Banned"), false);
}
test :: success();
test :: begin();
for (unsigned int i = 0; i < 24; i++) {
Track *track = tags :: get_track(i);
if (i >= 16)
check_equal(playlist :: has(track, "Favorites"), true);
else
check_equal(playlist :: has(track, "Favorites"), false);
}
test :: success();
test_for_each(0, 24, 1, _test_has_loop_banned);
test_for_each(0, 24, 1, _test_has_loop_favorites);
}
int main(int argc, char **argv)
{
test :: rm_data_dir();
run_test("Playlist Initialization Test", test_init);
run_test("Playlist Queue Test", test_queue);
run_test("Playlist Add Test", test_add);
run_test("Playlist Delete Test", test_delete);
run_test("Playlist Has Test", test_has);
test :: run("Playlist Initialization Test", test_init);
test :: run("Playlist Queue Test", test_queue);
test :: run("Playlist Add Test", test_add);
test :: run("Playlist Delete Test", test_delete);
test :: run("Playlist Has Test", test_has);
return 0;
}

View File

@ -12,6 +12,7 @@ unsigned int count_add = 0;
unsigned int count_del = 0;
unsigned int count_updated = 0;
unsigned int last_update = 0;
unsigned int expected = 0;
Track *TRACK_NULL = NULL;
@ -25,6 +26,7 @@ public:
std::vector <sort_info> get_sorder() { return _sort_order; };
};
TestQueue *Q = NULL, *R = NULL;
void test_add_cb_noop(Queue *q, unsigned int id) { }
void test_del_cb_noop(Queue *q, unsigned int id) { }
@ -74,35 +76,58 @@ void test_flags()
void test_add_cb(Queue *q, unsigned int id)
{
check_equal(id, count_add);
count_add++;
}
void test_del_cb(Queue *q, unsigned int id)
{
if (count_del % 2 == 0)
check_equal(id, (unsigned)0);
else
check_equal(id, 24 - ((count_del + 1) / 2));
count_del++;
}
void test_del_cb2(Queue *q, unsigned int id)
unsigned int _test_add_loop(unsigned int i)
{
check_equal(id, 23 - count_del);
count_del++;
Track *track = tags :: get_track(i % 24);
unsigned int index = Q->add(track);
expected += track->length();
if (index != i)
return LOOP_FAILED;
if ((index + 1) != count_add)
return LOOP_FAILED;
return LOOP_PASSED;
}
void test_del_cb3(Queue *q, unsigned int id)
unsigned int _test_del_loop(unsigned int i)
{
check_equal(id, (unsigned)0);
Track *track = tags :: get_track(i);
unsigned int j = (i + 1) * 2;
Q->del(track);
expected -= track->length() * 2;
if (count_del != j)
return LOOP_FAILED;
return LOOP_PASSED;
}
unsigned int _test_del_middle_loop(unsigned int i)
{
unsigned int j = 23 - i;
expected -= (*Q)[j]->length();
Q->del(j);
return (count_del == (i + 1)) ? LOOP_PASSED : LOOP_FAILED;
}
unsigned int _test_del_front_loop(unsigned int i)
{
expected -= (*Q)[0]->length();
Q->del((unsigned int)0);
return (count_del == (i + 1)) ? LOOP_PASSED : LOOP_FAILED;
}
void test_add_remove()
{
Track *track;
TestQueue q(0);
unsigned int expected = 0;
Q = &q;
get_callbacks()->on_queue_track_add = test_add_cb;
get_callbacks()->on_queue_track_del = test_del_cb;
@ -114,12 +139,7 @@ void test_add_remove()
/* Add tracks */
test :: begin();
for (unsigned int i = 0; i < 24; i++) {
check_equal(q.add(tags :: get_track(i)), i);
expected += 100 + (i * 10);
}
test :: success();
test_for_each(0, 24, 1, _test_add_loop);
test_equal(q.get_length(), expected);
test_equal(q.length_str(), (std::string)"1 hour, 26 minutes");
test_equal(q.size(), (unsigned)24);
@ -127,12 +147,7 @@ void test_add_remove()
/* Add everything again */
test :: begin();
for (unsigned int i = 0; i < 24; i++) {
check_equal(q.add(tags :: get_track(i)), i + 24);
expected += 100 + (i * 10);
}
test :: success();
test_for_each(24, 48, 1, _test_add_loop);
test_equal(q.get_length(), expected);
test_equal(q.length_str(), (std::string)"2 hours, 52 minutes");
test_equal(q.size(), (unsigned)48);
@ -140,13 +155,8 @@ void test_add_remove()
/* Test removing multiple tracks at once */
test :: begin();
for (unsigned int i = 0; i < 12; i++) {
track = tags :: get_track(i);
q.del(track);
expected -= 2 * (100 + (i * 10));
}
test :: success();
count_del = 0;
test_for_each(0, 12, 1, _test_del_loop);
test_equal(q.get_length(), expected);
test_equal(q.length_str(), (std::string)"1 hour, 50 minutes");
test_equal(q.size(), (unsigned)24);
@ -155,14 +165,7 @@ void test_add_remove()
/* Test removing tracks one at a time */
count_del = 0;
get_callbacks()->on_queue_track_del = test_del_cb2;
test :: begin();
for (unsigned int i = 23; i >= 12; i--) {
expected -= q[i]->length();
q.del(i);
}
test :: success();
test_for_each(0, 12, 1, _test_del_middle_loop);
test_equal(q.get_length(), expected);
test_equal(q.length_str(), (std::string)"55 minutes");
test_equal(q.size(), (unsigned)12);
@ -170,12 +173,8 @@ void test_add_remove()
/* Remove remaining tracks */
get_callbacks()->on_queue_track_del = test_del_cb3;
test :: begin();
while (q.size() > 0)
q.del((unsigned)0);
test :: success();
count_del = 0;
test_for_each(0, 12, 1, _test_del_front_loop);
test_equal(q.get_length(), (unsigned)0);
test_equal(q.length_str(), (std::string)"");
test_equal(q.size(), (unsigned)0);
@ -199,24 +198,29 @@ void test_updated_cb2(Queue *q, unsigned int row)
}
}
static void test_fill_q()
{
for (unsigned int i = 0; i < 24; i++)
Q->add(tags :: get_track(i));
}
unsigned int _test_update_loop(unsigned int i)
{
Q->updated(tags :: get_track(i));
return (last_update == i) ? LOOP_PASSED : LOOP_FAILED;
}
void test_updated()
{
Track *track;
TestQueue q(0);
Q = &q;
get_callbacks()->on_queue_track_add = test_add_cb_noop;
get_callbacks()->on_queue_track_changed = test_updated_cb;
/* Add tracks */
test :: begin();
for (unsigned int i = 0; i < 24; i++)
check_equal(q.add(tags :: get_track(i)), i);
test :: success();
test :: begin();
for (unsigned int i = 0; i < 24; i++)
q.updated(tags :: get_track(i));
test :: success();
test_fill_q();
test_for_each(0, 24, 1, _test_update_loop);
get_callbacks()->on_queue_track_changed = test_updated_cb2;
track = tags :: get_track(0);
@ -226,30 +230,35 @@ void test_updated()
test_equal(count_updated, (unsigned)3);
}
static void test_fill_q(TestQueue *q)
{
for (unsigned int i = 0; i < 24; i++)
q->add(tags :: get_track(i));
}
unsigned int expected_rand[] = { 1, 4, 8, 13, 19, 3, 14, 16, 20, 2, 11, 17,
23, 6, 12, 18, 0, 5, 9, 10, 15, 21, 22, 7 };
unsigned int _test_next_loop(unsigned int i)
{
Track *track = Q->next();
if (track == TRACK_NULL)
return LOOP_FAILED;
return (track->index() == (i % 24)) ? LOOP_PASSED : LOOP_FAILED;
}
unsigned int _test_next_rand_loop(unsigned int i)
{
Track *track = Q->next();
if (track == TRACK_NULL)
return LOOP_FAILED;
return (track->index() == expected_rand[i]) ? LOOP_PASSED : LOOP_FAILED;
}
void test_next()
{
Track *track;
TestQueue q(0);
Q = &q;
get_callbacks()->on_queue_track_del = test_del_cb_noop;
test_fill_q();
test_fill_q(&q);
test :: begin();
for (unsigned int i = 0; i < 24; i++) {
track = q.next();
check_not_equal(track, TRACK_NULL);
check_equal(track->index(), i);
}
test :: success();
test_for_each(0, 24, 1, _test_next_loop);
test_equal(q.size(), (unsigned)0);
test_equal(q.length_str(), (std::string)"");
test_equal(q.next(), TRACK_NULL);
@ -257,15 +266,9 @@ void test_next()
q.set_flag(Q_RANDOM);
random_seed(0);
test_fill_q();
test_fill_q(&q);
test :: begin();
for (unsigned int i = 0; i < 24; i++) {
track = q.next();
check_not_equal(track, TRACK_NULL);
check_equal(track->index(), expected_rand[i]);
}
test :: success();
test_for_each(0, 24, 1, _test_next_rand_loop);
test_equal(q.size(), (unsigned)0);
test_equal(q.length_str(), (std::string)"");
test_equal(q.next(), TRACK_NULL);
@ -273,21 +276,18 @@ void test_next()
q.set_flag(Q_REPEAT);
q.unset_flag(Q_RANDOM);
test_fill_q(&q);
test :: begin();
for (unsigned int i = 0; i < 48; i++) {
track = q.next();
check_not_equal(track, TRACK_NULL);
check_equal(track->index(), i % 24);
}
test :: success();
test_fill_q();
test_for_each(0, 48, 1, _test_next_loop);
test_equal(q.size(), (unsigned)24);
}
void test_select()
{
TestQueue q(0);
test_fill_q(&q);
Q = &q;
test_fill_q();
test_equal(q.size(), (unsigned)24);
q.track_selected(10);
@ -300,44 +300,70 @@ void test_select()
test_equal(q.next()->index(), (unsigned)1);
}
unsigned int exp_sort_title[] = { 1, 18, 19, 16, 20, 8, 2, 9, 23, 10, 17, 11,
3, 21, 4, 0, 5, 22, 6, 12, 7, 13, 14, 15 };
unsigned int exp_sort_ye_ti[] = { 0, 3, 2, 1, 7, 6, 5, 4, 11, 10, 9, 8,
22, 21, 17, 23, 20, 16, 19, 18, 15, 14, 13, 12 };
unsigned int _test_sort_title(unsigned int i)
{
if ((*Q)[i]->index() == exp_sort_title[i])
return LOOP_PASSED;
return LOOP_FAILED;
}
unsigned int _test_sort_title_reverse(unsigned int i)
{
if ((*Q)[i]->index() == exp_sort_title[23 - i])
return LOOP_PASSED;
return LOOP_FAILED;
}
unsigned int _test_sort_index(unsigned int i)
{
if ((*Q)[i]->index() == i)
return LOOP_PASSED;
return LOOP_FAILED;
}
unsigned int _test_sort_ye_ti(unsigned int i)
{
if ((*Q)[i]->index() == exp_sort_ye_ti[i])
return LOOP_PASSED;
return LOOP_FAILED;
}
void test_sorting()
{
TestQueue q(0);
Q = &q;
q.sort(SORT_TITLE, true);
test_equal(q.get_sorder().size(), (size_t)1);
test_fill_q(&q);
test :: begin();
for (unsigned int i = 0; i < 24; i++)
check_equal(q[i]->index(), exp_sort_title[i]);
test :: success();
test_fill_q();
test_for_each(0, 24, 1, _test_sort_title);
q.sort(SORT_TITLE, false);
test_equal(q.get_sorder().size(), (size_t)1);
test :: begin();
for (unsigned int i = 0; i < 24; i++)
check_equal(q[i]->index(), exp_sort_title[23 - i]);
test :: success();
test_for_each(0, 24, 1, _test_sort_title_reverse);
q.sort(SORT_LENGTH, true);
test :: begin();
for (unsigned int i = 0; i < 24; i++)
check_equal(q[i]->index(), i);
test :: success();
test_for_each(0, 1, 24, _test_sort_index);
q.sort(SORT_YEAR, true);
q.sort(SORT_TITLE, false);
q.sort(SORT_TITLE, false);
test_equal(q.get_sorder().size(), (size_t)2);
test :: begin();
for (unsigned int i = 0; i < 24; i++)
check_equal(q[i]->index(), exp_sort_ye_ti[i]);
test :: success();
test_for_each(0, 24, 1, _test_sort_ye_ti);
}
unsigned int _test_saving_loop(unsigned int i)
{
if ((*Q)[i]->index() == (*R)[i]->index())
return LOOP_PASSED;
return LOOP_FAILED;
}
void test_saving()
@ -346,29 +372,23 @@ void test_saving()
TestQueue r(0);
File f("test.q", 0);
test_fill_q(&q);
Q = &q;
R = &r;
test_fill_q();
test :: begin();
f.open(OPEN_WRITE);
q.write(f);
f.close();
test :: success();
test :: begin();
f.open(OPEN_READ);
r.read(f);
f.close();
test :: success();
test_equal(r.has_flag(Q_RANDOM), q.has_flag(Q_RANDOM));
test_equal(r.size(), q.size());
test_equal(r.size_str(), q.size_str());
test_equal(r.length_str(), q.length_str());
test :: begin();
for (unsigned int i = 0; i < q.size(); i++)
check_equal(r[i]->index(), q[i]->index());
test :: success();
test_for_each(0, 24, 1, _test_saving_loop);
}
int main(int argc, char **argv)
@ -376,14 +396,14 @@ int main(int argc, char **argv)
test :: cp_data_dir();
tags :: init();
run_test("Queue Default Constructor Test", test_default);
run_test("Queue Constructor Test", test_constructor);
run_test("Queue Flag Test", test_flags);
run_test("Queue Add and Remove Test", test_add_remove);
run_test("Queue Track Updated Test", test_updated);
run_test("Queue Pick Next Test", test_next);
run_test("Queue Select Track Test", test_select);
run_test("Queue Sorting Test", test_sorting);
run_test("Queue Save and Load Test", test_saving);
test :: run("Queue Default Constructor Test", test_default);
test :: run("Queue Constructor Test", test_constructor);
test :: run("Queue Flag Test", test_flags);
test :: run("Queue Add and Remove Test", test_add_remove);
test :: run("Queue Track Updated Test", test_updated);
test :: run("Queue Pick Next Test", test_next);
test :: run("Queue Select Track Test", test_select);
test :: run("Queue Sorting Test", test_sorting);
test :: run("Queue Save and Load Test", test_saving);
return 0;
}

View File

@ -7,15 +7,17 @@
#include <sstream>
static void do_test_rng(unsigned int seed)
unsigned int SEED = 0;
static void do_test_rng()
{
random_seed(seed);
random_seed(SEED);
for (unsigned int i = 0; i <= 10; i++) {
if (i <= seed)
test_equal(random(seed, i), seed);
if (i <= SEED)
test_equal(random(SEED, i), SEED);
else
test_equal(random(seed, i), seed + (i % (i - seed)));
test_equal(random(SEED, i), SEED + (i % (i - SEED)));
}
}
@ -24,8 +26,9 @@ static void test_rng(unsigned int seed)
std::stringstream ss;
ss << " (seed = " << seed << ")";
std::string seed_str = ss.str();
SEED = seed;
run_test("Random Number Generator Test" + seed_str, do_test_rng, seed);
test :: run("Random Number Generator Test" + seed_str, do_test_rng);
}
int main(int argc, char **argv)

View File

@ -54,7 +54,7 @@ static void test_album_tag_lookup()
int main(int argc, char **argv)
{
run_test("Album Tag Test", test_album_tag);
run_test("Album Tag Lookup Test", test_album_tag_lookup);
test :: run("Album Tag Test", test_album_tag);
test :: run("Album Tag Lookup Test", test_album_tag_lookup);
return 0;
}

View File

@ -36,7 +36,7 @@ static void test_artist_tag_lookup()
int main(int argc, char **argv)
{
run_test("Artist Tag Test", test_artist_tag);
run_test("Artist Tag Lookup Test", test_artist_tag_lookup);
test :: run("Artist Tag Test", test_artist_tag);
test :: run("Artist Tag Lookup Test", test_artist_tag_lookup);
return 0;
}

View File

@ -51,7 +51,7 @@ static void test_generic_tag_comparison()
int main(int argc, char **argv)
{
run_test("Generic Tag Test", test_generic_tag);
run_test("Generic Tag Compare Test", test_generic_tag_comparison);
test :: run("Generic Tag Test", test_generic_tag);
test :: run("Generic Tag Compare Test", test_generic_tag_comparison);
return 0;
}

View File

@ -36,7 +36,7 @@ static void test_genere_tag_lookup()
int main(int argc, char **argv)
{
run_test("Genre Tag Test", test_artist_tag);
run_test("Genre Tag Lookup Test", test_genere_tag_lookup);
test :: run("Genre Tag Test", test_artist_tag);
test :: run("Genre Tag Lookup Test", test_genere_tag_lookup);
return 0;
}

View File

@ -67,7 +67,7 @@ static void test_library_tag_lookup()
int main(int argc, char **argv)
{
run_test("Library Tag Test", test_library_tag);
run_test("Library Tag Lookup Test", test_library_tag_lookup);
test :: run("Library Tag Test", test_library_tag);
test :: run("Library Tag Lookup Test", test_library_tag_lookup);
return 0;
}

View File

@ -218,10 +218,10 @@ int main(int argc, char **argv)
genre = tags :: get_genre("Video Game Music");
library = tags :: get_library(MUSIC_DIR);
run_test("Track Tag Default Constructor Test", test_track_tag_default);
run_test("Track Tag Constructor Test", test_track_tag_constructor);
run_test("Track Tag Destructor Test", test_track_tag_destructor);
run_test("Track Tag Lookup Test", test_track_tag_lookup);
run_test("Track Tag Locale Test", test_track_tag_locale);
test :: run("Track Tag Default Constructor Test", test_track_tag_default);
test :: run("Track Tag Constructor Test", test_track_tag_constructor);
test :: run("Track Tag Destructor Test", test_track_tag_destructor);
test :: run("Track Tag Lookup Test", test_track_tag_lookup);
test :: run("Track Tag Locale Test", test_track_tag_locale);
return 0;
}

View File

@ -17,6 +17,6 @@ static void test_version()
int main(int argc, char **argv)
{
run_test("Version Test", test_version);
test :: run("Version Test", test_version);
return 0;
}

52
tests/sanity.cpp Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright 2015 (c) Anna Schumaker.
*/
#include <tests/test.h>
#include <cstdlib>
static unsigned int expected_failures = 0;
#define should_fail(code) \
code; \
expected_failures++
static unsigned int test_for_each_body(unsigned int i)
{
if (i > 10)
return LOOP_FAILED;
return LOOP_PASSED;
}
static void test_tests()
{
test_equal(0, 0);
test_equal((std::string)"2", (std::string)"2");
test_equal((void *)4, (void *)4);
should_fail(test_equal(0, 1));
should_fail(test_equal((std::string)"2", "3"));
should_fail(test_equal((void *)4, (void *)5));
test_not_equal(0, 1);
test_not_equal((std::string)"2", "3");
test_not_equal((void *)4, (void *)5);
should_fail(test_not_equal(0, 0));
should_fail(test_not_equal((std::string)"2", "2"));
should_fail(test_not_equal((void *)4, (void *)4));
test_for_each(0, 10, 1, test_for_each_body);
should_fail(test_for_each(0, 15, 1, test_for_each_body));
test_equal(test :: failed, expected_failures);
test :: failed -= expected_failures;
}
int main(int argc, char **argv)
{
test :: run("Testing Sanity Check", test_tests);
return 0;
}

137
tests/test.cpp Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright 2015 (c) Anna Schumaker.
*/
#include <tests/test.h>
#include <glib.h>
#include <iostream>
#include <stdlib.h>
static unsigned int test_num;
unsigned int test :: failed;
template <class T>
static void generic_equal(const T &a, const T &b, const unsigned int line)
{
std::cout << " " << test_num++ << ": ";
if (a == b)
std::cout << "Success!" << std::endl;
else {
std::cout << "Failed at line " << line << ":" << std::endl;
std::cout << " Actual: " << a << std::endl;
std::cout << " Expected: " << b << std::endl;
test :: failed++;
}
}
template <class T>
static void generic_not_equal(const T &a, const T &b, const unsigned int line)
{
std::cout << " " << test_num++ << ": ";
if (a != b)
std::cout << "Success!" << std::endl;
else {
std::cout << "Failed at line " << line << ":" << std::endl;
std::cout << " Unexpected: " << a << std::endl;
test :: failed++;
}
}
void test :: run(const std::string &name, void (*func)())
{
failed = 0;
test_num = 0;
std::cout << name << std::endl;
func();
std::cout << std::endl;
if (failed > 0) {
std::cout << failed << " tests failed =(" << std::endl << std::endl;
exit(failed);
}
}
void test :: for_each(unsigned int init, unsigned int max, unsigned int inc,
unsigned int (*func)(unsigned int), unsigned int line)
{
std::cout << " " << test_num++ << ": ";
for (unsigned int i = init; i < max; i += inc) {
int ret = func(i);
if (ret != 0) {
std::cout << "Failed loop at line: " << ret;
std::cout << " (i = " << i << ")" << std::endl;
std::cout << " Called from line: " << line << std::endl;
test :: failed++;
return;
}
}
std::cout << "Success!" << std::endl;
}
#define DEFINE_COMPARE_FUNC(name, type) \
void test :: name(const type a, const type b, unsigned int line) \
{ generic_##name(a, b, line); }
#define DEFINE_COMPARE(type) \
DEFINE_COMPARE_FUNC(equal, type) \
DEFINE_COMPARE_FUNC(not_equal, type)
DEFINE_COMPARE(int)
DEFINE_COMPARE(std::string &)
DEFINE_COMPARE(void *)
std::string test :: data_dir()
{
std::string res = g_get_user_data_dir();
res += "/ocarina-test";
return res;
}
std::string test :: data_file(const std::string &name)
{
return data_dir() + "/" + name;
}
bool test :: data_dir_exists()
{
return g_file_test(data_dir().c_str(), G_FILE_TEST_IS_DIR);
}
bool test :: data_file_exists(const std::string &name)
{
return g_file_test(data_file(name).c_str(), G_FILE_TEST_EXISTS);
}
void test :: rm_data_dir()
{
std::string cmd = "rm -r " + data_dir() + " 2>/dev/null";
if (data_dir_exists())
system(cmd.c_str());
}
void test :: reset_data_dir()
{
std::string cmd = "mkdir -p " + data_dir();
rm_data_dir();
system(cmd.c_str());
}
void test :: cp_data_dir()
{
reset_data_dir();
std::string cmd = "cp -r tests/Data/* " + data_dir();
system(cmd.c_str());
}
void test :: gen_library()
{
system("tests/gen_library.sh");
}
void test :: rm_library_dirs()
{
system("rm -r /tmp/ocarina/dir2 /tmp/ocarina/dir4");
}