Path: blob/main/lib/libc/tests/stdlib/tsearch_test.c
39530 views
/*-1* Copyright (c) 2015 Nuxi, https://nuxi.nl/2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6* 1. Redistributions of source code must retain the above copyright7* notice, this list of conditions and the following disclaimer.8* 2. Redistributions in binary form must reproduce the above copyright9* notice, this list of conditions and the following disclaimer in the10* documentation and/or other materials provided with the distribution.11*12* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND13* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE14* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE15* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE16* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL17* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS18* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)19* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT20* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY21* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF22* SUCH DAMAGE.23*/2425#include <atf-c.h>26#define _SEARCH_PRIVATE27#include <search.h>28#include <stdbool.h>29#include <stdlib.h>30#include <stdio.h>3132static int n_nodes = 0;33static int n_seen = 0;3435/* Validates the integrity of an AVL tree. */36static inline unsigned int37tnode_assert(const posix_tnode *n)38{39unsigned int height_left, height_right;40int balance;4142if (n == NULL)43return 0;44height_left = tnode_assert(n->llink);45height_right = tnode_assert(n->rlink);46balance = (int)height_left - (int)height_right;47ATF_CHECK(balance >= -1);48ATF_CHECK(balance <= 1);49ATF_CHECK_EQ(balance, n->balance);50return (height_left > height_right ? height_left : height_right) + 1;51}5253static int54compar(const void *a, const void *b)55{5657return *(int *)a - *(int *)b;58}5960static void61treewalk(const posix_tnode *node, VISIT v, int level)62{6364if (v == postorder || v == leaf)65n_seen++;66}6768ATF_TC_WITHOUT_HEAD(tsearch_test);69ATF_TC_BODY(tsearch_test, tc)70{71/*72* Run the test below in a deterministic fashion to prevent this73* test from potentially flapping. We assume that this provides74* enough coverage.75*/76#if 077unsigned short random_state[3];78arc4random_buf(random_state, sizeof(random_state));79#else80unsigned short random_state[3] = { 26554, 13330, 3246 };81#endif8283#define NKEYS 100084/* Create 1000 possible keys. */85int keys[NKEYS];86for (int i = 0; i < NKEYS; ++i)87keys[i] = i;8889/* Apply random operations on a binary tree and check the results. */90posix_tnode *root = NULL;91bool present[NKEYS] = {};92for (int i = 0; i < NKEYS * 10; ++i) {93int key = nrand48(random_state) % NKEYS;94int sample = i;9596/*97* Ensure each case is tested at least 10 times, plus a98* random sampling.99*/100if ((sample % NKEYS) > 3)101sample = nrand48(random_state) % 3;102103switch (sample) {104case 0: /* tdelete(). */105if (present[key]) {106ATF_CHECK(tdelete(&key, &root, compar) != NULL);107present[key] = false;108ATF_CHECK(n_nodes > 0);109n_nodes--;110} else {111ATF_CHECK_EQ(NULL,112tdelete(&key, &root, compar));113}114break;115case 1: /* tfind(). */116if (present[key]) {117ATF_CHECK_EQ(&keys[key],118*(int **)tfind(&key, &root, compar));119} else {120ATF_CHECK_EQ(NULL, tfind(&key, &root, compar));121}122break;123case 2: /* tsearch(). */124if (present[key]) {125ATF_CHECK_EQ(&keys[key],126*(int **)tsearch(&key, &root, compar));127} else {128ATF_CHECK_EQ(&keys[key], *(int **)tsearch(129&keys[key], &root, compar));130present[key] = true;131n_nodes++;132}133break;134}135tnode_assert(root);136}137138/* Walk the tree. */139twalk(root, treewalk);140ATF_CHECK_EQ(n_nodes, n_seen);141142/* Remove all entries from the tree. */143for (int key = 0; key < NKEYS; ++key)144if (present[key])145ATF_CHECK(tdelete(&key, &root, compar) != NULL);146ATF_CHECK_EQ(NULL, root);147}148149ATF_TP_ADD_TCS(tp)150{151152ATF_TP_ADD_TC(tp, tsearch_test);153154return (atf_no_error());155}156157158