From 743291a761e8ede91007bc6a8e4ecaefa13d6e9e Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 10 Feb 2014 10:34:42 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6688 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- test/lib/chtest.c | 288 +++++++++++++++++++++++++ test/lib/chtest.h | 186 ++++++++++++++++ test/lib/templates/test_root.c | 44 ++++ test/lib/templates/test_root.h | 49 +++++ test/lib/templates/test_sequence_XXX.c | 97 +++++++++ test/lib/templates/test_sequence_XXX.h | 22 ++ 6 files changed, 686 insertions(+) create mode 100644 test/lib/chtest.c create mode 100644 test/lib/chtest.h create mode 100644 test/lib/templates/test_root.c create mode 100644 test/lib/templates/test_root.h create mode 100644 test/lib/templates/test_sequence_XXX.c create mode 100644 test/lib/templates/test_sequence_XXX.h diff --git a/test/lib/chtest.c b/test/lib/chtest.c new file mode 100644 index 000000000..9d6cb8d02 --- /dev/null +++ b/test/lib/chtest.c @@ -0,0 +1,288 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ch_test.c + * @brief Unit Tests Engine module code. + * + * @addtogroup CH_TEST + * @{ + */ + +#include "hal.h" +#include "ch_test.h" +#include "test_root.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/** + * @brief Test step being executed. + */ +unsigned test_step; + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +static bool test_local_fail; +static bool test_global_fail; +static const char *test_failure_message; +static char test_tokens_buffer[TEST_MAX_TOKENS]; +static char *test_tokp; +static BaseSequentialStream *test_chp; + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +static void clear_tokens(void) { + + test_tokp = test_tokens_buffer; +} + +static void print_tokens(void) { + char *cp = test_tokens_buffer; + + while (cp < test_tokp) + streamPut(test_chp, *cp++); +} + +static void execute_test(const testcase_t *tcp) { + + /* Initialization */ + clear_tokens(); + test_local_fail = FALSE; + + if (tcp->setup != NULL) + tcp->setup(); + tcp->execute(); + if (tcp->teardown != NULL) + tcp->teardown(); +} + +static void print_line(void) { + unsigned i; + + for (i = 0; i < 76; i++) + streamPut(test_chp, '-'); + streamWrite(test_chp, (const uint8_t *)"\r\n", 2); +} + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +bool _test_fail(const char *msg) { + + test_local_fail = TRUE; + test_global_fail = TRUE; + test_failure_message = msg; + return TRUE; +} + +bool _test_assert(bool condition, const char *msg) { + + if (!condition) + return _test_fail(msg); + return FALSE; +} + +bool _test_assert_sequence(char *expected, const char *msg) { + char *cp = test_tokens_buffer; + + while (cp < test_tokp) { + if (*cp++ != *expected++) + return _test_fail(msg); + } + + if (*expected) + return _test_fail(msg); + + clear_tokens(); + + return FALSE; +} + +bool _test_assert_time_window(systime_t start, + systime_t end, + const char *msg) { + + return _test_assert(osalVTIsSystemTimeWithin(start, end), msg); +} + +/** + * @brief Prints a decimal unsigned number. + * + * @param[in] n the number to be printed + * + * @api + */ +void test_printn(uint32_t n) { + char buf[16], *p; + + if (!n) + streamPut(test_chp, '0'); + else { + p = buf; + while (n) + *p++ = (n % 10) + '0', n /= 10; + while (p > buf) + streamPut(test_chp, *--p); + } +} + +/** + * @brief Prints a line without final end-of-line. + * + * @param[in] msgp the message + * + * @api + */ +void test_print(const char *msgp) { + + while (*msgp) + streamPut(test_chp, *msgp++); +} + +/** + * @brief Prints a line. + * + * @param[in] msgp the message + * + * @api + */ +void test_println(const char *msgp) { + + test_print(msgp); + streamWrite(test_chp, (const uint8_t *)"\r\n", 2); +} + +/** + * @brief Emits a token into the tokens buffer. + * + * @param[in] token the token as a char + * + * @api + */ +void test_emit_token(char token) { + + osalSysLock(); + if (test_tokp < &test_tokens_buffer[TEST_MAX_TOKENS]) + *test_tokp++ = token; + osalSysUnlock(); +} + +/** + * @brief Emits a token into the tokens buffer from a critical zone. + * + * @param[in] token the token as a char + * + * @iclass + */ +void test_emit_token_i(char token) { + + if (test_tokp < &test_tokens_buffer[TEST_MAX_TOKENS]) + *test_tokp++ = token; +} + +/** + * @brief Test execution thread function. + * + * @param[in] stream pointer to a @p BaseSequentialStream object for test + * output + * @return A failure boolean value casted to @p msg_t. + * @retval FALSE if no errors occurred. + * @retval TRUE if one or more tests failed. + * + * @api + */ +msg_t test_execute(BaseSequentialStream *stream) { + int i, j; + + test_chp = stream; + test_println(""); +#if defined(TEST_SUITE_NAME) + test_println("*** " TEST_SUITE_NAME); +#else + test_println("*** ChibiOS test suite"); +#endif + test_println("***"); + test_print("*** Compiled: "); + test_println(__DATE__ " - " __TIME__); +#ifdef PLATFORM_NAME + test_print("*** Platform: "); + test_println(PLATFORM_NAME); +#endif +#ifdef BOARD_NAME + test_print("*** Test Board: "); + test_println(BOARD_NAME); +#endif + test_println(""); + + test_global_fail = FALSE; + i = 0; + while (test_suite[i]) { + j = 0; + while (test_suite[i][j]) { + print_line(); + test_print("--- Test Case "); + test_printn(i + 1); + test_print("."); + test_printn(j + 1); + test_print(" ("); + test_print(test_suite[i][j]->name); + test_println(")"); +#if TEST_DELAY_BETWEEN_TESTS > 0 + osalThreadSleepMilliseconds(TEST_DELAY_BETWEEN_TESTS); +#endif + execute_test(test_suite[i][j]); + if (test_local_fail) { + test_print("--- Result: FAILURE (#"); + test_printn(test_step); + test_print(" ["); + print_tokens(); + test_print("] \""); + test_print(test_failure_message); + test_println("\")"); + } + else + test_println("--- Result: SUCCESS"); + j++; + } + i++; + } + print_line(); + test_println(""); + test_print("Final result: "); + if (test_global_fail) + test_println("FAILURE"); + else + test_println("SUCCESS"); + + return (msg_t)test_global_fail; +} + +/** @} */ diff --git a/test/lib/chtest.h b/test/lib/chtest.h new file mode 100644 index 000000000..c8e03490c --- /dev/null +++ b/test/lib/chtest.h @@ -0,0 +1,186 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ch_test.h + * @brief Unit Tests Engine Module macros and structures. + * + * @addtogroup CH_TEST + * @{ + */ + +#ifndef _CH_TEST_H_ +#define _CH_TEST_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Maximum number of entries in the tokens buffer. + */ +#if !defined(TEST_MAX_TOKENS) || defined(__DOXYGEN__) +#define TEST_MAX_TOKENS 16 +#endif + +/** + * @brief Delay inserted between test cases. + */ +#if !defined(TEST_DELAY_BETWEEN_TESTS) || defined(__DOXYGEN__) +#define TEST_DELAY_BETWEEN_TESTS 200 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Structure representing a test case. + */ +typedef struct { + const char *name; /**< @brief Test case name. */ + void (*setup)(void); /**< @brief Test case preparation function. */ + void (*teardown)(void); /**< @brief Test case clean up function. */ + void (*execute)(void); /**< @brief Test case execution function. */ +} testcase_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Sets the step identifier. + * + * @param[in] step the step number + */ +#define test_set_step(step) test_step = (step) + +/** + * @brief Test failure enforcement. + * @note This function can only be called from test_case execute context. + * + * @param[in] msg failure message as string + * + * @api + */ +#define test_fail(msg) { \ + _test_fail(msg); \ + return; \ +} + +/** + * @brief Test assertion. + * @note This function can only be called from test_case execute context. + * + * @param[in] condition a boolean expression that must be verified to be true + * @param[in] msg failure message as string + * + * @api + */ +#define test_assert(condition, msg) { \ + if (_test_assert(condition, msg)) \ + return; \ +} + +/** + * @brief Test assertion with lock. + * @note This function can only be called from test_case execute context. + * + * @param[in] condition a boolean expression that must be verified to be true + * @param[in] msg failure message as string + * + * @api + */ +#define test_assert_lock(condition, msg) { \ + osalSysLock(); \ + if (_test_assert(condition, msg)) { \ + osalSysUnlock(); \ + return; \ + } \ + osalSysUnlock(); \ +} + +/** + * @brief Test sequence assertion. + * @note This function can only be called from test_case execute context. + * + * @param[in] expected string to be matched with the tokens buffer + * @param[in] msg failure message as string + * + * @api + */ +#define test_assert_sequence(expected, msg) { \ + if (_test_assert_sequence(expected, msg)) \ + return; \ +} + +/** + * @brief Test time window assertion. + * @note This function can only be called from test_case execute context. + * + * @param[in] start initial time in the window (included) + * @param[in] end final time in the window (not included) + * @param[in] msg failure message as string + * + * @api + */ +#define test_assert_time_window(start, end, msg) { \ + if (_test_assert_time_window(start, end, msg)) \ + return; \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern unsigned test_step; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + bool _test_fail(const char *message); + bool _test_assert(bool condition, const char *msg); + bool _test_assert_sequence(char *expected, const char *msg); + bool _test_assert_time_window(systime_t start, + systime_t end, + const char *msg); + void test_printn(uint32_t n); + void test_print(const char *msgp); + void test_println(const char *msgp); + void test_emit_token(char token); + void test_emit_token_i(char token); + msg_t test_execute(BaseSequentialStream *stream); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +#endif /* _CH_TEST_H_ */ + +/** @} */ diff --git a/test/lib/templates/test_root.c b/test/lib/templates/test_root.c new file mode 100644 index 000000000..8fb2ec9b9 --- /dev/null +++ b/test/lib/templates/test_root.c @@ -0,0 +1,44 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file test_root.c + * @brief Test Suite root structures code. + * + * @addtogroup CH_TEST_ROOT + * @{ + */ + +#include "hal.h" +#include "ch_test.h" +#include "test_root.h" + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/** + * @brief Array of all the test sequences. + */ +const testcase_t * const *test_suite[] = { + NULL +}; + +/*===========================================================================*/ +/* Shared code. */ +/*===========================================================================*/ + +/** @} */ diff --git a/test/lib/templates/test_root.h b/test/lib/templates/test_root.h new file mode 100644 index 000000000..3d26ecd50 --- /dev/null +++ b/test/lib/templates/test_root.h @@ -0,0 +1,49 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file test_root.h + * @brief Test Suite root structures header. + * + * @addtogroup CH_TEST_ROOT + * @{ + */ + +#ifndef _TEST_ROOT_H_ +#define _TEST_ROOT_H_ + +#include "test_000.h" + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +extern const testcase_t * const *test_suite[]; + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Shared definitions. */ +/*===========================================================================*/ + +#endif /* _TEST_ROOT_H_ */ + +/** @} */ diff --git a/test/lib/templates/test_sequence_XXX.c b/test/lib/templates/test_sequence_XXX.c new file mode 100644 index 000000000..3fb1df8e0 --- /dev/null +++ b/test/lib/templates/test_sequence_XXX.c @@ -0,0 +1,97 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "test_root.h" + +/** + * @page test_sequence_XXX Sequence brief description + * + * File: @ref test_sequence_XXX.c + * + *

Description

+ * Sequence detailed description. + * + *

Test Cases

+ * - @subpage test_XXX_000 + * . + */ + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +#if TEST_XXX_000_CONDITION || defined(__DOXYGEN__) +/** + * @page test_XXX_000 Brief description + * + *

Description

+ * Detailed description. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - TEST_XXX_000_CONDITION + * . + * + *

Test Steps

+ * - Step description. + * . + */ + +static void test_XXX_000_setup(void) { + +} + +static void test_XXX_000}_teardown(void) { + +} + +static void test_XXX_000_execute(void) { + + /* Step description.*/ + test_set_step(1); + { + } +} + +static const testcase_t test_XXX_000 = { + "Brief description", + test_XXX_000_setup, + test_XXX_000_teardown, + test_XXX_000_execute +}; + #endif /* TEST_XXX_000_CONDITION */ + + /**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Sequence brief description. + */ +const testcase_t * const test_sequence_XXX[] = { +#if TEST_XXX_000_CONDITION || defined(__DOXYGEN__) + &test_XXX_000, +#endif + NULL +}; diff --git a/test/lib/templates/test_sequence_XXX.h b/test/lib/templates/test_sequence_XXX.h new file mode 100644 index 000000000..86578fdca --- /dev/null +++ b/test/lib/templates/test_sequence_XXX.h @@ -0,0 +1,22 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _TEST_SEQUENCE_XXX_H_ +#define _TEST_SEQUENCE_XXX_H_ + +extern const testcase_t * const test_sequence_XXX[]; + +#endif /* _TEST_SEQUENCE_XXX_H_ */