fff: Add fff_extensions.h, RETURN_HANDLED_CONTEXT()
Add supplementary header <zephyr/fff_extensions.h>. Add macro
to fff_extensions.h for simplifying definition of custom fake functions
needing call-unique information for producing desired output data.
When an array of custom fake context structures is defined and
the return field within the first structure instance is registered
with the standard SET_RETURN_SEQ() macro of FFF, the
RETURN_HANDLED_CONTEXT() macro provides the inverse logic to
recover the context structure for this called instance. The body of
the custom fake handler is provided to the RETURN_HANDLED_CONTEXT()
macro for appropriate execution and access to the custom fake
parameters.
A test suite is also provided to verify macro implementation and
illustrate usage. It is at:
zephyr/tests/subsys/testsuite/fff_fake_contexts/
This code was verified by:
1. (Pass) west build -p always \
-b unit_testing tests/subsys/testsuite/fff_fake_contexts/ && \
./build/testbinary
2. (Pass) west build -p always \
-b native_posix tests/subsys/testsuite/fff_fake_contexts/ && \
./build/zephyr/zephyr.exe
3. (Pass) ./scripts/twister -p unit_testing \
-T tests/subsys/testsuite/fff_fake_contexts/
4. (Pass) ./scripts/twister -p native_posix \
-T tests/subsys/testsuite/fff_fake_contexts/
5. (Pass) cd doc && build html-fast
Fix #55246
Signed-off-by: Gregory Shue <gregory.shue@legrand.com>
This commit is contained in:
parent
2b66410675
commit
5623f54a35
12 changed files with 658 additions and 2 deletions
|
|
@ -520,13 +520,14 @@ Example output for a failed macro from
|
|||
.. doxygengroup:: ztest_assume
|
||||
|
||||
|
||||
.. _mocking-fff:
|
||||
|
||||
Ztress
|
||||
======
|
||||
|
||||
.. doxygengroup:: ztest_ztress
|
||||
|
||||
|
||||
.. _mocking-fff:
|
||||
|
||||
Mocking via FFF
|
||||
===============
|
||||
|
||||
|
|
@ -544,6 +545,9 @@ devicetree bindings for more information:
|
|||
- :dtcompatible:`zephyr,fake-can`
|
||||
- :dtcompatible:`zephyr,fake-eeprom`
|
||||
|
||||
Zephyr also has defined extensions to FFF for simplified declarations of fake functions.
|
||||
See :ref:`FFF Extensions <fff-extensions>`.
|
||||
|
||||
Customizing Test Output
|
||||
***********************
|
||||
The way output is presented when running tests can be customized.
|
||||
|
|
@ -594,4 +598,13 @@ For example
|
|||
$ zephyr.exe -test="fixture_tests::test_fixture_pointer,framework_tests::test_assert_mem_equal"
|
||||
$ zephyr.exe -test="framework_tests::*"
|
||||
|
||||
|
||||
.. _fff-extensions:
|
||||
|
||||
FFF Extensions
|
||||
**************
|
||||
|
||||
.. doxygengroup:: fff_extensions
|
||||
|
||||
|
||||
.. _FFF: https://github.com/meekrosoft/fff
|
||||
|
|
|
|||
|
|
@ -925,6 +925,7 @@ INPUT = @ZEPHYR_BASE@/doc/_doxygen/mainpage.md \
|
|||
@ZEPHYR_BASE@/kernel/include/kernel_arch_interface.h \
|
||||
@ZEPHYR_BASE@/include/ \
|
||||
@ZEPHYR_BASE@/lib/libc/minimal/include/ \
|
||||
@ZEPHYR_BASE@/subsys/testsuite/include/ \
|
||||
@ZEPHYR_BASE@/subsys/testsuite/ztest/include/ \
|
||||
@ZEPHYR_BASE@/tests/kernel/
|
||||
|
||||
|
|
|
|||
98
subsys/testsuite/include/zephyr/fff_extensions.h
Normal file
98
subsys/testsuite/include/zephyr/fff_extensions.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright(c) 2023 Legrand North America, LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Zephyr testing framework FFF extension macros
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_SUBSYS_TESTSUITE_INCLUDE_ZEPHYR_FFF_EXTENSIONS_H_
|
||||
#define ZEPHYR_SUBSYS_TESTSUITE_INCLUDE_ZEPHYR_FFF_EXTENSIONS_H_
|
||||
|
||||
#include <zephyr/fff.h>
|
||||
#include <zephyr/sys/util.h> /* for CONTAINER_OF */
|
||||
|
||||
/**
|
||||
* @defgroup fff_extensions FFF extensions
|
||||
* @ingroup all_tests
|
||||
*
|
||||
* This module provides extensions to FFF for simplifying the
|
||||
* configuration and usage of fakes.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wrap custom fake body to extract defined context struct
|
||||
*
|
||||
* Add extension macro for simplified creation of
|
||||
* fake functions needing call-specific context data.
|
||||
*
|
||||
* This macro enables a fake to be implemented as follows and
|
||||
* requires no familiarity with the inner workings of FFF.
|
||||
*
|
||||
* @code
|
||||
* struct FUNCNAME##_custom_fake_context
|
||||
* {
|
||||
* struct instance * const instance;
|
||||
* int result;
|
||||
* };
|
||||
*
|
||||
* int FUNCNAME##_custom_fake(
|
||||
* const struct instance **instance_out)
|
||||
* {
|
||||
* RETURN_HANDLED_CONTEXT(
|
||||
* FUNCNAME,
|
||||
* struct FUNCNAME##_custom_fake_context,
|
||||
* result,
|
||||
* context,
|
||||
* {
|
||||
* if (context != NULL)
|
||||
* {
|
||||
* if (context->result == 0)
|
||||
* {
|
||||
* if (instance_out != NULL)
|
||||
* {
|
||||
* *instance_out = context->instance;
|
||||
* }
|
||||
* }
|
||||
* return context->result;
|
||||
* }
|
||||
* return FUNCNAME##_fake.return_val;
|
||||
* }
|
||||
* );
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param FUNCNAME Name of function being faked
|
||||
* @param CONTEXTTYPE type of custom defined fake context struct
|
||||
* @param RESULTFIELD name of field holding the return type & value
|
||||
* @param CONTEXTPTRNAME expected name of pointer to custom defined fake context struct
|
||||
* @param HANDLERBODY in-line custom fake handling logic
|
||||
*/
|
||||
|
||||
#define RETURN_HANDLED_CONTEXT(FUNCNAME, \
|
||||
CONTEXTTYPE, RESULTFIELD, CONTEXTPTRNAME, HANDLERBODY) \
|
||||
if (FUNCNAME##_fake.return_val_seq_len) { \
|
||||
CONTEXTTYPE * const contexts = \
|
||||
CONTAINER_OF(FUNCNAME##_fake.return_val_seq, \
|
||||
CONTEXTTYPE, RESULTFIELD); \
|
||||
size_t const seq_idx = (FUNCNAME##_fake.return_val_seq_idx < \
|
||||
FUNCNAME##_fake.return_val_seq_len) ? \
|
||||
FUNCNAME##_fake.return_val_seq_idx++ :\
|
||||
FUNCNAME##_fake.return_val_seq_idx - 1;\
|
||||
CONTEXTTYPE * const CONTEXTPTRNAME = &contexts[seq_idx]; \
|
||||
HANDLERBODY; \
|
||||
} \
|
||||
return FUNCNAME##_fake.return_val
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ZEPHYR_SUBSYS_TESTSUITE_INCLUDE_ZEPHYR_FFF_EXTENSIONS_H_ */
|
||||
23
tests/subsys/testsuite/fff_fake_contexts/CMakeLists.txt
Normal file
23
tests/subsys/testsuite/fff_fake_contexts/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Copyright (c) 2023 Legrand North America, LLC.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
if(BOARD STREQUAL unit_testing)
|
||||
find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
set(target testbinary)
|
||||
else()
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
set(target app)
|
||||
endif()
|
||||
|
||||
project(base)
|
||||
target_sources(${target} PRIVATE
|
||||
src/code_under_test.c
|
||||
src/main.c
|
||||
src/fakes/called_API.c
|
||||
)
|
||||
|
||||
target_include_directories(${target} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Legrand North America, LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_INCLUDE_ZEPHYR_CALLED_API_H_
|
||||
#define ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_INCLUDE_ZEPHYR_CALLED_API_H_
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* A container struct for hidden instance data */
|
||||
struct called_API_info;
|
||||
|
||||
/**
|
||||
* @brief Provide an instance handle to a session of the called_API.
|
||||
*
|
||||
* This API is defined for the code_under_test() example to call.
|
||||
* It represents a routine which provides call-unique data to the caller
|
||||
* as well as providing a return value. This requires the _custom_fake
|
||||
* implementation to serve the data from a custom_fake context struture,
|
||||
* where each call needs to return a unique, configured value.
|
||||
*
|
||||
* @param instance_out Session instance handle for caller to use.
|
||||
*
|
||||
* @return zero(0) upon success, with *instance_out updated.
|
||||
* @return -EINVAL if invalid parameter(s)
|
||||
* @return -E2BIG if more calls were made than expected.
|
||||
*/
|
||||
int called_API_open(const struct called_API_info **instance_out);
|
||||
|
||||
/**
|
||||
* @brief Return an instance handle to a session of the called_API.
|
||||
*
|
||||
* This API is defined for the code_under_test() example to call.
|
||||
* It represents a routine which requires specific data from the caller
|
||||
* as well as providing a return value. This is defined to
|
||||
* have the code_under_test call multiple functions to illustrate
|
||||
* a way to verify a specific calling sequence was made
|
||||
*
|
||||
* @param instance Session instance handle provided by called_API_open
|
||||
*
|
||||
* @return zero(0) upon success, with instance invalidated.
|
||||
* @return -EINVAL if invalid parameter(s)
|
||||
* @return -E2BIG if more calls were made than expected.
|
||||
*/
|
||||
int called_API_close(const struct called_API_info *instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_INCLUDE_ZEPHYR_CALLED_API_H_ */
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Legrand North America, LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_INCLUDE_ZEPHYR_CODE_UNDER_TEST_H_
|
||||
#define ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_INCLUDE_ZEPHYR_CODE_UNDER_TEST_H_
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Opens and closes called_API session twice
|
||||
*
|
||||
* This routine loops twice on opening/closing a called_API session.
|
||||
* Failures cause early termination of the loop, and the error number
|
||||
* from the called routine is returned by this routine. This routine
|
||||
* is designed for exercising custom_fake routines that need to use
|
||||
* call-specific data.
|
||||
*
|
||||
* @return zero(0) upon success
|
||||
* @return -EINVAL if invalid parameter(s)
|
||||
* @return -E2BIG if more calls were made than expected.
|
||||
*/
|
||||
int code_under_test(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_INCLUDE_ZEPHYR_CODE_UNDER_TEST_H_ */
|
||||
5
tests/subsys/testsuite/fff_fake_contexts/prj.conf
Normal file
5
tests/subsys/testsuite/fff_fake_contexts/prj.conf
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) 2023 Legrand North America, LLC.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_ZTEST_NEW_API=y
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Legrand North America, LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* NULL */
|
||||
#include <zephyr/called_API.h>
|
||||
#include <zephyr/code_under_test.h>
|
||||
|
||||
|
||||
int code_under_test(void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
const struct called_API_info *called_API = NULL;
|
||||
|
||||
result = called_API_open(&called_API);
|
||||
if (result != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
result = called_API_close(called_API);
|
||||
if (result != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Legrand North America, LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/fff.h>
|
||||
|
||||
#include "fakes/called_API.h"
|
||||
|
||||
DEFINE_FAKE_VALUE_FUNC(int, called_API_open, const struct called_API_info **);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, called_API_close, const struct called_API_info *);
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Legrand North America, LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_FAKES_CALLED_API_H_
|
||||
#define ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_FAKES_CALLED_API_H_
|
||||
|
||||
#include <zephyr/fff.h>
|
||||
#include <zephyr/called_API.h>
|
||||
|
||||
#define ZEPHYR_CALLED_API_FFF_FAKES_LIST(FAKE) \
|
||||
FAKE(called_API_open) \
|
||||
FAKE(called_API_close) \
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DECLARE_FAKE_VALUE_FUNC(int, called_API_open, const struct called_API_info **);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, called_API_close, const struct called_API_info *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_TESTS_SUBSYS_TESTSUITE_FFF_FAKE_CONTEXTS_FAKES_CALLED_API_H_ */
|
||||
338
tests/subsys/testsuite/fff_fake_contexts/src/main.c
Normal file
338
tests/subsys/testsuite/fff_fake_contexts/src/main.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Legrand North America, LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/code_under_test.h>
|
||||
|
||||
|
||||
#include <zephyr/ztest.h>
|
||||
#include <zephyr/fff.h>
|
||||
#include <zephyr/fff_extensions.h>
|
||||
|
||||
#include "fakes/called_API.h"
|
||||
|
||||
|
||||
#define RESET_HISTORY_AND_FAKES() \
|
||||
ZEPHYR_CALLED_API_FFF_FAKES_LIST(RESET_FAKE) \
|
||||
FFF_RESET_HISTORY()
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
|
||||
/*
|
||||
* Custom Fakes:
|
||||
*/
|
||||
|
||||
struct called_API_open_custom_fake_context {
|
||||
/* Written to code under test by custom fake */
|
||||
const struct called_API_info * const instance_out;
|
||||
|
||||
int result;
|
||||
};
|
||||
|
||||
int called_API_open_custom_fake(
|
||||
const struct called_API_info **instance_out)
|
||||
{
|
||||
RETURN_HANDLED_CONTEXT(
|
||||
called_API_open,
|
||||
struct called_API_open_custom_fake_context,
|
||||
result, /* return field name in _fake_context struct */
|
||||
context, /* Name of context ptr variable used below */
|
||||
{
|
||||
if (context != NULL) {
|
||||
if (context->result == 0) {
|
||||
if (instance_out != NULL) {
|
||||
*instance_out = context->instance_out;
|
||||
}
|
||||
}
|
||||
|
||||
return context->result;
|
||||
}
|
||||
|
||||
return called_API_open_fake.return_val;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests
|
||||
*/
|
||||
|
||||
ZTEST(fff_fake_contexts_tests, test_code_under_test)
|
||||
{
|
||||
struct test_case {
|
||||
const char *description_oneliner;
|
||||
|
||||
void **expected_call_history;
|
||||
|
||||
/* Last FFF sequence entry is reused for excess calls.
|
||||
* Have an extra entry that returns a distinct failure (-E2BIG)
|
||||
*
|
||||
* Expect one less call than _len, or 0 if sequence ptr is NULL
|
||||
*
|
||||
* Configure to return -E2BIG if excess calls.
|
||||
*/
|
||||
int called_API_open_custom_fake_contexts_len;
|
||||
struct called_API_open_custom_fake_context *
|
||||
called_API_open_custom_fake_contexts;
|
||||
|
||||
int called_API_close_fake_return_val_seq_len;
|
||||
int *called_API_close_fake_return_val_seq;
|
||||
|
||||
int result_expected;
|
||||
}
|
||||
const test_cases[] = {
|
||||
{
|
||||
.description_oneliner = "First called_API_open() returns -EINVAL",
|
||||
.expected_call_history = (void * [])
|
||||
{
|
||||
called_API_open,
|
||||
NULL, /* mark end of array */
|
||||
},
|
||||
|
||||
.called_API_open_custom_fake_contexts_len = 2,
|
||||
.called_API_open_custom_fake_contexts =
|
||||
(struct called_API_open_custom_fake_context [])
|
||||
{
|
||||
{
|
||||
.result = -EINVAL,
|
||||
},
|
||||
{
|
||||
.result = -E2BIG, /* for excessive calls */
|
||||
},
|
||||
},
|
||||
|
||||
.called_API_close_fake_return_val_seq = NULL,
|
||||
|
||||
.result_expected = -EINVAL,
|
||||
},
|
||||
{
|
||||
.description_oneliner = "First called_API_close() returns -EINVAL",
|
||||
.expected_call_history = (void * [])
|
||||
{
|
||||
called_API_open,
|
||||
called_API_close,
|
||||
NULL, /* mark end of array */
|
||||
},
|
||||
|
||||
.called_API_open_custom_fake_contexts_len = 2,
|
||||
.called_API_open_custom_fake_contexts =
|
||||
(struct called_API_open_custom_fake_context [])
|
||||
{
|
||||
{
|
||||
.result = 0,
|
||||
},
|
||||
{
|
||||
.result = -E2BIG, /* for excessive calls */
|
||||
},
|
||||
},
|
||||
|
||||
.called_API_close_fake_return_val_seq_len = 2,
|
||||
.called_API_close_fake_return_val_seq = (int [])
|
||||
{
|
||||
-EINVAL,
|
||||
-E2BIG, /* for excessive calls */
|
||||
},
|
||||
|
||||
.result_expected = -EINVAL,
|
||||
},
|
||||
{
|
||||
.description_oneliner = "Second called_API_open() returns -EINVAL",
|
||||
.expected_call_history = (void * [])
|
||||
{
|
||||
called_API_open,
|
||||
called_API_close,
|
||||
called_API_open,
|
||||
NULL, /* mark end of array */
|
||||
},
|
||||
|
||||
.called_API_open_custom_fake_contexts_len = 3,
|
||||
.called_API_open_custom_fake_contexts =
|
||||
(struct called_API_open_custom_fake_context [])
|
||||
{
|
||||
{
|
||||
.result = 0,
|
||||
},
|
||||
{
|
||||
.result = -EINVAL,
|
||||
},
|
||||
{
|
||||
.result = -E2BIG, /* for excessive calls */
|
||||
},
|
||||
},
|
||||
|
||||
.called_API_close_fake_return_val_seq_len = 2,
|
||||
.called_API_close_fake_return_val_seq = (int [])
|
||||
{
|
||||
0,
|
||||
-E2BIG, /* for excessive calls */
|
||||
},
|
||||
|
||||
.result_expected = -EINVAL,
|
||||
},
|
||||
{
|
||||
.description_oneliner = "Second called_API_close() returns -EINVAL",
|
||||
.expected_call_history = (void * [])
|
||||
{
|
||||
called_API_open,
|
||||
called_API_close,
|
||||
called_API_open,
|
||||
called_API_close,
|
||||
NULL, /* mark end of array */
|
||||
},
|
||||
|
||||
.called_API_open_custom_fake_contexts_len = 3,
|
||||
.called_API_open_custom_fake_contexts =
|
||||
(struct called_API_open_custom_fake_context [])
|
||||
{
|
||||
{
|
||||
.result = 0,
|
||||
},
|
||||
{
|
||||
.result = 0,
|
||||
},
|
||||
{
|
||||
.result = -E2BIG, /* for excessive calls */
|
||||
},
|
||||
},
|
||||
|
||||
.called_API_close_fake_return_val_seq_len = 3,
|
||||
.called_API_close_fake_return_val_seq = (int [])
|
||||
{
|
||||
0,
|
||||
-EINVAL,
|
||||
-E2BIG, /* for excessive calls */
|
||||
},
|
||||
|
||||
.result_expected = -EINVAL,
|
||||
},
|
||||
{
|
||||
.description_oneliner = "All calls return no error",
|
||||
.expected_call_history = (void * [])
|
||||
{
|
||||
called_API_open,
|
||||
called_API_close,
|
||||
called_API_open,
|
||||
called_API_close,
|
||||
NULL, /* mark end of array */
|
||||
},
|
||||
|
||||
.called_API_open_custom_fake_contexts_len = 3,
|
||||
.called_API_open_custom_fake_contexts =
|
||||
(struct called_API_open_custom_fake_context [])
|
||||
{
|
||||
{
|
||||
.result = 0,
|
||||
},
|
||||
{
|
||||
.result = 0,
|
||||
},
|
||||
{
|
||||
.result = -E2BIG, /* for excessive calls */
|
||||
},
|
||||
},
|
||||
|
||||
.called_API_close_fake_return_val_seq_len = 3,
|
||||
.called_API_close_fake_return_val_seq = (int [])
|
||||
{
|
||||
0,
|
||||
0,
|
||||
-E2BIG, /* for excessive calls */
|
||||
},
|
||||
|
||||
.result_expected = 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(test_cases); ++i) {
|
||||
const struct test_case * const tc = &test_cases[i];
|
||||
|
||||
|
||||
printk("Checking test_cases[%i]: %s\n", i,
|
||||
(tc->description_oneliner != NULL) ? tc->description_oneliner : "");
|
||||
|
||||
/*
|
||||
* Set up pre-conditions
|
||||
*/
|
||||
RESET_HISTORY_AND_FAKES();
|
||||
|
||||
/* NOTE: Point to the return type field in the first returns struct.
|
||||
* This custom_fake:
|
||||
* - uses *_fake.return_val_seq and CONTAINER_OF()
|
||||
* to determine the beginning of the array of structures.
|
||||
* - uses *_fake.return_val_seq_id to index into
|
||||
* the array of structures.
|
||||
* This overloading is to allow the return_val_seq to
|
||||
* also contain call-specific output parameters to be
|
||||
* applied by the custom_fake.
|
||||
*/
|
||||
called_API_open_fake.return_val = -E2BIG; /* for excessive calls */
|
||||
SET_RETURN_SEQ(called_API_open,
|
||||
&tc->called_API_open_custom_fake_contexts[0].result,
|
||||
tc->called_API_open_custom_fake_contexts_len);
|
||||
called_API_open_fake.custom_fake = called_API_open_custom_fake;
|
||||
|
||||
/* NOTE: This uses the standard _fake without contexts */
|
||||
called_API_close_fake.return_val = -E2BIG; /* for excessive calls */
|
||||
SET_RETURN_SEQ(called_API_close,
|
||||
tc->called_API_close_fake_return_val_seq,
|
||||
tc->called_API_close_fake_return_val_seq_len);
|
||||
|
||||
|
||||
/*
|
||||
* Call code_under_test
|
||||
*/
|
||||
int result = code_under_test();
|
||||
|
||||
|
||||
/*
|
||||
* Verify expected behavior of code_under_test:
|
||||
* - call history, args per call
|
||||
* - results
|
||||
* - outputs
|
||||
*/
|
||||
if (tc->expected_call_history != NULL) {
|
||||
for (int j = 0; j < fff.call_history_idx; ++j) {
|
||||
zassert_equal(fff.call_history[j],
|
||||
tc->expected_call_history[j], NULL);
|
||||
}
|
||||
zassert_is_null(tc->expected_call_history[
|
||||
fff.call_history_idx], NULL);
|
||||
} else {
|
||||
zassert_equal(fff.call_history_idx, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
const int called_API_open_fake_call_count_expected =
|
||||
(tc->called_API_open_custom_fake_contexts == NULL) ? 0 :
|
||||
tc->called_API_open_custom_fake_contexts_len - 1;
|
||||
|
||||
zassert_equal(called_API_open_fake.call_count,
|
||||
called_API_open_fake_call_count_expected, NULL);
|
||||
for (int j = 0; j < called_API_open_fake_call_count_expected; ++j) {
|
||||
zassert_not_null(called_API_open_fake.arg0_history[j], NULL);
|
||||
}
|
||||
|
||||
|
||||
const int called_API_close_fake_call_count_expected =
|
||||
(tc->called_API_close_fake_return_val_seq == NULL) ? 0 :
|
||||
tc->called_API_close_fake_return_val_seq_len - 1;
|
||||
|
||||
zassert_equal(called_API_close_fake.call_count,
|
||||
called_API_close_fake_call_count_expected, NULL);
|
||||
for (int j = 0; j < called_API_close_fake_call_count_expected; ++j) {
|
||||
/* Verify code_under_test returns value provided by open. */
|
||||
zassert_equal(called_API_close_fake.arg0_history[j],
|
||||
tc->called_API_open_custom_fake_contexts[j]
|
||||
.instance_out, NULL);
|
||||
}
|
||||
|
||||
|
||||
zassert_equal(result, tc->result_expected, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ZTEST_SUITE(fff_fake_contexts_tests, NULL, NULL, NULL, NULL, NULL);
|
||||
13
tests/subsys/testsuite/fff_fake_contexts/testcase.yaml
Normal file
13
tests/subsys/testsuite/fff_fake_contexts/testcase.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Copyright (c) 2023 Legrand North America, LLC.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
tests:
|
||||
testing.testsuite.fff_fake_contexts.unit:
|
||||
tags: test_framework
|
||||
type: unit
|
||||
testing.testsuite.fff_fake_contexts:
|
||||
integration_platforms:
|
||||
- qemu_cortex_m3
|
||||
- native_posix_64
|
||||
tags: test_framework
|
||||
platform_allow: qemu_cortex_m3 native_posix_64
|
||||
Loading…
Reference in a new issue