Unit tests for crypto/stack.
[openssl.git] / test / stack_test.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /* ====================================================================
11  * Copyright (c) 2017 Oracle and/or its affiliates.  All rights reserved.
12  */
13
14 #include <stdio.h>
15 #include <string.h>
16
17 #include <openssl/opensslconf.h>
18 #include <openssl/safestack.h>
19 #include <openssl/err.h>
20 #include <openssl/crypto.h>
21
22 #include "e_os.h"
23 #include "test_main.h"
24 #include "testutil.h"
25
26 /* The macros below generate unused functions which error out one of the clang
27  * builds.  We disable this check here.
28  */
29 #ifdef __clang__
30 #pragma clang diagnostic ignored "-Wunused-function"
31 #endif
32
33 typedef struct {
34     int n;
35     char c;
36 } SS;
37
38 typedef union {
39     int n;
40     char c;
41 } SU;
42
43 DEFINE_SPECIAL_STACK_OF(sint, int)
44 DEFINE_SPECIAL_STACK_OF_CONST(uchar, unsigned char)
45 DEFINE_STACK_OF(SS)
46 DEFINE_STACK_OF_CONST(SU)
47
48 static int int_compare(const int *const *a, const int *const *b)
49 {
50     if (**a < **b)
51         return -1;
52     if (**a > **b)
53         return 1;
54     return 0;
55 }
56
57 static int test_int_stack(void)
58 {
59     static int v[] = { 1, 2, -4, 16, 999, 1, -173, 1, 9 };
60     const int n = OSSL_NELEM(v);
61     static struct {
62         int value;
63         int unsorted;
64         int sorted;
65         int ex;
66     } finds[] = {
67         { 2,    1,  5,  5   },
68         { 9,    7,  6,  6   },
69         { -173, 5,  0,  0   },
70         { 999,  3,  8,  8   },
71         { 0,   -1, -1,  1   }
72     };
73     const int n_finds = OSSL_NELEM(finds);
74     static struct {
75         int value;
76         int ex;
77     } exfinds[] = {
78         { 3,    5   },
79         { 1000, 8   },
80         { 20,   8   },
81         { -999, 0   },
82         { -5,   0   },
83         { 8,    5   }
84     };
85     const int n_exfinds = OSSL_NELEM(exfinds);
86     STACK_OF(sint) *s = sk_sint_new_null();
87     int i;
88     int testresult = 0;
89
90     /* Check push and num */
91     for (i = 0; i < n; i++) {
92         if (sk_sint_num(s) != i) {
93             fprintf(stderr, "test int stack size %d\n", i);
94             goto end;
95         }
96         sk_sint_push(s, v + i);
97     }
98     if (sk_sint_num(s) != n) {
99         fprintf(stderr, "test int stack size %d\n", n);
100         goto end;
101     }
102
103     /* check the values */
104     for (i = 0; i < n; i++)
105         if (sk_sint_value(s, i) != v + i) {
106             fprintf(stderr, "test int value %d\n", i);
107             goto end;
108         }
109
110     /* find unsorted -- the pointers are compared */
111     for (i = 0; i < n_finds; i++)
112         if (sk_sint_find(s, v + finds[i].unsorted) != finds[i].unsorted) {
113             fprintf(stderr, "test int unsorted find %d\n", i);
114             goto end;
115         }
116
117     /* find_ex unsorted */
118     for (i = 0; i < n_finds; i++)
119         if (sk_sint_find_ex(s, v + finds[i].unsorted) != finds[i].unsorted) {
120             fprintf(stderr, "test int unsorted find_ex %d\n", i);
121             goto end;
122         }
123
124     /* sorting */
125     if (sk_sint_is_sorted(s)) {
126         fprintf(stderr, "test int unsorted\n");
127         goto end;
128     }
129     sk_sint_set_cmp_func(s, &int_compare);
130     sk_sint_sort(s);
131     if (!sk_sint_is_sorted(s)) {
132         fprintf(stderr, "test int sorted\n");
133         goto end;
134     }
135
136     /* find sorted -- the value is matched so we don't need to locate it */
137     for (i = 0; i < n_finds; i++)
138         if (sk_sint_find(s, &finds[i].value) != finds[i].sorted) {
139             fprintf(stderr, "test int sorted find %d\n", i);
140             goto end;
141         }
142
143     /* find_ex sorted */
144     for (i = 0; i < n_finds; i++)
145         if (sk_sint_find_ex(s, &finds[i].value) != finds[i].ex) {
146             fprintf(stderr, "test int sorted find_ex present %d\n", i);
147             goto end;
148         }
149     for (i = 0; i < n_exfinds; i++)
150         if (sk_sint_find_ex(s, &exfinds[i].value) != exfinds[i].ex) {
151             fprintf(stderr, "test int sorted find_ex absent %d\n", i);
152             goto end;
153         }
154
155     /* shift */
156     if (sk_sint_shift(s) != v + 6) {
157         fprintf(stderr, "test int shift\n");
158         goto end;
159     }
160
161     testresult = 1;
162 end:
163     sk_sint_free(s);
164     return testresult;
165 }
166
167 static int uchar_compare(const unsigned char *const *a,
168                          const unsigned char *const *b)
169 {
170     return **a - (signed int)**b;
171 }
172
173 static int test_uchar_stack(void)
174 {
175     static const unsigned char v[] = { 1, 3, 7, 5, 255, 0 };
176     const int n = OSSL_NELEM(v);
177     STACK_OF(uchar) *s = sk_uchar_new(&uchar_compare), *r = NULL;
178     int i;
179     int testresult = 0;
180
181     /* unshift and num */
182     for (i = 0; i < n; i++) {
183         if (sk_uchar_num(s) != i) {
184             fprintf(stderr, "test uchar stack size %d\n", i);
185             goto end;
186         }
187         sk_uchar_unshift(s, v + i);
188     }
189     if (sk_uchar_num(s) != n) {
190         fprintf(stderr, "test uchar stack size %d\n", n);
191         goto end;
192     }
193
194     /* dup */
195     r = sk_uchar_dup(s);
196     if (sk_uchar_num(r) != n) {
197         fprintf(stderr, "test uchar dup size %d\n", n);
198         goto end;
199     }
200     sk_uchar_sort(r);
201
202     /* pop */
203     for (i = 0; i < n; i++) 
204         if (sk_uchar_pop(s) != v + i) {
205             fprintf(stderr, "test uchar pop %d\n", i);
206             goto end;
207         }
208
209     /* free -- we rely on the debug malloc to detect leakage here */
210     sk_uchar_free(s);
211     s = NULL;
212
213     /* dup again */
214     if (sk_uchar_num(r) != n) {
215         fprintf(stderr, "test uchar dup size %d\n", n);
216         goto end;
217     }
218
219     /* zero */
220     sk_uchar_zero(r);
221     if (sk_uchar_num(r) != 0) {
222         fprintf(stderr, "test uchar zero %d\n", n);
223         goto end;
224     }
225
226     /* insert */
227     sk_uchar_insert(r, v, 0);
228     sk_uchar_insert(r, v + 2, -1);
229     sk_uchar_insert(r, v + 1, 1);
230     for (i = 0; i < 3; i++)
231         if (sk_uchar_value(r, i) != v + i) {
232             fprintf(stderr, "test uchar insert %d\n", i);
233             goto end;
234         }
235
236     /* delete */
237     if (sk_uchar_delete(r, 12) != NULL) {
238         fprintf(stderr, "test uchar delete missing %d\n", n);
239         goto end;
240     }
241     if (sk_uchar_delete(r, 1) != v + 1) {
242         fprintf(stderr, "test uchar delete middle %d\n", n);
243         goto end;
244     }
245
246     /* set */
247     sk_uchar_set(r, 1, v + 1);
248     for (i = 0; i < 2; i++)
249         if (sk_uchar_value(r, i) != v + i) {
250             fprintf(stderr, "test uchar set %d\n", i);
251             goto end;
252         }
253
254     testresult = 1;
255 end:
256     sk_uchar_free(r);
257     sk_uchar_free(s);
258     return testresult;
259 }
260
261 static SS *SS_copy(const SS *p)
262 {
263     SS *q = OPENSSL_malloc(sizeof(*q));
264
265     if (q != NULL)
266         memcpy(q, p, sizeof(*q));
267     return q;
268 }
269
270 static void SS_free(SS *p) {
271     OPENSSL_free(p);
272 }
273
274 static int test_SS_stack(void)
275 {
276     STACK_OF(SS) *s = sk_SS_new_null();
277     STACK_OF(SS) *r = NULL;
278     SS *v[10], *p;
279     const int n = OSSL_NELEM(v);
280     int i;
281     int testresult = 0;
282
283     /* allocate and push */
284     for (i = 0; i < n; i++) {
285         v[i] = OPENSSL_malloc(sizeof(*v[i]));
286
287         if (v[i] == NULL) {
288             fprintf(stderr, "test SS memory allocation failure\n");
289             goto end;
290         }
291         v[i]->n = i;
292         v[i]->c = 'A' + i;
293         if (sk_SS_num(s) != i) {
294             fprintf(stderr, "test SS stack size %d\n", i);
295             goto end;
296         }
297         sk_SS_push(s, v[i]);
298     }
299     if (sk_SS_num(s) != n) {
300         fprintf(stderr, "test SS size %d\n", n);
301         goto end;
302     }
303
304     /* deepcopy */
305     r = sk_SS_deep_copy(s, &SS_copy, &SS_free);
306     if (r == NULL) {
307         fprintf(stderr, "test SS deepcopy failure\n");
308         goto end;
309     }
310     for (i = 0; i < n; i++) {
311         p = sk_SS_value(r, i);
312         if (p == v[i]) {
313             fprintf(stderr, "test SS deepcopy non-copy %d\n", i);
314             goto end;
315         }
316         if (p->n != v[i]->n || p->c != v[i]->c) {
317             fprintf(stderr, "test SS deepcopy values %d\n", i);
318             goto end;
319         }
320     }
321
322     /* pop_free - we rely on the malloc debug to catch the leak */
323     sk_SS_pop_free(r, &SS_free);
324     r = NULL;
325
326     /* delete_ptr */
327     if ((p = sk_SS_delete_ptr(s, v[3])) == NULL) {
328         fprintf(stderr, "test SS delete ptr not found\n");
329         goto end;
330     }
331     SS_free(p);
332     if (sk_SS_num(s) != n-1) {
333         fprintf(stderr, "test SS delete ptr size\n");
334         goto end;
335     }
336     for (i = 0; i < n-1; i++)
337         if (sk_SS_value(s, i) != v[i<3 ? i : 1+i]) {
338             fprintf(stderr, "test SS delete ptr item %d\n", i);
339             goto end;
340         }
341
342     testresult = 1;
343 end:
344     sk_SS_pop_free(r, &SS_free);
345     sk_SS_pop_free(s, &SS_free);
346     return testresult;
347 }
348
349 static int test_SU_stack(void)
350 {
351     STACK_OF(SU) *s = sk_SU_new_null();
352     SU v[10];
353     const int n = OSSL_NELEM(v);
354     int i;
355     int testresult = 0;
356
357     /* allocate and push */
358     for (i = 0; i < n; i++) {
359         if ((i & 1) == 0)
360             v[i].n = i;
361         else
362             v[i].c = 'A' + i;
363         if (sk_SU_num(s) != i) {
364             fprintf(stderr, "test SU stack size %d\n", i);
365             goto end;
366         }
367         sk_SU_push(s, v + i);
368     }
369     if (sk_SU_num(s) != n) {
370         fprintf(stderr, "test SU size %d\n", n);
371         goto end;
372     }
373
374     /* check the pointers are correct */
375     for (i = 0; i < n; i++)
376         if (sk_SU_value(s, i) != v + i) {
377             fprintf(stderr, "test SU pointer check %d\n", i);
378             goto end;
379         }
380
381     testresult = 1;
382 end:
383     sk_SU_free(s);
384     return testresult;
385 }
386
387 void register_tests(void)
388 {
389     ADD_TEST(test_int_stack);
390     ADD_TEST(test_uchar_stack);
391     ADD_TEST(test_SS_stack);
392     ADD_TEST(test_SU_stack);
393 }