blob: 98303a49aa9060d2cb96d3cae80896caddfed84e [file] [log] [blame]
Jakub Czapigaeb4bb6f2021-02-16 13:27:17 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
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"
6#undef memcpy
7
8#include <stdlib.h>
9#include <tests/test.h>
10#include <commonlib/helpers.h>
11#include <types.h>
12
13#define MEMCPY_BUFFER_SZ (4 * KiB)
14
15/* Prototype of memcpy() from string.h was changed to cb_memcpy().
16 It has to be defined again. */
17void *memcpy(void *dest, const void *src, size_t n);
18
19struct test_memcpy_data {
20 u8 *buffer_from;
21 u8 *buffer_to;
22 u8 *helper_buffer;
23};
24
25int setup_test(void **state)
26{
27 struct test_memcpy_data *s = malloc(sizeof(struct test_memcpy_data));
28
29 if (!s)
30 return -1;
31
32 s->buffer_from = malloc(MEMCPY_BUFFER_SZ);
33 s->buffer_to = malloc(MEMCPY_BUFFER_SZ);
34 s->helper_buffer = malloc(MEMCPY_BUFFER_SZ);
35
36 if (!s->buffer_from || !s->buffer_to || !s->helper_buffer) {
37 free(s->buffer_from);
38 free(s->buffer_to);
39 free(s->helper_buffer);
40 free(s);
41 return -1;
42 }
43
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
46 same value. */
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);
50
51 *state = s;
52
53 return 0;
54}
55
56int teardown_test(void **state)
57{
58 struct test_memcpy_data *s = *state;
59
60 free(s->buffer_from);
61 free(s->buffer_to);
62 free(s->helper_buffer);
63 free(s);
64
65 return 0;
66}
67
68/* Fill buffer with values from provided range [start; end] in circular way. */
69static void fill_buffer_data_range(u8 *buffer, size_t sz, u8 start_value, u8 end_value)
70{
71 for (size_t i = 0; i < sz; ++i)
72 buffer[i] = (start_value + i) % (end_value - start_value + 1);
73}
74
75static void test_memcpy_full_buffer_copy(void **state)
76{
77 struct test_memcpy_data *s = *state;
78 void *res_cb;
79
80 fill_buffer_data_range(s->buffer_from, MEMCPY_BUFFER_SZ, 0, 255);
81
82 res_cb = cb_memcpy(s->buffer_to, s->buffer_from, MEMCPY_BUFFER_SZ);
83
84 assert_ptr_equal(s->buffer_to, res_cb);
85 assert_memory_equal(s->buffer_from, s->buffer_to, MEMCPY_BUFFER_SZ);
86}
87
88static void test_memcpy_zero_size(void **state)
89{
90 struct test_memcpy_data *s = *state;
91 void *res_cb;
92
93 fill_buffer_data_range(s->buffer_from, MEMCPY_BUFFER_SZ, 'A', 'Z');
94
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);
99}
100
101static void test_memcpy_buffer_part(void **state)
102{
103 struct test_memcpy_data *s = *state;
104 void *res_cb;
105 const size_t offset = MEMCPY_BUFFER_SZ / 4;
106 const size_t sz = MEMCPY_BUFFER_SZ / 2;
107
108 /* Self-test for correct data ranges */
109 assert_true(offset + sz <= MEMCPY_BUFFER_SZ);
110
111 fill_buffer_data_range(s->buffer_from, MEMCPY_BUFFER_SZ, '0', '9');
112
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,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000119 MEMCPY_BUFFER_SZ - (offset + sz));
Jakub Czapigaeb4bb6f2021-02-16 13:27:17 +0100120}
121
122static void test_memcpy_buffer_part_unaligned(void **state)
123{
124 struct test_memcpy_data *s = *state;
125 void *res_cb;
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;
129
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);
133
134 fill_buffer_data_range(s->buffer_from, MEMCPY_BUFFER_SZ, 0x13, 0xB7);
135
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,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000141 MEMCPY_BUFFER_SZ - (dst_offset + sz));
Jakub Czapigaeb4bb6f2021-02-16 13:27:17 +0100142}
143
144static void test_memcpy_copy_to_itself(void **state)
145{
146 struct test_memcpy_data *s = *state;
147 void *res_cb;
148
149 fill_buffer_data_range(s->buffer_to, MEMCPY_BUFFER_SZ, 'G', 'X');
150 memcpy(s->buffer_to, s->helper_buffer, MEMCPY_BUFFER_SZ);
151
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);
156}
157
158static void test_memcpy_copy_part_of_itself_to_itself(void **state)
159{
160 struct test_memcpy_data *s = *state;
161 void *res_cb;
162 const size_t offset = MEMCPY_BUFFER_SZ / 8;
163 const size_t sz = MEMCPY_BUFFER_SZ - offset;
164
165 /* Self-test for correct data ranges */
166 assert_true(offset + sz <= MEMCPY_BUFFER_SZ);
167
168 fill_buffer_data_range(s->buffer_to, MEMCPY_BUFFER_SZ, 'd', 'v');
169 memcpy(s->helper_buffer, s->buffer_to, MEMCPY_BUFFER_SZ);
170
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);
176}
177
178int main(void)
179{
180 const struct CMUnitTest tests[] = {
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000181 cmocka_unit_test_setup_teardown(test_memcpy_full_buffer_copy, setup_test,
182 teardown_test),
183 cmocka_unit_test_setup_teardown(test_memcpy_zero_size, setup_test,
184 teardown_test),
185 cmocka_unit_test_setup_teardown(test_memcpy_buffer_part, setup_test,
186 teardown_test),
187 cmocka_unit_test_setup_teardown(test_memcpy_buffer_part_unaligned, setup_test,
188 teardown_test),
189 cmocka_unit_test_setup_teardown(test_memcpy_copy_to_itself, setup_test,
190 teardown_test),
Jakub Czapigaeb4bb6f2021-02-16 13:27:17 +0100191 cmocka_unit_test_setup_teardown(test_memcpy_copy_part_of_itself_to_itself,
192 setup_test, teardown_test),
193 };
194
Jakub Czapiga7c6081e2021-08-25 16:27:35 +0200195 return cb_run_group_tests(tests, NULL, NULL);
Jakub Czapigaeb4bb6f2021-02-16 13:27:17 +0100196}