When running multiple tests, e.g. by using unit-tests target, it is hard to differentiate, which output comes from which file and/or configuration. This patch makes the output easier to analyze and understand by using new wrapper macro cb_run_group_tests(). This macro uses __TEST_NAME__ value (containing test path and Makefile test name) as a group name when calling cmocka group runner. Example: Test path: tests/lib/ Makefile test name: cbmem_stage_cache-test Test group array name: tests Result: tests/lib/cbmem_stage_cache-test(tests) Signed-off-by: Jakub Czapiga <jacz@semihalf.com> Change-Id: I4fd936d00d77cbe2637b857ba03b4a208428ea0d Reviewed-on: https://review.coreboot.org/c/coreboot/+/57144 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
		
			
				
	
	
		
			251 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0-only */
 | |
| 
 | |
| #define memmove cb_memmove
 | |
| #include "../lib/memmove.c"
 | |
| #undef memmove
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <tests/test.h>
 | |
| #include <commonlib/helpers.h>
 | |
| #include <types.h>
 | |
| 
 | |
| #define MEMMOVE_BUFFER_SZ (4 * KiB)
 | |
| 
 | |
| /* Prototype of memmove() from string.h was changed to cb_memmove().
 | |
|    It has to be defined again. */
 | |
| void *memmove(void *dst, const void *src, size_t n);
 | |
| 
 | |
| struct test_memmove_data {
 | |
| 	u8 *buffer_from;
 | |
| 	u8 *buffer_to;
 | |
| 	u8 *helper_buffer;
 | |
| };
 | |
| 
 | |
| int setup_test(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = malloc(sizeof(struct test_memmove_data));
 | |
| 
 | |
| 	if (!s)
 | |
| 		return -1;
 | |
| 
 | |
| 	s->buffer_from = malloc(MEMMOVE_BUFFER_SZ);
 | |
| 	s->buffer_to = malloc(MEMMOVE_BUFFER_SZ);
 | |
| 	s->helper_buffer = malloc(MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	if (!s->buffer_from || !s->buffer_to || !s->helper_buffer) {
 | |
| 		free(s->buffer_from);
 | |
| 		free(s->buffer_to);
 | |
| 		free(s->helper_buffer);
 | |
| 		free(s);
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* Fill buffers with different values (other than zero) to make them distinguishable.
 | |
| 	   The helper buffer is often used as a backup of destination buffer so it has the
 | |
| 	   same value. */
 | |
| 	memset(s->buffer_from, 0xAB, MEMMOVE_BUFFER_SZ);
 | |
| 	memset(s->buffer_to, 0xBC, MEMMOVE_BUFFER_SZ);
 | |
| 	memset(s->helper_buffer, 0xBC, MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	*state = s;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int teardown_test(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 
 | |
| 	free(s->buffer_from);
 | |
| 	free(s->buffer_to);
 | |
| 	free(s->helper_buffer);
 | |
| 	free(s);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* Fill buffer with values from provided range [start; end] in circular way. */
 | |
| static void fill_buffer_data_range(u8 *buffer, size_t sz, u8 start_value, u8 end_value)
 | |
| {
 | |
| 	for (size_t i = 0; i < sz; ++i)
 | |
| 		buffer[i] = (start_value + i) % (end_value - start_value + 1);
 | |
| }
 | |
| 
 | |
| static void test_memmove_full_buffer_copy(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 0, 255);
 | |
| 
 | |
| 	res_cb = cb_memmove(s->buffer_to, s->buffer_from, MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	assert_ptr_equal(s->buffer_to, res_cb);
 | |
| 	assert_memory_equal(s->buffer_from, s->buffer_to, MEMMOVE_BUFFER_SZ);
 | |
| }
 | |
| 
 | |
| static void test_memmove_zero_size(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 'A', 'Z');
 | |
| 
 | |
| 	/* Expect no change in destination buffer. */
 | |
| 	res_cb = cb_memmove(s->buffer_to, s->buffer_from, 0);
 | |
| 	assert_ptr_equal(res_cb, s->buffer_to);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer, MEMMOVE_BUFFER_SZ);
 | |
| }
 | |
| 
 | |
| static void test_memmove_buffer_part(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 	const size_t offset = MEMMOVE_BUFFER_SZ / 4;
 | |
| 	const size_t sz = MEMMOVE_BUFFER_SZ / 3;
 | |
| 
 | |
| 	/* Self-test for correct data ranges */
 | |
| 	assert_true(offset + sz <= MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, '0', '9');
 | |
| 
 | |
| 	/* Expect only *sz* bytes of buffer to be copied. Helper buffer is used as template. */
 | |
| 	res_cb = cb_memmove(s->buffer_to + offset, s->buffer_from, sz);
 | |
| 	assert_ptr_equal(s->buffer_to + offset, res_cb);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer, offset);
 | |
| 	assert_memory_equal(s->buffer_to + offset, s->buffer_from, sz);
 | |
| 	assert_memory_equal(s->buffer_to + offset + sz, s->helper_buffer + offset + sz,
 | |
| 				MEMMOVE_BUFFER_SZ - (offset + sz));
 | |
| }
 | |
| 
 | |
| static void test_memmove_buffer_part_unaligned(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 	const size_t dst_offset = MEMMOVE_BUFFER_SZ / 8 + 3;
 | |
| 	const size_t src_offset = MEMMOVE_BUFFER_SZ / 4 - 3;
 | |
| 	const size_t sz = MEMMOVE_BUFFER_SZ / 4 + 7;
 | |
| 
 | |
| 	/* Self-test for correct data ranges */
 | |
| 	assert_true(dst_offset + sz <= MEMMOVE_BUFFER_SZ);
 | |
| 	assert_true(src_offset + sz <= MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 0x13, 0xB7);
 | |
| 
 | |
| 	res_cb = cb_memmove(s->buffer_to + dst_offset, s->buffer_from + src_offset, sz);
 | |
| 	assert_ptr_equal(s->buffer_to + dst_offset, res_cb);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer, dst_offset);
 | |
| 	assert_memory_equal(s->buffer_to + dst_offset, s->buffer_from + src_offset, sz);
 | |
| 	assert_memory_equal(s->buffer_to + dst_offset + sz, s->helper_buffer + dst_offset + sz,
 | |
| 				MEMMOVE_BUFFER_SZ - (dst_offset + sz));
 | |
| }
 | |
| 
 | |
| static void test_memmove_copy_to_itself(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'G', 'X');
 | |
| 	memmove(s->buffer_to, s->helper_buffer, MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	/* Expect no change in source/destination buffer. */
 | |
| 	res_cb = cb_memmove(s->buffer_to, s->buffer_to, MEMMOVE_BUFFER_SZ);
 | |
| 	assert_ptr_equal(res_cb, s->buffer_to);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer, MEMMOVE_BUFFER_SZ);
 | |
| }
 | |
| 
 | |
| static void test_memmove_self_higher_to_lower(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 	const size_t offset = MEMMOVE_BUFFER_SZ / 8;
 | |
| 	const size_t sz = MEMMOVE_BUFFER_SZ - offset;
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
 | |
| 	memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	/* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
 | |
| 	res_cb = cb_memmove(s->buffer_to, s->buffer_to + offset, sz);
 | |
| 	assert_ptr_equal(res_cb, s->buffer_to);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer + offset, sz);
 | |
| 	assert_memory_equal(s->buffer_to + sz, s->helper_buffer + sz, offset);
 | |
| }
 | |
| 
 | |
| static void test_memmove_self_higher_to_lower_unaligned(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 	const size_t offset = MEMMOVE_BUFFER_SZ / 6 + 7;
 | |
| 	const size_t sz = MEMMOVE_BUFFER_SZ - offset;
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
 | |
| 	memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	/* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
 | |
| 	res_cb = cb_memmove(s->buffer_to, s->buffer_to + offset, sz);
 | |
| 	assert_ptr_equal(res_cb, s->buffer_to);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer + offset, sz);
 | |
| 	assert_memory_equal(s->buffer_to + sz, s->helper_buffer + sz, offset);
 | |
| }
 | |
| 
 | |
| static void test_memmove_self_lower_to_higher(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 	const size_t offset = MEMMOVE_BUFFER_SZ / 4;
 | |
| 	const size_t sz = MEMMOVE_BUFFER_SZ - offset;
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
 | |
| 	memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	/* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
 | |
| 	res_cb = cb_memmove(s->buffer_to + offset, s->buffer_to, sz);
 | |
| 	assert_ptr_equal(res_cb, s->buffer_to + offset);
 | |
| 	assert_memory_equal(s->buffer_to + offset, s->helper_buffer, sz);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer, offset);
 | |
| }
 | |
| 
 | |
| static void test_memmove_self_lower_to_higher_unaligned(void **state)
 | |
| {
 | |
| 	struct test_memmove_data *s = *state;
 | |
| 	void *res_cb;
 | |
| 	const size_t offset = MEMMOVE_BUFFER_SZ / 4 - 17;
 | |
| 	const size_t sz = MEMMOVE_BUFFER_SZ - offset;
 | |
| 
 | |
| 	fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
 | |
| 	memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
 | |
| 
 | |
| 	/* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
 | |
| 	res_cb = cb_memmove(s->buffer_to + offset, s->buffer_to, sz);
 | |
| 	assert_ptr_equal(res_cb, s->buffer_to + offset);
 | |
| 	assert_memory_equal(s->buffer_to + offset, s->helper_buffer, sz);
 | |
| 	assert_memory_equal(s->buffer_to, s->helper_buffer, offset);
 | |
| }
 | |
| 
 | |
| int main(void)
 | |
| {
 | |
| 	const struct CMUnitTest tests[] = {
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_full_buffer_copy,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_zero_size,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_buffer_part,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_buffer_part_unaligned,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_copy_to_itself,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower_unaligned,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher,
 | |
| 						setup_test, teardown_test),
 | |
| 		cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher_unaligned,
 | |
| 						setup_test, teardown_test),
 | |
| 	};
 | |
| 
 | |
| 	return cb_run_group_tests(tests, NULL, NULL);
 | |
| }
 | |
| 
 |