| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | /* * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved. * * Licensed under the Apache License 2.0 (the "License").  You may not use * this file except in compliance with the License.  You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */#include <stdio.h>#include <string.h>#include <limits.h>#include <openssl/crypto.h>#include "internal/nelem.h"#include "crypto/sparse_array.h"#include "testutil.h"/* The macros below generate unused functions which error out one of the clang * builds.  We disable this check here. */#ifdef __clang__#pragma clang diagnostic ignored "-Wunused-function"#endifDEFINE_SPARSE_ARRAY_OF(char);static int test_sparse_array(void){    static const struct {        ossl_uintmax_t n;        char *v;    } cases[] = {        { 22, "a" }, { 0, "z" }, { 1, "b" }, { 290, "c" },        { INT_MAX, "m" }, { 6666666, "d" }, { (ossl_uintmax_t)-1, "H" },        { 99, "e" }    };    SPARSE_ARRAY_OF(char) *sa;    size_t i, j;    int res = 0;    if (!TEST_ptr(sa = ossl_sa_char_new())            || !TEST_ptr_null(ossl_sa_char_get(sa, 3))            || !TEST_ptr_null(ossl_sa_char_get(sa, 0))            || !TEST_ptr_null(ossl_sa_char_get(sa, UINT_MAX)))        goto err;    for (i = 0; i < OSSL_NELEM(cases); i++) {        if (!TEST_true(ossl_sa_char_set(sa, cases[i].n, cases[i].v))) {            TEST_note("iteration %zu", i + 1);            goto err;        }        for (j = 0; j <= i; j++)            if (!TEST_str_eq(ossl_sa_char_get(sa, cases[j].n), cases[j].v)) {                TEST_note("iteration %zu / %zu", i + 1, j + 1);                goto err;            }    }    res = 1;err:    ossl_sa_char_free(sa);    return res;}static int test_sparse_array_num(void){    static const struct {        size_t num;        ossl_uintmax_t n;        char *v;    } cases[] = {        { 1, 22, "a" }, { 2, 1021, "b" }, { 3, 3, "c" }, { 2, 22, NULL },        { 2, 3, "d" }, { 3, 22, "e" }, { 3, 666, NULL }, { 4, 666, "f" },        { 3, 3, NULL }, { 2, 22, NULL }, { 1, 666, NULL }, { 2, 64000, "g" },        { 1, 1021, NULL }, { 0, 64000, NULL }, { 1, 23, "h" }, { 0, 23, NULL }    };    SPARSE_ARRAY_OF(char) *sa = NULL;    size_t i;    int res = 0;    if (!TEST_size_t_eq(ossl_sa_char_num(NULL), 0)            || !TEST_ptr(sa = ossl_sa_char_new())            || !TEST_size_t_eq(ossl_sa_char_num(sa), 0))        goto err;    for (i = 0; i < OSSL_NELEM(cases); i++)        if (!TEST_true(ossl_sa_char_set(sa, cases[i].n, cases[i].v))                || !TEST_size_t_eq(ossl_sa_char_num(sa), cases[i].num))            goto err;    res = 1;err:    ossl_sa_char_free(sa);    return res;}struct index_cases_st {    ossl_uintmax_t n;    char *v;    int del;};struct doall_st {    SPARSE_ARRAY_OF(char) *sa;    size_t num_cases;    const struct index_cases_st *cases;    int res;    int all;};static void leaf_check_all(ossl_uintmax_t n, char *value, void *arg){    struct doall_st *doall_data = (struct doall_st *)arg;    const struct index_cases_st *cases = doall_data->cases;    size_t i;    doall_data->res = 0;    for (i = 0; i < doall_data->num_cases; i++)        if ((doall_data->all || !cases[i].del)            && n == cases[i].n && strcmp(value, cases[i].v) == 0) {            doall_data->res = 1;            return;        }    TEST_error("Index %ju with value %s not found", n, value);}static void leaf_delete(ossl_uintmax_t n, char *value, void *arg){    struct doall_st *doall_data = (struct doall_st *)arg;    const struct index_cases_st *cases = doall_data->cases;    size_t i;    doall_data->res = 0;    for (i = 0; i < doall_data->num_cases; i++)        if (n == cases[i].n && strcmp(value, cases[i].v) == 0) {            doall_data->res = 1;            ossl_sa_char_set(doall_data->sa, n, NULL);            return;        }    TEST_error("Index %ju with value %s not found", n, value);}static int test_sparse_array_doall(void){    static const struct index_cases_st cases[] = {        { 22, "A", 1 }, { 1021, "b", 0 }, { 3, "c", 0 }, { INT_MAX, "d", 1 },        { (ossl_uintmax_t)-1, "H", 0 }, { (ossl_uintmax_t)-2, "i", 1 },        { 666666666, "s", 1 }, { 1234567890, "t", 0 },    };    struct doall_st doall_data;    size_t i;    SPARSE_ARRAY_OF(char) *sa = NULL;    int res = 0;    if (!TEST_ptr(sa = ossl_sa_char_new()))        goto err;    doall_data.num_cases = OSSL_NELEM(cases);    doall_data.cases = cases;    doall_data.all = 1;    doall_data.sa = NULL;    for (i = 0; i <  OSSL_NELEM(cases); i++)        if (!TEST_true(ossl_sa_char_set(sa, cases[i].n, cases[i].v))) {            TEST_note("failed at iteration %zu", i + 1);            goto err;    }    ossl_sa_char_doall_arg(sa, &leaf_check_all, &doall_data);    if (doall_data.res == 0) {        TEST_info("while checking all elements");        goto err;    }    doall_data.all = 0;    doall_data.sa = sa;    ossl_sa_char_doall_arg(sa, &leaf_delete, &doall_data);    if (doall_data.res == 0) {        TEST_info("while deleting selected elements");        goto err;    }    ossl_sa_char_doall_arg(sa, &leaf_check_all, &doall_data);    if (doall_data.res == 0) {        TEST_info("while checking for deleted elements");        goto err;    }    res = 1;err:    ossl_sa_char_free(sa);    return res;}int setup_tests(void){    ADD_TEST(test_sparse_array);    ADD_TEST(test_sparse_array_num);    ADD_TEST(test_sparse_array_doall);    return 1;}
 |