/* * Copyright 2016 (c) Anna Schumaker. */ #include #include #include #include static struct playlist *cb_playlist = NULL; static struct track *cb_track = NULL; static void test_pl_updated(struct playlist *playlist, struct track *track) { cb_playlist = playlist; cb_track = track; } static struct playlist_ops test_noop; static struct playlist_ops test_ops = { .pl_can_select = playlist_generic_can_select, .pl_set_random = playlist_generic_set_random, .pl_sort = playlist_generic_sort, }; static struct playlist_callbacks test_cb = { .pl_cb_updated = test_pl_updated, }; static void test_null() { g_assert_null(playlist_new(PL_MAX_TYPE, "NULL")); g_assert_null(playlist_new(PL_MAX_TYPE, NULL)); g_assert_false(playlist_delete(NULL)); g_assert_null(playlist_lookup(PL_MAX_TYPE, "NULL")); g_assert_null(playlist_lookup(PL_MAX_TYPE, NULL)); g_assert_null(playlist_get(PL_MAX_TYPE, 0)); g_assert(playlist_current() == playlist_lookup(PL_SYSTEM, "Collection")); g_assert_false(playlist_select(NULL)); g_assert(playlist_current() == playlist_lookup(PL_SYSTEM, "Collection")); g_assert_null(playlist_next()); playlist_selected(NULL); playlist_played(NULL); g_assert_false(playlist_add(NULL, NULL)); g_assert_false(playlist_add(NULL, track_get(0))); g_assert_false(playlist_has(NULL, NULL)); g_assert_false(playlist_has(NULL, track_get(0))); g_assert_cmpuint(playlist_size(NULL), ==, 0); g_assert_false(playlist_remove(NULL, NULL)); g_assert_false(playlist_remove(NULL, track_get(0))); playlist_set_random(NULL, true); g_assert_false(playlist_sort(NULL, COMPARE_TRACK)); g_assert_false(playlist_sort(NULL, COMPARE_TRACK)); playlist_generic_resort(NULL); playlist_clear_sort(NULL); playlist_generic_update(NULL, NULL); playlist_generic_save(NULL, NULL, PL_SAVE_ALL); playlist_generic_load(NULL, NULL, PL_SAVE_ALL); } static void test_playlist() { struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); unsigned int i; playlist_generic_init(&p, NULL); for (i = 0; i < 13; i++) playlist_generic_add_track_front(&p, track_get(i)); /* Trigger an update for each track. */ for (i = 0; i < 13; i++) { playlist_generic_update(&p, track_get(i)); g_assert(cb_playlist == &p); g_assert(cb_track == track_get(i)); } playlist_generic_update(&p, NULL); g_assert(cb_playlist == &p); g_assert_null(cb_track); } static void test_sorting() { struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); struct track *track; unsigned int i; playlist_generic_init(&p, NULL); g_assert_cmpuint(g_slist_length(p.pl_queue.q_sort), ==, 3); playlist_clear_sort(&p); g_assert_cmpuint(g_slist_length(p.pl_queue.q_sort), ==, 0); cb_playlist = NULL; for (i = 0; i < 13; i++) { track = track_get(i); track->tr_count = (track->tr_track % 2) ? 4 : 2; playlist_generic_add_track_front(&p, track); } p.pl_ops = &test_noop; g_assert_false(playlist_sort(&p, COMPARE_TRACK)); g_assert_null(cb_playlist); g_assert_null(cb_track); p.pl_ops = &test_ops; g_assert_true(playlist_sort(&p, COMPARE_TRACK)); g_assert(cb_playlist == &p); g_assert_null(cb_track); for (i = 0; i < 13; i++) { track = queue_at(&p.pl_queue, i); g_assert_cmpuint(track->tr_track, ==, i + 1); } playlist_clear_sort(&p); playlist_generic_resort(&p); g_assert_true(playlist_sort(&p, COMPARE_COUNT)); for (i = 0; i < 13; i++) { track = queue_at(&p.pl_queue, i); g_assert_cmpuint(track->tr_count, ==, (i < 6) ? 2 : 4); } g_assert_true(playlist_sort(&p, COMPARE_TRACK)); for (i = 0; i < 13; i++) { track = queue_at(&p.pl_queue, i); g_assert_cmpuint(track->tr_count, ==, (i < 6) ? 2 : 4); if (i < 6) g_assert_cmpuint(track->tr_track, ==, (i + 1) * 2); else g_assert_cmpuint(track->tr_track, ==, (2 * i) - 11); } g_assert_true(playlist_sort(&p, COMPARE_COUNT)); for (i = 0; i < 13; i++) { track = queue_at(&p.pl_queue, i); g_assert_cmpuint(track->tr_count, ==, (i < 7) ? 4 : 2); if (i < 7) g_assert_cmpuint(track->tr_track, ==, (2 * i) + 1); else g_assert_cmpuint(track->tr_track, ==, (2 * i) - 12); } } static void test_next() { struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); struct track *track; unsigned int i; g_random_set_seed(0); playlist_generic_init(&p, NULL); for (i = 0; i < 13; i++) playlist_generic_add_track(&p, track_get(i)); g_assert_true(playlist_select(&p)); g_assert(playlist_current() == &p); g_assert_cmpuint(p.pl_queue.q_cur.it_pos, ==, UINT_MAX); /* Test playlist_next() with wraparound, but no random. */ for (i = 0; i < (13 * 2); i++) { track = playlist_next(); g_assert_nonnull(track); g_assert_cmpuint(track->tr_track, ==, (i % 13) + 1); g_assert_cmpuint(playlist_size(&p), ==, 13); } playlist_set_random(&p, true); g_assert_true(p.pl_random); /* rand() = { 10, 4, 6, 1, 8, 4, 1 } */ g_assert_cmpuint(playlist_next()->tr_track, ==, 9); g_assert_cmpuint(playlist_next()->tr_track, ==, 13); g_assert_cmpuint(playlist_next()->tr_track, ==, 6); g_assert_cmpuint(playlist_next()->tr_track, ==, 7); g_assert_cmpuint(playlist_next()->tr_track, ==, 2); g_assert_cmpuint(playlist_next()->tr_track, ==, 6); g_assert_cmpuint(playlist_next()->tr_track, ==, 1); g_assert_cmpuint(playlist_size(&p), ==, 13); } static void test_save_load() { struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); struct playlist q = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test 2", 0, NULL); struct playlist r = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops); struct playlist s = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test 2", 0, NULL); struct file f = FILE_INIT("test.playlist", 0); unsigned int i; for (i = 0; i < 13; i++) { queue_add(&p.pl_queue, track_get(i)); queue_add(&q.pl_queue, track_get(i)); } playlist_set_random(&p, true); playlist_clear_sort(&p); playlist_sort(&p, COMPARE_TRACK); p.pl_queue.q_cur.it_pos = 3; q.pl_queue.q_cur.it_pos = 4; g_assert_false(file_exists(&f)); g_assert_true( file_open(&f, OPEN_WRITE)); playlist_generic_save(&p, &f, PL_SAVE_METADATA); playlist_generic_save(&q, &f, PL_SAVE_ALL); file_close(&f); g_assert_true(file_open(&f, OPEN_READ)); playlist_generic_load(&r, &f, PL_SAVE_METADATA); playlist_generic_load(&s, &f, PL_SAVE_ALL); file_close(&f); g_assert_true(r.pl_random); g_assert_cmpuint(r.pl_queue.q_cur.it_pos, ==, 3); g_assert_cmpuint(g_slist_length(r.pl_queue.q_sort), ==, 1); g_assert_cmpuint(GPOINTER_TO_UINT(r.pl_queue.q_sort->data), ==, COMPARE_TRACK); g_assert_cmpuint(g_queue_get_length(&r.pl_queue.q_tracks), ==, 0); g_assert_false(s.pl_random); g_assert_cmpuint(s.pl_queue.q_cur.it_pos, ==, 4); g_assert(queue_iter_val(&s.pl_queue.q_cur) == queue_at(&q.pl_queue, 4)); g_assert_cmpuint(g_slist_length(s.pl_queue.q_sort), ==, 0); g_assert_cmpuint(g_queue_get_length(&s.pl_queue.q_tracks), ==, 13); } int main(int argc, char **argv) { struct library *library; int ret; idle_init_sync(); settings_init(); tags_init(); playlist_init(NULL, &test_cb); while (idle_run_task()) {}; library = library_find("tests/Music"); track_add(library, "tests/Music/Hyrule Symphony/01 - Title Theme.ogg"); track_add(library, "tests/Music/Hyrule Symphony/02 - Kokiri Forest.ogg"); track_add(library, "tests/Music/Hyrule Symphony/03 - Hyrule Field.ogg"); track_add(library, "tests/Music/Hyrule Symphony/04 - Hyrule Castle.ogg"); track_add(library, "tests/Music/Hyrule Symphony/05 - Lon Lon Ranch.ogg"); track_add(library, "tests/Music/Hyrule Symphony/06 - Kakariko Village.ogg"); track_add(library, "tests/Music/Hyrule Symphony/07 - Death Mountain.ogg"); track_add(library, "tests/Music/Hyrule Symphony/08 - Zora's Domain.ogg"); track_add(library, "tests/Music/Hyrule Symphony/09 - Gerudo Valley.ogg"); track_add(library, "tests/Music/Hyrule Symphony/10 - Ganondorf.ogg"); track_add(library, "tests/Music/Hyrule Symphony/11 - Princess Zelda.ogg"); track_add(library, "tests/Music/Hyrule Symphony/12 - Ocarina Medley.ogg"); track_add(library, "tests/Music/Hyrule Symphony/13 - The Legend of Zelda Medley.ogg"); g_test_init(&argc, &argv, NULL); g_test_add_func("/Core/Playlist/NULL", test_null); g_test_add_func("/Core/Playlists/General", test_playlist); g_test_add_func("/Core/Playlists/Sorting", test_sorting); g_test_add_func("/Core/Playlists/Next Track", test_next); g_test_add_func("/Core/Playlist/Save and Load", test_save_load); ret = g_test_run(); playlist_deinit(); tags_deinit(); settings_deinit(); idle_deinit(); return ret; }