mirror of
https://github.com/nmap/nmap.git
synced 2025-12-22 07:29:01 +00:00
216 lines
4.9 KiB
C
216 lines
4.9 KiB
C
/*
|
|
* Nsock regression test suite
|
|
* Same license as nmap -- see https://nmap.org/book/man-legal.html
|
|
*/
|
|
|
|
#include "test-common.h"
|
|
#include "../src/gh_heap.h"
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
|
|
|
|
#define HEAP_COUNT 3
|
|
|
|
struct testitem {
|
|
int val;
|
|
gh_hnode_t node;
|
|
};
|
|
|
|
static int hnode_int_cmp(gh_hnode_t *n1, gh_hnode_t *n2) {
|
|
struct testitem *a;
|
|
struct testitem *b;
|
|
|
|
a = container_of(n1, struct testitem, node);
|
|
b = container_of(n2, struct testitem, node);
|
|
|
|
return (a->val < b->val);
|
|
}
|
|
|
|
static gh_hnode_t *mknode(int val) {
|
|
struct testitem *item;
|
|
|
|
item = calloc(1, sizeof(struct testitem));
|
|
assert(item != NULL);
|
|
item->val = val;
|
|
gh_hnode_invalidate(&item->node);
|
|
return &item->node;
|
|
}
|
|
|
|
static int node2int(gh_hnode_t *hnode) {
|
|
struct testitem *item;
|
|
|
|
item = container_of(hnode, struct testitem, node);
|
|
return item->val;
|
|
}
|
|
|
|
void gh_heap_verify(gh_heap_t *heap) {
|
|
gh_hnode_t *a, *b, *c;
|
|
unsigned int bi, ci;
|
|
unsigned int count = gh_heap_count(heap);
|
|
for (unsigned int i=0; i < heap->count; i++) {
|
|
a = gh_heap_find(heap, i);
|
|
bi = (i << 1) + 1;
|
|
assert(a->index == i);
|
|
if (bi < count) {
|
|
b = gh_heap_find(heap, bi);
|
|
assert(b->index == bi);
|
|
assert(node2int(a) <= node2int(b));
|
|
ci = bi + 1;
|
|
if (ci < count) {
|
|
c = gh_heap_find(heap, ci);
|
|
assert(c->index == ci);
|
|
assert(node2int(a) <= node2int(c));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int ghheap_ordering(void *tdata) {
|
|
gh_heap_t heap;
|
|
int i, n, k;
|
|
|
|
gh_heap_init(&heap, hnode_int_cmp);
|
|
|
|
for (i = 25000; i < 50000; i++)
|
|
gh_heap_push(&heap, mknode(i));
|
|
|
|
gh_heap_verify(&heap);
|
|
|
|
for (i = 24999; i >= 0; i--)
|
|
gh_heap_push(&heap, mknode(i));
|
|
|
|
gh_heap_verify(&heap);
|
|
|
|
for (i = 0; i < 5000; i++) {
|
|
gh_hnode_t *current = gh_heap_find(&heap, rand() % gh_heap_count(&heap));
|
|
gh_heap_remove(&heap, current);
|
|
free(container_of(current, struct testitem, node));
|
|
}
|
|
|
|
gh_heap_verify(&heap);
|
|
|
|
for (i = 25000; i < 50000; i++)
|
|
gh_heap_push(&heap, mknode(i));
|
|
|
|
gh_heap_verify(&heap);
|
|
|
|
n = -1;
|
|
do {
|
|
gh_hnode_t *current;
|
|
|
|
current = gh_heap_pop(&heap);
|
|
assert(!gh_hnode_is_valid(current));
|
|
k = node2int(current);
|
|
|
|
if (k < n)
|
|
return -EINVAL;
|
|
|
|
n = k;
|
|
free(container_of(current, struct testitem, node));
|
|
} while (gh_heap_count(&heap) > 0);
|
|
|
|
gh_heap_free(&heap);
|
|
return 0;
|
|
}
|
|
|
|
static int ghheap_stress(void *tdata) {
|
|
gh_heap_t heaps[HEAP_COUNT];
|
|
int i, num;
|
|
|
|
for (i = 0; i < HEAP_COUNT; i++)
|
|
gh_heap_init(&heaps[i], hnode_int_cmp);
|
|
|
|
for (num = 25000; num < 50000; num++) {
|
|
for (i = 0; i < HEAP_COUNT; i++) {
|
|
gh_heap_push(&heaps[i], mknode(num));
|
|
}
|
|
}
|
|
for (i = 0; i < HEAP_COUNT; i++)
|
|
gh_heap_verify(&heaps[i]);
|
|
|
|
for (num = 24999; num >= 0; num--) {
|
|
for (i = 0; i < HEAP_COUNT; i++) {
|
|
gh_heap_push(&heaps[i], mknode(num));
|
|
}
|
|
}
|
|
for (i = 0; i < HEAP_COUNT; i++)
|
|
gh_heap_verify(&heaps[i]);
|
|
|
|
for (num = 0; num < 50000; num++) {
|
|
for (i = 0; i < HEAP_COUNT; i++) {
|
|
gh_heap_t *heap = &heaps[i];
|
|
gh_hnode_t *hnode;
|
|
if (num % 0x7f == 0) {
|
|
size_t count = gh_heap_count(heap);
|
|
hnode = gh_heap_find(heap, count-1);
|
|
if (hnode == NULL) {
|
|
fprintf(stderr, "Failed to find node at index %lu (count-1)\n", count-1);
|
|
return -EINVAL;
|
|
}
|
|
gh_heap_remove(heap, hnode);
|
|
free(container_of(hnode, struct testitem, node));
|
|
gh_heap_verify(heap);
|
|
}
|
|
else if (num % 0x1fff == 0 && num < gh_heap_count(heap)) {
|
|
hnode = gh_heap_find(heap, num);
|
|
if (hnode == NULL) {
|
|
fprintf(stderr, "Failed to find node at index %d (count = %lu)\n", num, gh_heap_count(heap));
|
|
return -EINVAL;
|
|
}
|
|
gh_heap_remove(heap, hnode);
|
|
free(container_of(hnode, struct testitem, node));
|
|
gh_heap_verify(heap);
|
|
}
|
|
else {
|
|
int r_min, r_pop;
|
|
|
|
r_min = node2int(gh_heap_min(heap));
|
|
hnode = gh_heap_pop(heap);
|
|
r_pop = node2int(hnode);
|
|
|
|
if (r_min != r_pop) {
|
|
fprintf(stderr, "Bogus min/pop return values (%d != %d)\n", r_min, r_pop);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (r_min > num) {
|
|
fprintf(stderr, "Bogus return value %d when expected <=%d\n", r_min, num);
|
|
return -EINVAL;
|
|
}
|
|
|
|
free(container_of(hnode, struct testitem, node));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < HEAP_COUNT; i++) {
|
|
void *ret;
|
|
|
|
ret = gh_heap_pop(&heaps[i]);
|
|
if (ret != NULL) {
|
|
fprintf(stderr, "Ret is bogus for heap %d\n", i);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < HEAP_COUNT; i++)
|
|
gh_heap_free(&heaps[i]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
const struct test_case TestGHHeaps = {
|
|
.t_name = "test nsock internal ghheaps",
|
|
.t_setup = NULL,
|
|
.t_run = ghheap_stress,
|
|
.t_teardown = NULL
|
|
};
|
|
|
|
const struct test_case TestHeapOrdering = {
|
|
.t_name = "test heaps conditions",
|
|
.t_setup = NULL,
|
|
.t_run = ghheap_ordering,
|
|
.t_teardown = NULL
|
|
};
|