From 7c125397e07c2af0371b2f4921be52361879582c Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Sun, 27 Nov 2022 18:54:20 +0100 Subject: [PATCH] Increase test coverage by adding bluealsa-cli test --- .github/workflows/build-and-test.yaml | 6 + .github/workflows/code-scanning.yaml | 3 + .github/workflows/codecov-report.yaml | 4 + Makefile.am | 4 +- src/shared/dbus-client.c | 1 + test/Makefile.am | 5 + test/inc/server.inc | 10 +- test/test-alsa-ctl.c | 5 +- test/test-alsa-pcm.c | 5 +- test/test-utils-cli.c | 305 ++++++++++++++++++++++++++ 10 files changed, 334 insertions(+), 14 deletions(-) create mode 100644 test/test-utils-cli.c diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index f71e0956d..0fce2ab22 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -5,6 +5,9 @@ on: pull_request: branches: [ master ] +env: + MAKEFLAGS: -j8 + jobs: check: @@ -86,6 +89,7 @@ jobs: working-directory: ${{ github.workspace }}/build run: | ${{ github.workspace }}/configure \ + --disable-aplay \ --enable-aac \ --enable-faststream \ --enable-mp3lame \ @@ -93,6 +97,7 @@ jobs: --enable-msbc \ --enable-ofono \ --enable-upower \ + --enable-cli \ --enable-test - name: Build working-directory: ${{ github.workspace }}/build @@ -102,6 +107,7 @@ jobs: - name: Run Tests working-directory: ${{ github.workspace }}/build/test env: + CK_DEFAULT_TIMEOUT: 15 LD_PRELOAD_SANITIZER: libasan.so.5 run: make check-TESTS - name: Show Tests Log diff --git a/.github/workflows/code-scanning.yaml b/.github/workflows/code-scanning.yaml index 6c639b610..495af4bb0 100644 --- a/.github/workflows/code-scanning.yaml +++ b/.github/workflows/code-scanning.yaml @@ -5,6 +5,9 @@ on: pull_request: branches: [ master ] +env: + MAKEFLAGS: -j8 + permissions: actions: read contents: read diff --git a/.github/workflows/codecov-report.yaml b/.github/workflows/codecov-report.yaml index 382b7f43e..6879b733e 100644 --- a/.github/workflows/codecov-report.yaml +++ b/.github/workflows/codecov-report.yaml @@ -5,6 +5,9 @@ on: pull_request: branches: [ master ] +env: + MAKEFLAGS: -j8 + jobs: coverage: @@ -45,6 +48,7 @@ jobs: --enable-msbc \ --enable-ofono \ --enable-upower \ + --enable-cli \ --enable-test \ --with-coverage - name: Generate Coverage Report diff --git a/Makefile.am b/Makefile.am index 73c690645..f783af516 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ # BlueALSA - Makefile.am -# Copyright (c) 2016-2021 Arkadiusz Bokowy +# Copyright (c) 2016-2022 Arkadiusz Bokowy ACLOCAL_AMFLAGS = -I m4 SUBDIRS = misc src utils @@ -15,7 +15,7 @@ endif if WITH_COVERAGE cov: $(MAKE) $(AM_MAKEFLAGS) check CFLAGS="$(CFLAGS) -O0 --coverage" - $(LCOV) --capture -d src -d test --exclude '/usr/*' --exclude "*/test/*" -o cov.info + $(LCOV) --capture -d src -d utils -d test --exclude '/usr/*' --exclude "*/test/*" -o cov.info $(GENHTML) -o coverage -t $(PACKAGE) cov.info clean-local: find $(top_builddir) -name "*.gcno" -delete diff --git a/src/shared/dbus-client.c b/src/shared/dbus-client.c index 618f367d7..e6b625130 100644 --- a/src/shared/dbus-client.c +++ b/src/shared/dbus-client.c @@ -634,6 +634,7 @@ static dbus_bool_t bluealsa_dbus_message_iter_pcm_get_codecs_cb(const char *key, struct ba_pcm_codec *codec = &tmp[len]; codecs->codecs = tmp; + memset(codec, 0, sizeof(*codec)); strncpy(codec->name, key, sizeof(codec->name)); codec->name[sizeof(codec->name) - 1] = '\0'; diff --git a/test/Makefile.am b/test/Makefile.am index 8dabdbd54..1d4dc6ac4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -31,6 +31,11 @@ TESTS += test-msbc check_PROGRAMS += test-msbc endif +if ENABLE_CLI +TESTS += test-utils-cli +check_PROGRAMS += test-utils-cli +endif + check_LTLIBRARIES = \ aloader.la aloader_la_LDFLAGS = \ diff --git a/test/inc/server.inc b/test/inc/server.inc index afce18d2c..0a498b910 100644 --- a/test/inc/server.inc +++ b/test/inc/server.inc @@ -92,8 +92,9 @@ static void *spawn_bluealsa_server_stderr_proxy(void *userdata) { return NULL; } -/* path with the bluealsa-mock binary */ -char *bluealsa_mock_path = "."; +/** + * Full path to the bluealsa-mock executable. */ +char bluealsa_mock_path[256] = "bluealsa-mock"; /** * Spawn bluealsa server mock. @@ -143,9 +144,6 @@ pid_t spawn_bluealsa_server(const char *service, bool wait_for_ready, ...) { va_end(ap); - char path[256]; - sprintf(path, "%s/bluealsa-mock", bluealsa_mock_path); - int fds[2]; if (pipe(fds) == -1) return -1; @@ -155,7 +153,7 @@ pid_t spawn_bluealsa_server(const char *service, bool wait_for_ready, ...) { dup2(fds[1], 2); close(fds[0]); close(fds[1]); - execv(path, argv); + execv(bluealsa_mock_path, argv); } close(fds[1]); diff --git a/test/test-alsa-ctl.c b/test/test-alsa-ctl.c index 380e4c8ea..565d30d17 100644 --- a/test/test-alsa-ctl.c +++ b/test/test-alsa-ctl.c @@ -591,10 +591,9 @@ START_TEST(test_alsa_high_level_control_interface) { int main(int argc, char *argv[], char *envp[]) { preload(argc, argv, envp, ".libs/aloader.so"); - /* test-alsa-ctl and bluealsa-mock shall - * be placed in the same directory */ char *argv_0 = strdup(argv[0]); - bluealsa_mock_path = dirname(argv_0); + snprintf(bluealsa_mock_path, sizeof(bluealsa_mock_path), + "%s/bluealsa-mock", dirname(argv_0)); Suite *s = suite_create(__FILE__); TCase *tc = tcase_create(__FILE__); diff --git a/test/test-alsa-pcm.c b/test/test-alsa-pcm.c index 49883b8ee..ac5ddf5e3 100644 --- a/test/test-alsa-pcm.c +++ b/test/test-alsa-pcm.c @@ -1040,10 +1040,9 @@ int main(int argc, char *argv[], char *envp[]) { return 1; } - /* test-alsa-pcm and bluealsa-mock shall - * be placed in the same directory */ char *argv_0 = strdup(argv[0]); - bluealsa_mock_path = dirname(argv_0); + snprintf(bluealsa_mock_path, sizeof(bluealsa_mock_path), + "%s/bluealsa-mock", dirname(argv_0)); if (argc == optind) { run_capture = true; diff --git a/test/test-utils-cli.c b/test/test-utils-cli.c new file mode 100644 index 000000000..45e88e10f --- /dev/null +++ b/test/test-utils-cli.c @@ -0,0 +1,305 @@ +/* + * test-utils-cli.c + * Copyright (c) 2016-2022 Arkadiusz Bokowy + * + * This file is a part of bluez-alsa. + * + * This project is licensed under the terms of the MIT license. + * + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include "inc/preload.inc" +#include "inc/server.inc" + +static char bluealsa_cli_path[256]; +static int run_bluealsa_cli(const char *arguments, char *output, size_t size) { + + FILE *f; + char command[1024]; + + snprintf(command, sizeof(command), "%s %s", bluealsa_cli_path, + arguments != NULL ? arguments : ""); + ck_assert_ptr_ne(f = popen(command, "r"), NULL); + + size_t len = fread(output, 1, size - 1, f); + output[len] = '\0'; + + fprintf(stderr, "%s", output); + + return pclose(f); +} + +START_TEST(test_status) { + fprintf(stderr, "\nSTART TEST: %s (%s:%d)\n", __func__, __FILE__, __LINE__); + + pid_t pid; + ck_assert_int_ne(pid = spawn_bluealsa_server(NULL, true, + "--profile=a2dp-source", + "--profile=hfp-ag", + NULL), -1); + + char output[512]; + + /* check printing help text */ + ck_assert_int_eq(run_bluealsa_cli("--help", output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "-h, --help"), NULL); + + /* check default command */ + ck_assert_int_eq(run_bluealsa_cli(NULL, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "Service: org.bluealsa"), NULL); + ck_assert_ptr_ne(strstr(output, "A2DP-source"), NULL); + ck_assert_ptr_ne(strstr(output, "HFP-AG"), NULL); + + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); + +} END_TEST + +START_TEST(test_list_services) { + fprintf(stderr, "\nSTART TEST: %s (%s:%d)\n", __func__, __FILE__, __LINE__); + + pid_t pid; + ck_assert_int_ne(pid = spawn_bluealsa_server("test", true, NULL), -1); + + char output[512]; + const char *args = "list-services"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + + ck_assert_ptr_ne(strstr(output, "org.bluealsa.test"), NULL); + + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); + +} END_TEST + +START_TEST(test_list_pcms) { + fprintf(stderr, "\nSTART TEST: %s (%s:%d)\n", __func__, __FILE__, __LINE__); + + pid_t pid; + ck_assert_int_ne(pid = spawn_bluealsa_server(NULL, true, + "--profile=a2dp-sink", + "--profile=hfp-ag", + NULL), -1); + + char output[2048]; + const char *args = "--verbose list-pcms"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + + ck_assert_ptr_ne(strstr(output, + "/org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsnk/source"), NULL); + ck_assert_ptr_ne(strstr(output, + "/org/bluealsa/hci0/dev_12_34_56_78_9A_BC/hfpag/source"), NULL); + ck_assert_ptr_ne(strstr(output, + "/org/bluealsa/hci0/dev_12_34_56_78_9A_BC/hfpag/sink"), NULL); + ck_assert_ptr_ne(strstr(output, + "/org/bluealsa/hci0/dev_23_45_67_89_AB_CD/a2dpsnk/source"), NULL); + + /* check verbose output */ + ck_assert_ptr_ne(strstr(output, + "Device: /org/bluez/hci0/dev_12_34_56_78_9A_BC"), NULL); + ck_assert_ptr_ne(strstr(output, + "Device: /org/bluez/hci0/dev_23_45_67_89_AB_CD"), NULL); + + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); + +} END_TEST + +START_TEST(test_info) { + fprintf(stderr, "\nSTART TEST: %s (%s:%d)\n", __func__, __FILE__, __LINE__); + + pid_t pid; + ck_assert_int_ne(pid = spawn_bluealsa_server(NULL, true, + "--profile=a2dp-source", + NULL), -1); + + char output[512]; + const char *args = "info /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + + ck_assert_ptr_ne(strstr(output, + "Device: /org/bluez/hci0/dev_12_34_56_78_9A_BC"), NULL); + ck_assert_ptr_ne(strstr(output, + "Transport: A2DP-source"), NULL); + ck_assert_ptr_ne(strstr(output, + "Selected codec: SBC"), NULL); + + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); + +} END_TEST + +START_TEST(test_codec) { + fprintf(stderr, "\nSTART TEST: %s (%s:%d)\n", __func__, __FILE__, __LINE__); + + pid_t pid; + ck_assert_int_ne(pid = spawn_bluealsa_server(NULL, true, + "--profile=hfp-ag", + NULL), -1); + + char output[512]; + const char *args; + + args = "-v codec /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/hfpag/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "Available codecs: CVSD"), NULL); + +#if !ENABLE_MSBC + /* CVSD shall be automatically selected if mSBC is not supported. */ + ck_assert_ptr_ne(strstr(output, "Selected codec: CVSD"), NULL); +#endif + +#if ENABLE_MSBC + args = "codec /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/hfpag/sink mSBC"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + + args = "-v codec /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/hfpag/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "Selected codec: mSBC"), NULL); +#endif + + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); + +} END_TEST + +START_TEST(test_volume) { + fprintf(stderr, "\nSTART TEST: %s (%s:%d)\n", __func__, __FILE__, __LINE__); + + pid_t pid; + ck_assert_int_ne(pid = spawn_bluealsa_server(NULL, true, + "--profile=a2dp-source", + NULL), -1); + + char output[512]; + const char *args; + + /* check default volume */ + args = "volume /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "Volume: L: 127 R: 127"), NULL); + + /* check default mute */ + args = "mute /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "Muted: L: N R: N"), NULL); + + /* check default soft-volume */ + args = "soft-volume /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "SoftVolume: Y"), NULL); + + /* check setting volume */ + args = "volume /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink 10 50"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + args = "volume /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "Volume: L: 10 R: 50"), NULL); + + /* check setting mute */ + args = "mute /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink N Y"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + args = "mute /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "Muted: L: N R: Y"), NULL); + + /* check setting soft-volume */ + args = "soft-volume /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink N"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + args = "soft-volume /org/bluealsa/hci0/dev_12_34_56_78_9A_BC/a2dpsrc/sink"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + ck_assert_ptr_ne(strstr(output, "SoftVolume: N"), NULL); + + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); + +} END_TEST + +START_TEST(test_monitor) { + fprintf(stderr, "\nSTART TEST: %s (%s:%d)\n", __func__, __FILE__, __LINE__); + + pid_t pid; + ck_assert_int_ne(pid = spawn_bluealsa_server(NULL, false, + "--timeout=0", + "--fuzzing=200", + "--profile=a2dp-source", + "--profile=hsp-ag", + NULL), -1); + + char output[2048]; + const char *args = "-v monitor"; + ck_assert_int_eq(run_bluealsa_cli(args, output, sizeof(output)), 0); + + /* notifications for service start/stop */ + ck_assert_ptr_ne(strstr(output, "ServiceRunning org.bluealsa"), NULL); + ck_assert_ptr_ne(strstr(output, "ServiceStopped org.bluealsa"), NULL); + + /* notifications for PCM add/remove */ + ck_assert_ptr_ne(strstr(output, + "PCMAdded /org/bluealsa/hci0/dev_23_45_67_89_AB_CD/a2dpsrc/sink"), NULL); + ck_assert_ptr_ne(strstr(output, + "PCMRemoved /org/bluealsa/hci0/dev_23_45_67_89_AB_CD/a2dpsrc/sink"), NULL); + + /* notifications for RFCOMM add/remove (because HSP is enabled) */ + ck_assert_ptr_ne(strstr(output, + "RFCOMMAdded /org/bluealsa/hci0/dev_23_45_67_89_AB_CD/rfcomm"), NULL); + ck_assert_ptr_ne(strstr(output, + "RFCOMMRemoved /org/bluealsa/hci0/dev_23_45_67_89_AB_CD/rfcomm"), NULL); + + /* check verbose output */ + ck_assert_ptr_ne(strstr(output, + "Device: /org/bluez/hci0/dev_12_34_56_78_9A_BC"), NULL); + ck_assert_ptr_ne(strstr(output, + "Device: /org/bluez/hci0/dev_23_45_67_89_AB_CD"), NULL); + + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); + +} END_TEST + +int main(int argc, char *argv[], char *envp[]) { + preload(argc, argv, envp, ".libs/aloader.so"); + + char *argv_0 = strdup(argv[0]); + char *argv_0_dir = dirname(argv_0); + + snprintf(bluealsa_mock_path, sizeof(bluealsa_mock_path), + "%s/bluealsa-mock", argv_0_dir); + snprintf(bluealsa_cli_path, sizeof(bluealsa_cli_path), + "%s/../utils/cli/bluealsa-cli", argv_0_dir); + + Suite *s = suite_create(__FILE__); + TCase *tc = tcase_create(__FILE__); + SRunner *sr = srunner_create(s); + + suite_add_tcase(s, tc); + + tcase_add_test(tc, test_status); + tcase_add_test(tc, test_list_services); + tcase_add_test(tc, test_list_pcms); + tcase_add_test(tc, test_info); + tcase_add_test(tc, test_codec); + tcase_add_test(tc, test_volume); + tcase_add_test(tc, test_monitor); + + srunner_run_all(sr, CK_ENV); + int nf = srunner_ntests_failed(sr); + + srunner_free(sr); + free(argv_0); + + return nf == 0 ? 0 : 1; +}