/* * Copyright 2014 (c) Anna Schumaker. */ #include #include #include #include #include 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; class TestQueue : public Queue { public: TestQueue() : Queue() {} TestQueue(unsigned int f) : Queue(f) {} unsigned int get_cur() { return _cur; } unsigned int get_flags() { return _flags; } unsigned int get_length() { return _length; } std::vector 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) { } void test_default() { TestQueue q; test_equal(q.get_cur(), (unsigned)-1); test_equal(q.get_flags(), (unsigned)0); test_equal(q.get_length(), (unsigned)0); test_equal(q.get_sorder().size(), (size_t)0); test_equal(q.next(), (Track *)NULL); } void test_constructor() { unsigned int flags = Q_ENABLED | Q_RANDOM; TestQueue q(flags); test_equal(q.get_cur(), (unsigned)-1); test_equal(q.get_flags(), flags); test_equal(q.get_length(), (unsigned)0); test_equal(q.get_sorder().size(), (size_t)0); test_equal(q.next(), (Track *)NULL); } void test_flags() { TestQueue q(0); test_equal(q.get_flags(), (unsigned)0); q.set_flag(Q_ENABLED); test_equal(q.get_flags(), (unsigned)Q_ENABLED); q.unset_flag(Q_ENABLED); test_equal(q.get_flags(), (unsigned)0); q.set_flag(Q_REPEAT); q.set_flag(Q_RANDOM); test_equal(q.has_flag(Q_ENABLED), false); test_equal(q.has_flag(Q_RANDOM), true); test_equal(q.has_flag(Q_REPEAT), true); test_equal(q.has_flag(Q_NO_SORT), false); } void test_add_cb(Queue *q, unsigned int id) { count_add++; } void test_del_cb(Queue *q, unsigned int id) { count_del++; } unsigned int _test_add_loop(unsigned int i) { 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; } unsigned int _test_del_loop(unsigned int i) { 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() { TestQueue q(0); Q = &q; get_callbacks()->on_queue_track_add = test_add_cb; get_callbacks()->on_queue_track_del = test_del_cb; test_equal(q.get_length(), expected); test_equal(q.length_str(), (std::string)""); test_equal(q.size(), (unsigned)0); test_equal(q.size_str(), (std::string)"0"); /* Add tracks */ 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); test_equal(q.size_str(), (std::string)"24"); /* Add everything again */ 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); test_equal(q.size_str(), (std::string)"48"); /* Test removing multiple tracks at once */ 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); test_equal(q.size_str(), (std::string)"24"); /* Test removing tracks one at a time */ count_del = 0; 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); test_equal(q.size_str(), (std::string)"12"); /* Remove remaining tracks */ 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); test_equal(q.size_str(), (std::string)"0"); } void test_updated_cb(Queue *q, unsigned int row) { last_update = row; } void test_updated_cb2(Queue *q, unsigned int row) { switch (row) { case 0: case 24: case 25: count_updated++; default: break; } } 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; 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); q.add(track); q.add(track); q.updated(track); test_equal(count_updated, (unsigned)3); } 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() { TestQueue q(0); Q = &q; get_callbacks()->on_queue_track_del = test_del_cb_noop; test_fill_q(); 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); q.set_flag(Q_RANDOM); random_seed(0); test_fill_q(); 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); q.set_flag(Q_REPEAT); q.unset_flag(Q_RANDOM); test_fill_q(); test_for_each(0, 48, 1, _test_next_loop); test_equal(q.size(), (unsigned)24); } void test_select() { TestQueue q(0); Q = &q; test_fill_q(); test_equal(q.size(), (unsigned)24); q.track_selected(10); test_equal(q.size(), (unsigned)23); test_equal(q.next()->index(), (unsigned)11); q.set_flag(Q_REPEAT); q.track_selected(0); test_equal(q.size(), (unsigned)22); 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(); test_for_each(0, 24, 1, _test_sort_title); q.sort(SORT_TITLE, false); test_equal(q.get_sorder().size(), (size_t)1); test_for_each(0, 24, 1, _test_sort_title_reverse); q.sort(SORT_LENGTH, true); 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_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() { TestQueue q(Q_RANDOM); TestQueue r(0); File f("test.q", 0); Q = &q; R = &r; test_fill_q(); f.open(OPEN_WRITE); q.write(f); f.close(); f.open(OPEN_READ); r.read(f); f.close(); 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_for_each(0, 24, 1, _test_saving_loop); } int main(int argc, char **argv) { test :: cp_data_dir(); tags :: init(); 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; }