diff --git a/src/libbluechi/test/cli/command/command_add_option_test.c b/src/libbluechi/test/cli/command/command_add_option_test.c new file mode 100644 index 0000000000..f9e854f618 --- /dev/null +++ b/src/libbluechi/test/cli/command/command_add_option_test.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "libbluechi/cli/command.h" + + +static const OptionType option_types[] = { + {'f', "force", 1 }, + { 'r', "reload", 11}, + { 0, NULL, 0 }, +}; + +int main() { + bool result = true; + + _cleanup_command_ Command *command = new_command(); + + /* adding command option without value */ + int r = command_add_option(command, 'f', NULL, &option_types[0]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* adding same command option with value */ + r = command_add_option(command, 'f', "value", &option_types[0]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* adding different command option without value */ + r = command_add_option(command, 'r', NULL, &option_types[1]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* Test validation: + * Check that command options have been added without other functions + * from command.h + */ + + int option_count = 0; + int expected_option_count = 3; + + CommandOption *curr = NULL; + CommandOption *next = NULL; + LIST_FOREACH_SAFE(options, curr, next, command->command_options) { + // first command found + if (curr->key == 'f' && curr->value == NULL && curr->is_flag) { + option_count++; + } + // second command found + else if (curr->key == 'f' && curr->value != NULL && streq(curr->value, "value") && + !curr->is_flag) { + option_count++; + } + // third command found + else if (curr->key == 'r' && curr->value == NULL && curr->is_flag) { + option_count++; + } else { + fprintf(stderr, "FAILED: Found unexpected command option with key: %d\n", curr->key); + result = false; + } + } + + if (option_count != expected_option_count) { + fprintf(stderr, "FAILED: Missing command options detected\n"); + } + + if (result) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/src/libbluechi/test/cli/command/command_execute_test.c b/src/libbluechi/test/cli/command/command_execute_test.c new file mode 100644 index 0000000000..f37ebe6612 --- /dev/null +++ b/src/libbluechi/test/cli/command/command_execute_test.c @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "libbluechi/cli/command.h" + + +static int method_dummy_call_count = 0; +static int method_dummy(UNUSED Command *command, UNUSED void *userdata) { + method_dummy_call_count++; + return 0; +} + +static int usage_dummy_call_count = 0; +static void usage_dummy() { + usage_dummy_call_count++; +} + + +bool test_command_execute_is_help() { + usage_dummy_call_count = 0; + method_dummy_call_count = 0; + + const Method method = { "dummy", 0, 0, 0, method_dummy, usage_dummy }; + + _cleanup_command_ Command *command = new_command(); + command->is_help = true; + command->method = &method; + + bool result = true; + int r = command_execute(command, NULL); + if (r != 0) { + fprintf(stderr, + "FAILED (%s): Expected command_execute for help method return 0, but got %d\n", + __func__, + r); + result = false; + } + if (usage_dummy_call_count != 1) { + fprintf(stderr, + "FAILED (%s): Expected command_execute to call usage(), but did not\n", + __func__); + result = false; + } + + return result; +} + +bool test_command_execute_min_max_args() { + usage_dummy_call_count = 0; + method_dummy_call_count = 0; + + // define method with min_args=1 and max_args=2 + const Method method = { "dummy", 1, 2, 0, method_dummy, usage_dummy }; + + _cleanup_command_ Command *command = new_command(); + command->is_help = false; + command->method = &method; + + bool result = true; + + command->opargc = 0; + int r = command_execute(command, NULL); + if (r != -EINVAL) { + fprintf(stderr, + "FAILED (%s): Expected command_execute with too few arguments to return %d, but got %d\n", + __func__, + -EINVAL, + r); + result = false; + } + + command->opargc = 3; + r = command_execute(command, NULL); + if (r != -EINVAL) { + fprintf(stderr, + "FAILED (%s): Expected command_execute with too many arguments to return %d, but got %d\n", + __func__, + -EINVAL, + r); + result = false; + } + + if (usage_dummy_call_count != 0) { + fprintf(stderr, + "FAILED (%s): Expected command_execute not to call usage(), but did\n", + __func__); + result = false; + } + if (method_dummy_call_count != 0) { + fprintf(stderr, + "FAILED (%s): Expected command_execute not to call dispatch(), but did\n", + __func__); + result = false; + } + + return result; +} + +bool test_command_execute_dispatch() { + usage_dummy_call_count = 0; + method_dummy_call_count = 0; + + const Method method = { "dummy", 0, 0, 0, method_dummy, usage_dummy }; + + _cleanup_command_ Command *command = new_command(); + command->is_help = false; + command->opargc = 0; + command->method = &method; + + bool result = true; + int r = command_execute(command, NULL); + if (r != 0) { + fprintf(stderr, + "FAILED (%s): Expected command_execute to return %d on dispatch(), but got %d\n", + __func__, + 0, + r); + } + if (usage_dummy_call_count != 0) { + fprintf(stderr, + "FAILED (%s): Expected command_execute not to call usage(), but did\n", + __func__); + result = false; + } + if (method_dummy_call_count != 1) { + fprintf(stderr, + "FAILED (%s): Expected command_execute to call dispatch() exactly once, but called it %d times\n", + __func__, + method_dummy_call_count); + result = false; + } + + return result; +} + +int main() { + bool result = true; + + result = result && test_command_execute_is_help(); + result = result && test_command_execute_min_max_args(); + result = result && test_command_execute_dispatch(); + + if (result) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/src/libbluechi/test/cli/command/command_flag_exists_test.c b/src/libbluechi/test/cli/command/command_flag_exists_test.c new file mode 100644 index 0000000000..bf2a92ebbf --- /dev/null +++ b/src/libbluechi/test/cli/command/command_flag_exists_test.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "libbluechi/cli/command.h" + + +static const OptionType option_types[] = { + {'f', "force", 1 }, + { 'r', "reload", 11}, + { 0, NULL, 0 }, +}; + +int main() { + bool result = true; + + _cleanup_command_ Command *command = new_command(); + + /* adding command option without value */ + int r = command_add_option(command, 'f', NULL, &option_types[0]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* adding same command option with value */ + r = command_add_option(command, 'f', "value", &option_types[0]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* adding different command option without value */ + r = command_add_option(command, 'r', NULL, &option_types[1]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* Test validation: + * Check command_flag_exists finds added options and test if + */ + + if (!command_flag_exists(command, 'f')) { + fprintf(stderr, "FAILED: Expected flag 'f' to exist, but couldn't find it\n"); + result = false; + } + if (!command_flag_exists(command, 'r')) { + fprintf(stderr, "FAILED: Expected flag 'r' to exist, but couldn't find it\n"); + result = false; + } + if (command_flag_exists(command, 'x')) { + fprintf(stderr, "FAILED: Found unexpected flag 'x'\n"); + result = false; + } + + if (result) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/src/libbluechi/test/cli/command/command_get_option_test.c b/src/libbluechi/test/cli/command/command_get_option_test.c new file mode 100644 index 0000000000..819c1fbe39 --- /dev/null +++ b/src/libbluechi/test/cli/command/command_get_option_test.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "libbluechi/cli/command.h" + + +static const OptionType option_types[] = { + {'f', "force", 1 }, + { 'r', "reload", 11}, + { 0, NULL, 0 }, +}; + +int main() { + bool result = true; + + _cleanup_command_ Command *command = new_command(); + + /* adding same command option with value */ + int r = command_add_option(command, 'f', "yes", &option_types[0]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* adding different command option without value */ + r = command_add_option(command, 'r', NULL, &option_types[1]); + if (r < 0) { + fprintf(stderr, "FAILED: Unexpected error adding command option: %s\n", strerror(-r)); + return EXIT_FAILURE; + } + + /* Test validation: + * Check command_get_option get the value of an option if found by key + */ + + char *got = command_get_option(command, 'f'); + if (got == NULL || !streq(got, "yes")) { + fprintf(stderr, "FAILED: Expected value 'yes' for flag 'f', but got '%s'\n", got); + result = false; + } + got = command_get_option(command, 'r'); + if (got != NULL) { + fprintf(stderr, "FAILED: Expected NULL value for flag 'r', but got '%s'\n", got); + result = false; + } + got = command_get_option(command, 'x'); + if (got != NULL) { + fprintf(stderr, "FAILED: Expected NULL value for unknown flag 'x', but got '%s'\n", got); + result = false; + } + + if (result) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/src/libbluechi/test/cli/command/get_option_type_test.c b/src/libbluechi/test/cli/command/get_option_type_test.c new file mode 100644 index 0000000000..ec1d405b24 --- /dev/null +++ b/src/libbluechi/test/cli/command/get_option_type_test.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "libbluechi/cli/command.h" + + +static const OptionType option_types[] = { + {0, "zero", 1 }, + { 1, "one", 11}, + { 0, NULL, 0 }, +}; + +bool check_option_type(const OptionType *got, OptionType *expected) { + if (got == NULL && expected != NULL) { + fprintf(stderr, + "FAILED: Expected option type '%s' for get_option_type(types, %d), but got NULL\n", + expected->option_long, + expected->option_short); + return false; + } + if (got != NULL && expected == NULL) { + fprintf(stderr, "FAILED: Expected NULL for get_option_type, but got %s\n", got->option_long); + return false; + } + + if (got != NULL && expected != NULL && !streq(got->option_long, expected->option_long)) { + fprintf(stderr, + "FAILED: Expected option type '%s' for get_option_type(types, %d), but got %s\n", + expected->option_long, + expected->option_short, + got->option_long); + return false; + } + + return true; +} + +int main() { + bool result = true; + + const OptionType *type = NULL; + OptionType expected = option_types[0]; + type = get_option_type(option_types, 0); + result = result && check_option_type(type, &expected); + + expected = option_types[1]; + type = get_option_type(option_types, 1); + result = result && check_option_type(type, &expected); + + type = get_option_type(option_types, 2); + result = result && check_option_type(type, NULL); + + type = get_option_type(option_types, -1); + result = result && check_option_type(type, NULL); + + + if (result) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/src/libbluechi/test/cli/command/meson.build b/src/libbluechi/test/cli/command/meson.build new file mode 100644 index 0000000000..bd23475114 --- /dev/null +++ b/src/libbluechi/test/cli/command/meson.build @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +command_src = [ + 'command_add_option_test', + 'command_flag_exists_test', + 'command_get_option_test', + 'get_option_type_test', + 'command_execute_test', + 'methods_get_method_test', +] + +foreach src : command_src + exec_test = executable(src, src + '.c', + link_with: [ + bluechi_lib, + ], + include_directories: include_directories('../../../..'), + ) + test(src, exec_test) +endforeach diff --git a/src/libbluechi/test/cli/command/methods_get_method_test.c b/src/libbluechi/test/cli/command/methods_get_method_test.c new file mode 100644 index 0000000000..1f49b7bc01 --- /dev/null +++ b/src/libbluechi/test/cli/command/methods_get_method_test.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "libbluechi/cli/command.h" + + +static int method_dummy_one(UNUSED Command *command, UNUSED void *userdata) { + return 0; +} + +static int method_dummy_two(UNUSED Command *command, UNUSED void *userdata) { + return 0; +} + +static void usage_dummy() { +} + +static const Method methods[] = { + {"dummy-one", 0, 0, 0, method_dummy_one, usage_dummy}, + { "dummy-two", 0, 0, 0, method_dummy_two, usage_dummy}, + { NULL, 0, 0, 0, NULL, NULL } +}; + +int main() { + bool result = true; + + const Method *m = NULL; + m = methods_get_method(NULL, methods); + if (m != NULL) { + result = false; + fprintf(stderr, "FAILED: Expected methods_get_method(NULL, methods) to return NULL\n"); + } + + m = methods_get_method("dummy-one", methods); + if (m == NULL || m->dispatch != method_dummy_one) { + result = false; + fprintf(stderr, + "FAILED: Expected methods_get_method('dummy-one', methods) to return method pointing to matching Method\n"); + } + + m = methods_get_method("dummy-two", methods); + if (m == NULL || m->dispatch != method_dummy_two) { + result = false; + fprintf(stderr, + "FAILED: Expected methods_get_method('dummy-two', methods) to return method pointing to matching Method\n"); + } + + m = methods_get_method("dumy-two", methods); + if (m != NULL) { + result = false; + fprintf(stderr, "FAILED: Expected methods_get_method(NULL, methods) to return NULL\n"); + } + + + if (result) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/src/libbluechi/test/cli/meson.build b/src/libbluechi/test/cli/meson.build new file mode 100644 index 0000000000..d0a6130148 --- /dev/null +++ b/src/libbluechi/test/cli/meson.build @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +subdir('command') diff --git a/src/libbluechi/test/meson.build b/src/libbluechi/test/meson.build index ac97ac6f26..c3b85601f7 100644 --- a/src/libbluechi/test/meson.build +++ b/src/libbluechi/test/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: LGPL-2.1-or-later subdir('bus') +subdir('cli') subdir('common') subdir('log') subdir('socket')