1*b0d17251Schristos /*
2*b0d17251Schristos * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3*b0d17251Schristos * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
4*b0d17251Schristos *
5*b0d17251Schristos * Licensed under the Apache License 2.0 (the "License"). You may not use
6*b0d17251Schristos * this file except in compliance with the License. You can obtain a copy
7*b0d17251Schristos * in the file LICENSE in the source distribution or at
8*b0d17251Schristos * https://www.openssl.org/source/license.html
9*b0d17251Schristos */
10*b0d17251Schristos
11*b0d17251Schristos #include <stdio.h>
12*b0d17251Schristos #include <string.h>
13*b0d17251Schristos #include <limits.h>
14*b0d17251Schristos
15*b0d17251Schristos #include <openssl/crypto.h>
16*b0d17251Schristos #include "internal/nelem.h"
17*b0d17251Schristos #include "crypto/sparse_array.h"
18*b0d17251Schristos #include "testutil.h"
19*b0d17251Schristos
20*b0d17251Schristos /* The macros below generate unused functions which error out one of the clang
21*b0d17251Schristos * builds. We disable this check here.
22*b0d17251Schristos */
23*b0d17251Schristos #ifdef __clang__
24*b0d17251Schristos #pragma clang diagnostic ignored "-Wunused-function"
25*b0d17251Schristos #endif
26*b0d17251Schristos
27*b0d17251Schristos DEFINE_SPARSE_ARRAY_OF(char);
28*b0d17251Schristos
test_sparse_array(void)29*b0d17251Schristos static int test_sparse_array(void)
30*b0d17251Schristos {
31*b0d17251Schristos static const struct {
32*b0d17251Schristos ossl_uintmax_t n;
33*b0d17251Schristos char *v;
34*b0d17251Schristos } cases[] = {
35*b0d17251Schristos { 22, "a" }, { 0, "z" }, { 1, "b" }, { 290, "c" },
36*b0d17251Schristos { INT_MAX, "m" }, { 6666666, "d" }, { (ossl_uintmax_t)-1, "H" },
37*b0d17251Schristos { 99, "e" }
38*b0d17251Schristos };
39*b0d17251Schristos SPARSE_ARRAY_OF(char) *sa;
40*b0d17251Schristos size_t i, j;
41*b0d17251Schristos int res = 0;
42*b0d17251Schristos
43*b0d17251Schristos if (!TEST_ptr(sa = ossl_sa_char_new())
44*b0d17251Schristos || !TEST_ptr_null(ossl_sa_char_get(sa, 3))
45*b0d17251Schristos || !TEST_ptr_null(ossl_sa_char_get(sa, 0))
46*b0d17251Schristos || !TEST_ptr_null(ossl_sa_char_get(sa, UINT_MAX)))
47*b0d17251Schristos goto err;
48*b0d17251Schristos
49*b0d17251Schristos for (i = 0; i < OSSL_NELEM(cases); i++) {
50*b0d17251Schristos if (!TEST_true(ossl_sa_char_set(sa, cases[i].n, cases[i].v))) {
51*b0d17251Schristos TEST_note("iteration %zu", i + 1);
52*b0d17251Schristos goto err;
53*b0d17251Schristos }
54*b0d17251Schristos for (j = 0; j <= i; j++)
55*b0d17251Schristos if (!TEST_str_eq(ossl_sa_char_get(sa, cases[j].n), cases[j].v)) {
56*b0d17251Schristos TEST_note("iteration %zu / %zu", i + 1, j + 1);
57*b0d17251Schristos goto err;
58*b0d17251Schristos }
59*b0d17251Schristos }
60*b0d17251Schristos
61*b0d17251Schristos res = 1;
62*b0d17251Schristos err:
63*b0d17251Schristos ossl_sa_char_free(sa);
64*b0d17251Schristos return res;
65*b0d17251Schristos }
66*b0d17251Schristos
test_sparse_array_num(void)67*b0d17251Schristos static int test_sparse_array_num(void)
68*b0d17251Schristos {
69*b0d17251Schristos static const struct {
70*b0d17251Schristos size_t num;
71*b0d17251Schristos ossl_uintmax_t n;
72*b0d17251Schristos char *v;
73*b0d17251Schristos } cases[] = {
74*b0d17251Schristos { 1, 22, "a" }, { 2, 1021, "b" }, { 3, 3, "c" }, { 2, 22, NULL },
75*b0d17251Schristos { 2, 3, "d" }, { 3, 22, "e" }, { 3, 666, NULL }, { 4, 666, "f" },
76*b0d17251Schristos { 3, 3, NULL }, { 2, 22, NULL }, { 1, 666, NULL }, { 2, 64000, "g" },
77*b0d17251Schristos { 1, 1021, NULL }, { 0, 64000, NULL }, { 1, 23, "h" }, { 0, 23, NULL }
78*b0d17251Schristos };
79*b0d17251Schristos SPARSE_ARRAY_OF(char) *sa = NULL;
80*b0d17251Schristos size_t i;
81*b0d17251Schristos int res = 0;
82*b0d17251Schristos
83*b0d17251Schristos if (!TEST_size_t_eq(ossl_sa_char_num(NULL), 0)
84*b0d17251Schristos || !TEST_ptr(sa = ossl_sa_char_new())
85*b0d17251Schristos || !TEST_size_t_eq(ossl_sa_char_num(sa), 0))
86*b0d17251Schristos goto err;
87*b0d17251Schristos for (i = 0; i < OSSL_NELEM(cases); i++)
88*b0d17251Schristos if (!TEST_true(ossl_sa_char_set(sa, cases[i].n, cases[i].v))
89*b0d17251Schristos || !TEST_size_t_eq(ossl_sa_char_num(sa), cases[i].num))
90*b0d17251Schristos goto err;
91*b0d17251Schristos res = 1;
92*b0d17251Schristos err:
93*b0d17251Schristos ossl_sa_char_free(sa);
94*b0d17251Schristos return res;
95*b0d17251Schristos }
96*b0d17251Schristos
97*b0d17251Schristos struct index_cases_st {
98*b0d17251Schristos ossl_uintmax_t n;
99*b0d17251Schristos char *v;
100*b0d17251Schristos int del;
101*b0d17251Schristos };
102*b0d17251Schristos
103*b0d17251Schristos struct doall_st {
104*b0d17251Schristos SPARSE_ARRAY_OF(char) *sa;
105*b0d17251Schristos size_t num_cases;
106*b0d17251Schristos const struct index_cases_st *cases;
107*b0d17251Schristos int res;
108*b0d17251Schristos int all;
109*b0d17251Schristos };
110*b0d17251Schristos
leaf_check_all(ossl_uintmax_t n,char * value,void * arg)111*b0d17251Schristos static void leaf_check_all(ossl_uintmax_t n, char *value, void *arg)
112*b0d17251Schristos {
113*b0d17251Schristos struct doall_st *doall_data = (struct doall_st *)arg;
114*b0d17251Schristos const struct index_cases_st *cases = doall_data->cases;
115*b0d17251Schristos size_t i;
116*b0d17251Schristos
117*b0d17251Schristos doall_data->res = 0;
118*b0d17251Schristos for (i = 0; i < doall_data->num_cases; i++)
119*b0d17251Schristos if ((doall_data->all || !cases[i].del)
120*b0d17251Schristos && n == cases[i].n && strcmp(value, cases[i].v) == 0) {
121*b0d17251Schristos doall_data->res = 1;
122*b0d17251Schristos return;
123*b0d17251Schristos }
124*b0d17251Schristos TEST_error("Index %ju with value %s not found", n, value);
125*b0d17251Schristos }
126*b0d17251Schristos
leaf_delete(ossl_uintmax_t n,char * value,void * arg)127*b0d17251Schristos static void leaf_delete(ossl_uintmax_t n, char *value, void *arg)
128*b0d17251Schristos {
129*b0d17251Schristos struct doall_st *doall_data = (struct doall_st *)arg;
130*b0d17251Schristos const struct index_cases_st *cases = doall_data->cases;
131*b0d17251Schristos size_t i;
132*b0d17251Schristos
133*b0d17251Schristos doall_data->res = 0;
134*b0d17251Schristos for (i = 0; i < doall_data->num_cases; i++)
135*b0d17251Schristos if (n == cases[i].n && strcmp(value, cases[i].v) == 0) {
136*b0d17251Schristos doall_data->res = 1;
137*b0d17251Schristos ossl_sa_char_set(doall_data->sa, n, NULL);
138*b0d17251Schristos return;
139*b0d17251Schristos }
140*b0d17251Schristos TEST_error("Index %ju with value %s not found", n, value);
141*b0d17251Schristos }
142*b0d17251Schristos
test_sparse_array_doall(void)143*b0d17251Schristos static int test_sparse_array_doall(void)
144*b0d17251Schristos {
145*b0d17251Schristos static const struct index_cases_st cases[] = {
146*b0d17251Schristos { 22, "A", 1 }, { 1021, "b", 0 }, { 3, "c", 0 }, { INT_MAX, "d", 1 },
147*b0d17251Schristos { (ossl_uintmax_t)-1, "H", 0 }, { (ossl_uintmax_t)-2, "i", 1 },
148*b0d17251Schristos { 666666666, "s", 1 }, { 1234567890, "t", 0 },
149*b0d17251Schristos };
150*b0d17251Schristos struct doall_st doall_data;
151*b0d17251Schristos size_t i;
152*b0d17251Schristos SPARSE_ARRAY_OF(char) *sa = NULL;
153*b0d17251Schristos int res = 0;
154*b0d17251Schristos
155*b0d17251Schristos if (!TEST_ptr(sa = ossl_sa_char_new()))
156*b0d17251Schristos goto err;
157*b0d17251Schristos doall_data.num_cases = OSSL_NELEM(cases);
158*b0d17251Schristos doall_data.cases = cases;
159*b0d17251Schristos doall_data.all = 1;
160*b0d17251Schristos doall_data.sa = NULL;
161*b0d17251Schristos for (i = 0; i < OSSL_NELEM(cases); i++)
162*b0d17251Schristos if (!TEST_true(ossl_sa_char_set(sa, cases[i].n, cases[i].v))) {
163*b0d17251Schristos TEST_note("failed at iteration %zu", i + 1);
164*b0d17251Schristos goto err;
165*b0d17251Schristos }
166*b0d17251Schristos
167*b0d17251Schristos ossl_sa_char_doall_arg(sa, &leaf_check_all, &doall_data);
168*b0d17251Schristos if (doall_data.res == 0) {
169*b0d17251Schristos TEST_info("while checking all elements");
170*b0d17251Schristos goto err;
171*b0d17251Schristos }
172*b0d17251Schristos doall_data.all = 0;
173*b0d17251Schristos doall_data.sa = sa;
174*b0d17251Schristos ossl_sa_char_doall_arg(sa, &leaf_delete, &doall_data);
175*b0d17251Schristos if (doall_data.res == 0) {
176*b0d17251Schristos TEST_info("while deleting selected elements");
177*b0d17251Schristos goto err;
178*b0d17251Schristos }
179*b0d17251Schristos ossl_sa_char_doall_arg(sa, &leaf_check_all, &doall_data);
180*b0d17251Schristos if (doall_data.res == 0) {
181*b0d17251Schristos TEST_info("while checking for deleted elements");
182*b0d17251Schristos goto err;
183*b0d17251Schristos }
184*b0d17251Schristos res = 1;
185*b0d17251Schristos
186*b0d17251Schristos err:
187*b0d17251Schristos ossl_sa_char_free(sa);
188*b0d17251Schristos return res;
189*b0d17251Schristos }
190*b0d17251Schristos
setup_tests(void)191*b0d17251Schristos int setup_tests(void)
192*b0d17251Schristos {
193*b0d17251Schristos ADD_TEST(test_sparse_array);
194*b0d17251Schristos ADD_TEST(test_sparse_array_num);
195*b0d17251Schristos ADD_TEST(test_sparse_array_doall);
196*b0d17251Schristos return 1;
197*b0d17251Schristos }
198