Module: xenomai-forge Branch: next Commit: b8aae9e832f952b9f2a9c7ba2b3d7898a8f34a68 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=b8aae9e832f952b9f2a9c7ba2b3d7898a8f34a68
Author: Philippe Gerum <r...@xenomai.org> Date: Tue Jul 1 12:10:45 2014 +0200 lib/smokey: add general documentation --- doc/doxygen/xeno3prm-common.conf.in | 1 + lib/smokey/init.c | 189 +++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+) diff --git a/doc/doxygen/xeno3prm-common.conf.in b/doc/doxygen/xeno3prm-common.conf.in index 5f0c183..904724e 100644 --- a/doc/doxygen/xeno3prm-common.conf.in +++ b/doc/doxygen/xeno3prm-common.conf.in @@ -865,6 +865,7 @@ INPUT = \ @top_srcdir@/kernel/cobalt \ @top_srcdir@/kernel/drivers \ @top_srcdir@/lib/cobalt \ + @top_srcdir@/lib/smokey \ @top_srcdir@/lib/analogy \ @top_srcdir@/lib/alchemy \ @top_srcdir@/lib/vxworks \ diff --git a/lib/smokey/init.c b/lib/smokey/init.c index 8c39011..6a55c08 100644 --- a/lib/smokey/init.c +++ b/lib/smokey/init.c @@ -35,6 +35,195 @@ * @defgroup smokey Smokey API * * A simple infrastructure for writing and running smoke tests. + * + * Smokey is based on the Copperplate API, therefore is available over + * the single and dual kernel Xenomai configurations indifferently. + * + * The API provides a set of services for declaring any number of test + * plugins, embodied into a test program. Each plugin usually + * implements a single smoke test, checking a particular feature of + * interest. Each plugin present in the running executable is + * automatically detected by the Smokey init routine. In addition, the + * Smokey API parses all arguments and options passed on the command + * line to the executable, running pre-defined actions which are + * therefore automatically recognized by all programs linked against + * the Smokey library. + * + * @par Writing smoke tests with Smokey + * + * A smoke test is composed of a routine which implements the test + * code, and a set of runtime settings/attributes for running such + * code. The routine prototype shall be: + * + * @code + * int run_<test_name>(struct smokey_test *t, int argc, char *const argv[]) + * @endcode + * + * The test routine should return a zero value for success, or any + * negated POSIX error code for indicating the failure to the test + * driver (e.g. -EINVAL if some value is found to be wrong). + * + * With @a t referring to the Smokey test descriptor, and @a argc, @a + * argv the argument count and vector expunged from all the inner + * options which may have been previously interpreted by the Smokey + * API and inner layers (such as Copperplate). + * + * The Smokey API provides the services to declare a complete test + * (named @b foo in this example) as follows: + * + * @code + * #include <smokey/smokey.h> + * + * smokey_test_plugin(foo, // test name + * SMOKEY_ARGLIST( // argument list + * SMOKEY_INT(some_integer), + * SMOKEY_STRING(some_string), + * SMOKEY_BOOL(some_boolean), + * ), + * // description + * "A dummy Smokey-based test plugin\n" + * "\taccepting three optional arguments:\n" + * "\tsome_integer=<value>\n" + * "\tsome_string=<string>\n" + * "\tsome_bool[=0/1]\n" + * ); + * + * static int run_foo(struct smokey_test *t, int argc, char *const argv[]) + * { + * char *s_arg = NULL; + * bool b_arg = false; + * int i_arg = 0, ret; + * + * ret = smokey_parse_args(t, argc, argv); + * if (ret) + * return ret; + * + * if (SMOKEY_ARG_ISSET(foo, 0)) + * i_arg = SMOKEY_ARG_INT(foo, 0); + * if (SMOKEY_ARG_ISSET(foo, 1)) + * s_arg = SMOKEY_ARG_STRING(foo, 1); + * if (SMOKEY_ARG_ISSET(foo, 2)) + * b_arg = SMOKEY_ARG_INT(foo, 2); + * + * return run_some_hypothetical_smoke_test_code(i_arg, s_arg, b_arg); + * } + * @endcode + * + * As illustrated, a smoke test is at least composed of a test plugin + * descriptor (i.e. @a smokey_test_plugin()), and a run handler named + * after the test. + * + * @par Test arguments + * + * Smokey recognizes three argument declarators, namely: + * SMOKEY_INT(name) for a C (signed) integer, SMOKEY_BOOL(name) for a + * boolean value and SMOKEY_STRING(name) for a character string. + * + * Each argument can be passed to the test code as a name=value pair, + * where @a name should match one of the declarators. Before the + * test-specific arguments can be accessed, a call to + * smokey_parse_args() must be issued by the test code, passing the + * parameters received in the run handler. + * + * Once smokey_parse_args() has returned, each argument can be checked + * individually for presence. If a valid argument was matched on the + * command line, SMOKEY_ARG_ISSET(name, position) returns non-zero, + * with @a position defined as the 0-based argument position in the + * declarator list. In the latter case, its value can be retrieved by + * a corresponding call to SMOKEY_ARG_INT(name, position), + * SMOKEY_ARG_STRING(name, position) or SMOKEY_ARG_BOOL(name, + * position). + * + * In the above example, passing "some_integer=3" on the command line of + * any program implementing such Smokey-based test would cause the + * variable i_arg to receive "3" as a value. + * + * @par Pre-defined Smokey options + * + * Any program linked against the Smokey API implicitly recognizes the + * following options: + * + * - --list dumps the list of tests implemented in the program to + * stdout. The information given includes the description strings + * provided in the plugin declarators (smokey_test_plugin()). The + * position and symbolic name of each test is also issued, which may + * be used in id specifications with the --run option (see below). + * + * @note Test positions may vary depending on changes to the host + * program like adding or removing other tests, the symbolic name + * however is stable and identifies each test uniquely. + * + * - --run[=<id[,id...]>] selects the tests to be run, determining the + * active test list among the overall set of tests detected in the + * host program. The test driver code (e.g. implementing a test + * harness program on top of Smokey) may then iterate over the @a + * smokey_test_list for accessing each active test individually, in + * the enumeration order specified by the user. + * + * If no argument is passed to --run, Smokey assumes that all tests + * detected in the current program should be picked, filling @a + * smokey_test_list with tests by increasing position order. + * + * Otherwise, id may be a test position, a symbolic name, or a range + * thereof delimited by a dash character. A symbolic name may be + * matched using a glob(3) type regular expression. + * + * id specification may be: + * + * - 0-9, picks tests #0 to #9 + * - -3, picks tests #0 to #3 + * - 5-, picks tests #5 to the highest possible test position + * - 2-0, picks tests #2 to #0, in decreasing order + * - foo, picks test foo only + * - 0,1,foo- picks tests #0, #1, and any test from foo up to the + * last test defined + * - fo* picks any test with a name starting by "fo" + * + * - --keep-going sets the boolean flag @a smokey_keep_going to a + * non-zero value, indicating to the test driver that receiving a + * failure code from a smoke test should not abort the test loop. + * This flag is not otherwise interpreted by the Smokey API. + * + * @par Writing a test driver based on the Smokey API + * + * A test driver provides the main() entry point, which should iterate + * over the test list (@a smokey_test_list) prepared by the Smokey + * API, for running each test individually. The @a for_each_smokey_test() + * helper is available for iterating over the active test list. + * + * When this entry point is called, all the initialization chores, + * including the test detection and the active test selection have + * been performed by the Smokey API already. + * + * Therefore, a possible implementation of a test driver could be as + * basic as: + * + * @code + * #include <stdio.h> + * #include <error.h> + * #include <smokey/smokey.h> + * + * int main(int argc, char *const argv[]) + * { + * struct smokey_test *t; + * int ret; + * + * if (pvlist_empty(&smokey_test_list)) + * return 0; + * + * for_each_smokey_test(t) { + * ret = t->run(t, argc, argv); + * if (ret) { + * if (smokey_keep_going) + * continue; + * error(1, -ret, "test %s failed", t->name); + * } + * printf("%s OK\n", t->name); + * } + * + * return 0; + * } + * @endcode */ DEFINE_PRIVATE_LIST(smokey_test_list); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git