From: Krzysztof Opasiak Date: Fri, 14 Nov 2014 15:14:23 +0000 (+0100) Subject: libusbgx: tests: Allow to skip some tests X-Git-Tag: libusbgx-v0.1.0~132 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5b4eb3c5de296d403b7a1212a3dc444525b69e36;p=platform%2Fupstream%2Flibusbg.git libusbgx: tests: Allow to skip some tests In some cases we may want to mark some tests as skipped. Doing this in code requires recompilation after each change. This patch extends the tests framework and allows to create configuration file and mark some tests as skipped (for example using # and comment some test and run them always from the same binary file. We use stdin/stdout for reading/writing configuration because we are wrapping filesystem operations in our mock framework (usbg-io-wrappers). To keep our mock framework as simple as we can we use those standard streams which are forrwarded by framework to original implementations of those functions. Signed-off-by: Krzysztof Opasiak --- diff --git a/tests/test.c b/tests/test.c index de477b0..7fae1cb 100644 --- a/tests/test.c +++ b/tests/test.c @@ -5,6 +5,10 @@ #include #include #include +#include +#include +#include +#include #include "usbg-test.h" @@ -451,47 +455,280 @@ void teardown_state(void **state) #define USBG_TEST_TS(name, test, setup) \ USBG_TEST(name, test, setup, teardown_state) -int main(void) +static UnitTest tests[] = { + /* Check if init was successfull on simple configfs state */ + USBG_TEST_TS("test_init_simple", + test_init, setup_simple_state), + + /* Check if init was successfull when all avaible functions + * are present in configfs */ + USBG_TEST_TS("test_init_all_funcs", + test_init, setup_all_funcs_state), + + /* Check if simple gadget will be correcty returned */ + USBG_TEST_TS("test_get_gadget_simple", + test_get_gadget, setup_simple_state), + + /* Check if getting non-existing and wrong gadgets cause + * expected failure and error codes are correct */ + USBG_TEST_TS("test_get_gadget_fail_simple", + test_get_gadget_fail, setup_simple_state), + + /* Check if gadget returned by get_first_gadget + * is actually first one */ + USBG_TEST_TS("test_get_first_gadget_simple", + test_get_first_gadget, setup_simple_state), + + /* Check if getting first gadget from state returns NULL when + * invalid parameters are passed */ + unit_test(test_get_first_gadget_fail), + + /* Check if returned gadget name matches expected value */ + USBG_TEST_TS("test_get_gadget_name_simple", + test_get_gadget_name, setup_simple_state), + + /* Check if returned simple gadget name length matches expected value */ + USBG_TEST_TS("test_get_gadget_name_len_simple", + test_get_gadget_name_len, setup_simple_state), + + /* Check if trying to get name of invalid gadget + * cause expected failure (name is null) */ + unit_test(test_get_gadget_name_fail), + + /* Check if getting simple gadget name into buffer work as expected*/ + USBG_TEST_TS("test_cpy_gadget_name_simple", + test_cpy_gadget_name, setup_simple_state), + + /* Check if writting gadget name into buffer fail when + * invalid parameters are passed */ + USBG_TEST_TS("test_cpy_gadget_name_fail_simple", + test_cpy_gadget_name_fail, setup_simple_state), +}; + +#define TESTS_TAG "tests" + +int gen_test_config(FILE *output) +{ + config_t cfg; + config_setting_t *root; + config_setting_t *tests_node, *node; + int i; + int ret = 0, cfg_ret = 0; + + config_init(&cfg); + config_set_tab_width(&cfg, 4); + + root = config_root_setting(&cfg); + tests_node = config_setting_add(root, TESTS_TAG, CONFIG_TYPE_LIST); + if (!tests_node) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + if (tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST) + continue; + + node = config_setting_add(tests_node, NULL, CONFIG_TYPE_STRING); + if (!node) { + ret = -ENOMEM; + goto out; + } + + cfg_ret = config_setting_set_string(node, tests[i].name); + if (cfg_ret != CONFIG_TRUE) { + ret = -EINVAL; + goto out; + } + } + + config_write(&cfg, output); +out: + config_destroy(&cfg); + return ret; +} + +int lookup_test(const char *name) { - const UnitTest tests[] = { - /* Check if init was successfull on simple configfs state */ - USBG_TEST("test_init_simple", - test_init, setup_simple_state), - /* Check if init was successfull when all avaible functions - * are present in configfs */ - USBG_TEST("test_init_all_funcs", - test_init, setup_all_funcs_state), - /* Check if simple gadget will be correcty returned */ - USBG_TEST("test_get_gadget_simple", - test_get_gadget, setup_simple_state), - /* Check if getting non-existing and wrong gadgets cause - * expected failure and error codes are correct */ - USBG_TEST("test_get_gadget_fail_simple", - test_get_gadget_fail, setup_simple_state), - /* Check if gadget returned by get_first_gadget - * is actually first one */ - USBG_TEST("test_get_first_gadget_simple", - test_get_first_gadget, setup_simple_state), - /* Check if getting first gadget from state returns NULL when - * invalid parameters are passed */ - unit_test(test_get_first_gadget_fail), - /* Check if returned gadget name matches expected value */ - USBG_TEST("test_get_gadget_name_simple", - test_get_gadget_name, setup_simple_state), - /* Check if returned simple gadget name length matches expected value */ - USBG_TEST("test_get_gadget_name_len_simple", - test_get_gadget_name_len, setup_simple_state), - /* Check if trying to get name of invalid gadget - * cause expected failure (name is null) */ - unit_test(test_get_gadget_name_fail), - /* Check if getting simple gadget name into buffer work as expected*/ - USBG_TEST("test_cpy_gadget_name_simple", - test_cpy_gadget_name, setup_simple_state), - /* Check if writting gadget name into buffer fail when - * invalid parameters are passed */ - USBG_TEST("test_cpy_gadget_name_fail_simple", - test_cpy_gadget_name_fail, setup_simple_state), + int i; + for (i = 0; i < ARRAY_SIZE(tests); ++i) + if (tests[i].function_type == UNIT_TEST_FUNCTION_TYPE_TEST && + !strcmp(name, tests[i].name)) + return i; + + return -1; +} + +int apply_test_config(FILE *input) +{ + config_t cfg; + config_setting_t *root; + config_setting_t *tests_node, *node; + int i, count, ind; + int ret = 0, cfg_ret = 0; + const char *test_name; + char selected[ARRAY_SIZE(tests)]; + + for (i = 0; i < ARRAY_SIZE(selected); ++i) + selected[i] = 0; + + config_init(&cfg); + + cfg_ret = config_read(&cfg, input); + if (cfg_ret != CONFIG_TRUE) { + fprintf(stderr, "Wrong config format\n"); + ret = -EINVAL; + goto out; + } + + root = config_root_setting(&cfg); + tests_node = config_setting_get_member(root, TESTS_TAG); + if (!tests_node || !config_setting_is_list(tests_node)) { + fprintf(stderr, "Missing or incorrect tests list\n"); + ret = -EINVAL; + goto out; + } + + count = config_setting_length(tests_node); + for (i = 0; i < count; ++i) { + node = config_setting_get_elem(tests_node, i); + if (!node) { + ret = -EINVAL; + goto out; + } + + test_name = config_setting_get_string(node); + if (!test_name) { + fprintf(stderr, "Incorrect tests list. Element %d\n", i); + ret = -EINVAL; + goto out; + } + + ind = lookup_test(test_name); + if (ind < 0) { + fprintf(stderr, "Test %s not found.\n", test_name); + ret = -EINVAL; + goto out; + } + + selected[ind] = 1; + } + + /* Structures with NULL function are skipped by cmocka*/ + for (i = 0; i < ARRAY_SIZE(selected); ++i) { + if (selected[i] || + tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST) + continue; + + if (i - 1 >= 0 && tests[i - 1].function_type == + UNIT_TEST_FUNCTION_TYPE_SETUP) + tests[i - 1].function = NULL; + + tests[i].function = NULL; + + if (i + 1 < ARRAY_SIZE(tests) && tests[i + 1].function_type == + UNIT_TEST_FUNCTION_TYPE_TEARDOWN) + tests[i + 1].function = NULL; + } +out: + config_destroy(&cfg); + return ret; +} + +void print_skipped_tests(FILE *stream) +{ + int i = 0, nmb_skipped = 0; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + if (tests[i].function || + tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST) + continue; + ++nmb_skipped; + } + + if (nmb_skipped == 0) + return; + + fprintf(stream, "[==========] %d test(s) skipped.\n", + nmb_skipped); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + if (tests[i].function || + tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST) + continue; + + fprintf(stream, "[ SKIPPED ] %s\n", tests[i].name); + } +} + +void print_help() +{ + fprintf(stderr, + "libusbgx test suit:\n" + " --generate-config - generates config to stdout and exit\n" + " --use-config - runs test suit using config from stdin\n" + " -h --help - print this message\n" + ); +} + +int main(int argc, char **argv) +{ + enum { + GENERATE_CONFIG = 0x01, + USE_CONFIG = 0x02, + }; + + int options = 0; + int opt; + int ret = -EINVAL; + + static struct option long_options[] = { + {"generate-config", no_argument, 0, 1}, + {"use-config", no_argument, 0, 2}, + {"help", no_argument, 0, 'h'}, + {NULL, 0, 0, 0} }; - return run_tests(tests); + while (1) { + opt = getopt_long(argc, argv, "h", long_options, NULL); + if (opt < 0) + break; + + switch (opt) { + case 1: + options |= GENERATE_CONFIG; + break; + case 2: + options |= USE_CONFIG; + break; + case 'h': + default: + print_help(); + goto out; + } + } + + if (optind < argc || + ((options & GENERATE_CONFIG) && + (options & USE_CONFIG))) { + print_help(); + goto out; + } + + if (options & GENERATE_CONFIG) { + ret = gen_test_config(stdout); + goto out; + } + + if (options & USE_CONFIG) { + ret = apply_test_config(stdin); + if (ret) + goto out; + } + + ret = run_tests(tests); + print_skipped_tests(stderr); + +out: + return ret; }