1 /* SPDX-License-Identifier: GPL-2.0-only */
3 /* Include memcpy() source code and alter its name to compare results with libc memcpy() */
4 #define memcpy cb_memcpy
5 #include "../lib/memcpy.c"
9 #include <tests/test.h>
10 #include <commonlib/helpers.h>
13 #define MEMCPY_BUFFER_SZ (4 * KiB)
15 /* Prototype of memcpy() from string.h was changed to cb_memcpy().
16 It has to be defined again. */
17 void *memcpy(void *dest
, const void *src
, size_t n
);
19 struct test_memcpy_data
{
25 int setup_test(void **state
)
27 struct test_memcpy_data
*s
= malloc(sizeof(struct test_memcpy_data
));
32 s
->buffer_from
= malloc(MEMCPY_BUFFER_SZ
);
33 s
->buffer_to
= malloc(MEMCPY_BUFFER_SZ
);
34 s
->helper_buffer
= malloc(MEMCPY_BUFFER_SZ
);
36 if (!s
->buffer_from
|| !s
->buffer_to
|| !s
->helper_buffer
) {
39 free(s
->helper_buffer
);
44 /* Fill buffers with different values (other than zero) to make them distinguishable.
45 The helper buffer is often used as a backup of destination buffer so it has the
47 memset(s
->buffer_from
, 0xAB, MEMCPY_BUFFER_SZ
);
48 memset(s
->buffer_to
, 0xBC, MEMCPY_BUFFER_SZ
);
49 memset(s
->helper_buffer
, 0xBC, MEMCPY_BUFFER_SZ
);
56 int teardown_test(void **state
)
58 struct test_memcpy_data
*s
= *state
;
62 free(s
->helper_buffer
);
68 /* Fill buffer with values from provided range [start; end] in circular way. */
69 static void fill_buffer_data_range(u8
*buffer
, size_t sz
, u8 start_value
, u8 end_value
)
71 for (size_t i
= 0; i
< sz
; ++i
)
72 buffer
[i
] = (start_value
+ i
) % (end_value
- start_value
+ 1);
75 static void test_memcpy_full_buffer_copy(void **state
)
77 struct test_memcpy_data
*s
= *state
;
80 fill_buffer_data_range(s
->buffer_from
, MEMCPY_BUFFER_SZ
, 0, 255);
82 res_cb
= cb_memcpy(s
->buffer_to
, s
->buffer_from
, MEMCPY_BUFFER_SZ
);
84 assert_ptr_equal(s
->buffer_to
, res_cb
);
85 assert_memory_equal(s
->buffer_from
, s
->buffer_to
, MEMCPY_BUFFER_SZ
);
88 static void test_memcpy_zero_size(void **state
)
90 struct test_memcpy_data
*s
= *state
;
93 fill_buffer_data_range(s
->buffer_from
, MEMCPY_BUFFER_SZ
, 'A', 'Z');
95 /* Expect no change in destination buffer. */
96 res_cb
= cb_memcpy(s
->buffer_to
, s
->buffer_from
, 0);
97 assert_ptr_equal(s
->buffer_to
, res_cb
);
98 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, MEMCPY_BUFFER_SZ
);
101 static void test_memcpy_buffer_part(void **state
)
103 struct test_memcpy_data
*s
= *state
;
105 const size_t offset
= MEMCPY_BUFFER_SZ
/ 4;
106 const size_t sz
= MEMCPY_BUFFER_SZ
/ 2;
108 /* Self-test for correct data ranges */
109 assert_true(offset
+ sz
<= MEMCPY_BUFFER_SZ
);
111 fill_buffer_data_range(s
->buffer_from
, MEMCPY_BUFFER_SZ
, '0', '9');
113 /* Expect only *sz* bytes of buffer to be copied. Helper buffer is used as template. */
114 res_cb
= cb_memcpy(s
->buffer_to
+ offset
, s
->buffer_from
, sz
);
115 assert_ptr_equal(s
->buffer_to
+ offset
, res_cb
);
116 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, offset
);
117 assert_memory_equal(s
->buffer_to
+ offset
, s
->buffer_from
, sz
);
118 assert_memory_equal(s
->buffer_to
+ offset
+ sz
, s
->helper_buffer
+ offset
+ sz
,
119 MEMCPY_BUFFER_SZ
- (offset
+ sz
));
122 static void test_memcpy_buffer_part_unaligned(void **state
)
124 struct test_memcpy_data
*s
= *state
;
126 const size_t dst_offset
= MEMCPY_BUFFER_SZ
/ 8 + 3;
127 const size_t src_offset
= MEMCPY_BUFFER_SZ
/ 4 - 3;
128 const size_t sz
= MEMCPY_BUFFER_SZ
/ 4 + 7;
130 /* Self-test for correct data ranges */
131 assert_true(dst_offset
+ sz
<= MEMCPY_BUFFER_SZ
);
132 assert_true(src_offset
+ sz
<= MEMCPY_BUFFER_SZ
);
134 fill_buffer_data_range(s
->buffer_from
, MEMCPY_BUFFER_SZ
, 0x13, 0xB7);
136 res_cb
= cb_memcpy(s
->buffer_to
+ dst_offset
, s
->buffer_from
+ src_offset
, sz
);
137 assert_ptr_equal(s
->buffer_to
+ dst_offset
, res_cb
);
138 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, dst_offset
);
139 assert_memory_equal(s
->buffer_to
+ dst_offset
, s
->buffer_from
+ src_offset
, sz
);
140 assert_memory_equal(s
->buffer_to
+ dst_offset
+ sz
, s
->helper_buffer
+ dst_offset
+ sz
,
141 MEMCPY_BUFFER_SZ
- (dst_offset
+ sz
));
144 static void test_memcpy_copy_to_itself(void **state
)
146 struct test_memcpy_data
*s
= *state
;
149 fill_buffer_data_range(s
->buffer_to
, MEMCPY_BUFFER_SZ
, 'G', 'X');
150 memcpy(s
->buffer_to
, s
->helper_buffer
, MEMCPY_BUFFER_SZ
);
152 /* Expect no change in source/destination buffer. */
153 res_cb
= cb_memcpy(s
->buffer_to
, s
->buffer_to
, MEMCPY_BUFFER_SZ
);
154 assert_ptr_equal(s
->buffer_to
, res_cb
);
155 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, MEMCPY_BUFFER_SZ
);
158 static void test_memcpy_copy_part_of_itself_to_itself(void **state
)
160 struct test_memcpy_data
*s
= *state
;
162 const size_t offset
= MEMCPY_BUFFER_SZ
/ 8;
163 const size_t sz
= MEMCPY_BUFFER_SZ
- offset
;
165 /* Self-test for correct data ranges */
166 assert_true(offset
+ sz
<= MEMCPY_BUFFER_SZ
);
168 fill_buffer_data_range(s
->buffer_to
, MEMCPY_BUFFER_SZ
, 'd', 'v');
169 memcpy(s
->helper_buffer
, s
->buffer_to
, MEMCPY_BUFFER_SZ
);
171 /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
172 res_cb
= cb_memcpy(s
->buffer_to
, s
->buffer_to
+ offset
, sz
);
173 assert_ptr_equal(s
->buffer_to
, res_cb
);
174 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
+ offset
, sz
);
175 assert_memory_equal(s
->buffer_to
+ sz
, s
->helper_buffer
+ sz
, offset
);
180 const struct CMUnitTest tests
[] = {
181 cmocka_unit_test_setup_teardown(test_memcpy_full_buffer_copy
, setup_test
,
183 cmocka_unit_test_setup_teardown(test_memcpy_zero_size
, setup_test
,
185 cmocka_unit_test_setup_teardown(test_memcpy_buffer_part
, setup_test
,
187 cmocka_unit_test_setup_teardown(test_memcpy_buffer_part_unaligned
, setup_test
,
189 cmocka_unit_test_setup_teardown(test_memcpy_copy_to_itself
, setup_test
,
191 cmocka_unit_test_setup_teardown(test_memcpy_copy_part_of_itself_to_itself
,
192 setup_test
, teardown_test
),
195 return cb_run_group_tests(tests
, NULL
, NULL
);