1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #define memmove cb_memmove
4 #include "../lib/memmove.c"
8 #include <tests/test.h>
9 #include <commonlib/helpers.h>
12 #define MEMMOVE_BUFFER_SZ (4 * KiB)
14 /* Prototype of memmove() from string.h was changed to cb_memmove().
15 It has to be defined again. */
16 void *memmove(void *dst
, const void *src
, size_t n
);
18 struct test_memmove_data
{
24 int setup_test(void **state
)
26 struct test_memmove_data
*s
= malloc(sizeof(struct test_memmove_data
));
31 s
->buffer_from
= malloc(MEMMOVE_BUFFER_SZ
);
32 s
->buffer_to
= malloc(MEMMOVE_BUFFER_SZ
);
33 s
->helper_buffer
= malloc(MEMMOVE_BUFFER_SZ
);
35 if (!s
->buffer_from
|| !s
->buffer_to
|| !s
->helper_buffer
) {
38 free(s
->helper_buffer
);
43 /* Fill buffers with different values (other than zero) to make them distinguishable.
44 The helper buffer is often used as a backup of destination buffer so it has the
46 memset(s
->buffer_from
, 0xAB, MEMMOVE_BUFFER_SZ
);
47 memset(s
->buffer_to
, 0xBC, MEMMOVE_BUFFER_SZ
);
48 memset(s
->helper_buffer
, 0xBC, MEMMOVE_BUFFER_SZ
);
55 int teardown_test(void **state
)
57 struct test_memmove_data
*s
= *state
;
61 free(s
->helper_buffer
);
67 /* Fill buffer with values from provided range [start; end] in circular way. */
68 static void fill_buffer_data_range(u8
*buffer
, size_t sz
, u8 start_value
, u8 end_value
)
70 for (size_t i
= 0; i
< sz
; ++i
)
71 buffer
[i
] = (start_value
+ i
) % (end_value
- start_value
+ 1);
74 static void test_memmove_full_buffer_copy(void **state
)
76 struct test_memmove_data
*s
= *state
;
79 fill_buffer_data_range(s
->buffer_from
, MEMMOVE_BUFFER_SZ
, 0, 255);
81 res_cb
= cb_memmove(s
->buffer_to
, s
->buffer_from
, MEMMOVE_BUFFER_SZ
);
83 assert_ptr_equal(s
->buffer_to
, res_cb
);
84 assert_memory_equal(s
->buffer_from
, s
->buffer_to
, MEMMOVE_BUFFER_SZ
);
87 static void test_memmove_zero_size(void **state
)
89 struct test_memmove_data
*s
= *state
;
92 fill_buffer_data_range(s
->buffer_from
, MEMMOVE_BUFFER_SZ
, 'A', 'Z');
94 /* Expect no change in destination buffer. */
95 res_cb
= cb_memmove(s
->buffer_to
, s
->buffer_from
, 0);
96 assert_ptr_equal(res_cb
, s
->buffer_to
);
97 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, MEMMOVE_BUFFER_SZ
);
100 static void test_memmove_buffer_part(void **state
)
102 struct test_memmove_data
*s
= *state
;
104 const size_t offset
= MEMMOVE_BUFFER_SZ
/ 4;
105 const size_t sz
= MEMMOVE_BUFFER_SZ
/ 3;
107 /* Self-test for correct data ranges */
108 assert_true(offset
+ sz
<= MEMMOVE_BUFFER_SZ
);
110 fill_buffer_data_range(s
->buffer_from
, MEMMOVE_BUFFER_SZ
, '0', '9');
112 /* Expect only *sz* bytes of buffer to be copied. Helper buffer is used as template. */
113 res_cb
= cb_memmove(s
->buffer_to
+ offset
, s
->buffer_from
, sz
);
114 assert_ptr_equal(s
->buffer_to
+ offset
, res_cb
);
115 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, offset
);
116 assert_memory_equal(s
->buffer_to
+ offset
, s
->buffer_from
, sz
);
117 assert_memory_equal(s
->buffer_to
+ offset
+ sz
, s
->helper_buffer
+ offset
+ sz
,
118 MEMMOVE_BUFFER_SZ
- (offset
+ sz
));
121 static void test_memmove_buffer_part_unaligned(void **state
)
123 struct test_memmove_data
*s
= *state
;
125 const size_t dst_offset
= MEMMOVE_BUFFER_SZ
/ 8 + 3;
126 const size_t src_offset
= MEMMOVE_BUFFER_SZ
/ 4 - 3;
127 const size_t sz
= MEMMOVE_BUFFER_SZ
/ 4 + 7;
129 /* Self-test for correct data ranges */
130 assert_true(dst_offset
+ sz
<= MEMMOVE_BUFFER_SZ
);
131 assert_true(src_offset
+ sz
<= MEMMOVE_BUFFER_SZ
);
133 fill_buffer_data_range(s
->buffer_from
, MEMMOVE_BUFFER_SZ
, 0x13, 0xB7);
135 res_cb
= cb_memmove(s
->buffer_to
+ dst_offset
, s
->buffer_from
+ src_offset
, sz
);
136 assert_ptr_equal(s
->buffer_to
+ dst_offset
, res_cb
);
137 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, dst_offset
);
138 assert_memory_equal(s
->buffer_to
+ dst_offset
, s
->buffer_from
+ src_offset
, sz
);
139 assert_memory_equal(s
->buffer_to
+ dst_offset
+ sz
, s
->helper_buffer
+ dst_offset
+ sz
,
140 MEMMOVE_BUFFER_SZ
- (dst_offset
+ sz
));
143 static void test_memmove_copy_to_itself(void **state
)
145 struct test_memmove_data
*s
= *state
;
148 fill_buffer_data_range(s
->buffer_to
, MEMMOVE_BUFFER_SZ
, 'G', 'X');
149 memmove(s
->buffer_to
, s
->helper_buffer
, MEMMOVE_BUFFER_SZ
);
151 /* Expect no change in source/destination buffer. */
152 res_cb
= cb_memmove(s
->buffer_to
, s
->buffer_to
, MEMMOVE_BUFFER_SZ
);
153 assert_ptr_equal(res_cb
, s
->buffer_to
);
154 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, MEMMOVE_BUFFER_SZ
);
157 static void test_memmove_self_higher_to_lower(void **state
)
159 struct test_memmove_data
*s
= *state
;
161 const size_t offset
= MEMMOVE_BUFFER_SZ
/ 8;
162 const size_t sz
= MEMMOVE_BUFFER_SZ
- offset
;
164 fill_buffer_data_range(s
->buffer_to
, MEMMOVE_BUFFER_SZ
, 'd', 'v');
165 memmove(s
->helper_buffer
, s
->buffer_to
, MEMMOVE_BUFFER_SZ
);
167 /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
168 res_cb
= cb_memmove(s
->buffer_to
, s
->buffer_to
+ offset
, sz
);
169 assert_ptr_equal(res_cb
, s
->buffer_to
);
170 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
+ offset
, sz
);
171 assert_memory_equal(s
->buffer_to
+ sz
, s
->helper_buffer
+ sz
, offset
);
174 static void test_memmove_self_higher_to_lower_unaligned(void **state
)
176 struct test_memmove_data
*s
= *state
;
178 const size_t offset
= MEMMOVE_BUFFER_SZ
/ 6 + 7;
179 const size_t sz
= MEMMOVE_BUFFER_SZ
- offset
;
181 fill_buffer_data_range(s
->buffer_to
, MEMMOVE_BUFFER_SZ
, 'd', 'v');
182 memmove(s
->helper_buffer
, s
->buffer_to
, MEMMOVE_BUFFER_SZ
);
184 /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
185 res_cb
= cb_memmove(s
->buffer_to
, s
->buffer_to
+ offset
, sz
);
186 assert_ptr_equal(res_cb
, s
->buffer_to
);
187 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
+ offset
, sz
);
188 assert_memory_equal(s
->buffer_to
+ sz
, s
->helper_buffer
+ sz
, offset
);
191 static void test_memmove_self_lower_to_higher(void **state
)
193 struct test_memmove_data
*s
= *state
;
195 const size_t offset
= MEMMOVE_BUFFER_SZ
/ 4;
196 const size_t sz
= MEMMOVE_BUFFER_SZ
- offset
;
198 fill_buffer_data_range(s
->buffer_to
, MEMMOVE_BUFFER_SZ
, 'd', 'v');
199 memmove(s
->helper_buffer
, s
->buffer_to
, MEMMOVE_BUFFER_SZ
);
201 /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
202 res_cb
= cb_memmove(s
->buffer_to
+ offset
, s
->buffer_to
, sz
);
203 assert_ptr_equal(res_cb
, s
->buffer_to
+ offset
);
204 assert_memory_equal(s
->buffer_to
+ offset
, s
->helper_buffer
, sz
);
205 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, offset
);
208 static void test_memmove_self_lower_to_higher_unaligned(void **state
)
210 struct test_memmove_data
*s
= *state
;
212 const size_t offset
= MEMMOVE_BUFFER_SZ
/ 4 - 17;
213 const size_t sz
= MEMMOVE_BUFFER_SZ
- offset
;
215 fill_buffer_data_range(s
->buffer_to
, MEMMOVE_BUFFER_SZ
, 'd', 'v');
216 memmove(s
->helper_buffer
, s
->buffer_to
, MEMMOVE_BUFFER_SZ
);
218 /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
219 res_cb
= cb_memmove(s
->buffer_to
+ offset
, s
->buffer_to
, sz
);
220 assert_ptr_equal(res_cb
, s
->buffer_to
+ offset
);
221 assert_memory_equal(s
->buffer_to
+ offset
, s
->helper_buffer
, sz
);
222 assert_memory_equal(s
->buffer_to
, s
->helper_buffer
, offset
);
227 const struct CMUnitTest tests
[] = {
228 cmocka_unit_test_setup_teardown(test_memmove_full_buffer_copy
, setup_test
,
230 cmocka_unit_test_setup_teardown(test_memmove_zero_size
, setup_test
,
232 cmocka_unit_test_setup_teardown(test_memmove_buffer_part
, setup_test
,
234 cmocka_unit_test_setup_teardown(test_memmove_buffer_part_unaligned
, setup_test
,
236 cmocka_unit_test_setup_teardown(test_memmove_copy_to_itself
, setup_test
,
238 cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower
, setup_test
,
240 cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower_unaligned
,
241 setup_test
, teardown_test
),
242 cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher
, setup_test
,
244 cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher_unaligned
,
245 setup_test
, teardown_test
),
248 return cb_run_group_tests(tests
, NULL
, NULL
);