1 /**********************************************************************
2 Copyright(c) 2011-2015 Intel Corporation All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29
30 #include <stdio.h>
31 #include <stdint.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include "raid.h"
35 #include "test.h"
36
37 #define TEST_SOURCES 16
38 #define TEST_LEN 1024
39 #define TEST_MEM ((TEST_SOURCES + 2) * (TEST_LEN))
40 #ifndef TEST_SEED
41 #define TEST_SEED 0x1234
42 #endif
43
44 int
ref_multi_pq(int vects,int len,void ** array)45 ref_multi_pq(int vects, int len, void **array)
46 {
47 int i, j;
48 unsigned char p, q, s;
49 unsigned char **src = (unsigned char **) array;
50
51 for (i = 0; i < len; i++) {
52 q = p = src[vects - 3][i];
53
54 for (j = vects - 4; j >= 0; j--) {
55 p ^= s = src[j][i];
56 q = s ^ ((q << 1) ^ ((q & 0x80) ? 0x1d : 0)); // mult by GF{2}
57 }
58
59 src[vects - 2][i] = p; // second to last pointer is p
60 src[vects - 1][i] = q; // last pointer is q
61 }
62 return 0;
63 }
64
65 // Generates pseudo-random data
66
67 void
rand_buffer(unsigned char * buf,long buffer_size)68 rand_buffer(unsigned char *buf, long buffer_size)
69 {
70 long i;
71 for (i = 0; i < buffer_size; i++)
72 buf[i] = rand();
73 }
74
75 int
main(int argc,char * argv[])76 main(int argc, char *argv[])
77 {
78 int i, j, k, ret, fail = 0;
79 void *buffs[TEST_SOURCES + 2] = { NULL };
80 char c;
81 char *tmp_buf[TEST_SOURCES + 2] = { NULL };
82 int serr, lerr;
83
84 printf("Test pq_check_test %d sources X %d bytes\n", TEST_SOURCES, TEST_LEN);
85
86 srand(TEST_SEED);
87
88 // Allocate the arrays
89 for (i = 0; i < TEST_SOURCES + 2; i++) {
90 void *buf;
91 if (posix_memalign(&buf, 16, TEST_LEN)) {
92 printf("alloc error: Fail");
93 return 1;
94 }
95 buffs[i] = buf;
96 }
97
98 // Test of all zeros
99 for (i = 0; i < TEST_SOURCES + 2; i++)
100 memset(buffs[i], 0, TEST_LEN);
101
102 ref_multi_pq(TEST_SOURCES + 2, TEST_LEN, buffs);
103 ret = pq_check(TEST_SOURCES + 2, TEST_LEN, buffs);
104 if (ret != 0) {
105 fail++;
106 printf("\nfail zero test %d\n", ret);
107 }
108
109 ((char *) (buffs[0]))[TEST_LEN - 2] = 0x7; // corrupt buffer
110 ret = pq_check(TEST_SOURCES + 2, TEST_LEN, buffs);
111 if (ret == 0) {
112 fail++;
113 printf("\nfail corrupt buffer test %d\n", ret);
114 }
115 ((char *) (buffs[0]))[TEST_LEN - 2] = 0; // un-corrupt buffer
116
117 // Test corrupted buffer any location on all sources
118 for (j = 0; j < TEST_SOURCES + 2; j++) {
119 for (i = TEST_LEN - 1; i >= 0; i--) {
120 ((char *) buffs[j])[i] = 0x5; // corrupt buffer
121 ret = pq_check(TEST_SOURCES + 2, TEST_LEN, buffs);
122 if (ret == 0) {
123 fail++;
124 printf("\nfail corrupt zero buffer test j=%d, i=%d\n", j, i);
125 goto exit;
126 }
127 ((char *) buffs[j])[i] = 0; // un-corrupt buffer
128 }
129 #ifdef TEST_VERBOSE
130 putchar('.');
131 #endif
132 }
133
134 // Test rand1
135 for (i = 0; i < TEST_SOURCES + 2; i++)
136 rand_buffer(buffs[i], TEST_LEN);
137
138 ref_multi_pq(TEST_SOURCES + 2, TEST_LEN, buffs);
139 ret = pq_check(TEST_SOURCES + 2, TEST_LEN, buffs);
140 if (ret != 0) {
141 fail++;
142 printf("fail first rand test %d\n", ret);
143 }
144
145 c = ((char *) (buffs[0]))[TEST_LEN - 2];
146 ((char *) (buffs[0]))[TEST_LEN - 2] = c ^ 0x1;
147 ret = pq_check(TEST_SOURCES + 2, TEST_LEN, buffs);
148 if (ret == 0) {
149 fail++;
150 printf("\nFail corrupt buffer test, passed when should have failed\n");
151 }
152 ((char *) (buffs[0]))[TEST_LEN - 2] = c; // un-corrupt buffer
153
154 // Test corrupted buffer any location on all sources w/ random data
155 for (j = 0; j < TEST_SOURCES + 2; j++) {
156 for (i = TEST_LEN - 1; i >= 0; i--) {
157 // Check it still passes
158 ret = pq_check(TEST_SOURCES + 2, TEST_LEN, buffs);
159 if (ret != 0) { // should pass
160 fail++;
161 printf("\nFail rand test with un-corrupted buffer j=%d, i=%d\n", j,
162 i);
163 goto exit;
164 }
165 c = ((char *) buffs[j])[i];
166 ((char *) buffs[j])[i] = c ^ 1; // corrupt buffer
167 ret = pq_check(TEST_SOURCES + 2, TEST_LEN, buffs);
168 if (ret == 0) { // Check it now fails
169 fail++;
170 printf("\nfail corrupt buffer test j=%d, i=%d\n", j, i);
171 goto exit;
172 }
173 ((char *) buffs[j])[i] = c; // un-corrupt buffer
174 }
175 #ifdef TEST_VERBOSE
176 putchar('.');
177 #endif
178 }
179
180 // Test various number of sources, full length
181 for (j = 4; j <= TEST_SOURCES + 2; j++) {
182 // New random data
183 for (i = 0; i < j; i++)
184 rand_buffer(buffs[i], TEST_LEN);
185
186 // Generate p,q parity for this number of sources
187 ref_multi_pq(j, TEST_LEN, buffs);
188
189 // Set errors up in each source and len position
190 for (i = 0; i < j; i++) {
191 for (k = 0; k < TEST_LEN; k++) {
192 // See if it still passes
193 ret = pq_check(j, TEST_LEN, buffs);
194 if (ret != 0) { // Should pass
195 printf("\nfail rand fixed len test %d sources\n", j);
196 fail++;
197 goto exit;
198 }
199
200 c = ((char *) buffs[i])[k];
201 ((char *) buffs[i])[k] = c ^ 1; // corrupt buffer
202
203 ret = pq_check(j, TEST_LEN, buffs);
204 if (ret == 0) { // Should fail
205 printf("\nfail rand fixed len test corrupted buffer %d "
206 "sources\n",
207 j);
208 fail++;
209 goto exit;
210 }
211 ((char *) buffs[i])[k] = c; // un-corrupt buffer
212 }
213 }
214 #ifdef TEST_VERBOSE
215 putchar('.');
216 #endif
217 }
218
219 fflush(0);
220
221 // Test various number of sources and len
222 k = 16;
223 while (k <= TEST_LEN) {
224 char *tmp;
225 for (j = 4; j <= TEST_SOURCES + 2; j++) {
226 for (i = 0; i < j; i++)
227 rand_buffer(buffs[i], k);
228
229 // Generate p,q parity for this number of sources
230 ref_multi_pq(j, k, buffs);
231
232 // Inject errors at various source and len positions
233 for (lerr = 0; lerr < k; lerr++) {
234 for (serr = 0; serr < j; serr++) {
235 // See if it still passes
236 ret = pq_check(j, k, buffs);
237 if (ret != 0) { // Should pass
238 printf("\nfail rand var src, len test %d sources, "
239 "len=%d\n",
240 j, k);
241 fail++;
242 goto exit;
243 }
244
245 tmp = (char *) buffs[serr];
246 c = tmp[lerr];
247 ((char *) buffs[serr])[lerr] = c ^ 1; // corrupt buffer
248
249 ret = pq_check(j, k, buffs);
250 if (ret == 0) { // Should fail
251 printf("\nfail rand var src, len test corrupted "
252 "buffer "
253 "%d sources, len=%d, ret=%d\n",
254 j, k, ret);
255 fail++;
256 goto exit;
257 }
258 ((char *) buffs[serr])[lerr] = c; // un-corrupt buffer
259 }
260 }
261 #ifdef TEST_VERBOSE
262 putchar('.');
263 #endif
264 fflush(0);
265 }
266 k += 16;
267 }
268
269 // Test at the end of buffer
270 for (i = 0; i < TEST_LEN; i += 16) {
271 for (j = 0; j < TEST_SOURCES + 2; j++) {
272 rand_buffer(buffs[j], TEST_LEN - i);
273 tmp_buf[j] = (char *) buffs[j] + i;
274 }
275
276 pq_gen_base(TEST_SOURCES + 2, TEST_LEN - i, (void *) tmp_buf);
277
278 // Test good data
279 ret = pq_check(TEST_SOURCES + 2, TEST_LEN - i, (void *) tmp_buf);
280 if (ret != 0) {
281 printf("fail end test - offset: %d, len: %d\n", i, TEST_LEN - i);
282 fail++;
283 return 1;
284 }
285 // Test bad data
286 for (serr = 0; serr < TEST_SOURCES + 2; serr++) {
287 for (lerr = 0; lerr < (TEST_LEN - i); lerr++) {
288 c = tmp_buf[serr][lerr];
289 tmp_buf[serr][lerr] = c ^ 1;
290
291 ret = pq_check(TEST_SOURCES + 2, TEST_LEN - i, (void *) tmp_buf);
292 if (ret == 0) {
293 printf("fail end test corrupted buffer - "
294 "offset: %d, len: %d, ret: %d\n",
295 i, TEST_LEN - i, ret);
296 fail++;
297 goto exit;
298 }
299
300 tmp_buf[serr][lerr] = c;
301 }
302 }
303
304 #ifdef TEST_VERBOSE
305 putchar('.');
306 #endif
307 fflush(0);
308 }
309
310 if (fail == 0)
311 printf("Pass\n");
312
313 exit:
314 for (i = 0; i < TEST_SOURCES + 2; i++)
315 aligned_free(buffs[i]);
316 return fail;
317 }
318