/* * Copyright 2014 (c) Anna Schumaker. */ #include #include #include #include unsigned int count_init = 0; unsigned int count_deinit = 0; unsigned int count_added = 0; unsigned int count_deleted = 0; unsigned int count_cleared = 0; unsigned int count_updated = 0; static void *queue_op_init(struct queue *queue, void *data) { count_init++; return GUINT_TO_POINTER(count_init); } static void queue_op_deinit(struct queue *queue) { count_deinit++; } static void queue_op_added(struct queue *queue, unsigned int pos) { count_added++; } static void queue_op_removed(struct queue *queue, unsigned int pos) { count_deleted++; } static void queue_op_cleared(struct queue *queue, unsigned int n) { count_cleared++; } static void queue_op_updated(struct queue *queue, unsigned int pos) { count_updated++; } static const struct queue_ops test_ops = { .qop_init = queue_op_init, .qop_deinit = queue_op_deinit, .qop_added = queue_op_added, .qop_removed = queue_op_removed, .qop_cleared = queue_op_cleared, .qop_updated = queue_op_updated, }; static void test_init() { struct queue q; struct queue_iter it; queue_init(&q, NULL, NULL); g_assert_cmpuint(count_init, ==, 0); g_assert_null(q.q_private); g_assert_cmpuint(q.q_cur.it_pos, ==, (unsigned int)-1); g_assert_cmpuint(q.q_length, ==, 0); g_assert_null(q.q_sort); g_assert_null(q.q_ops); queue_iter_init(&q, &it); g_assert_null(it.it_iter); g_assert_cmpuint(it.it_pos, ==, (unsigned int)-1); g_assert_null(queue_iter_val(&it)); queue_deinit(&q); g_assert_cmpuint(count_deinit, ==, 0); queue_init(&q, &test_ops, NULL); g_assert_cmpuint(count_init, ==, 1); g_assert_cmpuint(GPOINTER_TO_UINT(q.q_private), ==, 1); g_assert_cmpuint(q.q_cur.it_pos, ==, (unsigned int)-1); g_assert_cmpuint(q.q_length, ==, 0); g_assert_null(q.q_sort); g_assert(q.q_ops == &test_ops); queue_deinit(&q); g_assert_cmpuint(count_deinit, ==, 1); } static void test_queue(gconstpointer arg) { unsigned int N = GPOINTER_TO_UINT(arg); unsigned int ex_length = 0; unsigned int ex_size = N; struct queue_iter it; struct track *track; unsigned int i; struct queue q; count_added = 0; count_deleted = 0; count_cleared = 0; count_updated = 0; queue_init(&q, &test_ops, NULL); /* queue_add() */ for (i = 0; i < N; i++) { track = track_get(i % 13); ex_length += track->tr_length; g_assert_cmpuint(queue_add(&q, track), ==, i); g_assert_cmpuint(count_added, ==, i + 1); } g_assert_cmpuint(q.q_length, ==, ex_length); g_assert_cmpuint(queue_size(&q), ==, ex_size); /* queue_iter_init() */ if (N > 0) { queue_iter_init(&q, &it); g_assert_nonnull(it.it_iter); g_assert_cmpuint(it.it_pos, ==, 0); } /* queue_for_each() */ i = 0; queue_for_each(&q, &it) { g_assert_cmpuint(it.it_pos, ==, i); g_assert(queue_iter_val(&it) == track_get(i % 13)); i++; } g_assert_cmpuint(i, ==, N); g_assert_cmpuint(queue_size(&q), ==, ex_size); /* queue_remove_all() and queue_has() */ track = track_get(0); ex_length -= track->tr_length * (N / 13); ex_size -= (N / 13); if (N > 0) g_assert_true(queue_has(&q, track)); else g_assert_false(queue_has(&q, track)); g_assert_cmpuint(queue_remove_all(&q, track), ==, N / 13); g_assert_cmpuint(q.q_length, ==, ex_length); g_assert_cmpuint(queue_size(&q), ==, ex_size); g_assert_false(queue_has(&q, track)); /* queue_remove() and queue_erase() == true */ track = track_get(1); ex_length -= track->tr_length * (N / 13); ex_size -= (N / 13); for (i = 0; i < ex_size; i += 11) { g_assert(queue_at(&q, i) == track); queue_remove(&q, i); } g_assert_cmpuint(q.q_length, ==, ex_length); g_assert_cmpuint(queue_size(&q), ==, ex_size); /* queue_updated() */ track = track_get(2); queue_updated(&q, track); g_assert_cmpuint(count_updated, ==, N / 13); /* Tracks should not be removed. */ for (i = 0; i < ex_size; i++) { queue_selected(&q, i); g_assert_cmpuint(count_updated, ==, (N / 13) + (i + 1)); g_assert_cmpuint(queue_size(&q), ==, ex_size); } queue_clear(&q); g_assert_cmpuint(count_cleared, ==, 1); g_assert_cmpuint(queue_size(&q), ==, 0); g_assert_cmpuint(q.q_length, ==, 0); queue_deinit(&q); g_assert_cmpuint(count_cleared, ==, 2); g_assert_null(q.q_sort); } static void test_rand_select() { unsigned int i; struct queue q; g_random_set_seed(0); queue_init(&q, &test_ops, NULL); q.q_sort = g_slist_append(q.q_sort, GINT_TO_POINTER(COMPARE_TRACK)); for (i = 0; i < 13; i++) queue_add(&q, track_get(i)); /* * The comments below use the following notation: * : The value pointed to by q._cur. * (val): The value selected by q.track_selected(). * [val]: The value picked by q.next(). */ /* select = 6, track = 7 */ g_assert_cmpuint(queue_selected(&q, 6)->tr_track, ==, 7); /* select = 7, track = 8 */ g_assert_cmpuint(queue_selected(&q, 7)->tr_track, ==, 8); /* select = 2, track = 3 */ g_assert_cmpuint(queue_selected(&q, 2)->tr_track, ==, 3); g_assert_null(queue_selected(&q, 14)); queue_deinit(&q); } int main(int argc, char **argv) { struct library *library; int ret; idle_init_sync(); tags_init(); 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/Queue/Initialization", test_init); g_test_add_data_func("/Core/Queue/n = 0", GUINT_TO_POINTER( 0), test_queue); g_test_add_data_func("/Core/Queue/n = 13", GUINT_TO_POINTER( 13), test_queue); g_test_add_data_func("/Core/Queue/n = 100,009)", GUINT_TO_POINTER(100009), test_queue); g_test_add_func("/Core/Queue/Random Next and Selection", test_rand_select); ret = g_test_run(); tags_deinit(); idle_deinit(); return ret; }