diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/DumpDatabase.cxx | 148 | ||||
-rw-r--r-- | test/FakeReplayGainConfig.cxx | 25 | ||||
-rw-r--r-- | test/FakeSong.cxx | 33 | ||||
-rw-r--r-- | test/dump_playlist.cxx (renamed from test/dump_playlist.c) | 23 | ||||
-rw-r--r-- | test/dump_text_file.cxx (renamed from test/dump_text_file.c) | 12 | ||||
-rw-r--r-- | test/read_mixer.cxx (renamed from test/read_mixer.c) | 16 | ||||
-rw-r--r-- | test/read_tags.cxx (renamed from test/read_tags.c) | 58 | ||||
-rw-r--r-- | test/run_convert.c | 2 | ||||
-rw-r--r-- | test/run_decoder.cxx (renamed from test/run_decoder.c) | 37 | ||||
-rw-r--r-- | test/run_filter.c | 11 | ||||
-rw-r--r-- | test/run_inotify.cxx (renamed from test/run_inotify.c) | 31 | ||||
-rw-r--r-- | test/run_input.cxx (renamed from test/run_input.c) | 18 | ||||
-rw-r--r-- | test/run_output.cxx (renamed from test/run_output.c) | 42 | ||||
-rw-r--r-- | test/test_queue_priority.c | 175 | ||||
-rw-r--r-- | test/test_queue_priority.cxx | 186 |
15 files changed, 510 insertions, 307 deletions
diff --git a/test/DumpDatabase.cxx b/test/DumpDatabase.cxx new file mode 100644 index 000000000..ea0ebb44c --- /dev/null +++ b/test/DumpDatabase.cxx @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2003-2012 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "DatabaseRegistry.hxx" +#include "DatabasePlugin.hxx" +#include "DatabaseSelection.hxx" +#include "Directory.hxx" +#include "song.h" +#include "PlaylistVector.hxx" +#include "conf.h" +#include "tag.h" + +#include <iostream> +using std::cout; +using std::cerr; +using std::endl; + +#include <stdlib.h> + +static void +my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, + const gchar *message, G_GNUC_UNUSED gpointer user_data) +{ + if (log_domain != NULL) + g_printerr("%s: %s\n", log_domain, message); + else + g_printerr("%s\n", message); +} + +static bool +DumpDirectory(const Directory &directory, GError **) +{ + cout << "D " << directory.path << endl; + return true; +} + +static bool +DumpSong(song &song, GError **) +{ + cout << "S " << song.parent->path << "/" << song.uri << endl; + return true; +} + +static bool +DumpPlaylist(const PlaylistInfo &playlist, + const Directory &directory, GError **) +{ + cout << "P " << directory.path << "/" << playlist.name.c_str() << endl; + return true; +} + +int +main(int argc, char **argv) +{ + GError *error = nullptr; + + if (argc != 3) { + cerr << "Usage: DumpDatabase CONFIG PLUGIN" << endl; + return 1; + } + + const char *const config_path = argv[1]; + const char *const plugin_name = argv[2]; + + const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name); + if (plugin == NULL) { + cerr << "No such database plugin: " << plugin_name << endl; + return EXIT_FAILURE; + } + + /* initialize GLib */ + + g_thread_init(nullptr); + g_log_set_default_handler(my_log_func, nullptr); + + /* initialize MPD */ + + config_global_init(); + + if (!config_read_file(config_path, &error)) { + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + tag_lib_init(); + + /* do it */ + + const struct config_param *path = config_get_param(CONF_DB_FILE); + struct config_param *param = config_new_param("database", path->line); + if (path != nullptr) + config_add_block_param(param, "path", path->value, path->line); + + Database *db = plugin->create(param, &error); + + config_param_free(param); + + if (db == nullptr) { + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + if (!db->Open(&error)) { + delete db; + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + const DatabaseSelection selection("", true); + + if (!db->Visit(selection, DumpDirectory, DumpSong, DumpPlaylist, + &error)) { + db->Close(); + delete db; + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + db->Close(); + delete db; + + /* deinitialize everything */ + + config_global_finish(); + + return EXIT_SUCCESS; +} diff --git a/test/FakeReplayGainConfig.cxx b/test/FakeReplayGainConfig.cxx new file mode 100644 index 000000000..9c2431bf2 --- /dev/null +++ b/test/FakeReplayGainConfig.cxx @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "replay_gain_config.h" + +float replay_gain_preamp = 1.0; +float replay_gain_missing_preamp = 1.0; +bool replay_gain_limit = true; diff --git a/test/FakeSong.cxx b/test/FakeSong.cxx new file mode 100644 index 000000000..927a07652 --- /dev/null +++ b/test/FakeSong.cxx @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2003-2012 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "song.h" +#include "directory.h" +#include "gcc.h" + +#include <stdlib.h> + +struct directory detached_root; + +struct song * +song_dup_detached(gcc_unused const struct song *src) +{ + abort(); +} diff --git a/test/dump_playlist.c b/test/dump_playlist.cxx index 84ac69045..c95d4376e 100644 --- a/test/dump_playlist.c +++ b/test/dump_playlist.cxx @@ -18,23 +18,29 @@ */ #include "config.h" -#include "io_thread.h" -#include "input_init.h" +#include "TagSave.hxx" +#include "song.h" +#include "Directory.hxx" #include "input_stream.h" -#include "tag_pool.h" -#include "tag_save.h" #include "conf.h" -#include "song.h" #include "decoder_api.h" +#include "InputInit.hxx" +#include "IOThread.hxx" + +extern "C" { #include "decoder_list.h" #include "playlist_list.h" #include "playlist_plugin.h" +} #include <glib.h> #include <unistd.h> #include <stdlib.h> +Directory::Directory() {} +Directory::~Directory() {} + static void my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, const gchar *message, G_GNUC_UNUSED gpointer user_data) @@ -107,7 +113,7 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, return DECODE_COMMAND_NONE; } -float +void decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, const struct replay_gain_info *replay_gain_info) { @@ -121,13 +127,10 @@ decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, if (replay_gain_tuple_defined(tuple)) g_printerr("replay_gain[track]: gain=%f peak=%f\n", tuple->gain, tuple->peak); - - return 0.0; } void decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, - G_GNUC_UNUSED float replay_gain_db, char *mixramp_start, char *mixramp_end) { g_free(mixramp_start); @@ -157,7 +160,6 @@ int main(int argc, char **argv) /* initialize MPD */ - tag_pool_init(); config_global_init(); success = config_read_file(argv[1], &error); if (!success) { @@ -249,7 +251,6 @@ int main(int argc, char **argv) input_stream_global_finish(); io_thread_deinit(); config_global_finish(); - tag_pool_deinit(); return 0; } diff --git a/test/dump_text_file.c b/test/dump_text_file.cxx index f14371441..60da1c31c 100644 --- a/test/dump_text_file.c +++ b/test/dump_text_file.cxx @@ -18,17 +18,19 @@ */ #include "config.h" -#include "io_thread.h" -#include "input_init.h" +#include "IOThread.hxx" +#include "InputInit.hxx" #include "input_stream.h" -#include "text_input_stream.h" -#include "tag_pool.h" #include "conf.h" #include "stdbin.h" +extern "C" { +#include "text_input_stream.h" + #ifdef ENABLE_ARCHIVE #include "archive_list.h" #endif +} #include <glib.h> @@ -112,7 +114,6 @@ int main(int argc, char **argv) /* initialize MPD */ - tag_pool_init(); config_global_init(); io_thread_init(); @@ -164,7 +165,6 @@ int main(int argc, char **argv) io_thread_deinit(); config_global_finish(); - tag_pool_deinit(); return ret; } diff --git a/test/read_mixer.c b/test/read_mixer.cxx index f6de8177d..c7a5a3e03 100644 --- a/test/read_mixer.c +++ b/test/read_mixer.cxx @@ -18,11 +18,17 @@ */ #include "config.h" + +extern "C" { #include "mixer_control.h" #include "mixer_list.h" #include "filter_registry.h" +} + #include "pcm_volume.h" -#include "event_pipe.h" +#include "GlobalEvents.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" #include <glib.h> @@ -30,6 +36,8 @@ #include <string.h> #include <unistd.h> +EventLoop *main_loop; + #ifdef HAVE_PULSE #include "output/pulse_output_plugin.h" @@ -84,7 +92,7 @@ roar_output_set_volume(G_GNUC_UNUSED struct roar *roar, #endif void -event_pipe_emit(G_GNUC_UNUSED enum pipe_event event) +GlobalEvents::Emit(gcc_unused Event event) { } @@ -118,6 +126,8 @@ int main(int argc, G_GNUC_UNUSED char **argv) g_thread_init(NULL); + main_loop = new EventLoop(EventLoop::Default()); + mixer = mixer_new(&alsa_mixer_plugin, NULL, NULL, &error); if (mixer == NULL) { g_printerr("mixer_new() failed: %s\n", error->message); @@ -137,6 +147,8 @@ int main(int argc, G_GNUC_UNUSED char **argv) mixer_close(mixer); mixer_free(mixer); + delete main_loop; + assert(volume >= -1 && volume <= 100); if (volume < 0) { diff --git a/test/read_tags.c b/test/read_tags.cxx index faf9a45c0..f971c5ce1 100644 --- a/test/read_tags.c +++ b/test/read_tags.cxx @@ -18,17 +18,19 @@ */ #include "config.h" -#include "io_thread.h" +#include "IOThread.hxx" +extern "C" { #include "decoder_list.h" +} #include "decoder_api.h" -#include "input_init.h" +#include "InputInit.hxx" #include "input_stream.h" #include "audio_format.h" -#include "pcm_volume.h" +extern "C" { #include "tag_ape.h" #include "tag_id3.h" +} #include "tag_handler.h" -#include "idle.h" #include <glib.h> @@ -40,25 +42,6 @@ #include <locale.h> #endif -/** - * No-op dummy. - */ -void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - -/** - * No-op dummy. - */ -bool -pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED size_t length, - G_GNUC_UNUSED enum sample_format format, - G_GNUC_UNUSED int volume) -{ - return true; -} - void decoder_initialized(G_GNUC_UNUSED struct decoder *decoder, G_GNUC_UNUSED const struct audio_format *audio_format, @@ -118,16 +101,14 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, return DECODE_COMMAND_NONE; } -float +void decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, G_GNUC_UNUSED const struct replay_gain_info *replay_gain_info) { - return 0.0; } void decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, - G_GNUC_UNUSED float replay_gain_db, char *mixramp_start, char *mixramp_end) { g_free(mixramp_start); @@ -156,9 +137,9 @@ print_pair(const char *name, const char *value, G_GNUC_UNUSED void *ctx) } static const struct tag_handler print_handler = { - .duration = print_duration, - .tag = print_tag, - .pair = print_pair, + print_duration, + print_tag, + print_pair, }; int main(int argc, char **argv) @@ -218,6 +199,25 @@ int main(int argc, char **argv) return 1; } + g_mutex_lock(mutex); + + while (!is->ready) { + g_cond_wait(cond, mutex); + input_stream_update(is); + } + + if (!input_stream_check(is, &error)) { + g_mutex_unlock(mutex); + + g_printerr("Failed to read %s: %s\n", + path, error->message); + g_error_free(error); + + return EXIT_FAILURE; + } + + g_mutex_unlock(mutex); + success = decoder_plugin_scan_stream(plugin, is, &print_handler, NULL); input_stream_close(is); diff --git a/test/run_convert.c b/test/run_convert.c index 4f57400fd..21be83f73 100644 --- a/test/run_convert.c +++ b/test/run_convert.c @@ -28,7 +28,7 @@ #include "audio_format.h" #include "pcm_convert.h" #include "conf.h" -#include "fifo_buffer.h" +#include "util/fifo_buffer.h" #include "stdbin.h" #include <glib.h> diff --git a/test/run_decoder.c b/test/run_decoder.cxx index e6712c75b..b3e90844c 100644 --- a/test/run_decoder.c +++ b/test/run_decoder.cxx @@ -18,15 +18,14 @@ */ #include "config.h" -#include "io_thread.h" +#include "IOThread.hxx" +extern "C" { #include "decoder_list.h" +} #include "decoder_api.h" -#include "tag_pool.h" -#include "input_init.h" +#include "InputInit.hxx" #include "input_stream.h" #include "audio_format.h" -#include "pcm_volume.h" -#include "idle.h" #include "stdbin.h" #include <glib.h> @@ -45,25 +44,6 @@ my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, g_printerr("%s\n", message); } -/** - * No-op dummy. - */ -void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - -/** - * No-op dummy. - */ -bool -pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED size_t length, - G_GNUC_UNUSED enum sample_format format, - G_GNUC_UNUSED int volume) -{ - return true; -} - struct decoder { const char *uri; @@ -140,7 +120,7 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, return DECODE_COMMAND_NONE; } -float +void decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, const struct replay_gain_info *replay_gain_info) { @@ -154,13 +134,10 @@ decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, if (replay_gain_tuple_defined(tuple)) g_printerr("replay_gain[track]: gain=%f peak=%f\n", tuple->gain, tuple->peak); - - return 0.0; } void decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, - G_GNUC_UNUSED float replay_gain_db, char *mixramp_start, char *mixramp_end) { g_free(mixramp_start); @@ -191,8 +168,6 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - tag_pool_init(); - if (!input_stream_global_init(&error)) { g_warning("%s", error->message); g_error_free(error); @@ -248,7 +223,5 @@ int main(int argc, char **argv) return 1; } - tag_pool_deinit(); - return 0; } diff --git a/test/run_filter.c b/test/run_filter.c index 8e793b768..7a4bd9d80 100644 --- a/test/run_filter.c +++ b/test/run_filter.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,9 +23,7 @@ #include "audio_format.h" #include "filter_plugin.h" #include "pcm_volume.h" -#include "idle.h" #include "mixer_control.h" -#include "playlist.h" #include "stdbin.h" #include <glib.h> @@ -35,13 +33,6 @@ #include <errno.h> #include <unistd.h> -struct playlist g_playlist; - -void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - bool mixer_set_volume(G_GNUC_UNUSED struct mixer *mixer, G_GNUC_UNUSED unsigned volume, G_GNUC_UNUSED GError **error_r) diff --git a/test/run_inotify.c b/test/run_inotify.cxx index 3e7c70dba..29fcf70ab 100644 --- a/test/run_inotify.c +++ b/test/run_inotify.cxx @@ -18,18 +18,20 @@ */ #include "config.h" -#include "inotify_source.h" +#include "InotifySource.hxx" +#include "event/Loop.hxx" + +#include <glib.h> -#include <stdbool.h> #include <sys/inotify.h> #include <signal.h> -static GMainLoop *main_loop; +static EventLoop *event_loop; static void exit_signal_handler(G_GNUC_UNUSED int signum) { - g_main_loop_quit(main_loop); + event_loop->Break(); } enum { @@ -59,26 +61,25 @@ int main(int argc, char **argv) path = argv[1]; - struct mpd_inotify_source *source = - mpd_inotify_source_new(my_inotify_callback, NULL, - &error); + event_loop = new EventLoop(EventLoop::Default()); + + InotifySource *source = InotifySource::Create(*event_loop, + my_inotify_callback, + nullptr, &error); if (source == NULL) { g_warning("%s", error->message); g_error_free(error); return 2; } - int descriptor = mpd_inotify_source_add(source, path, - IN_MASK, &error); + int descriptor = source->Add(path, IN_MASK, &error); if (descriptor < 0) { - mpd_inotify_source_free(source); + delete source; g_warning("%s", error->message); g_error_free(error); return 2; } - main_loop = g_main_loop_new(NULL, false); - struct sigaction sa; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); @@ -86,8 +87,8 @@ int main(int argc, char **argv) sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); - g_main_loop_run(main_loop); - g_main_loop_unref(main_loop); + event_loop->Run(); - mpd_inotify_source_free(source); + delete source; + delete event_loop; } diff --git a/test/run_input.c b/test/run_input.cxx index 676e4e618..1508d0d94 100644 --- a/test/run_input.c +++ b/test/run_input.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,17 +18,19 @@ */ #include "config.h" -#include "io_thread.h" -#include "input_init.h" -#include "input_stream.h" -#include "tag_pool.h" -#include "tag_save.h" -#include "conf.h" +#include "TagSave.hxx" #include "stdbin.h" +#include "tag.h" +#include "conf.h" +#include "input_stream.h" +#include "InputInit.hxx" +#include "IOThread.hxx" +extern "C" { #ifdef ENABLE_ARCHIVE #include "archive_list.h" #endif +} #include <glib.h> @@ -127,7 +129,6 @@ int main(int argc, char **argv) /* initialize MPD */ - tag_pool_init(); config_global_init(); io_thread_init(); @@ -179,7 +180,6 @@ int main(int argc, char **argv) io_thread_deinit(); config_global_finish(); - tag_pool_deinit(); return ret; } diff --git a/test/run_output.c b/test/run_output.cxx index bbb1be7d2..505423479 100644 --- a/test/run_output.c +++ b/test/run_output.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,18 +18,23 @@ */ #include "config.h" -#include "io_thread.h" +#include "OutputControl.hxx" +#include "conf.h" +#include "Idle.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" +#include "GlobalEvents.hxx" +#include "IOThread.hxx" + +extern "C" { #include "output_plugin.h" #include "output_internal.h" -#include "output_control.h" -#include "conf.h" #include "audio_parser.h" #include "filter_registry.h" #include "pcm_convert.h" -#include "event_pipe.h" -#include "idle.h" -#include "playlist.h" -#include "player_control.h" +} + +#include "PlayerControl.hxx" #include "stdbin.h" #include <glib.h> @@ -39,15 +44,10 @@ #include <unistd.h> #include <stdlib.h> -struct playlist g_playlist; +EventLoop *main_loop; void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - -void -event_pipe_emit(G_GNUC_UNUSED enum pipe_event event) +GlobalEvents::Emit(gcc_unused Event event) { } @@ -94,6 +94,10 @@ find_named_config_block(const char *block, const char *name) return NULL; } +player_control::player_control(gcc_unused unsigned _buffer_chunks, + gcc_unused unsigned _buffered_before_play) {} +player_control::~player_control() {} + static struct audio_output * load_audio_output(const char *name) { @@ -103,10 +107,10 @@ load_audio_output(const char *name) param = find_named_config_block(CONF_AUDIO_OUTPUT, name); if (param == NULL) { g_printerr("No such configured audio output: %s\n", name); - return false; + return nullptr; } - static struct player_control dummy_player_control; + static struct player_control dummy_player_control(32, 4); struct audio_output *ao = audio_output_new(param, &dummy_player_control, &error); @@ -211,6 +215,8 @@ int main(int argc, char **argv) return 1; } + main_loop = new EventLoop(EventLoop::Default()); + io_thread_init(); if (!io_thread_start(&error)) { g_warning("%s", error->message); @@ -247,6 +253,8 @@ int main(int argc, char **argv) io_thread_deinit(); + delete main_loop; + config_global_finish(); return success ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/test/test_queue_priority.c b/test/test_queue_priority.c deleted file mode 100644 index 5543edbba..000000000 --- a/test/test_queue_priority.c +++ /dev/null @@ -1,175 +0,0 @@ -#include "queue.h" -#include "song.h" - -void -song_free(G_GNUC_UNUSED struct song *song) -{ -} - -G_GNUC_UNUSED -static void -dump_order(const struct queue *queue) -{ - g_printerr("queue length=%u, order:\n", queue_length(queue)); - for (unsigned i = 0; i < queue_length(queue); ++i) - g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], - queue->items[queue->order[i]].priority); -} - -static void -check_descending_priority(G_GNUC_UNUSED const struct queue *queue, - unsigned start_order) -{ - assert(start_order < queue_length(queue)); - - uint8_t last_priority = 0xff; - for (unsigned order = start_order; order < queue_length(queue); ++order) { - unsigned position = queue_order_to_position(queue, order); - uint8_t priority = queue->items[position].priority; - assert(priority <= last_priority); - (void)last_priority; - last_priority = priority; - } -} - -int -main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) -{ - struct song songs[16]; - - struct queue queue; - queue_init(&queue, 32); - - for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i) - queue_append(&queue, &songs[i], 0); - - assert(queue_length(&queue) == G_N_ELEMENTS(songs)); - - /* priority=10 for 4 items */ - - queue_set_priority_range(&queue, 4, 8, 10, -1); - - queue.random = true; - queue_shuffle_order(&queue); - check_descending_priority(&queue, 0); - - for (unsigned i = 0; i < 4; ++i) { - assert(queue_position_to_order(&queue, i) >= 4); - } - - for (unsigned i = 4; i < 8; ++i) { - assert(queue_position_to_order(&queue, i) < 4); - } - - for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) { - assert(queue_position_to_order(&queue, i) >= 4); - } - - /* priority=50 one more item */ - - queue_set_priority_range(&queue, 15, 16, 50, -1); - check_descending_priority(&queue, 0); - - assert(queue_position_to_order(&queue, 15) == 0); - - for (unsigned i = 0; i < 4; ++i) { - assert(queue_position_to_order(&queue, i) >= 4); - } - - for (unsigned i = 4; i < 8; ++i) { - assert(queue_position_to_order(&queue, i) >= 1 && - queue_position_to_order(&queue, i) < 5); - } - - for (unsigned i = 8; i < 15; ++i) { - assert(queue_position_to_order(&queue, i) >= 5); - } - - /* priority=20 for one of the 4 priority=10 items */ - - queue_set_priority_range(&queue, 3, 4, 20, -1); - check_descending_priority(&queue, 0); - - assert(queue_position_to_order(&queue, 3) == 1); - assert(queue_position_to_order(&queue, 15) == 0); - - for (unsigned i = 0; i < 3; ++i) { - assert(queue_position_to_order(&queue, i) >= 5); - } - - for (unsigned i = 4; i < 8; ++i) { - assert(queue_position_to_order(&queue, i) >= 2 && - queue_position_to_order(&queue, i) < 6); - } - - for (unsigned i = 8; i < 15; ++i) { - assert(queue_position_to_order(&queue, i) >= 6); - } - - /* priority=20 for another one of the 4 priority=10 items; - pass "after_order" (with priority=10) and see if it's moved - after that one */ - - unsigned current_order = 4; - unsigned current_position = - queue_order_to_position(&queue, current_order); - - unsigned a_order = 3; - unsigned a_position = queue_order_to_position(&queue, a_order); - assert(queue.items[a_position].priority == 10); - queue_set_priority(&queue, a_position, 20, current_order); - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - a_order = queue_position_to_order(&queue, a_position); - assert(a_order == 4); - - check_descending_priority(&queue, current_order + 1); - - /* priority=70 for one of the last items; must be inserted - right after the current song, before the priority=20 one we - just created */ - - unsigned b_order = 10; - unsigned b_position = queue_order_to_position(&queue, b_order); - assert(queue.items[b_position].priority == 0); - queue_set_priority(&queue, b_position, 70, current_order); - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - b_order = queue_position_to_order(&queue, b_position); - assert(b_order == 4); - - check_descending_priority(&queue, current_order + 1); - - /* priority=60 for the old prio50 item; must not be moved, - because it's before the current song, and it's status - hasn't changed (it was already higher before) */ - - unsigned c_order = 0; - unsigned c_position = queue_order_to_position(&queue, c_order); - assert(queue.items[c_position].priority == 50); - queue_set_priority(&queue, c_position, 60, current_order); - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - c_order = queue_position_to_order(&queue, c_position); - assert(c_order == 0); - - /* move the prio=20 item back */ - - a_order = queue_position_to_order(&queue, a_position); - assert(a_order == 5); - assert(queue.items[a_position].priority == 20); - queue_set_priority(&queue, a_position, 5, current_order); - - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - a_order = queue_position_to_order(&queue, a_position); - assert(a_order == 6); -} diff --git a/test/test_queue_priority.cxx b/test/test_queue_priority.cxx new file mode 100644 index 000000000..cab56d82f --- /dev/null +++ b/test/test_queue_priority.cxx @@ -0,0 +1,186 @@ +#include "config.h" +#include "Queue.hxx" +#include "song.h" +#include "Directory.hxx" + +Directory detached_root; + +Directory::Directory() {} +Directory::~Directory() {} + +struct song * +song_dup_detached(const struct song *src) +{ + return const_cast<song *>(src); +} + +void +song_free(G_GNUC_UNUSED struct song *song) +{ +} + +G_GNUC_UNUSED +static void +dump_order(const struct queue *queue) +{ + g_printerr("queue length=%u, order:\n", queue->GetLength()); + for (unsigned i = 0; i < queue->GetLength(); ++i) + g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], + queue->items[queue->order[i]].priority); +} + +static void +check_descending_priority(const struct queue *queue, + unsigned start_order) +{ + assert(start_order < queue->GetLength()); + + uint8_t last_priority = 0xff; + for (unsigned order = start_order; order < queue->GetLength(); ++order) { + unsigned position = queue->OrderToPosition(order); + uint8_t priority = queue->items[position].priority; + assert(priority <= last_priority); + (void)last_priority; + last_priority = priority; + } +} + +int +main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) +{ + static struct song songs[16]; + + struct queue queue(32); + + for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i) + queue.Append(&songs[i], 0); + + assert(queue.GetLength() == G_N_ELEMENTS(songs)); + + /* priority=10 for 4 items */ + + queue.SetPriorityRange(4, 8, 10, -1); + + queue.random = true; + queue.ShuffleOrder(); + check_descending_priority(&queue, 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue.PositionToOrder(i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue.PositionToOrder(i) < 4); + } + + for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) { + assert(queue.PositionToOrder(i) >= 4); + } + + /* priority=50 one more item */ + + queue.SetPriorityRange(15, 16, 50, -1); + check_descending_priority(&queue, 0); + + assert(queue.PositionToOrder(15) == 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue.PositionToOrder(i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue.PositionToOrder(i) >= 1 && + queue.PositionToOrder(i) < 5); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue.PositionToOrder(i) >= 5); + } + + /* priority=20 for one of the 4 priority=10 items */ + + queue.SetPriorityRange(3, 4, 20, -1); + check_descending_priority(&queue, 0); + + assert(queue.PositionToOrder(3) == 1); + assert(queue.PositionToOrder(15) == 0); + + for (unsigned i = 0; i < 3; ++i) { + assert(queue.PositionToOrder(i) >= 5); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue.PositionToOrder(i) >= 2 && + queue.PositionToOrder(i) < 6); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue.PositionToOrder(i) >= 6); + } + + /* priority=20 for another one of the 4 priority=10 items; + pass "after_order" (with priority=10) and see if it's moved + after that one */ + + unsigned current_order = 4; + unsigned current_position = + queue.OrderToPosition(current_order); + + unsigned a_order = 3; + unsigned a_position = queue.OrderToPosition(a_order); + assert(queue.items[a_position].priority == 10); + queue.SetPriority(a_position, 20, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + a_order = queue.PositionToOrder(a_position); + assert(a_order == 4); + + check_descending_priority(&queue, current_order + 1); + + /* priority=70 for one of the last items; must be inserted + right after the current song, before the priority=20 one we + just created */ + + unsigned b_order = 10; + unsigned b_position = queue.OrderToPosition(b_order); + assert(queue.items[b_position].priority == 0); + queue.SetPriority(b_position, 70, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + b_order = queue.PositionToOrder(b_position); + assert(b_order == 4); + + check_descending_priority(&queue, current_order + 1); + + /* priority=60 for the old prio50 item; must not be moved, + because it's before the current song, and it's status + hasn't changed (it was already higher before) */ + + unsigned c_order = 0; + unsigned c_position = queue.OrderToPosition(c_order); + assert(queue.items[c_position].priority == 50); + queue.SetPriority(c_position, 60, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + c_order = queue.PositionToOrder(c_position); + assert(c_order == 0); + + /* move the prio=20 item back */ + + a_order = queue.PositionToOrder(a_position); + assert(a_order == 5); + assert(queue.items[a_position].priority == 20); + queue.SetPriority(a_position, 5, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + a_order = queue.PositionToOrder(a_position); + assert(a_order == 6); +} |