subsys/testsuite: Extended mocking API to support arrays

I was missing mocking api to compare data under an address pointed
by a parameter as some functions may copy buffers before passing
further.
Created ztest_expect_data and ztest_check_expected_data.

Signed-off-by: Marek Porwisz <marek.porwisz@nordicsemi.no>
This commit is contained in:
Marek Porwisz 2020-04-16 15:48:06 +02:00 committed by Carles Cufí
commit d9f8a6f8e9
2 changed files with 106 additions and 38 deletions

View file

@ -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,9 +48,40 @@
*
* @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(), tell that the data ponted by @a param
* should be same as data at @a data.
* 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), (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 does @a param have a value to be expected, and
* then checks whether the data pointed by parameter are 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), (param), \
(length))
/**
* @brief Tell @a func that it should return @a value
@ -58,7 +89,7 @@
* @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 +100,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 +110,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 +130,11 @@ 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,
u32_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 +148,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 /* __ZTEST_H__ */

View file

@ -41,7 +41,6 @@ static struct parameter *alloc_parameter(void)
void z_init_mock(void)
{
}
void printk(const char *fmt, ...)
@ -64,12 +63,11 @@ void vprintk(const char *fmt, va_list ap)
* 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]
#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)
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;
@ -81,12 +79,13 @@ int sys_bitfield_find_first_clear(const unsigned long *bitmap,
*/
for (cnt = 0U; cnt < words; cnt++) {
neg_bitmap = ~bitmap[cnt];
if (neg_bitmap == 0) /* all full */
if (neg_bitmap == 0) /* all full */
continue;
else if (neg_bitmap == ~0UL) /* first bit */
else if (neg_bitmap == ~0UL) /* first bit */
return cnt * BITS_PER_UL;
else
return cnt * BITS_PER_UL + __builtin_ffsl(neg_bitmap) - 1;
return cnt * BITS_PER_UL + __builtin_ffsl(neg_bitmap) -
1;
}
return -1;
}
@ -94,8 +93,7 @@ int sys_bitfield_find_first_clear(const unsigned long *bitmap,
static DEFINE_BITFIELD(params_allocation, CONFIG_ZTEST_PARAMETER_COUNT);
static struct parameter params[CONFIG_ZTEST_PARAMETER_COUNT];
static
void free_parameter(struct parameter *param)
static void free_parameter(struct parameter *param)
{
unsigned int allocation_index = param - params;
@ -104,12 +102,10 @@ void free_parameter(struct parameter *param)
__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);
sys_bitfield_clear_bit((mem_addr_t)params_allocation, allocation_index);
}
static
struct parameter *alloc_parameter(void)
static struct parameter *alloc_parameter(void)
{
int allocation_index;
struct parameter *param;
@ -120,7 +116,7 @@ struct parameter *alloc_parameter(void)
printk("No more mock parameters available for allocation\n");
ztest_test_fail();
}
sys_bitfield_set_bit((mem_addr_t) params_allocation, allocation_index);
sys_bitfield_set_bit((mem_addr_t)params_allocation, allocation_index);
param = params + allocation_index;
(void)memset(param, 0, sizeof(*param));
return param;
@ -133,8 +129,7 @@ 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;
@ -182,7 +177,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;
@ -200,23 +195,57 @@ 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,
u32_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);
ztest_test_fail();
}
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 fhile expected null pointer\n", fn,
name);
ztest_test_fail();
} else if (data != NULL) {
if (memcmp(data, expected, length) != 0) {
PRINT("%s:%s data provided dont match\n", fn, name);
ztest_test_fail();
}
}
}
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);
@ -245,9 +274,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;
}