xref: /isa-l/raid/pq_check_test.c (revision ae951677ab3f79d379a9da251b5a1245e7b76aca)
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