Issue 187 enable skipped ztest suites (#189)

* Fix some ztests that were skipped

* Expose bacapp_same_value()

* Fix bacapp, ptransfer tests

* Fix bugs in Load_Control object & tests

* refactor days functions from datetime module

* fix legacy ctests

* Add bacnet/basic/sys/days.[ch] to Zephyr build

* Update ztest to match from Zephyr v2.6.0; update ringbuf, datetime to build

* Fixup ztest test for object/acc

* Fix bvlc_address_from_ascii; enable/fix bvlc test

* Comment cleanup

* test/bacnet/basic/object/lc partially enabled

* Fix bacapp_decode_data_len return status on erroneous input

* fix ztest include fatal error

* fix ztest strsignal reference fatal error

* fix zassert_mem_equal reference syntax error

* fix zassert_mem_equal reference syntax error

Co-authored-by: Gregory Shue <gregory.shue@legrand.us>
Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Greg Shue
2021-08-16 15:29:40 -07:00
committed by GitHub
parent 541f4024fb
commit 8b8ef8f338
102 changed files with 3178 additions and 1208 deletions
+60 -9
View File
@@ -6,8 +6,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __TC_UTIL_H__
#define __TC_UTIL_H__
#ifndef ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_
#define ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_
#include <zephyr.h>
@@ -92,6 +92,31 @@ static inline const char *TC_RESULT_TO_STR(int result)
}
}
static uint32_t tc_start_time;
static uint32_t tc_spend_time;
static inline void get_start_time_cyc(void)
{
/* Besides the ztest framework, some testcase will also call
* TC_START() in their code. But the caller thread cannot be
* in userspace.
*/
#if 0
if (!k_is_user_context()) {
tc_start_time = k_cycle_get_32();
}
#endif
}
static inline void test_time_ms(void)
{
#if 0
uint32_t spend_cycle = k_cycle_get_32() - tc_start_time;
tc_spend_time = k_cyc_to_ms_ceil32(spend_cycle);
#endif
}
#ifndef TC_ERROR
#define TC_ERROR(fmt, ...) \
do { \
@@ -105,7 +130,11 @@ static inline const char *TC_RESULT_TO_STR(int result)
#endif
#ifndef TC_START
#define TC_START(name) PRINT_DATA("starting test - %s\n", name)
#define TC_START(name) \
do { \
PRINT_DATA("START - %s\n", name); \
get_start_time_cyc(); \
} while (0)
#endif
#ifndef TC_END
@@ -114,10 +143,13 @@ static inline const char *TC_RESULT_TO_STR(int result)
#ifndef Z_TC_END_RESULT
/* prints result and the function name */
#define Z_TC_END_RESULT(result, func) \
do { \
TC_END(result, "%s - %s\n", TC_RESULT_TO_STR(result), func); \
PRINT_LINE; \
#define Z_TC_END_RESULT(result, func) \
do { \
test_time_ms(); \
TC_END(result, " %s - %s in %u.%u seconds\n", \
TC_RESULT_TO_STR(result), func, tc_spend_time/1000, \
tc_spend_time%1000); \
PRINT_LINE; \
} while (0)
#endif
@@ -126,6 +158,25 @@ static inline const char *TC_RESULT_TO_STR(int result)
Z_TC_END_RESULT((result), __func__)
#endif
#ifndef TC_SUITE_START
#define TC_SUITE_START(name) \
do { \
TC_PRINT("Running test suite %s\n", name); \
PRINT_LINE; \
} while (0)
#endif
#ifndef TC_SUITE_END
#define TC_SUITE_END(name, result) \
do { \
if (result == TC_PASS) { \
TC_PRINT("Test suite %s succeeded\n", name); \
} else { \
TC_PRINT("Test suite %s failed.\n", name); \
} \
} while (0)
#endif
#if defined(CONFIG_ARCH_POSIX)
#define TC_END_POST(result) posix_exit(result)
#else
@@ -157,7 +208,7 @@ static inline const char *TC_RESULT_TO_STR(int result)
#define TC_CMD_ITEM(name) cmd_##name
#else
#define TC_CMD_DEFINE(name) \
int cmd_##name(int argc, char *argv[]) \
int cmd_##name(int argc, char *argv[]) \
{ \
TC_START(__func__); \
name(); \
@@ -167,4 +218,4 @@ static inline const char *TC_RESULT_TO_STR(int result)
#define TC_CMD_ITEM(name) {STRINGIFY(name), cmd_##name, "none"}
#endif
#endif /* __TC_UTIL_H__ */
#endif /* ZEPHYR_TESTSUITE_INCLUDE_TC_UTIL_H_ */
+7 -7
View File
@@ -35,19 +35,19 @@
#include <tc_util.h>
#include <tinycrypt/constants.h>
static inline void show_str(const char *label, const u8_t *s, size_t len)
static inline void show_str(const char *label, const uint8_t *s, size_t len)
{
u32_t i;
uint32_t i;
TC_PRINT("%s = ", label);
for (i = 0U; i < (u32_t)len; ++i) {
for (i = 0U; i < (uint32_t)len; ++i) {
TC_PRINT("%02x", s[i]);
}
TC_PRINT("\n");
}
static inline
void fatal(u32_t testnum, const void *expected, size_t expectedlen,
void fatal(uint32_t testnum, const void *expected, size_t expectedlen,
const void *computed, size_t computedlen)
{
TC_ERROR("\tTest #%d Failed!\n", testnum);
@@ -57,11 +57,11 @@ void fatal(u32_t testnum, const void *expected, size_t expectedlen,
}
static inline
u32_t check_result(u32_t testnum, const void *expected,
uint32_t check_result(uint32_t testnum, const void *expected,
size_t expectedlen, const void *computed,
size_t computedlen, u32_t verbose)
size_t computedlen, uint32_t verbose)
{
u32_t result = TC_PASS;
uint32_t result = TC_PASS;
ARG_UNUSED(verbose);
+14 -16
View File
@@ -2,34 +2,29 @@
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*
* Modified from zephyr_v2.2.0 subsys/testsuite/ztest/include/ztest.h
* because:
* 1. This port will never be run in the Zephyr kernel.
* This repository is extended to be a Zephyr module for that.
* 2. This port will not support multiple CPUs or toolchains.
*
* Modifications:
* a. Code conditionally compiled on the following CPP symbols were deleted
* (as they were kernel-specific):
* KERNEL
*/
/**
* @file
*
* @brief Zephyr testing suite
* @brief Zephyr Testsuite
*
* From zephyr_v2.6.0 subsys/testsuite/ztest/include/ztest.h
* Note:
* 1. This port will never be run in the Zephyr kernel.
* This repository is extended to be a Zephyr module for that.
* 2. This port will not support multiple CPUs or toolchains.
*/
/**
* @brief Zephyr Tests
* @brief Zephyr Tests (ZTest)
* @defgroup all_tests Zephyr Tests
* @{
* @}
*/
#ifndef __ZTEST_H__
#define __ZTEST_H__
#ifndef ZEPHYR_TESTSUITE_INCLUDE_ZTEST_H_
#define ZEPHYR_TESTSUITE_INCLUDE_ZTEST_H_
/**
* @defgroup ztest Zephyr testing suite
@@ -39,6 +34,7 @@
#error "You need to add CONFIG_ZTEST to your config file."
#endif
#ifndef KERNEL
#define CONFIG_STDOUT_CONSOLE 1
#define CONFIG_ZTEST_ASSERT_VERBOSE 1
#define CONFIG_ZTEST_MOCKING
@@ -48,6 +44,7 @@
#define CONFIG_MP_NUM_CPUS 1
#define CONFIG_SYS_CLOCK_TICKS_PER_SEC 100
#define CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC 10000000
#define ARCH_STACK_PTR_ALIGN 8
/* FIXME: Properly integrate with Zephyr's arch specific code */
#define CONFIG_X86 1
#define CONFIG_PRINTK 1
@@ -59,6 +56,7 @@ typedef struct esf z_arch_esf_t;
#ifdef __cplusplus
}
#endif
#endif /* KERNEL */
#include <sys/printk.h>
#define PRINT printk
@@ -80,4 +78,4 @@ void test_main(void);
}
#endif
#endif /* __ZTEST_H__ */
#endif /* ZEPHYR_TESTSUITE_INCLUDE_ZTEST_H_ */
+32 -13
View File
@@ -10,8 +10,8 @@
* @brief Zephyr testing framework assertion macros
*/
#ifndef __ZTEST_ASSERT_H__
#define __ZTEST_ASSERT_H__
#ifndef ZEPHYR_TESTSUITE_ZTEST_ASSERT_H_
#define ZEPHYR_TESTSUITE_ZTEST_ASSERT_H_
#include <ztest.h>
#include <stdarg.h>
@@ -23,16 +23,20 @@
extern "C" {
#endif
const char *ztest_relative_filename(const char *file);
void ztest_test_fail(void);
#if CONFIG_ZTEST_ASSERT_VERBOSE == 0
static inline void z_zassert_(bool cond, const char *file, int line)
static inline bool z_zassert_(bool cond, const char *file, int line)
{
if (cond == false) {
PRINT("\n Assertion failed at %s:%d\n",
file, line);
ztest_relative_filename(file), line);
ztest_test_fail();
return false;
}
return true;
}
#define z_zassert(cond, default_msg, file, line, func, msg, ...) \
@@ -40,7 +44,7 @@ static inline void z_zassert_(bool cond, const char *file, int line)
#else /* CONFIG_ZTEST_ASSERT_VERBOSE != 0 */
static inline void z_zassert(bool cond,
static inline bool z_zassert(bool cond,
const char *default_msg,
const char *file,
int line, const char *func,
@@ -51,18 +55,20 @@ static inline void z_zassert(bool cond,
va_start(vargs, msg);
PRINT("\n Assertion failed at %s:%d: %s: %s\n",
file, line, func, default_msg);
ztest_relative_filename(file), line, func, default_msg);
vprintk(msg, vargs);
printk("\n");
va_end(vargs);
ztest_test_fail();
return false;
}
#if CONFIG_ZTEST_ASSERT_VERBOSE == 2
else {
PRINT("\n Assertion succeeded at %s:%d (%s)\n",
file, line, func);
ztest_relative_filename(file), line, func);
}
#endif
return true;
}
#endif /* CONFIG_ZTEST_ASSERT_VERBOSE */
@@ -83,14 +89,19 @@ static inline void z_zassert(bool cond,
* You probably don't need to call this macro directly. You should
* instead use zassert_{condition} macros below.
*
* Note that when CONFIG_MULTITHREADING=n macro returns from the function. It is
* then expected that in that case ztest asserts will be used only in the
* context of the test function.
*
* @param cond Condition to check
* @param msg Optional, can be NULL. Message to print if @a cond is false.
* @param default_msg Message to print if @a cond is false
*/
#define zassert(cond, default_msg, msg, ...) \
z_zassert(cond, msg ? ("(" default_msg ")") : (default_msg), \
__FILE__, __LINE__, __func__, msg ? msg : "", ##__VA_ARGS__)
#define zassert(cond, default_msg, msg, ...) do { \
bool _ret = z_zassert(cond, msg ? ("(" default_msg ")") : (default_msg), \
__FILE__, __LINE__, __func__, \
msg ? msg : "", ##__VA_ARGS__); \
} while (0)
/**
* @brief Assert that this function call won't be reached
@@ -115,6 +126,14 @@ static inline void z_zassert(bool cond,
#define zassert_false(cond, msg, ...) zassert(!(cond), #cond " is true", \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a cond is 0 (success)
* @param cond Condition to check
* @param msg Optional message to print if the assertion fails
*/
#define zassert_ok(cond, msg, ...) zassert(!(cond), #cond " is non-zero", \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a ptr is NULL
* @param ptr Pointer to compare
@@ -181,7 +200,7 @@ static inline void z_zassert(bool cond,
* @param msg Optional message to print if the assertion fails
*/
#define zassert_within(a, b, d, msg, ...) \
zassert(((a) > ((b) - (d))) && ((a) < ((b) + (d))), \
zassert(((a) >= ((b) - (d))) && ((a) <= ((b) + (d))), \
#a " not within " #b " +/- " #d, \
msg, ##__VA_ARGS__)
@@ -222,4 +241,4 @@ static inline void z_zassert(bool cond,
}
#endif
#endif /* __ZTEST_ASSERT_H__ */
#endif /* ZEPHYR_TESTSUITE_ZTEST_ASSERT_H_ */
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2020 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_ZTEST_FATAL_HOOK_H_
#define ZEPHYR_INCLUDE_ZTEST_FATAL_HOOK_H_
#include <zephyr.h>
#if defined(CONFIG_ZTEST_FATAL_HOOK)
/**
* @brief Set the flag that treat fatal error happened as expected
*
* @details This is used for negative test cases which triggers a fatal
* error. Set the param true will still pass the test case when expected
* fatal error happened. For normal test case, set it false makes it back
* to normal behavior.
*
* @param valid flag indicate fault is expected
*/
__syscall void ztest_set_fault_valid(bool valid);
/* @brief A hook after fatal error handler
*
* @details This is a test case hook that can run code from test case, in
* order to deal with some special case when catching the expected fatal
* error.
*
* Usage: Define your own hook function in your test case code, and do what
* you want to do after fatal error handler.
*
* By default, it will do nothing before leaving error handler.
*/
void ztest_post_fatal_error_hook(unsigned int reason,
const z_arch_esf_t *pEsf);
#endif
#if defined(CONFIG_ZTEST_ASSERT_HOOK)
/**
* @brief Set the flag that treat assert fail happened as expected
*
* @details This is used for negative test cases which triggers a assert
* fail. Set the param true will still pass the test case when expected
* assert fail happened. For normal test case, set it false make it back
* to normal behavior.
*
* @param valid flag indicate assert is expected
*/
__syscall void ztest_set_assert_valid(bool valid);
/* @brief A hook after assert fault handler
*
* @details This is a test case hook that can run code from test case, in
* order to deal with some special case when catching the expected assert
* failed.
*
* Usage: Define your own hook function in your test case code, and do what
* you want to do after assert handler.
*
* By default, it will abort the thread which assert failed.
*/
void ztest_post_assert_fail_hook(void);
#endif
#if defined(CONFIG_ZTEST_FATAL_HOOK) || defined(CONFIG_ZTEST_ASSERT_HOOK)
#include <syscalls/ztest_error_hook.h>
#endif
#endif /* ZEPHYR_INCLUDE_ZTEST_FATAL_HOOK_H_ */
+80 -15
View File
@@ -10,8 +10,8 @@
* @brief Ztest mocking support
*/
#ifndef __ZTEST_MOCK_H__
#define __ZTEST_MOCK_H__
#ifndef ZEPHYR_TESTSUITE_ZTEST_MOCK_H_
#define ZEPHYR_TESTSUITE_ZTEST_MOCK_H_
/**
* @defgroup ztest_mock Ztest mocking support
@@ -33,9 +33,9 @@
* @param param Parameter for which the value should be set
* @param value Value for @a param
*/
#define ztest_expect_value(func, param, value) \
z_ztest_expect_value(STRINGIFY(func), STRINGIFY(param), \
(uintptr_t)(value))
#define ztest_expect_value(func, param, value) \
z_ztest_expect_value(STRINGIFY(func), STRINGIFY(param), \
(uintptr_t)(value))
/**
* @brief If @a param doesn't match the value set by ztest_expect_value(),
@@ -48,17 +48,75 @@
*
* @param param Parameter to check
*/
#define ztest_check_expected_value(param) \
z_ztest_check_expected_value(__func__, STRINGIFY(param), \
(uintptr_t)(param))
#define ztest_check_expected_value(param) \
z_ztest_check_expected_value(__func__, STRINGIFY(param), \
(uintptr_t)(param))
/**
* @brief Tell function @a func to expect the data @a data for @a param
*
* When using ztest_check_expected_data(), the data pointed to by
* @a param should be same @a data in this function. Only data pointer is stored
* by this function, so it must still be valid when ztest_check_expected_data is
* called.
*
* @param func Function in question
* @param param Parameter for which the data should be set
* @param data pointer for the data for parameter @a param
*/
#define ztest_expect_data(func, param, data) \
z_ztest_expect_data(STRINGIFY(func), STRINGIFY(param), (void *)(data))
/**
* @brief If data pointed by @a param don't match the data set by
* ztest_expect_data(), fail the test
*
* This will first check that @a param is expected to be null or non-null and
* then check whether the data pointed by parameter is equal to expected data.
* If either of these checks fail, the current test will fail. This
* must be called from the called function.
*
* @param param Parameter to check
* @param length Length of the data to compare
*/
#define ztest_check_expected_data(param, length) \
z_ztest_check_expected_data(__func__, STRINGIFY(param), \
(void *)(param), (length))
/**
* @brief Tell function @a func to return the data @a data for @a param
*
* When using ztest_return_data(), the data pointed to by @a param should be
* same @a data in this function. Only data pointer is stored by this function,
* so it must still be valid when ztest_copy_return_data is called.
*
* @param func Function in question
* @param param Parameter for which the data should be set
* @param data pointer for the data for parameter @a param
*/
#define ztest_return_data(func, param, data) \
z_ztest_return_data(STRINGIFY(func), STRINGIFY(param), (void *)(data))
/**
* @brief Copy the data set by ztest_return_data to the memory pointed by
* @a param
*
* This will first check that @a param is not null and then copy the data.
* This must be called from the called function.
*
* @param param Parameter to return data for
* @param length Length of the data to return
*/
#define ztest_copy_return_data(param, length) \
z_ztest_copy_return_data(__func__, STRINGIFY(param), \
(void *)(param), (length))
/**
* @brief Tell @a func that it should return @a value
*
* @param func Function that should return @a value
* @param value Value to return from @a func
*/
#define ztest_returns_value(func, value) \
#define ztest_returns_value(func, value) \
z_ztest_returns_value(STRINGIFY(func), (uintptr_t)(value))
/**
@@ -69,8 +127,7 @@
*
* @returns The value the current function should return
*/
#define ztest_get_return_value() \
z_ztest_get_return_value(__func__)
#define ztest_get_return_value() z_ztest_get_return_value(__func__)
/**
* @brief Get the return value as a pointer for current function
@@ -80,7 +137,7 @@
*
* @returns The value the current function should return as a `void *`
*/
#define ztest_get_return_value_ptr() \
#define ztest_get_return_value_ptr() \
((void *)z_ztest_get_return_value(__func__))
/**
@@ -100,7 +157,15 @@ int z_cleanup_mock(void);
void z_ztest_expect_value(const char *fn, const char *name, uintptr_t value);
void z_ztest_check_expected_value(const char *fn, const char *param,
uintptr_t value);
uintptr_t value);
void z_ztest_expect_data(const char *fn, const char *name, void *val);
void z_ztest_check_expected_data(const char *fn, const char *name, void *data,
uint32_t length);
void z_ztest_return_data(const char *fn, const char *name, void *val);
void z_ztest_copy_return_data(const char *fn, const char *name, void *data,
uint32_t length);
void z_ztest_returns_value(const char *fn, uintptr_t value);
uintptr_t z_ztest_get_return_value(const char *fn);
@@ -114,6 +179,6 @@ uintptr_t z_ztest_get_return_value(const char *fn);
#define z_init_mock()
#define z_cleanup_mock() 0
#endif /* CONFIG_ZTEST_MOCKING */
#endif /* CONFIG_ZTEST_MOCKING */
#endif /* __ZTEST_H__ */
#endif /* ZEPHYR_TESTSUITE_ZTEST_MOCK_H_ */
+39 -14
View File
@@ -9,26 +9,24 @@
*
* @brief Zephyr testing framework _test.
*
* Modified from zephyr_v2.2.0 subsys/testsuite/ztest/src/ztest.c
* because:
* From zephyr_v2.6.0 subsys/testsuite/ztest/src/ztest.c
* Note:
* 1. This port will never be run in the Zephyr kernel.
* This repository is extended to be a Zephyr module for that.
* 2. This port will not support multiple CPUs or toolchains.
*
* Modifications:
* a. Code conditionally compiled on the following CPP symbols were deleted
* (as they were kernel-specific):
* CONFIG_USERSPACE
* CONFIG_SMP
* KERNEL
* b. Inclusion of The following header files were removed as irrelevant.
* <app_memory/app_memdomain.h>
* c. syscall declarations and inclusions.
* 1. Added __ZEPHYR__ conditionals around:
* a. #include <app_memory/app_memdomain.h>
* b. syscall declarations and inclusions.
*/
#ifndef __ZTEST_TEST_H__
#define __ZTEST_TEST_H__
#ifndef ZEPHYR_TESTSUITE_ZTEST_TEST_H_
#define ZEPHYR_TESTSUITE_ZTEST_TEST_H_
#if 0 /* __ZEPHYR__ */
#include <app_memory/app_memdomain.h>
#endif /* __ZEPHYR__ */
#ifdef __cplusplus
extern "C" {
@@ -39,7 +37,7 @@ struct unit_test {
void (*test)(void);
void (*setup)(void);
void (*teardown)(void);
u32_t thread_options;
uint32_t thread_options;
};
void z_ztest_run_test_suite(const char *name, struct unit_test *suite);
@@ -145,6 +143,11 @@ static inline void unit_test_noop(void)
#define ztest_user_unit_test(fn) \
ztest_user_unit_test_setup_teardown(fn, unit_test_noop, unit_test_noop)
#if 0 /* __ZEPHYR__ */
__syscall void z_test_1cpu_start(void);
__syscall void z_test_1cpu_stop(void);
#endif /* __ZEPHYR__ */
/**
* @brief Define a SMP-unsafe test function
*
@@ -153,7 +156,12 @@ static inline void unit_test_noop(void)
*
* @param fn Test function
*/
#ifdef CONFIG_SMP
#define ztest_1cpu_unit_test(fn) \
ztest_unit_test_setup_teardown(fn, z_test_1cpu_start, z_test_1cpu_stop)
#else
#define ztest_1cpu_unit_test(fn) ztest_unit_test(fn)
#endif
/**
* @brief Define a SMP-unsafe test function that should run as a user thread
@@ -163,12 +171,24 @@ static inline void unit_test_noop(void)
*
* @param fn Test function
*/
#ifdef CONFIG_SMP
#define ztest_1cpu_user_unit_test(fn) \
ztest_user_unit_test_setup_teardown(fn, z_test_1cpu_start, z_test_1cpu_stop)
#else
#define ztest_1cpu_user_unit_test(fn) ztest_user_unit_test(fn)
#endif
/* definitions for use with testing application shared memory */
#ifdef CONFIG_USERSPACE
#define ZTEST_DMEM K_APP_DMEM(ztest_mem_partition)
#define ZTEST_BMEM K_APP_BMEM(ztest_mem_partition)
#define ZTEST_SECTION K_APP_DMEM_SECTION(ztest_mem_partition)
extern struct k_mem_partition ztest_mem_partition;
#else
#define ZTEST_DMEM
#define ZTEST_BMEM
#define ZTEST_SECTION .data
#endif
/**
* @brief Define a test suite
@@ -200,9 +220,14 @@ static inline void unit_test_noop(void)
/**
* @}
*/
#ifndef ZTEST_UNITTEST
#if 0 /* __ZEPHYR__ */
#include <syscalls/ztest_test.h>
#endif /* _ZEPHYR__ */
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ZTEST_ASSERT_H__ */
#endif /* ZEPHYR_TESTSUITE_ZTEST_TEST_H_ */
+322 -34
View File
@@ -2,26 +2,26 @@
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*
* Modified from zephyr_v2.2.0 subsys/testsuite/ztest/src/ztest.c
* because:
* 1. This port will never be run in the Zephyr kernel.
* This repository is extended to be a Zephyr module for that.
* 2. This port will not support multiple CPUs or toolchains.
*
* Modifications:
* a. Deleted code conditionally compiled on the following CPP symbols:
* (as they were kernel-specific):
* CONFIG_USERSPACE
* KERNEL
* b. Removed irrelevant inclusion of the following header files:
* <app_memory/app_memdomain.h>
* <power/reboot.h>
* c. Addition of test_skip functionality missing from non-kernel paths.
*/
#include <ztest.h>
#include <stdio.h>
#include <tc_util.h>
#if 0
#include <app_memory/app_memdomain.h>
#ifdef CONFIG_USERSPACE
#include <sys/libc-hooks.h>
#endif
#endif
#ifdef KERNEL
#include <sys/reboot.h>
static struct k_thread ztest_thread;
#endif
#ifdef CONFIG_ARCH_POSIX
#include <unistd.h>
#endif
/* ZTEST_DMEM and ZTEST_BMEM are used for the application shared memory test */
@@ -34,6 +34,31 @@ ZTEST_DMEM enum {
static ZTEST_BMEM int test_status;
/**
* @brief Try to shorten a filename by removing the current directory
*
* This helps to reduce the very long filenames in assertion failures. It
* removes the current directory from the filename and returns the rest.
* This makes assertions a lot more readable, and sometimes they fit on one
* line.
*
* @param file Filename to check
* @returns Shortened filename, or @file if it could not be shortened
*/
const char *ztest_relative_filename(const char *file)
{
#ifdef CONFIG_ARCH_POSIX
const char *cwd;
char buf[200];
cwd = getcwd(buf, sizeof(buf));
if (cwd && strlen(file) > strlen(cwd) &&
!strncmp(file, cwd, strlen(cwd)))
return file + strlen(cwd) + 1; /* move past the trailing '/' */
#endif
return file;
}
static int cleanup_test(struct unit_test *test)
{
int ret = TC_PASS;
@@ -41,6 +66,16 @@ static int cleanup_test(struct unit_test *test)
mock_status = z_cleanup_mock();
#ifdef KERNEL
/* we need to remove the ztest_thread information from the timeout_q.
* Because we reuse the same k_thread structure this would
* causes some problems.
*/
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
k_thread_abort(&ztest_thread);
}
#endif
if (!ret && mock_status == 1) {
PRINT("Test %s failed: Unused mock parameter values\n",
test->name);
@@ -49,11 +84,123 @@ static int cleanup_test(struct unit_test *test)
PRINT("Test %s failed: Unused mock return values\n",
test->name);
ret = TC_FAIL;
} else {
;
}
return ret;
}
#ifdef KERNEL
#ifdef CONFIG_SMP
#define NUM_CPUHOLD (CONFIG_MP_NUM_CPUS - 1)
#else
#define NUM_CPUHOLD 0
#endif
#define CPUHOLD_STACK_SZ (512 + CONFIG_TEST_EXTRA_STACKSIZE)
static struct k_thread cpuhold_threads[NUM_CPUHOLD];
K_KERNEL_STACK_ARRAY_DEFINE(cpuhold_stacks, NUM_CPUHOLD, CPUHOLD_STACK_SZ);
static struct k_sem cpuhold_sem;
volatile int cpuhold_active;
/* "Holds" a CPU for use with the "1cpu" test cases. Note that we
* can't use tools like the cpumask feature because we have tests that
* may need to control that configuration themselves. We do this at
* the lowest level, but locking interrupts directly and spinning.
*/
static void cpu_hold(void *arg1, void *arg2, void *arg3)
{
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
unsigned int key = arch_irq_lock();
uint32_t dt, start_ms = k_uptime_get_32();
k_sem_give(&cpuhold_sem);
#if defined(CONFIG_ARM64) && defined(CONFIG_FPU_SHARING)
/*
* We'll be spinning with IRQs disabled. The flush-your-FPU request
* IPI will never be serviced during that time. Therefore we flush
* the FPU preemptively here to prevent any other CPU waiting after
* this CPU forever and deadlock the system.
*/
extern void z_arm64_flush_local_fpu(void);
z_arm64_flush_local_fpu();
#endif
while (cpuhold_active) {
k_busy_wait(1000);
}
/* Holding the CPU via spinning is expensive, and abusing this
* for long-running test cases tends to overload the CI system
* (qemu runs separate CPUs in different threads, but the CI
* logic views it as one "job") and cause other test failures.
*/
dt = k_uptime_get_32() - start_ms;
zassert_true(dt < 3000,
"1cpu test took too long (%d ms)", dt);
arch_irq_unlock(key);
}
void z_impl_z_test_1cpu_start(void)
{
cpuhold_active = 1;
#ifdef CONFIG_THREAD_NAME
char tname[CONFIG_THREAD_MAX_NAME_LEN];
#endif
k_sem_init(&cpuhold_sem, 0, 999);
/* Spawn N-1 threads to "hold" the other CPUs, waiting for
* each to signal us that it's locked and spinning.
*
* Note that NUM_CPUHOLD can be a value that causes coverity
* to flag the following loop as DEADCODE so suppress the warning.
*/
/* coverity[DEADCODE] */
for (int i = 0; i < NUM_CPUHOLD; i++) {
k_thread_create(&cpuhold_threads[i],
cpuhold_stacks[i], CPUHOLD_STACK_SZ,
(k_thread_entry_t) cpu_hold, NULL, NULL, NULL,
K_HIGHEST_THREAD_PRIO, 0, K_NO_WAIT);
#ifdef CONFIG_THREAD_NAME
snprintk(tname, CONFIG_THREAD_MAX_NAME_LEN, "cpuhold%02d", i);
k_thread_name_set(&cpuhold_threads[i], tname);
#endif
k_sem_take(&cpuhold_sem, K_FOREVER);
}
}
void z_impl_z_test_1cpu_stop(void)
{
cpuhold_active = 0;
/* Note that NUM_CPUHOLD can be a value that causes coverity
* to flag the following loop as DEADCODE so suppress the warning.
*/
/* coverity[DEADCODE] */
for (int i = 0; i < NUM_CPUHOLD; i++) {
k_thread_abort(&cpuhold_threads[i]);
}
}
#ifdef CONFIG_USERSPACE
void z_vrfy_z_test_1cpu_start(void)
{
z_impl_z_test_1cpu_start();
}
#include <syscalls/z_test_1cpu_start_mrsh.c>
void z_vrfy_z_test_1cpu_stop(void)
{
z_impl_z_test_1cpu_stop();
}
#include <syscalls/z_test_1cpu_stop_mrsh.c>
#endif /* CONFIG_USERSPACE */
#endif
static void run_test_functions(struct unit_test *test)
{
phase = TEST_PHASE_SETUP;
@@ -62,6 +209,7 @@ static void run_test_functions(struct unit_test *test)
test->test();
}
#ifndef KERNEL
#include <setjmp.h>
#include <signal.h>
#include <string.h>
@@ -71,7 +219,6 @@ static void run_test_functions(struct unit_test *test)
static jmp_buf test_fail;
static jmp_buf test_pass;
static jmp_buf test_skip;
static jmp_buf stack_fail;
void ztest_test_fail(void)
@@ -84,11 +231,6 @@ void ztest_test_pass(void)
longjmp(test_pass, 1);
}
void ztest_test_skip(void)
{
longjmp(test_skip, 1);
}
static void handle_signal(int sig)
{
static const char *const phase_str[] = {
@@ -141,11 +283,6 @@ static int run_test(struct unit_test *test)
goto out;
}
if (setjmp(test_skip)) {
ret = TC_SKIP;
goto out;
}
run_test_functions(test);
out:
ret |= cleanup_test(test);
@@ -154,6 +291,112 @@ out:
return ret;
}
#else /* KERNEL */
/* Zephyr's probably going to cause all tests to fail if one test fails, so
* skip the rest of tests if one of them fails
*/
#ifdef CONFIG_ZTEST_FAIL_FAST
#define FAIL_FAST 1
#else
#define FAIL_FAST 0
#endif
K_THREAD_STACK_DEFINE(ztest_thread_stack, CONFIG_ZTEST_STACKSIZE +
CONFIG_TEST_EXTRA_STACKSIZE);
static ZTEST_BMEM int test_result;
static void test_finalize(void)
{
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
k_thread_abort(&ztest_thread);
k_thread_abort(k_current_get());
}
}
void ztest_test_fail(void)
{
test_result = -1;
test_finalize();
}
void ztest_test_pass(void)
{
test_result = 0;
test_finalize();
}
void ztest_test_skip(void)
{
test_result = -2;
test_finalize();
}
static void init_testing(void)
{
k_object_access_all_grant(&ztest_thread);
}
static void test_cb(void *a, void *dummy2, void *dummy)
{
struct unit_test *test = (struct unit_test *)a;
ARG_UNUSED(dummy2);
ARG_UNUSED(dummy);
test_result = 1;
run_test_functions(test);
test_result = 0;
}
static int run_test(struct unit_test *test)
{
int ret = TC_PASS;
TC_START(test->name);
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
k_thread_create(&ztest_thread, ztest_thread_stack,
K_THREAD_STACK_SIZEOF(ztest_thread_stack),
(k_thread_entry_t) test_cb, (struct unit_test *)test,
NULL, NULL, CONFIG_ZTEST_THREAD_PRIORITY,
test->thread_options | K_INHERIT_PERMS,
K_FOREVER);
if (test->name != NULL) {
k_thread_name_set(&ztest_thread, test->name);
}
k_thread_start(&ztest_thread);
k_thread_join(&ztest_thread, K_FOREVER);
} else {
test_result = 1;
run_test_functions(test);
}
phase = TEST_PHASE_TEARDOWN;
test->teardown();
phase = TEST_PHASE_FRAMEWORK;
if (test_result == -1) {
ret = TC_FAIL;
}
if (!test_result || !FAIL_FAST) {
ret |= cleanup_test(test);
}
if (test_result == -2) {
Z_TC_END_RESULT(TC_SKIP, test->name);
} else {
Z_TC_END_RESULT(ret, test->name);
}
return ret;
}
#endif /* !KERNEL */
void z_ztest_run_test_suite(const char *name, struct unit_test *suite)
{
int fail = 0;
@@ -164,8 +407,7 @@ void z_ztest_run_test_suite(const char *name, struct unit_test *suite)
init_testing();
PRINT("Running test suite %s\n", name);
PRINT_LINE;
TC_SUITE_START(name);
while (suite->test) {
fail += run_test(suite);
suite++;
@@ -174,11 +416,7 @@ void z_ztest_run_test_suite(const char *name, struct unit_test *suite)
break;
}
}
if (fail) {
TC_PRINT("Test suite %s failed.\n", name);
} else {
TC_PRINT("Test suite %s succeeded\n", name);
}
TC_SUITE_END(name, (fail > 0 ? TC_FAIL : TC_PASS));
test_status = (test_status || fail) ? 1 : 0;
}
@@ -192,6 +430,11 @@ void end_report(void)
}
}
#ifdef CONFIG_USERSPACE
K_APPMEM_PARTITION_DEFINE(ztest_mem_partition);
#endif
#ifndef KERNEL
int main(void)
{
z_init_mock();
@@ -200,3 +443,48 @@ int main(void)
return test_status;
}
#else
void main(void)
{
#ifdef CONFIG_USERSPACE
/* Partition containing globals tagged with ZTEST_DMEM and ZTEST_BMEM
* macros. Any variables that user code may reference need to be
* placed in this partition if no other memory domain configuration
* is made.
*/
k_mem_domain_add_partition(&k_mem_domain_default,
&ztest_mem_partition);
#ifdef Z_MALLOC_PARTITION_EXISTS
/* Allow access to malloc() memory */
k_mem_domain_add_partition(&k_mem_domain_default,
&z_malloc_partition);
#endif
#endif /* CONFIG_USERSPACE */
z_init_mock();
test_main();
end_report();
if (IS_ENABLED(CONFIG_ZTEST_RETEST_IF_PASSED)) {
static __noinit struct {
uint32_t magic;
uint32_t boots;
} state;
const uint32_t magic = 0x152ac523;
if (state.magic != magic) {
state.magic = magic;
state.boots = 0;
}
state.boots += 1;
if (test_status == 0) {
PRINT("Reset board #%u to test again\n",
state.boots);
k_msleep(10);
sys_reboot(SYS_REBOOT_COLD);
} else {
PRINT("Failed after %u attempts\n", state.boots);
state.boots = 0;
}
}
}
#endif
+147
View File
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2020 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <ztest.h>
#if defined(CONFIG_ZTEST_FATAL_HOOK)
/* This is a flag indicate if treating fatal error as expected, then take
* action dealing with it. It's SMP-safe.
*/
ZTEST_BMEM volatile bool fault_in_isr;
ZTEST_BMEM volatile k_tid_t valid_fault_tid;
static inline void reset_stored_fault_status(void)
{
valid_fault_tid = NULL;
fault_in_isr = false;
}
void z_impl_ztest_set_fault_valid(bool valid)
{
if (valid) {
if (k_is_in_isr()) {
fault_in_isr = true;
} else {
valid_fault_tid = k_current_get();
}
} else {
reset_stored_fault_status();
}
}
#if defined(CONFIG_USERSPACE)
static inline void z_vrfy_ztest_set_fault_valid(bool valid)
{
z_impl_ztest_set_fault_valid(valid);
}
#include <syscalls/ztest_set_fault_valid_mrsh.c>
#endif
__weak void ztest_post_fatal_error_hook(unsigned int reason,
const z_arch_esf_t *pEsf)
{
}
void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf)
{
k_tid_t curr_tid = k_current_get();
bool valid_fault = (curr_tid == valid_fault_tid) || fault_in_isr;
printk("Caught system error -- reason %d %d\n", reason, valid_fault);
if (valid_fault) {
printk("Fatal error expected as part of test case.\n");
/* reset back to normal */
reset_stored_fault_status();
/* do some action after expected fatal error happened */
ztest_post_fatal_error_hook(reason, pEsf);
} else {
printk("Fatal error was unexpected, aborting...\n");
k_fatal_halt(reason);
}
}
#endif
#if defined(CONFIG_ZTEST_ASSERT_HOOK)
/* This is a flag indicate if treating assert fail as expected, then take
* action dealing with it. It's SMP-safe.
*/
ZTEST_BMEM volatile bool assert_in_isr;
ZTEST_BMEM volatile k_tid_t valid_assert_tid;
static inline void reset_stored_assert_status(void)
{
valid_assert_tid = NULL;
assert_in_isr = 0;
}
void z_impl_ztest_set_assert_valid(bool valid)
{
if (valid) {
if (k_is_in_isr()) {
assert_in_isr = true;
} else {
valid_assert_tid = k_current_get();
}
} else {
reset_stored_assert_status();
}
}
#if defined(CONFIG_USERSPACE)
static inline void z_vrfy_ztest_set_assert_valid(bool valid)
{
z_impl_ztest_set_assert_valid(valid);
}
#include <syscalls/ztest_set_assert_valid_mrsh.c>
#endif
__weak void ztest_post_assert_fail_hook(void)
{
k_thread_abort(k_current_get());
}
#ifdef CONFIG_ASSERT_NO_FILE_INFO
void assert_post_action(void)
#else
void assert_post_action(const char *file, unsigned int line)
#endif
{
#ifndef CONFIG_ASSERT_NO_FILE_INFO
ARG_UNUSED(file);
ARG_UNUSED(line);
#endif
printk("Caught assert failed\n");
if ((k_current_get() == valid_assert_tid) || assert_in_isr) {
printk("Assert error expected as part of test case.\n");
/* reset back to normal */
reset_stored_assert_status();
/* It won't go back to caller when assert failed, and it
* will terminate the thread.
*/
ztest_post_assert_fail_hook();
} else {
printk("Assert failed was unexpected, aborting...\n");
#ifdef CONFIG_USERSPACE
/* User threads aren't allowed to induce kernel panics; generate
* an oops instead.
*/
if (k_is_user_context()) {
k_oops();
}
#endif
k_panic();
}
}
#endif
+180 -17
View File
@@ -3,22 +3,32 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* Modified from zephyr_v2.2.0 subsys/testsuite/ztest/src/ztest_mock.c
* because:
* From zephyr_v2.6.0 subsys/testsuite/ztest/src/ztest_mock.c
* NOTE:
* 1. This port will never be run in the Zephyr kernel.
* This repository is extended to be a Zephyr module for that.
* 2. This port will not support multiple CPUs or toolchains.
*
* Modifications:
* a. Code conditionally compiled on the following CPP symbols were deleted
* (as they were kernel-specific):
* KERNEL
*/
#ifdef KERNEL
#error Why is KERNEL defined by hered?
#endif
#include <ztest.h>
#ifdef KERNEL
#error Why is KERNEL defined by hered?
#endif
#include <zephyr/types.h>
#ifdef KERNEL
#error Why is KERNEL defined by hered?
#endif
#include <string.h>
#ifdef KERNEL
#error Why is KERNEL defined by hered?
#endif
#include <stdio.h>
#ifdef KERNEL
#error Why is KERNEL defined by hered?
#endif
struct parameter {
struct parameter *next;
@@ -27,6 +37,8 @@ struct parameter {
uintptr_t value;
};
#ifndef KERNEL
#include <stdlib.h>
#include <stdarg.h>
@@ -50,7 +62,6 @@ static struct parameter *alloc_parameter(void)
void z_init_mock(void)
{
}
void printk(const char *fmt, ...)
@@ -66,10 +77,89 @@ void vprintk(const char *fmt, va_list ap)
{
vprintf(fmt, ap);
}
#else
/*
* FIXME: move to sys_io.h once the argument signature for bitmap has
* been fixed to void* or similar GH-2825
*/
#define BITS_PER_UL (8 * sizeof(unsigned long int))
#define DEFINE_BITFIELD(name, bits) \
unsigned long int(name)[((bits) + BITS_PER_UL - 1) / BITS_PER_UL]
static inline int sys_bitfield_find_first_clear(const unsigned long *bitmap,
const unsigned int bits)
{
const size_t words = (bits + BITS_PER_UL - 1) / BITS_PER_UL;
size_t cnt;
unsigned int long neg_bitmap;
/*
* By bitwise negating the bitmap, we are actually implementing
* ffc (find first clear) using ffs (find first set).
*/
for (cnt = 0; cnt < words; cnt++) {
neg_bitmap = ~bitmap[cnt];
if (neg_bitmap == 0) {
/* All full. Try next word. */
continue;
} else if (neg_bitmap == ~0UL) {
/* First bit is free */
return cnt * BITS_PER_UL;
} else {
const unsigned int bit = (cnt * BITS_PER_UL) +
__builtin_ffsl(neg_bitmap) - 1;
/* Ensure first free bit is within total bits count */
if (bit < bits) {
return bit;
} else {
return -1;
}
}
}
return -1;
}
static DEFINE_BITFIELD(params_allocation, CONFIG_ZTEST_PARAMETER_COUNT);
static struct parameter params[CONFIG_ZTEST_PARAMETER_COUNT];
static void free_parameter(struct parameter *param)
{
unsigned int allocation_index = param - params;
if (param == NULL)
return;
__ASSERT(allocation_index < CONFIG_ZTEST_PARAMETER_COUNT,
"param %p given to free is not in the static buffer %p:%u",
param, params, CONFIG_ZTEST_PARAMETER_COUNT);
sys_bitfield_clear_bit((mem_addr_t)params_allocation, allocation_index);
}
static struct parameter *alloc_parameter(void)
{
int allocation_index;
struct parameter *param;
allocation_index = sys_bitfield_find_first_clear(
params_allocation, CONFIG_ZTEST_PARAMETER_COUNT);
if (allocation_index == -1) {
printk("No more mock parameters available for allocation\n");
ztest_test_fail();
}
sys_bitfield_set_bit((mem_addr_t)params_allocation, allocation_index);
param = params + allocation_index;
(void)memset(param, 0, sizeof(*param));
return param;
}
void z_init_mock(void)
{
}
#endif
static struct parameter *find_and_delete_value(struct parameter *param,
const char *fn,
const char *name)
const char *fn, const char *name)
{
struct parameter *value;
@@ -117,7 +207,7 @@ void z_ztest_expect_value(const char *fn, const char *name, uintptr_t val)
}
void z_ztest_check_expected_value(const char *fn, const char *name,
uintptr_t val)
uintptr_t val)
{
struct parameter *param;
uintptr_t expected;
@@ -135,23 +225,91 @@ void z_ztest_check_expected_value(const char *fn, const char *name,
/* We need to cast these values since the toolchain doesn't
* provide inttypes.h
*/
PRINT("%s received wrong value: Got %lu, expected %lu\n",
fn, (unsigned long)val, (unsigned long)expected);
PRINT("%s:%s received wrong value: Got %lu, expected %lu\n", fn,
name, (unsigned long)val, (unsigned long)expected);
ztest_test_fail();
}
}
void z_ztest_returns_value(const char *fn, uintptr_t value)
void z_ztest_expect_data(const char *fn, const char *name, void *val)
{
insert_value(&parameter_list, fn, name, (uintptr_t)val);
}
void z_ztest_check_expected_data(const char *fn, const char *name, void *data,
uint32_t length)
{
struct parameter *param;
void *expected;
param = find_and_delete_value(&parameter_list, fn, name);
if (!param) {
PRINT("Failed to find parameter %s for %s\n", name, fn);
/* No return from this function but for coverity reasons
* put a return after to avoid the warning of a null
* dereference of param below.
*/
ztest_test_fail();
return;
}
expected = (void *)param->value;
free_parameter(param);
if (expected == NULL && data != NULL) {
PRINT("%s:%s received null pointer\n", fn, name);
ztest_test_fail();
} else if (data == NULL && expected != NULL) {
PRINT("%s:%s received data while expected null pointer\n", fn,
name);
ztest_test_fail();
} else if (data != NULL) {
if (memcmp(data, expected, length) != 0) {
PRINT("%s:%s data provided don't match\n", fn, name);
ztest_test_fail();
}
}
}
void z_ztest_return_data(const char *fn, const char *name, void *val)
{
insert_value(&parameter_list, fn, name, (uintptr_t)val);
}
void z_ztest_copy_return_data(const char *fn, const char *name, void *data,
uint32_t length)
{
struct parameter *param;
void *return_data;
if (data == NULL) {
PRINT("%s:%s received null pointer\n", fn, name);
ztest_test_fail();
return;
}
param = find_and_delete_value(&parameter_list, fn, name);
if (!param) {
PRINT("Failed to find parameter %s for %s\n", name, fn);
memset(data, 0, length);
ztest_test_fail();
} else {
return_data = (void *)param->value;
free_parameter(param);
memcpy(data, return_data, length);
}
}
void z_ztest_returns_value(const char *fn, uintptr_t value)
{
insert_value(&return_value_list, fn, "", value);
}
uintptr_t z_ztest_get_return_value(const char *fn)
{
uintptr_t value;
struct parameter *param = find_and_delete_value(&return_value_list,
fn, "");
struct parameter *param =
find_and_delete_value(&return_value_list, fn, "");
if (!param) {
PRINT("Failed to find return value for function %s\n", fn);
@@ -180,9 +338,14 @@ int z_cleanup_mock(void)
int fail = 0;
if (parameter_list.next) {
PRINT("Parameter not used by mock: %s:%s\n",
parameter_list.next->fn,
parameter_list.next->name);
fail = 1;
}
if (return_value_list.next) {
PRINT("Return value no used by mock: %s\n",
return_value_list.next->fn);
fail = 2;
}