blob: 3854dd65acab9322963a98771035b27e19bf077e [file] [log] [blame]
Jakub Czapigaf5e636c2021-02-19 10:09:42 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#define memmove cb_memmove
4#include "../lib/memmove.c"
5#undef memmove
6
7#include <stdlib.h>
8#include <tests/test.h>
9#include <commonlib/helpers.h>
10#include <types.h>
11
12#define MEMMOVE_BUFFER_SZ (4 * KiB)
13
14/* Prototype of memmove() from string.h was changed to cb_memmove().
15 It has to be defined again. */
16void *memmove(void *dst, const void *src, size_t n);
17
18struct test_memmove_data {
19 u8 *buffer_from;
20 u8 *buffer_to;
21 u8 *helper_buffer;
22};
23
24int setup_test(void **state)
25{
26 struct test_memmove_data *s = malloc(sizeof(struct test_memmove_data));
27
28 if (!s)
29 return -1;
30
31 s->buffer_from = malloc(MEMMOVE_BUFFER_SZ);
32 s->buffer_to = malloc(MEMMOVE_BUFFER_SZ);
33 s->helper_buffer = malloc(MEMMOVE_BUFFER_SZ);
34
35 if (!s->buffer_from || !s->buffer_to || !s->helper_buffer) {
36 free(s->buffer_from);
37 free(s->buffer_to);
38 free(s->helper_buffer);
39 free(s);
40 return -1;
41 }
42
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
45 same value. */
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);
49
50 *state = s;
51
52 return 0;
53}
54
55int teardown_test(void **state)
56{
57 struct test_memmove_data *s = *state;
58
59 free(s->buffer_from);
60 free(s->buffer_to);
61 free(s->helper_buffer);
62 free(s);
63
64 return 0;
65}
66
67/* Fill buffer with values from provided range [start; end] in circular way. */
68static void fill_buffer_data_range(u8 *buffer, size_t sz, u8 start_value, u8 end_value)
69{
70 for (size_t i = 0; i < sz; ++i)
71 buffer[i] = (start_value + i) % (end_value - start_value + 1);
72}
73
74static void test_memmove_full_buffer_copy(void **state)
75{
76 struct test_memmove_data *s = *state;
77 void *res_cb;
78
79 fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 0, 255);
80
81 res_cb = cb_memmove(s->buffer_to, s->buffer_from, MEMMOVE_BUFFER_SZ);
82
83 assert_ptr_equal(s->buffer_to, res_cb);
84 assert_memory_equal(s->buffer_from, s->buffer_to, MEMMOVE_BUFFER_SZ);
85}
86
87static void test_memmove_zero_size(void **state)
88{
89 struct test_memmove_data *s = *state;
90 void *res_cb;
91
92 fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 'A', 'Z');
93
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);
98}
99
100static void test_memmove_buffer_part(void **state)
101{
102 struct test_memmove_data *s = *state;
103 void *res_cb;
104 const size_t offset = MEMMOVE_BUFFER_SZ / 4;
105 const size_t sz = MEMMOVE_BUFFER_SZ / 3;
106
107 /* Self-test for correct data ranges */
108 assert_true(offset + sz <= MEMMOVE_BUFFER_SZ);
109
110 fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, '0', '9');
111
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,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000118 MEMMOVE_BUFFER_SZ - (offset + sz));
Jakub Czapigaf5e636c2021-02-19 10:09:42 +0100119}
120
121static void test_memmove_buffer_part_unaligned(void **state)
122{
123 struct test_memmove_data *s = *state;
124 void *res_cb;
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;
128
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);
132
133 fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 0x13, 0xB7);
134
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,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000140 MEMMOVE_BUFFER_SZ - (dst_offset + sz));
Jakub Czapigaf5e636c2021-02-19 10:09:42 +0100141}
142
143static void test_memmove_copy_to_itself(void **state)
144{
145 struct test_memmove_data *s = *state;
146 void *res_cb;
147
148 fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'G', 'X');
149 memmove(s->buffer_to, s->helper_buffer, MEMMOVE_BUFFER_SZ);
150
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);
155}
156
157static void test_memmove_self_higher_to_lower(void **state)
158{
159 struct test_memmove_data *s = *state;
160 void *res_cb;
161 const size_t offset = MEMMOVE_BUFFER_SZ / 8;
162 const size_t sz = MEMMOVE_BUFFER_SZ - offset;
163
164 fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
165 memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
166
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);
172}
173
174static void test_memmove_self_higher_to_lower_unaligned(void **state)
175{
176 struct test_memmove_data *s = *state;
177 void *res_cb;
178 const size_t offset = MEMMOVE_BUFFER_SZ / 6 + 7;
179 const size_t sz = MEMMOVE_BUFFER_SZ - offset;
180
181 fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
182 memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
183
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);
189}
190
191static void test_memmove_self_lower_to_higher(void **state)
192{
193 struct test_memmove_data *s = *state;
194 void *res_cb;
195 const size_t offset = MEMMOVE_BUFFER_SZ / 4;
196 const size_t sz = MEMMOVE_BUFFER_SZ - offset;
197
198 fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
199 memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
200
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);
206}
207
208static void test_memmove_self_lower_to_higher_unaligned(void **state)
209{
210 struct test_memmove_data *s = *state;
211 void *res_cb;
212 const size_t offset = MEMMOVE_BUFFER_SZ / 4 - 17;
213 const size_t sz = MEMMOVE_BUFFER_SZ - offset;
214
215 fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
216 memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
217
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);
223}
224
225int main(void)
226{
227 const struct CMUnitTest tests[] = {
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000228 cmocka_unit_test_setup_teardown(test_memmove_full_buffer_copy, setup_test,
229 teardown_test),
230 cmocka_unit_test_setup_teardown(test_memmove_zero_size, setup_test,
231 teardown_test),
232 cmocka_unit_test_setup_teardown(test_memmove_buffer_part, setup_test,
233 teardown_test),
234 cmocka_unit_test_setup_teardown(test_memmove_buffer_part_unaligned, setup_test,
235 teardown_test),
236 cmocka_unit_test_setup_teardown(test_memmove_copy_to_itself, setup_test,
237 teardown_test),
238 cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower, setup_test,
239 teardown_test),
Jakub Czapigaf5e636c2021-02-19 10:09:42 +0100240 cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower_unaligned,
241 setup_test, teardown_test),
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000242 cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher, setup_test,
243 teardown_test),
Jakub Czapigaf5e636c2021-02-19 10:09:42 +0100244 cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher_unaligned,
245 setup_test, teardown_test),
246 };
247
Jakub Czapiga7c6081e2021-08-25 16:27:35 +0200248 return cb_run_group_tests(tests, NULL, NULL);
Jakub Czapigaf5e636c2021-02-19 10:09:42 +0100249}