tests: move testsuite and configs into subsys/

Move test related code and the testsuite away from tests/ and make it a
proper subsystem.
The way tests were integrate in the tree was not obvious and actual
tests were intermixed with the testsuite code.

This will allow us to have trees with the testcode and without the
samples by just remove the folders tests/ and samples, needed for
isolating actual code from test/sample code.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Anas Nashif 2019-02-19 15:45:18 -05:00
commit ccad9d0d09
38 changed files with 16 additions and 14 deletions

View file

@ -0,0 +1,6 @@
add_subdirectory_if_kconfig(ztest)
zephyr_include_directories_ifdef(CONFIG_TEST
$ENV{ZEPHYR_BASE}/subsys/testsuite/include
)
add_subdirectory_ifdef(CONFIG_COVERAGE_GCOV coverage)

91
subsys/testsuite/Kconfig Normal file
View file

@ -0,0 +1,91 @@
#
# Copyright (c) 2016 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
menu Testing
source "subsys/testsuite/ztest/Kconfig"
config TEST
bool "Mark project as a test"
help
Mark a project or an application as a test. This will enable a few
test defaults.
config TEST_SHELL
bool "Enable various shells for testing"
select GPIO_SHELL if GPIO
select PCI_SHELL if PCI
help
Enable various platform and driver related shells for testing.
config TEST_EXTRA_STACKSIZE
int "Test function extra thread stack size"
default 1024 if COVERAGE_GCOV
default 768 if XTENSA
default 0
help
Additional stack for tests on some platform where default is not
enough.
config HAS_COVERAGE_SUPPORT
bool
help
The code coverage report generation is only available on boards
with enough spare RAM to buffer the coverage data, or on boards
based on the POSIX ARCH.
config COVERAGE
bool "Create coverage data"
depends on HAS_COVERAGE_SUPPORT
default n
help
This option will build your application with the -coverage option
which will generate data that can be used to create coverage reports.
Currently this is fully supported only on the native POSIX port.
if COVERAGE
config COVERAGE_GCOV
bool "Create Coverage data from hardware platform"
depends on !NATIVE_APPLICATION
default y
help
This option will select the custom gcov library. The reports will
be available over serial. This serial dump can be passed to
gen_gcov_files.py which creates the required .gcda files. These
can be read by gcov utility. For more details see gcovr.com .
endif
config TEST_USERSPACE
bool "Enable userspace if available"
depends on ARCH_HAS_USERSPACE
depends on TEST
select USERSPACE
select APP_SHARED_MEM
select DYNAMIC_OBJECTS
default y
help
This option will help test the userspace mode. This can be enabled
only when CONFIG_ARCH_HAS_USERSPACE is set.
config TEST_HW_STACK_PROTECTION
bool "Enable hardware-based stack overflow detection if available"
depends on ARCH_HAS_STACK_PROTECTION
depends on TEST
select HW_STACK_PROTECTION
default y
help
This option will enable hardware-based stack protection by default
for all test cases if the hardware supports it.
config TEST_FLASH_DRIVERS
bool "Test flash drivers"
depends on BOARD_QEMU_X86
select FLASH_HAS_DRIVER_ENABLED
select FLASH_HAS_PAGE_LAYOUT
help
This option will help test the flash drivers. This should be enabled
only when using qemu_x86.
endmenu

View file

@ -0,0 +1,132 @@
/* tc_utilities.h - testcase utilities header file */
/*
* Copyright (c) 2012-2015 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __TC_UTIL_H__
#define __TC_UTIL_H__
#include <zephyr.h>
#include <string.h>
#include <shell/shell.h>
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT_DATA(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#include <misc/printk.h>
#define PRINT_DATA(fmt, ...) printk(fmt, ##__VA_ARGS__)
#endif /* CONFIG_STDOUT_CONSOLE */
#if defined CONFIG_ARCH_POSIX
#include "posix_board_if.h"
#endif
/**
* @def TC_PRINT_RUNID
* @brief Report a Run ID
*
* When the CPP symbol \c TC_RUNID is defined (for example, from the
* compile environment), print the defined string ``RunID:
* <TC_RUNID>`` when called (TC_END_REPORT() will also call it).
*
* This is used mainly when automating the execution and running of
* multiple test cases, to verify that the expected image is being
* executed (as sometimes the targets fail to flash or reset
* properly).
*
* TC_RUNID is any string, that will be converted to a string literal.
*/
#define __str(x) #x
#define _str(x) __str(x)
#ifdef TC_RUNID
#define TC_PRINT_RUNID PRINT_DATA("RunID: " _str(TC_RUNID) "\n")
#else
#define TC_PRINT_RUNID do {} while (0)
#endif
#define PRINT_LINE \
PRINT_DATA( \
"============================================================" \
"=======\n")
/* stack size and priority for test suite task */
#define TASK_STACK_SIZE (1024 * 2)
#define FMT_ERROR "%s - %s@%d. "
#define TC_PASS 0
#define TC_FAIL 1
#define TC_SKIP 2
static __unused const char *TC_RESULT_STR[] = {
[TC_PASS] = "PASS",
[TC_FAIL] = "FAIL",
[TC_SKIP] = "SKIP",
};
#define TC_RESULT_TO_STR(result) TC_RESULT_STR[result]
#define TC_ERROR(fmt, ...) \
do { \
PRINT_DATA(FMT_ERROR, "FAIL", __func__, __LINE__); \
PRINT_DATA(fmt, ##__VA_ARGS__); \
} while (0)
#define TC_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
#define TC_START(name) PRINT_DATA("starting test - %s\n", name)
#define TC_END(result, fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
/* prints result and the function name */
#define _TC_END_RESULT(result, func) \
do { \
TC_END(result, "%s - %s\n", TC_RESULT_TO_STR(result), func); \
PRINT_LINE; \
} while (0)
#define TC_END_RESULT(result) \
_TC_END_RESULT((result), __func__)
#if defined(CONFIG_ARCH_POSIX)
#define TC_END_POST(result) posix_exit(result)
#else
#define TC_END_POST(result)
#endif /* CONFIG_ARCH_POSIX */
#define TC_END_REPORT(result) \
do { \
PRINT_LINE; \
TC_PRINT_RUNID; \
TC_END(result, \
"PROJECT EXECUTION %s\n", \
(result) == TC_PASS ? "SUCCESSFUL" : "FAILED"); \
TC_END_POST(result); \
} while (0)
#if CONFIG_SHELL
#define TC_CMD_DEFINE(name) \
static int cmd_##name(const struct shell *shell, size_t argc, \
char **argv) \
{ \
TC_START(__func__); \
name(); \
TC_END_RESULT(TC_PASS); \
return 0; \
}
#define TC_CMD_ITEM(name) cmd_##name
#else
#define TC_CMD_DEFINE(name) \
int cmd_##name(int argc, char *argv[]) \
{ \
TC_START(__func__); \
name(); \
TC_END_RESULT(TC_PASS); \
return 0; \
}
#define TC_CMD_ITEM(name) {STRINGIFY(name), cmd_##name, "none"}
#endif
#endif /* __TC_UTIL_H__ */

View file

@ -0,0 +1,53 @@
/* GCC specific test inline assembler functions and macros */
/*
* Copyright (c) 2015, Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _TEST_ASM_INLINE_GCC_H
#define _TEST_ASM_INLINE_GCC_H
#if !defined(__GNUC__)
#error test_asm_inline_gcc.h goes only with GCC
#endif
#if defined(CONFIG_X86)
static inline void timestamp_serialize(void)
{
__asm__ __volatile__ (/* serialize */
"xorl %%eax,%%eax;\n\t"
"cpuid;\n\t"
:
:
: "%eax", "%ebx", "%ecx", "%edx");
}
#elif defined(CONFIG_X86_64)
static inline void timestamp_serialize(void)
{
__asm__ volatile("xorq %%rax,%%rax; cpuid"
::: "rax", "rdx", "rbx", "rcx");
}
#elif defined(CONFIG_CPU_CORTEX_M)
#include <arch/arm/cortex_m/cmsis.h>
static inline void timestamp_serialize(void)
{
/* isb is avaialble in all Cortex-M */
__ISB();
}
#elif defined(CONFIG_CPU_ARCV2)
#define timestamp_serialize()
#elif defined(CONFIG_ARCH_POSIX)
#define timestamp_serialize()
#elif defined(CONFIG_XTENSA)
#define timestamp_serialize()
#elif defined(CONFIG_NIOS2)
#define timestamp_serialize()
#elif defined(CONFIG_RISCV32)
#define timestamp_serialize()
#else
#error implementation of timestamp_serialize() not provided for your CPU target
#endif
#endif /* _TEST_ASM_INLINE_GCC_H */

View file

@ -0,0 +1,102 @@
/* test_ecc_utils.h - TinyCrypt interface to common functions for ECC tests */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* test_ecc_utils.h -- Interface to common functions for ECC tests.
*/
#ifndef __TEST_ECC_UTILS_H__
#define __TEST_ECC_UTILS_H__
#define ENABLE_TESTS 1
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/ecc.h>
#include <test_utils.h>
int hex2int(char hex);
/*
* Convert hex string to byte string
* Return number of bytes written to buf, or 0 on error
*/
int hex2bin(uint8_t *buf, const size_t buflen, const char *hex,
const size_t hexlen);
/*
* Convert hex string to zero-padded nanoECC scalar
*/
void string2scalar(unsigned int *scalar, unsigned int num_word32, char *str);
void print_ecc_scalar(const char *label, const unsigned int *p_vli,
unsigned int num_word32);
int check_ecc_result(const int num, const char *name,
const unsigned int *expected,
const unsigned int *computed,
const unsigned int num_word32, const bool verbose);
/* Test ecc_make_keys, and also as keygen part of other tests */
int keygen_vectors(char **d_vec, char **qx_vec, char **qy_vec, int tests, bool verbose);
void vli_print_bytes(uint8_t *vli, unsigned int size);
int check_code(const int num, const int expected,
const int computed, const int verbose);
#endif /* __TEST_ECC_UTILS_H__ */

View file

@ -0,0 +1,85 @@
/* test_utils.h - TinyCrypt interface to common functions for tests */
/*
* Copyright (C) 2015 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __TEST_UTILS_H__
#define __TEST_UTILS_H__
#include <tc_util.h>
#include <tinycrypt/constants.h>
static inline void show_str(const char *label, const u8_t *s, size_t len)
{
u32_t i;
TC_PRINT("%s = ", label);
for (i = 0; i < (u32_t)len; ++i) {
TC_PRINT("%02x", s[i]);
}
TC_PRINT("\n");
}
static inline
void fatal(u32_t testnum, const void *expected, size_t expectedlen,
const void *computed, size_t computedlen)
{
TC_ERROR("\tTest #%d Failed!\n", testnum);
show_str("\t\tExpected", expected, expectedlen);
show_str("\t\tComputed ", computed, computedlen);
TC_PRINT("\n");
}
static inline
u32_t check_result(u32_t testnum, const void *expected,
size_t expectedlen, const void *computed,
size_t computedlen, u32_t verbose)
{
u32_t result = TC_PASS;
ARG_UNUSED(verbose);
if (expectedlen != computedlen) {
TC_ERROR("The length of the computed buffer (%zu)",
computedlen);
TC_ERROR("does not match the expected length (%zu).",
expectedlen);
result = TC_FAIL;
} else {
if (memcmp(computed, expected, computedlen) != 0) {
fatal(testnum, expected, expectedlen,
computed, computedlen);
result = TC_FAIL;
}
}
return result;
}
#endif

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2012-2015 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* @file macroses for measuring time in benchmarking tests
*
* This file contains the macroses for taking and converting time for
* benchmarking tests.
*/
#ifndef _TIMESTAMP_H_
#define _TIMESTAMP_H_
#include <zephyr.h>
#include <limits.h>
#if defined(__GNUC__)
#include <test_asm_inline_gcc.h>
#else
#include <test_asm_inline_other.h>
#endif
#define TICK_SYNCH() k_sleep(1)
#define OS_GET_TIME() k_cycle_get_32()
/* time necessary to read the time */
extern u32_t tm_off;
static inline u32_t TIME_STAMP_DELTA_GET(u32_t ts)
{
u32_t t;
/* serialize so OS_GET_TIME() is not reordered */
timestamp_serialize();
t = OS_GET_TIME();
u32_t res = (t >= ts) ? (t - ts) : (ULONG_MAX - ts + t);
if (ts > 0) {
res -= tm_off;
}
return res;
}
/*
* Routine initializes the benchmark timing measurement
* The function sets up the global variable tm_off
*/
static inline void bench_test_init(void)
{
u32_t t = OS_GET_TIME();
tm_off = OS_GET_TIME() - t;
}
/* timestamp for checks */
static s64_t tCheck;
/*
* Routines are invoked before and after the benchmark and check
* if penchmarking code took less time than necessary for the
* high precision timer register overflow.
* Functions modify the tCheck global variable.
*/
static inline void bench_test_start(void)
{
tCheck = 0;
/* before reading time we synchronize to the start of the timer tick */
TICK_SYNCH();
tCheck = k_uptime_delta(&tCheck);
}
/* returns 0 if the completed within a second and -1 if not */
static inline int bench_test_end(void)
{
tCheck = k_uptime_delta(&tCheck);
/* Flag an error if the test ran for more than a second.
* (Note: Existing benchmarks have CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 set,
* in such configs this check can be an indicator of whether
* timer tick interrupt overheads too are getting accounted towards
* benchmark time)
*/
if (tCheck >= MSEC_PER_SEC) {
return -1;
}
return 0;
}
/*
* Returns -1 if number of ticks cause high precision timer counter
* overflow and 0 otherwise
* Called after bench_test_end to see if we still can use timing
* results or is it completely invalid
*/
static inline int high_timer_overflow(void)
{
/* Check if the time elapsed in msec is sufficient to trigger an
* overflow of the high precision timer
*/
if (tCheck >= (SYS_CLOCK_HW_CYCLES_TO_NS64(UINT_MAX) /
(NSEC_PER_USEC * USEC_PER_MSEC))) {
return -1;
}
return 0;
}
#endif /* _TIMESTAMP_H_ */

View file

@ -0,0 +1,91 @@
cmake_minimum_required(VERSION 3.13.1)
cmake_policy(SET CMP0000 OLD)
cmake_policy(SET CMP0002 NEW)
enable_language(C CXX ASM)
# Parameters:
# SOURCES: list of source files, default main.c
# INCLUDE: list of additional include paths relative to ZEPHYR_BASE
separate_arguments( EXTRA_CFLAGS_AS_LIST UNIX_COMMAND ${EXTRA_CFLAGS})
separate_arguments( EXTRA_AFLAGS_AS_LIST UNIX_COMMAND ${EXTRA_AFLAGS})
separate_arguments(EXTRA_CPPFLAGS_AS_LIST UNIX_COMMAND ${EXTRA_CPPFLAGS})
separate_arguments(EXTRA_CXXFLAGS_AS_LIST UNIX_COMMAND ${EXTRA_CXXFLAGS})
separate_arguments(EXTRA_LDFLAGS_AS_LIST UNIX_COMMAND ${EXTRA_LDFLAGS})
if(NOT SOURCES)
set(SOURCES main.c)
endif()
add_executable(testbinary ${SOURCES})
set(KOBJ_TYPES_H_TARGET kobj_types_h_target)
include($ENV{ZEPHYR_BASE}/cmake/kobj.cmake)
add_dependencies(testbinary ${KOBJ_TYPES_H_TARGET})
gen_kobj(KOBJ_GEN_DIR)
list(APPEND INCLUDE
subsys/testsuite/ztest/include
subsys/testsuite/include
include
.
)
set (CMAKE_C_FLAGS "-m32")
target_compile_options(testbinary PRIVATE
-Wall
-I ${KOBJ_GEN_DIR}
${EXTRA_CPPFLAGS_AS_LIST}
${EXTRA_CFLAGS_AS_LIST}
$<$<COMPILE_LANGUAGE:CXX>:${EXTRA_CXXFLAGS_AS_LIST}>
$<$<COMPILE_LANGUAGE:ASM>:${EXTRA_AFLAGS_AS_LIST}>
)
target_link_libraries(testbinary PRIVATE
${EXTRA_LDFLAGS_AS_LIST}
)
if(COVERAGE)
target_compile_options(testbinary PRIVATE
-fno-default-inline
-fno-inline
-fprofile-arcs
-ftest-coverage
)
endif()
if(LIBS)
message(FATAL_ERROR "This variable is not supported, see SOURCES instead")
endif()
target_sources(testbinary PRIVATE
$ENV{ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest.c
$ENV{ZEPHYR_BASE}/subsys/testsuite/ztest/src/ztest_mock.c
)
target_compile_definitions(testbinary PRIVATE ZTEST_UNITTEST)
foreach(inc ${INCLUDE})
target_include_directories(testbinary PRIVATE $ENV{ZEPHYR_BASE}/${inc})
endforeach()
find_program(VALGRIND_PROGRAM valgrind)
if(VALGRIND_PROGRAM)
set(VALGRIND ${VALGRIND_PROGRAM})
set(VALGRIND_FLAGS
--leak-check=full
--error-exitcode=1
--log-file=valgrind.log
)
endif()
add_custom_target(run-test
COMMAND
${VALGRIND} ${VALGRIND_FLAGS}
$<TARGET_FILE:testbinary>
DEPENDS testbinary
WORKING_DIRECTORY ${APPLICATION_BINARY_DIR}
)
# TODO: Redirect output to unit.log

View file

@ -0,0 +1,8 @@
zephyr_include_directories(
$ENV{ZEPHYR_BASE}/subsys/testsuite/include
$ENV{ZEPHYR_BASE}/subsys/testsuite/ztest/include
)
zephyr_library()
zephyr_library_sources( src/ztest.c)
zephyr_library_sources_ifdef(CONFIG_ZTEST_MOCKING src/ztest_mock.c)

View file

@ -0,0 +1,49 @@
#
# Copyright (c) 2016 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
config ZTEST
bool "Zephyr testing framework"
select TEST
help
Enable the Zephyr testing framework. You should enable this only
if you're writing automated tests.
config ZTEST_STACKSIZE
int "Test function thread stack size"
depends on ZTEST
default 1024
config ZTEST_FAIL_FAST
bool "Abort on first failing test"
depends on ZTEST
help
Stop and abort on first failing test. Do not continue with other
tests that might be in the queue.
config ZTEST_ASSERT_VERBOSE
int "Assertion verbosity level"
depends on ZTEST
default 1
help
Set verbosity level for assertions.
Assertion verbosity levels:
0 Write only file and line for failed assertions
1 Write file, line number, function and reason for failed assertions
2 Log also successful assertions
config ZTEST_MOCKING
bool "Mocking support functions"
depends on ZTEST
help
Enable mocking support for Ztest. This allows the test to set
return values and expected parameters to functions.
config ZTEST_PARAMETER_COUNT
int "Count of parameters or return values reserved"
depends on ZTEST_MOCKING
default 1
help
Maximum amount of concurrent return values / expected parameters.

View file

@ -0,0 +1 @@
/* This file exists as a hack around Zephyr's dependencies */

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Per-arch thread definition
*
* This file contains definitions for
*
* struct _thread_arch
* struct _callee_saved
* struct _caller_saved
*
* necessary to instantiate instances of struct k_thread.
*/
#ifndef _kernel_arch_thread__h_
#define _kernel_arch_thread__h_
#ifndef _ASMLANGUAGE
struct _caller_saved {
};
typedef struct _caller_saved _caller_saved_t;
struct _callee_saved {
};
typedef struct _callee_saved _callee_saved_t;
struct _thread_arch {
};
typedef struct _thread_arch _thread_arch_t;
#endif /* _ASMLANGUAGE */
#endif /* _kernel_arch_thread__h_ */

View file

@ -0,0 +1,14 @@
#ifndef __GEN_OFFSETS_H__
#define __GEN_OFFSETS_H__
/*
* This file is a fake replacement for
* $build_dir/zephyr/include/generated/offsets.h
*
* The unittest infrastructure does not know how to generate
* offsets.h, so until this is supported we fake it with this
* file. This allows us to test source files that include offsets.h,
* but don't actually use anything from it when unit testing.
*/
#endif

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
*
* @brief Zephyr testing suite
*/
/**
* @brief Zephyr Tests
* @defgroup all_tests Zephyr Tests
* @{
* @}
*/
#ifndef __ZTEST_H__
#define __ZTEST_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup ztest Zephyr testing suite
*/
#if !defined(CONFIG_ZTEST) && !defined(ZTEST_UNITTEST)
#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
#define CONFIG_NUM_COOP_PRIORITIES 16
#define CONFIG_COOP_ENABLED 1
#define CONFIG_PREEMPT_ENABLED 1
#define CONFIG_SYS_CLOCK_TICKS_PER_SEC 100
#define CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC 10000000
/* FIXME: Properly integrate with Zephyr's arch specific code */
#define CONFIG_X86 1
#define PRINT printf
#endif /* !KERNEL */
#include <zephyr.h>
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT printf
#else /* !CONFIG_STDOUT_CONSOLE */
#include <misc/printk.h>
#define PRINT printk
#endif /* CONFIG_STDOUT_CONSOLE */
#include <ztest_assert.h>
#include <ztest_mock.h>
#include <ztest_test.h>
#include <tc_util.h>
void test_main(void);
#ifdef __cplusplus
}
#endif
#endif /* __ZTEST_H__ */

View file

@ -0,0 +1,194 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
*
* @brief Zephyr testing framework assertion macros
*/
#ifndef __ZTEST_ASSERT_H__
#define __ZTEST_ASSERT_H__
#include <ztest.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
void ztest_test_fail(void);
#if CONFIG_ZTEST_ASSERT_VERBOSE == 0
static inline void _zassert_(int cond, const char *file, int line)
{
if (!(cond)) {
PRINT("\n Assertion failed at %s:%d\n",
file, line);
ztest_test_fail();
}
}
#define _zassert(cond, default_msg, file, line, func, msg, ...) \
_zassert_(cond, file, line)
#else /* CONFIG_ZTEST_ASSERT_VERBOSE != 0 */
static inline void _zassert(int cond,
const char *default_msg,
const char *file,
int line, const char *func,
const char *msg, ...)
{
if (!(cond)) {
va_list vargs;
va_start(vargs, msg);
PRINT("\n Assertion failed at %s:%d: %s: %s\n",
file, line, func, default_msg);
#if defined(CONFIG_STDOUT_CONSOLE)
vprintf(msg, vargs);
printf("\n");
#else
vprintk(msg, vargs);
printk("\n");
#endif
va_end(vargs);
ztest_test_fail();
}
#if CONFIG_ZTEST_ASSERT_VERBOSE == 2
else {
PRINT("\n Assertion succeeded at %s:%d (%s)\n",
file, line, func);
}
#endif
}
#endif /* CONFIG_ZTEST_ASSERT_VERBOSE */
/**
* @defgroup ztest_assert Ztest assertion macros
* @ingroup ztest
*
* This module provides assertions when using Ztest.
*
* @{
*/
/**
* @brief Fail the test, if @a cond is false
*
* You probably don't need to call this macro directly. You should
* instead use zassert_{condition} macros below.
*
* @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, ...) \
_zassert(cond, msg ? ("(" default_msg ")") : (default_msg), \
__FILE__, __LINE__, __func__, msg ? msg : "", ##__VA_ARGS__)
/**
* @brief Assert that this function call won't be reached
* @param msg Optional message to print if the assertion fails
*/
#define zassert_unreachable(msg, ...) zassert(0, "Reached unreachable code", \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a cond is true
* @param cond Condition to check
* @param msg Optional message to print if the assertion fails
*/
#define zassert_true(cond, msg, ...) zassert(cond, #cond " is false", \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a cond is false
* @param cond Condition to check
* @param msg Optional message to print if the assertion fails
*/
#define zassert_false(cond, msg, ...) zassert(!(cond), #cond " is true", \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a ptr is NULL
* @param ptr Pointer to compare
* @param msg Optional message to print if the assertion fails
*/
#define zassert_is_null(ptr, msg, ...) zassert((ptr) == NULL, \
#ptr " is not NULL", \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a ptr is not NULL
* @param ptr Pointer to compare
* @param msg Optional message to print if the assertion fails
*/
#define zassert_not_null(ptr, msg, ...) zassert((ptr) != NULL, \
#ptr " is NULL", msg, \
##__VA_ARGS__)
/**
* @brief Assert that @a a equals @a b
*
* @a a and @a b won't be converted and will be compared directly.
*
* @param a Value to compare
* @param b Value to compare
* @param msg Optional message to print if the assertion fails
*/
#define zassert_equal(a, b, msg, ...) zassert((a) == (b), \
#a " not equal to " #b, \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a a does not equal @a b
*
* @a a and @a b won't be converted and will be compared directly.
*
* @param a Value to compare
* @param b Value to compare
* @param msg Optional message to print if the assertion fails
*/
#define zassert_not_equal(a, b, msg, ...) zassert((a) != (b), \
#a " equal to " #b, \
msg, ##__VA_ARGS__)
/**
* @brief Assert that @a a equals @a b
*
* @a a and @a b will be converted to `void *` before comparing.
*
* @param a Value to compare
* @param b Value to compare
* @param msg Optional message to print if the assertion fails
*/
#define zassert_equal_ptr(a, b, msg, ...) \
zassert((void *)(a) == (void *)(b), #a " not equal to " #b, \
msg, ##__VA_ARGS__)
/**
* @brief Assert that 2 memory buffers have the same contents
*
* @param buf Buffer to compare
* @param exp Buffer with expected contents
* @param size Size of buffers
* @param msg Optional message to print if the assertion fails
*/
static inline void zassert_mem_equal(void *buf, void *exp, size_t size,
const char *msg)
{
zassert_equal(memcmp(buf, exp, size), 0, msg);
}
/**
* @}
*/
#endif /* __ZTEST_ASSERT_H__ */

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
*
* @brief Ztest mocking support
*/
#ifndef __ZTEST_MOCK_H__
#define __ZTEST_MOCK_H__
/**
* @defgroup ztest_mock Ztest mocking support
* @ingroup ztest
*
* This module provides simple mocking functions for unit testing. These
* need CONFIG_ZTEST_MOCKING=y.
*
* @{
*/
/**
* @brief Tell function @a func to expect the value @a value for @a param
*
* When using ztest_check_expected_value(), tell that the value of @a param
* should be @a value. The value will internally be stored as an `uintptr_t`.
*
* @param func Function in question
* @param param Parameter for which the value should be set
* @param value Value for @a param
*/
#define ztest_expect_value(func, param, value) \
_ztest_expect_value(STRINGIFY(func), STRINGIFY(param), \
(uintptr_t)(value))
/**
* @brief If @a param doesn't match the value set by ztest_expect_value(),
* fail the test
*
* This will first check that does @a param have a value to be expected, and
* then checks whether the value of the parameter is equal to the expected
* value. If either of these checks fail, the current test will fail. This
* must be called from the called function.
*
* @param param Parameter to check
*/
#define ztest_check_expected_value(param) \
_ztest_check_expected_value(__func__, STRINGIFY(param), \
(uintptr_t)(param))
/**
* @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) \
_ztest_returns_value(STRINGIFY(func), (uintptr_t)(value))
/**
* @brief Get the return value for current function
*
* The return value must have been set previously with ztest_returns_value().
* If no return value exists, the current test will fail.
*
* @returns The value the current function should return
*/
#define ztest_get_return_value() \
_ztest_get_return_value(__func__)
/**
* @brief Get the return value as a pointer for current function
*
* The return value must have been set previously with ztest_returns_value().
* If no return value exists, the current test will fail.
*
* @returns The value the current function should return as a `void *`
*/
#define ztest_get_return_value_ptr() \
((void *)_ztest_get_return_value(__func__))
/**
* @}
*/
#ifdef CONFIG_ZTEST_MOCKING
#include <zephyr/types.h>
void _init_mock(void);
int _cleanup_mock(void);
void _ztest_expect_value(const char *fn, const char *name, uintptr_t value);
void _ztest_check_expected_value(const char *fn, const char *param,
uintptr_t value);
void _ztest_returns_value(const char *fn, uintptr_t value);
uintptr_t _ztest_get_return_value(const char *fn);
#else /* !CONFIG_ZTEST_MOCKING */
#define _init_mock()
#define _cleanup_mock() 0
#endif /* CONFIG_ZTEST_MOCKING */
#endif /* __ZTEST_H__ */

View file

@ -0,0 +1,173 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
*
* @brief Zephyr testing framework _test.
*/
#ifndef __ZTEST_TEST_H__
#define __ZTEST_TEST_H__
#include <app_memory/app_memdomain.h>
struct unit_test {
const char *name;
void (*test)(void);
void (*setup)(void);
void (*teardown)(void);
u32_t thread_options;
};
void _ztest_run_test_suite(const char *name, struct unit_test *suite);
/**
* @defgroup ztest_test Ztest testing macros
* @ingroup ztest
*
* This module eases the testing process by providing helpful macros and other
* testing structures.
*
* @{
*/
/**
* @brief Fail the currently running test.
*
* This is the function called from failed assertions and the like. You
* probably don't need to call it yourself.
*/
void ztest_test_fail(void);
/**
* @brief Pass the currently running test.
*
* Normally a test passes just by returning without an assertion failure.
* However, if the success case for your test involves a fatal fault,
* you can call this function from _SysFatalErrorHandler to indicate that
* the test passed before aborting the thread.
*/
void ztest_test_pass(void);
/**
* @brief Skip the current test.
*
*/
void ztest_test_skip(void);
/**
* @brief Do nothing, successfully.
*
* Unit test / setup function / teardown function that does
* nothing, successfully. Can be used as a parameter to
* ztest_unit_test_setup_teardown().
*/
static inline void unit_test_noop(void)
{
}
/**
* @brief Define a test with setup and teardown functions
*
* This should be called as an argument to ztest_test_suite. The test will
* be run in the following order: @a setup, @a fn, @a teardown.
*
* @param fn Main test function
* @param setup Setup function
* @param teardown Teardown function
*/
#define ztest_unit_test_setup_teardown(fn, setup, teardown) { \
STRINGIFY(fn), fn, setup, teardown, 0 \
}
/**
* @brief Define a user mode test with setup and teardown functions
*
* This should be called as an argument to ztest_test_suite. The test will
* be run in the following order: @a setup, @a fn, @a teardown. ALL
* test functions will be run in user mode, and only if CONFIG_USERSPACE
* is enabled, otherwise this is the same as ztest_unit_test_setup_teardown().
*
* @param fn Main test function
* @param setup Setup function
* @param teardown Teardown function
*/
#define ztest_user_unit_test_setup_teardown(fn, setup, teardown) { \
STRINGIFY(fn), fn, setup, teardown, K_USER \
}
/**
* @brief Define a test function
*
* This should be called as an argument to ztest_test_suite.
*
* @param fn Test function
*/
#define ztest_unit_test(fn) \
ztest_unit_test_setup_teardown(fn, unit_test_noop, unit_test_noop)
/**
* @brief Define a test function that should run as a user thread
*
* This should be called as an argument to ztest_test_suite.
* If CONFIG_USERSPACE is not enabled, this is functionally identical to
* ztest_unit_test().
*
* @param fn Test function
*/
#define ztest_user_unit_test(fn) \
ztest_user_unit_test_setup_teardown(fn, unit_test_noop, unit_test_noop)
/**
* @brief Define a test suite
*
* This function should be called in the following fashion:
* ```{.c}
* ztest_test_suite(test_suite_name,
* ztest_unit_test(test_function),
* ztest_unit_test(test_other_function)
* );
*
* ztest_run_test_suite(test_suite_name);
* ```
*
* @param name Name of the testing suite
*/
/* definitions for use with testing application shared memory */
#ifdef CONFIG_APP_SHARED_MEM
#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;
extern struct k_mem_domain ztest_mem_domain;
#else
#define ZTEST_DMEM
#define ZTEST_BMEM
#define ZTEST_SECTION .data
#endif
#define ztest_test_suite(name, ...) \
static ZTEST_DMEM struct unit_test _##name[] = { \
__VA_ARGS__, { 0 } \
}
/**
* @brief Run the specified test suite.
*
* @param suite Test suite to run.
*/
#define ztest_run_test_suite(suite) \
_ztest_run_test_suite(#suite, _##suite)
/**
* @}
*/
#endif /* __ZTEST_ASSERT_H__ */

View file

@ -0,0 +1,325 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <stdio.h>
#include <app_memory/app_memdomain.h>
#ifdef CONFIG_APP_SHARED_MEM
#include <misc/libc-hooks.h>
#endif
#ifdef KERNEL
static struct k_thread ztest_thread;
#endif
/* ZTEST_DMEM and ZTEST_BMEM are used for the application shared memory test */
ZTEST_DMEM enum {
TEST_PHASE_SETUP,
TEST_PHASE_TEST,
TEST_PHASE_TEARDOWN,
TEST_PHASE_FRAMEWORK
} phase = TEST_PHASE_FRAMEWORK;
static ZTEST_BMEM int test_status;
static int cleanup_test(struct unit_test *test)
{
int ret = TC_PASS;
int mock_status;
mock_status = _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.
*/
k_thread_abort(&ztest_thread);
#endif
if (!ret && mock_status == 1) {
PRINT("Test %s failed: Unused mock parameter values\n",
test->name);
ret = TC_FAIL;
} else if (!ret && mock_status == 2) {
PRINT("Test %s failed: Unused mock return values\n",
test->name);
ret = TC_FAIL;
}
return ret;
}
static void run_test_functions(struct unit_test *test)
{
phase = TEST_PHASE_SETUP;
test->setup();
phase = TEST_PHASE_TEST;
test->test();
phase = TEST_PHASE_TEARDOWN;
test->teardown();
phase = TEST_PHASE_FRAMEWORK;
}
#ifndef KERNEL
#include <setjmp.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#define FAIL_FAST 0
static jmp_buf test_fail;
static jmp_buf test_pass;
static jmp_buf stack_fail;
void ztest_test_fail(void)
{
raise(SIGABRT);
}
void ztest_test_pass(void)
{
longjmp(test_pass, 1);
}
static void handle_signal(int sig)
{
static const char *const phase_str[] = {
"setup",
"unit test",
"teardown",
};
PRINT(" %s", strsignal(sig));
switch (phase) {
case TEST_PHASE_SETUP:
case TEST_PHASE_TEST:
case TEST_PHASE_TEARDOWN:
PRINT(" at %s function\n", phase_str[phase]);
longjmp(test_fail, 1);
case TEST_PHASE_FRAMEWORK:
PRINT("\n");
longjmp(stack_fail, 1);
}
}
static void init_testing(void)
{
signal(SIGABRT, handle_signal);
signal(SIGSEGV, handle_signal);
if (setjmp(stack_fail)) {
PRINT("Test suite crashed.");
exit(1);
}
}
static int run_test(struct unit_test *test)
{
int ret = TC_PASS;
TC_START(test->name);
if (setjmp(test_fail)) {
ret = TC_FAIL;
goto out;
}
if (setjmp(test_pass)) {
ret = TC_PASS;
goto out;
}
run_test_functions(test);
out:
ret |= cleanup_test(test);
_TC_END_RESULT(ret, test->name);
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 struct k_sem test_end_signal;
void ztest_test_fail(void)
{
test_result = -1;
k_sem_give(&test_end_signal);
k_thread_abort(k_current_get());
}
void ztest_test_pass(void)
{
test_result = 0;
k_sem_give(&test_end_signal);
k_thread_abort(k_current_get());
}
void ztest_test_skip(void)
{
test_result = -2;
k_sem_give(&test_end_signal);
k_thread_abort(k_current_get());
}
static void init_testing(void)
{
k_sem_init(&test_end_signal, 0, 1);
k_object_access_all_grant(&test_end_signal);
}
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;
k_sem_give(&test_end_signal);
}
static int run_test(struct unit_test *test)
{
int ret = TC_PASS;
TC_START(test->name);
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, -1, test->thread_options | K_INHERIT_PERMS,
0);
/*
* There is an implicit expectation here that the thread that was
* spawned is still higher priority than the current thread.
*
* If that is not the case, it will have given the semaphore, which
* will have caused the current thread to run, _if_ the test case
* thread is preemptible, since it is higher priority. If there is
* another test case to be run after the current one finishes, the
* thread_stack will be reused for that new test case while the current
* test case has not finished running yet (it has given the semaphore,
* but has _not_ gone back to _thread_entry() and completed it's "abort
* phase": this will corrupt the kernel ready queue.
*/
k_sem_take(&test_end_signal, K_FOREVER);
if (test_result == -1) {
ret = TC_FAIL;
}
if (!test_result || !FAIL_FAST) {
ret |= cleanup_test(test);
}
if (test_result == -2) {
_TC_END_RESULT(TC_SKIP, test->name);
} else {
_TC_END_RESULT(ret, test->name);
}
return ret;
}
#endif /* !KERNEL */
void _ztest_run_test_suite(const char *name, struct unit_test *suite)
{
int fail = 0;
if (test_status < 0) {
return;
}
init_testing();
PRINT("Running test suite %s\n", name);
PRINT_LINE;
while (suite->test) {
fail += run_test(suite);
suite++;
if (fail && FAIL_FAST) {
break;
}
}
if (fail) {
TC_PRINT("Test suite %s failed.\n", name);
} else {
TC_PRINT("Test suite %s succeeded\n", name);
}
test_status = (test_status || fail) ? 1 : 0;
}
void end_report(void)
{
if (test_status) {
TC_END_REPORT(TC_FAIL);
} else {
TC_END_REPORT(TC_PASS);
}
}
#ifdef CONFIG_APP_SHARED_MEM
struct k_mem_domain ztest_mem_domain;
K_APPMEM_PARTITION_DEFINE(ztest_mem_partition);
#endif
#ifndef KERNEL
int main(void)
{
_init_mock();
test_main();
end_report();
return test_status;
}
#else
void main(void)
{
#ifdef CONFIG_APP_SHARED_MEM
struct k_mem_partition *parts[] = {
&ztest_mem_partition,
#ifdef CONFIG_NEWLIB_LIBC
/* Newlib libc.a library and hooks globals */
&z_newlib_partition,
#endif
/* Both minimal and newlib libc expose this for malloc arena */
&z_malloc_partition
};
/* Ztests just have one memory domain with one partition.
* Any variables that user code may reference need to go in them,
* using the ZTEST_DMEM and ZTEST_BMEM macros.
*/
k_mem_domain_init(&ztest_mem_domain, ARRAY_SIZE(parts), parts);
k_mem_domain_add_thread(&ztest_mem_domain, k_current_get());
#endif /* CONFIG_APP_SHARED_MEM */
_init_mock();
test_main();
end_report();
}
#endif

View file

@ -0,0 +1,247 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <zephyr/types.h>
#include <string.h>
#include <stdio.h>
struct parameter {
struct parameter *next;
const char *fn;
const char *name;
uintptr_t value;
};
#ifndef KERNEL
#include <stdlib.h>
static void free_parameter(struct parameter *param)
{
free(param);
}
static struct parameter *alloc_parameter(void)
{
struct parameter *param;
param = calloc(1, sizeof(struct parameter));
if (!param) {
PRINT("Failed to allocate mock parameter\n");
ztest_test_fail();
}
return param;
}
void _init_mock(void)
{
}
#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,
unsigned int bits)
{
unsigned int words = (bits + BITS_PER_UL - 1) / BITS_PER_UL;
unsigned int cnt;
unsigned int long neg_bitmap;
/*
* By bitwise negating the bitmap, we are actually implemeting
* ffc (find first clear) using ffs (find first set).
*/
for (cnt = 0U; cnt < words; cnt++) {
neg_bitmap = ~bitmap[cnt];
if (neg_bitmap == 0) /* all full */
continue;
else if (neg_bitmap == ~0UL) /* first bit */
return cnt * BITS_PER_UL;
else
return cnt * BITS_PER_UL + __builtin_ffsl(neg_bitmap) - 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 _init_mock(void)
{
}
#endif
static struct parameter *find_and_delete_value(struct parameter *param,
const char *fn,
const char *name)
{
struct parameter *value;
if (!param->next) {
return NULL;
}
if (strcmp(param->next->name, name) || strcmp(param->next->fn, fn)) {
return find_and_delete_value(param->next, fn, name);
}
value = param->next;
param->next = param->next->next;
value->next = NULL;
return value;
}
static void insert_value(struct parameter *param, const char *fn,
const char *name, uintptr_t val)
{
struct parameter *value;
value = alloc_parameter();
value->fn = fn;
value->name = name;
value->value = val;
/* Seek to end of linked list to ensure correct discovery order in find_and_delete_value */
while (param->next) {
param = param->next;
}
/* Append to end of linked list */
value->next = param->next;
param->next = value;
}
static struct parameter parameter_list = { NULL, "", "", 0 };
static struct parameter return_value_list = { NULL, "", "", 0 };
void _ztest_expect_value(const char *fn, const char *name, uintptr_t val)
{
insert_value(&parameter_list, fn, name, val);
}
void _ztest_check_expected_value(const char *fn, const char *name,
uintptr_t val)
{
struct parameter *param;
uintptr_t expected;
param = find_and_delete_value(&parameter_list, fn, name);
if (!param) {
PRINT("Failed to find parameter %s for %s\n", name, fn);
ztest_test_fail();
}
expected = param->value;
free_parameter(param);
if (expected != val) {
/* 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);
ztest_test_fail();
}
}
void _ztest_returns_value(const char *fn, uintptr_t value)
{
insert_value(&return_value_list, fn, "", value);
}
uintptr_t _ztest_get_return_value(const char *fn)
{
uintptr_t value;
struct parameter *param = find_and_delete_value(&return_value_list,
fn, "");
if (!param) {
PRINT("Failed to find return value for function %s\n", fn);
ztest_test_fail();
}
value = param->value;
free_parameter(param);
return value;
}
static void free_param_list(struct parameter *param)
{
struct parameter *next;
while (param) {
next = param->next;
free_parameter(param);
param = next;
}
}
int _cleanup_mock(void)
{
int fail = 0;
if (parameter_list.next) {
fail = 1;
}
if (return_value_list.next) {
fail = 2;
}
free_param_list(parameter_list.next);
free_param_list(return_value_list.next);
parameter_list.next = NULL;
return_value_list.next = NULL;
return fail;
}