67 changed files with 173 additions and 8448 deletions
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
Copyright 2011 David Robillard <http://drobilla.net> |
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
# SPDX-FileCopyrightText: ยฉ 2019 Alexandros Theodotou <alex@zrythm.org> |
||||
# SPDX-License-Identifier: LicenseRef-ZrythmLicense |
||||
|
||||
subdir ('zix') |
@ -1,115 +0,0 @@
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
Copyright 2011-2016 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include "zix/ampatree.h" |
||||
|
||||
static const char* strings[] = { |
||||
"http://example.org/foo", |
||||
"http://example.org/bar", |
||||
"http://example.org/baz", |
||||
"http://example.net/foo", |
||||
"http://example.net/bar", |
||||
"http://example.net/baz", |
||||
"http://drobilla.net/", |
||||
"http://drobilla.net/software/zix", |
||||
"http://www.gbengasesan.com/blog", |
||||
"http://www.gbengasesan.com", |
||||
"http://echo.jpl.nasa.gov/~lance/delta_v/delta_v.rendezvous.html", |
||||
"http://echo.jpl.nasa.gov/asteroids/1986da/1986DA.html", |
||||
"http://echo.jpl.nasa.gov/", |
||||
"http://echo.jpl.nasa.gov/asteroids/1620_Geographos/geographos.html", |
||||
"http://echo.jpl.nasa.gov/~ostro/KY26/", |
||||
"http://echo.jpl.nasa.gov/~ostro/KY26/JPL_press_release.text", |
||||
"http://echo.jpl.nasa.gov", |
||||
"http://echo.jpl.nasa.gov/asteroids/4179_Toutatis/toutatis.html", |
||||
"http://echo.jpl.nasa.gov/asteroids/4769_Castalia/cast01.html", |
||||
"http://echo.jpl.nasa.gov/publications/review_abs.html", |
||||
}; |
||||
|
||||
static int |
||||
test_fail(const char* fmt, ...) |
||||
{ |
||||
va_list args; |
||||
va_start(args, fmt); |
||||
fprintf(stderr, "error: "); |
||||
vfprintf(stderr, fmt, args); |
||||
va_end(args); |
||||
return 1; |
||||
} |
||||
|
||||
int |
||||
main(int argc, char** argv) |
||||
{ |
||||
ZixAMPatree* patree = zix_ampatree_new(); |
||||
|
||||
const size_t n_strings = sizeof(strings) / sizeof(char*); |
||||
|
||||
// Insert each string
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
ZixStatus st = zix_ampatree_insert(patree, strings[i], strlen(strings[i])); |
||||
if (st) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
FILE* dot_file = fopen("ampatree.dot", "w"); |
||||
zix_ampatree_print_dot(patree, dot_file); |
||||
fclose(dot_file); |
||||
|
||||
// Attempt to insert each string again
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
ZixStatus st = zix_ampatree_insert(patree, strings[i], strlen(strings[i])); |
||||
if (st != ZIX_STATUS_EXISTS) { |
||||
return test_fail("Double inserted `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
// Search for each string
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
const char* match = NULL; |
||||
ZixStatus st = zix_ampatree_find(patree, strings[i], &match); |
||||
if (st) { |
||||
return test_fail("Failed to find `%s'\n", strings[i]); |
||||
} |
||||
if (match != strings[i]) { |
||||
return test_fail("Bad match for `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
// Try some false matches
|
||||
const char* not_indexed[] = { |
||||
"ftp://example.org/not-there-at-all", |
||||
"http://example.org/foobar", |
||||
"http://", |
||||
"http://otherdomain.com" |
||||
}; |
||||
const size_t n_not_indexed = sizeof(not_indexed) / sizeof(char*); |
||||
for (size_t i = 0; i < n_not_indexed; ++i) { |
||||
const char* match = NULL; |
||||
ZixStatus st = zix_ampatree_find(patree, not_indexed[i], &match); |
||||
if (st != ZIX_STATUS_NOT_FOUND) { |
||||
return test_fail("Unexpectedly found `%s'\n", not_indexed[i]); |
||||
} |
||||
} |
||||
|
||||
zix_ampatree_free(patree); |
||||
|
||||
return 0; |
||||
} |
@ -1,44 +0,0 @@
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
Copyright 2011 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#define _POSIX_C_SOURCE 199309L |
||||
|
||||
#include <time.h> |
||||
#include <sys/time.h> |
||||
|
||||
static inline double |
||||
elapsed_s(const struct timespec* start, const struct timespec* end) |
||||
{ |
||||
return ( (end->tv_sec - start->tv_sec) |
||||
+ ((end->tv_nsec - start->tv_nsec) * 0.000000001) ); |
||||
} |
||||
|
||||
static inline struct timespec |
||||
bench_start(void) |
||||
{ |
||||
struct timespec start_t; |
||||
clock_gettime(CLOCK_MONOTONIC, &start_t); |
||||
return start_t; |
||||
} |
||||
|
||||
static inline double |
||||
bench_end(const struct timespec* start_t) |
||||
{ |
||||
struct timespec end_t; |
||||
clock_gettime(CLOCK_MONOTONIC, &end_t); |
||||
return elapsed_s(start_t, &end_t); |
||||
} |
||||
|
@ -1,82 +0,0 @@
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
Copyright 2014-2016 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
|
||||
#include "zix/bitset.h" |
||||
|
||||
#define N_BITS 256 |
||||
#define N_ELEMS (ZIX_BITSET_ELEMS(N_BITS)) |
||||
|
||||
static int |
||||
test_fail(const char* fmt, ...) |
||||
{ |
||||
va_list args; |
||||
va_start(args, fmt); |
||||
fprintf(stderr, "error: "); |
||||
vfprintf(stderr, fmt, args); |
||||
va_end(args); |
||||
return 1; |
||||
} |
||||
|
||||
int |
||||
main(int argc, char** argv) |
||||
{ |
||||
ZixBitset b[N_ELEMS]; |
||||
ZixBitsetTally t[N_ELEMS]; |
||||
|
||||
zix_bitset_clear(b, t, N_BITS); |
||||
if (zix_bitset_count_up_to(b, t, N_BITS) != 0) { |
||||
return test_fail("Cleared bitset has non-zero count\n"); |
||||
} |
||||
|
||||
for (size_t i = 0; i < N_BITS; ++i) { |
||||
zix_bitset_set(b, t, i); |
||||
const size_t count = zix_bitset_count_up_to(b, t, N_BITS); |
||||
if (count != i + 1) { |
||||
return test_fail("Count %zu != %zu\n", count, i + 1); |
||||
} else if (!zix_bitset_get(b, i)) { |
||||
return test_fail("Bit %zu is not set\n", i); |
||||
} |
||||
} |
||||
|
||||
for (size_t i = 0; i <= N_BITS; ++i) { |
||||
const size_t count = zix_bitset_count_up_to(b, t, i); |
||||
if (count != i) { |
||||
return test_fail("Count up to %zu is %zu != %zu\n", i, count, i); |
||||
} |
||||
} |
||||
|
||||
for (size_t i = 0; i <= N_BITS; ++i) { |
||||
zix_bitset_reset(b, t, i); |
||||
const size_t count = zix_bitset_count_up_to(b, t, i); |
||||
if (count != 0) { |
||||
return test_fail("Count up to %zu is %zu != %zu\n", i, count, 0); |
||||
} |
||||
} |
||||
|
||||
zix_bitset_clear(b, t, N_BITS); |
||||
for (size_t i = 0; i <= N_BITS; i += 2) { |
||||
zix_bitset_set(b, t, i); |
||||
const size_t count = zix_bitset_count_up_to(b, t, i + 1); |
||||
if (count != i / 2 + 1) { |
||||
return test_fail("Count up to %zu is %zu != %zu\n", i, count, i / 2 + 1); |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -1,428 +0,0 @@
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
Copyright 2011-2014 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <limits.h> |
||||
#include <stdarg.h> |
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <time.h> |
||||
|
||||
#ifdef _MSC_VER |
||||
# define PRIdPTR "Id" |
||||
#else |
||||
# include <inttypes.h> |
||||
#endif |
||||
|
||||
#include "test_malloc.h" |
||||
#include "zix/zix.h" |
||||
|
||||
static bool expect_failure = false; |
||||
|
||||
// Return a pseudo-pseudo-pseudo-random-ish integer with no duplicates
|
||||
static uint32_t |
||||
unique_rand(uint32_t i) |
||||
{ |
||||
i ^= 0x00005CA1E; // Juggle bits to avoid linear clumps
|
||||
|
||||
// Largest prime < 2^32 which satisfies (2^32 = 3 mod 4)
|
||||
static const uint32_t prime = 4294967291; |
||||
if (i >= prime) { |
||||
return i; // Values >= prime are mapped to themselves
|
||||
} else { |
||||
const uint32_t residue = ((uint64_t)i * i) % prime; |
||||
return (i <= prime / 2) ? residue : prime - residue; |
||||
} |
||||
} |
||||
|
||||
static int |
||||
int_cmp(const void* a, const void* b, void* user_data) |
||||
{ |
||||
const uintptr_t ia = (uintptr_t)a; |
||||
const uintptr_t ib = (uintptr_t)b; |
||||
// note the (ia - ib) trick here would overflow
|
||||
if (ia == ib) { |
||||
return 0; |
||||
} else if (ia < ib) { |
||||
return -1; |
||||
} else { |
||||
return 1; |
||||
} |
||||
} |
||||
|
||||
static uint32_t |
||||
ith_elem(int test_num, size_t n_elems, int i) |
||||
{ |
||||
switch (test_num % 3) { |
||||
case 0: return i + 1; // Increasing
|
||||
case 1: return n_elems - i; // Decreasing
|
||||
default: return unique_rand(i); // Pseudo-random
|
||||
} |
||||
} |
||||
|
||||
static void destroy(void* ptr) |
||||
{ |
||||
} |
||||
|
||||
typedef struct { |
||||
int test_num; |
||||
size_t n_elems; |
||||
} TestContext; |
||||
|
||||
static uint32_t |
||||
wildcard_cut(int test_num, size_t n_elems) |
||||
{ |
||||
return ith_elem(test_num, n_elems, n_elems / 3); |
||||
} |
||||
|
||||
/** Wildcard comparator where 0 matches anything >= wildcard_cut(n_elems). */ |
||||
static int |
||||
wildcard_cmp(const void* a, const void* b, void* user_data) |
||||
{ |
||||
const TestContext* ctx = (TestContext*)user_data; |
||||
const size_t n_elems = ctx->n_elems; |
||||
const int test_num = ctx->test_num; |
||||
const uintptr_t ia = (uintptr_t)a; |
||||
const uintptr_t ib = (uintptr_t)b; |
||||
if (ia == 0) { |
||||
if (ib >= wildcard_cut(test_num, n_elems)) { |
||||
return 0; // Wildcard match
|
||||
} else { |
||||
return 1; // Wildcard a > b
|
||||
} |
||||
} else if (ib == 0) { |
||||
if (ia >= wildcard_cut(test_num, n_elems)) { |
||||
return 0; // Wildcard match
|
||||
} else { |
||||
return -1; // Wildcard b > a
|
||||
} |
||||
} else { |
||||
return int_cmp(a, b, user_data); |
||||
} |
||||
} |
||||
|
||||
static int |
||||
test_fail(ZixBTree* t, const char* fmt, ...) |
||||
{ |
||||
zix_btree_free(t); |
||||
if (expect_failure) { |
||||
return EXIT_SUCCESS; |
||||
} |
||||
va_list args; |
||||
va_start(args, fmt); |
||||
fprintf(stderr, "error: "); |
||||
vfprintf(stderr, fmt, args); |
||||
va_end(args); |
||||
return EXIT_FAILURE; |
||||
} |
||||
|
||||
static int |
||||
stress(int test_num, size_t n_elems) |
||||
{ |
||||
uintptr_t r = 0; |
||||
ZixBTreeIter* ti = NULL; |
||||
ZixBTree* t = zix_btree_new(int_cmp, NULL, NULL); |
||||
ZixStatus st = ZIX_STATUS_SUCCESS; |
||||
|
||||
if (!t) { |
||||
return test_fail(t, "Failed to allocate tree\n"); |
||||
} |
||||
|
||||
// Ensure begin iterator is end on empty tree
|
||||
ti = zix_btree_begin(t); |
||||
if (!ti) { |
||||
return test_fail(t, "Failed to allocate iterator\n"); |
||||
} else if (!zix_btree_iter_is_end(ti)) { |
||||
return test_fail(t, "Begin iterator on empty tree is not end\n"); |
||||
} |
||||
zix_btree_iter_free(ti); |
||||
|
||||
// Insert n_elems elements
|
||||
for (size_t i = 0; i < n_elems; ++i) { |
||||
r = ith_elem(test_num, n_elems, i); |
||||
if (!zix_btree_find(t, (void*)r, &ti)) { |
||||
return test_fail(t, "%lu already in tree\n", (uintptr_t)r); |
||||
} else if ((st = zix_btree_insert(t, (void*)r))) { |
||||
return test_fail(t, "Insert %lu failed (%s)\n", |
||||
(uintptr_t)r, zix_strerror(st)); |
||||
} |
||||
} |
||||
|
||||
// Ensure tree size is correct
|
||||
if (zix_btree_size(t) != n_elems) { |
||||
return test_fail(t, "Tree size %zu != %zu\n", zix_btree_size(t), n_elems); |
||||
} |
||||
|
||||
// Search for all elements
|
||||
for (size_t i = 0; i < n_elems; ++i) { |
||||
r = ith_elem(test_num, n_elems, i); |
||||
if (zix_btree_find(t, (void*)r, &ti)) { |
||||
return test_fail(t, "Find %lu @ %zu failed\n", (uintptr_t)r, i); |
||||
} else if ((uintptr_t)zix_btree_get(ti) != r) { |
||||
return test_fail(t, "Search data corrupt (%" PRIdPTR " != %" PRIdPTR ")\n", |
||||
(uintptr_t)zix_btree_get(ti), r); |
||||
} |
||||
zix_btree_iter_free(ti); |
||||
} |
||||
|
||||
if (zix_btree_lower_bound(NULL, (void*)r, &ti) != ZIX_STATUS_BAD_ARG) { |
||||
return test_fail(t, "Lower bound on NULL tree succeeded\n"); |
||||
} |
||||
|
||||
// Find the lower bound of all elements and ensure it's exact
|
||||
for (size_t i = 0; i < n_elems; ++i) { |
||||
r = ith_elem(test_num, n_elems, i); |
||||
if (zix_btree_lower_bound(t, (void*)r, &ti)) { |
||||
return test_fail(t, "Lower bound %lu @ %zu failed\n", (uintptr_t)r, i); |
||||
} else if (zix_btree_iter_is_end(ti)) { |
||||
return test_fail(t, "Lower bound %lu @ %zu hit end\n", (uintptr_t)r, i); |
||||
} else if ((uintptr_t)zix_btree_get(ti) != r) { |
||||
return test_fail(t, "Lower bound corrupt (%" PRIdPTR " != %" PRIdPTR "\n", |
||||
(uintptr_t)zix_btree_get(ti), r); |
||||
} |
||||
zix_btree_iter_free(ti); |
||||
} |
||||
|
||||
// Search for elements that don't exist
|
||||
for (size_t i = 0; i < n_elems; ++i) { |
||||
r = ith_elem(test_num, n_elems * 3, n_elems + i); |
||||
if (!zix_btree_find(t, (void*)r, &ti)) { |
||||
return test_fail(t, "Unexpectedly found %lu\n", (uintptr_t)r); |
||||
} |
||||
} |
||||
|
||||
// Iterate over all elements
|
||||
size_t i = 0; |
||||
uintptr_t last = 0; |
||||
for (ti = zix_btree_begin(t); |
||||
!zix_btree_iter_is_end(ti); |
||||
zix_btree_iter_increment(ti), ++i) { |
||||
const uintptr_t iter_data = (uintptr_t)zix_btree_get(ti); |
||||
if (iter_data < last) { |
||||
return test_fail(t, "Iter @ %zu corrupt (%" PRIdPTR " < %" PRIdPTR ")\n", |
||||
i, iter_data, last); |
||||
} |
||||
last = iter_data; |
||||
} |
||||
zix_btree_iter_free(ti); |
||||
if (i != n_elems) { |
||||
return test_fail(t, "Iteration stopped at %zu/%zu elements\n", i, n_elems); |
||||
} |
||||
|
||||
// Insert n_elems elements again, ensuring duplicates fail
|
||||
for (i = 0; i < n_elems; ++i) { |
||||
r = ith_elem(test_num, n_elems, i); |
||||
if (!zix_btree_insert(t, (void*)r)) { |
||||
return test_fail(t, "Duplicate insert succeeded\n"); |
||||
} |
||||
} |
||||
|
||||
// Search for the middle element then iterate from there
|
||||
r = ith_elem(test_num, n_elems, n_elems / 2); |
||||
if (zix_btree_find(t, (void*)r, &ti)) { |
||||
return test_fail(t, "Find %lu failed\n", (uintptr_t)r); |
||||
} |
||||
last = (uintptr_t)zix_btree_get(ti); |
||||
zix_btree_iter_increment(ti); |
||||
for (i = 1; !zix_btree_iter_is_end(ti); zix_btree_iter_increment(ti), ++i) { |
||||
if ((uintptr_t)zix_btree_get(ti) == last) { |
||||
return test_fail(t, "Duplicate element @ %u %" PRIdPTR "\n", i, last); |
||||
} |
||||
last = (uintptr_t)zix_btree_get(ti); |
||||
} |
||||
zix_btree_iter_free(ti); |
||||
|
||||
// Delete all elements
|
||||
ZixBTreeIter* next = NULL; |
||||
for (size_t e = 0; e < n_elems; e++) { |
||||
r = ith_elem(test_num, n_elems, e); |
||||
uintptr_t removed; |
||||
if (zix_btree_remove(t, (void*)r, (void**)&removed, &next)) { |
||||
return test_fail(t, "Error removing item %lu\n", (uintptr_t)r); |
||||
} else if (removed != r) { |
||||
return test_fail(t, "Removed wrong item %lu != %lu\n", |
||||
removed, (uintptr_t)r); |
||||
} else if (test_num == 0) { |
||||
const uintptr_t next_value = ith_elem(test_num, n_elems, e + 1); |
||||
if (!((zix_btree_iter_is_end(next) && e == n_elems - 1) || |
||||
(uintptr_t)zix_btree_get(next) == next_value)) { |
||||
return test_fail(t, "Delete all next iterator %lu != %lu\n", |
||||
(uintptr_t)zix_btree_get(next), next_value); |
||||
} |
||||
} |
||||
} |
||||
zix_btree_iter_free(next); |
||||
next = NULL; |
||||
|
||||
// Ensure the tree is empty
|
||||
if (zix_btree_size(t) != 0) { |
||||
return test_fail(t, "Tree size %zu != 0\n", zix_btree_size(t)); |
||||
} |
||||
|
||||
// Insert n_elems elements again (to test non-empty destruction)
|
||||
for (size_t e = 0; e < n_elems; ++e) { |
||||
r = ith_elem(test_num, n_elems, e); |
||||
if (zix_btree_insert(t, (void*)r)) { |
||||
return test_fail(t, "Post-deletion insert failed\n"); |
||||
} |
||||
} |
||||
|
||||
// Delete elements that don't exist
|
||||
for (size_t e = 0; e < n_elems; e++) { |
||||
r = ith_elem(test_num, n_elems * 3, n_elems + e); |
||||
uintptr_t removed; |
||||
if (!zix_btree_remove(t, (void*)r, (void**)&removed, &next)) { |
||||
return test_fail(t, "Non-existant deletion of %lu succeeded\n", (uintptr_t)r); |
||||
} |
||||
} |
||||
zix_btree_iter_free(next); |
||||
next = NULL; |
||||
|
||||
// Ensure tree size is still correct
|
||||
if (zix_btree_size(t) != n_elems) { |
||||
return test_fail(t, "Tree size %zu != %zu\n", zix_btree_size(t), n_elems); |
||||
} |
||||
|
||||
// Delete some elements towards the end
|
||||
for (size_t e = 0; e < n_elems / 4; e++) { |
||||
r = ith_elem(test_num, n_elems, n_elems - (n_elems / 4) + e); |
||||
uintptr_t removed; |
||||
if (zix_btree_remove(t, (void*)r, (void**)&removed, &next)) { |
||||
return test_fail(t, "Deletion of %lu failed\n", (uintptr_t)r); |
||||
} else if (removed != r) { |
||||
return test_fail(t, "Removed wrong item %lu != %lu\n", |
||||
removed, (uintptr_t)r); |
||||
} else if (test_num == 0) { |
||||
const uintptr_t next_value = ith_elem(test_num, n_elems, e + 1); |
||||
if (!zix_btree_iter_is_end(next) && |
||||
(uintptr_t)zix_btree_get(next) == next_value) { |
||||
return test_fail(t, "Next iterator %lu != %lu\n", |
||||
(uintptr_t)zix_btree_get(next), next_value); |
||||
} |
||||
} |
||||
} |
||||
zix_btree_iter_free(next); |
||||
next = NULL; |
||||
|
||||
// Check tree size
|
||||
if (zix_btree_size(t) != n_elems - (n_elems / 4)) { |
||||
return test_fail(t, "Tree size %zu != %zu\n", zix_btree_size(t), n_elems); |
||||
} |
||||
|
||||
// Delete some elements in a random order
|
||||
for (size_t e = 0; e < zix_btree_size(t); e++) { |
||||
r = ith_elem(test_num, n_elems, rand() % n_elems); |
||||
uintptr_t removed; |
||||
ZixStatus rst = zix_btree_remove(t, (void*)r, (void**)&removed, &next); |
||||
if (rst != ZIX_STATUS_SUCCESS && rst != ZIX_STATUS_NOT_FOUND) { |
||||
return test_fail(t, "Error deleting %lu\n", (uintptr_t)r); |
||||
} |
||||
} |
||||
zix_btree_iter_free(next); |
||||
next = NULL; |
||||
|
||||
zix_btree_free(t); |
||||
|
||||
// Test lower_bound with wildcard comparator
|
||||
|
||||
TestContext ctx = { test_num, n_elems }; |
||||
if (!(t = zix_btree_new(wildcard_cmp, &ctx, destroy))) { |
||||
return test_fail(t, "Failed to allocate tree\n"); |
||||
} |
||||
|
||||
// Insert n_elems elements
|
||||
for (i = 0; i < n_elems; ++i) { |
||||
r = ith_elem(test_num, n_elems, i); |
||||
if (r != 0) { // Can't insert wildcards
|
||||
if ((st = zix_btree_insert(t, (void*)r))) { |
||||
return test_fail(t, "Insert %lu failed (%s)\n", |
||||
(uintptr_t)r, zix_strerror(st)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Find lower bound of wildcard
|
||||
const uintptr_t wildcard = 0; |
||||
if (zix_btree_lower_bound(t, (void*)wildcard, &ti)) { |
||||
return test_fail(t, "Lower bound failed\n"); |
||||
} else if (zix_btree_iter_is_end(ti)) { |
||||
return test_fail(t, "Lower bound reached end\n"); |
||||
} |
||||
|
||||
// Check value
|
||||
const uintptr_t iter_data = (uintptr_t)zix_btree_get(ti); |
||||
const uintptr_t cut = wildcard_cut(test_num, n_elems); |
||||
if (iter_data != cut) { |
||||
return test_fail(t, "Lower bound %" PRIdPTR " != %" PRIdPTR "\n", |
||||
iter_data, cut); |
||||
} else if (wildcard_cmp((void*)wildcard, (void*)iter_data, &ctx)) { |
||||
return test_fail(t, "Wildcard lower bound %" PRIdPTR " != %" PRIdPTR "\n", |
||||
iter_data, cut); |
||||
} |
||||
|
||||
zix_btree_iter_free(ti); |
||||
|
||||
// Find lower bound of value past end
|
||||
const uintptr_t max = (uintptr_t)-1; |
||||
if (zix_btree_lower_bound(t, (void*)max, &ti)) { |
||||
return test_fail(t, "Lower bound failed\n"); |
||||
} else if (!zix_btree_iter_is_end(ti)) { |
||||
return test_fail(t, "Lower bound of maximum value is not end\n"); |
||||
} |
||||
|
||||
zix_btree_iter_free(ti); |
||||
zix_btree_free(t); |
||||
|
||||
return EXIT_SUCCESS; |
||||
} |
||||
|
||||
int |
||||
main(int argc, char** argv) |
||||
{ |
||||
if (argc > 2) { |
||||
fprintf(stderr, "Usage: %s [N_ELEMS]\n", argv[0]); |
||||
return EXIT_FAILURE; |
||||
} |
||||
|
||||
const unsigned n_tests = 3; |
||||
unsigned n_elems = (argc > 1) ? atol(argv[1]) : 100000; |
||||
|
||||
printf("Running %u tests with %u elements", n_tests, n_elems); |
||||
for (unsigned i = 0; i < n_tests; ++i) { |
||||
printf("."); |
||||
fflush(stdout); |
||||
if (stress(i, n_elems)) { |
||||
return EXIT_FAILURE; |
||||
} |
||||
} |
||||
printf("\n"); |
||||
|
||||
const size_t total_n_allocs = test_malloc_get_n_allocs(); |
||||
const size_t fail_n_elems = 1000; |
||||
printf("Testing 0 ... %zu failed allocations\n", total_n_allocs); |
||||
expect_failure = true; |
||||
for (size_t i = 0; i < total_n_allocs; ++i) { |
||||
test_malloc_reset(i); |
||||
stress(0, fail_n_elems); |
||||
if (i > test_malloc_get_n_allocs()) { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
test_malloc_reset((size_t)-1); |
||||
|
||||
return EXIT_SUCCESS; |
||||
} |
@ -1,253 +0,0 @@
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
Copyright 2011-2014 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include "bench.h" |
||||
|
||||
#include <ctype.h> |
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <glib.h> |
||||
|
||||
#include "zix/ampatree.h" |
||||
#include "zix/chunk.h" |
||||
#include "zix/hash.h" |
||||
#include "zix/patree.h" |
||||
#include "zix/trie.h" |
||||
|
||||
const unsigned seed = 1; |
||||
|
||||
static int |
||||
test_fail(const char* fmt, ...) |
||||
{ |
||||
va_list args; |
||||
va_start(args, fmt); |
||||
fprintf(stderr, "error: "); |
||||
vfprintf(stderr, fmt, args); |
||||
va_end(args); |
||||
return 1; |
||||
} |
||||
|
||||
int |
||||
main(int argc, char** argv) |
||||
{ |
||||
if (argc != 2) { |
||||
return test_fail("Usage: %s INPUT_FILE\n", argv[0]); |
||||
} |
||||
|
||||
const char* file = argv[1]; |
||||
FILE* fd = fopen(file, "r"); |
||||
if (!fd) { |
||||
return test_fail("Failed to open file %s\n", file); |
||||
} |
||||
|
||||
size_t max_n_strings = 100000000; |
||||
|
||||
/* Read input strings */ |
||||
char** strings = NULL; |
||||
size_t* lengths = NULL; |
||||
size_t n_strings = 0; |
||||
char* buf = calloc(1, 1); |
||||
size_t buf_len = 1; |
||||
size_t this_str_len = 0; |
||||
for (char c; (c = fgetc(fd)) != EOF;) { |
||||
if (isspace(c)) { |
||||
if (this_str_len == 0) { |
||||
continue; |
||||
} |
||||
strings = realloc(strings, (n_strings + 1) * sizeof(char*)); |
||||
lengths = realloc(lengths, (n_strings + 1) * sizeof(size_t)); |
||||
strings[n_strings] = malloc(buf_len); |
||||
lengths[n_strings] = this_str_len; |
||||
memcpy(strings[n_strings], buf, buf_len); |
||||
this_str_len = 0; |
||||
if (++n_strings == max_n_strings) { |
||||
break; |
||||
} |
||||
} else { |
||||
++this_str_len; |
||||
if (buf_len < this_str_len + 1) { |
||||
buf_len = this_str_len + 1; |
||||
buf = realloc(buf, buf_len); |
||||
} |
||||
buf[this_str_len - 1] = c; |
||||
buf[this_str_len] = '\0'; |
||||
} |
||||
} |
||||
|
||||
fclose(fd); |
||||
|
||||
FILE* insert_dat = fopen("dict_insert.txt", "w"); |
||||
FILE* search_dat = fopen("dict_search.txt", "w"); |
||||
fprintf(insert_dat, "# n\tGHashTable\tZixHash\tZixPatree\tZixTrie\tZixAMPatree\n"); |
||||
fprintf(search_dat, "# n\tGHashTable\tZixHash\tZixPatree\tZixTrie\tZixAMPatree\n"); |
||||
|
||||
for (size_t n = n_strings / 16; n <= n_strings; n *= 2) { |
||||
printf("Benchmarking n = %zu\n", n); |
||||
ZixPatree* patree = zix_patree_new(); |
||||
ZixAMPatree* ampatree = zix_ampatree_new(); |
||||
ZixTrie* trie = zix_trie_new(); |
||||
GHashTable* hash = g_hash_table_new(g_str_hash, g_str_equal); |
||||
ZixHash* zhash = zix_hash_new((ZixHashFunc)zix_chunk_hash, |
||||
(ZixEqualFunc)zix_chunk_equal, |
||||
sizeof(ZixChunk)); |
||||
fprintf(insert_dat, "%zu", n); |
||||
fprintf(search_dat, "%zu", n); |
||||
|
||||
// Benchmark insertion
|
||||
|
||||
// GHashTable
|
||||
struct timespec insert_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
g_hash_table_insert(hash, strings[i], strings[i]); |
||||
} |
||||
fprintf(insert_dat, "\t%lf", bench_end(&insert_start)); |
||||
|
||||
// ZixHash
|
||||
insert_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
const ZixChunk chunk = { strings[i], lengths[i] + 1 }; |
||||
ZixStatus st = zix_hash_insert(zhash, &chunk, NULL); |
||||
if (st && st != ZIX_STATUS_EXISTS) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
fprintf(insert_dat, "\t%lf", bench_end(&insert_start)); |
||||
|
||||
// ZixPatree
|
||||
insert_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
ZixStatus st = zix_patree_insert(patree, strings[i], lengths[i]); |
||||
if (st && st != ZIX_STATUS_EXISTS) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
fprintf(insert_dat, "\t%lf", bench_end(&insert_start)); |
||||
|
||||
// ZixTrie
|
||||
insert_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
ZixStatus st = zix_trie_insert(trie, strings[i], lengths[i]); |
||||
if (st && st != ZIX_STATUS_EXISTS) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
fprintf(insert_dat, "\t%lf", bench_end(&insert_start)); |
||||
|
||||
// ZixAMPatree
|
||||
insert_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
ZixStatus st = zix_ampatree_insert(ampatree, strings[i], lengths[i]); |
||||
if (st && st != ZIX_STATUS_EXISTS) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
fprintf(insert_dat, "\t%lf\n", bench_end(&insert_start)); |
||||
|
||||
// Benchmark search
|
||||
|
||||
// GHashTable
|
||||
srand(seed); |
||||
struct timespec search_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
const size_t index = rand() % n; |
||||
char* match = g_hash_table_lookup(hash, strings[index]); |
||||
if (strcmp(match, strings[index])) { |
||||
return test_fail("Bad match for `%s'\n", strings[index]); |
||||
} |
||||
} |
||||
fprintf(search_dat, "\t%lf", bench_end(&search_start)); |
||||
|
||||
// ZixHash
|
||||
srand(seed); |
||||
search_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
const size_t index = rand() % n; |
||||
const ZixChunk key = { strings[index], lengths[index] + 1 }; |
||||
const ZixChunk* match = NULL; |
||||
if (!(match = zix_hash_find(zhash, &key))) { |
||||
return test_fail("Hash: Failed to find `%s'\n", strings[index]); |
||||
} |
||||
if (strcmp(match->buf, strings[index])) { |
||||
return test_fail("Hash: Bad match %p for `%s': `%s'\n", |
||||
(void*)match, strings[index], match->buf); |
||||
} |
||||
} |
||||
fprintf(search_dat, "\t%lf", bench_end(&search_start)); |
||||
|
||||
// ZixPatree
|
||||
srand(seed); |
||||
search_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
const size_t index = rand() % n; |
||||
const char* match = NULL; |
||||
if (zix_patree_find(patree, strings[index], &match)) { |
||||
return test_fail("Patree: Failed to find `%s'\n", strings[index]); |
||||
} |
||||
if (strcmp(match, strings[index])) { |
||||
return test_fail("Patree: Bad match for `%s'\n", strings[index]); |
||||
} |
||||
} |
||||
fprintf(search_dat, "\t%lf", bench_end(&search_start)); |
||||
|
||||
// ZixTrie
|
||||
srand(seed); |
||||
search_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
const size_t index = rand() % n; |
||||
const char* match = NULL; |
||||
if (zix_trie_find(trie, strings[index], &match)) { |
||||
return test_fail("Trie: Failed to find `%s'\n", strings[index]); |
||||
} |
||||
if (strcmp(match, strings[index])) { |
||||
return test_fail("Trie: Bad match `%s' for `%s'\n", |
||||
match, strings[index]); |
||||
} |
||||
} |
||||
fprintf(search_dat, "\t%lf", bench_end(&search_start)); |
||||
|
||||
// ZixAMPatree
|
||||
srand(seed); |
||||
search_start = bench_start(); |
||||
for (size_t i = 0; i < n; ++i) { |
||||
const size_t index = rand() % n; |
||||
const char* match = NULL; |
||||
if (zix_ampatree_find(ampatree, strings[index], &match)) { |
||||
return test_fail("AMPatree: Failed to find `%s'\n", strings[index]); |
||||
} |
||||
if (strcmp(match, strings[index])) { |
||||
return test_fail("AMPatree: Bad match `%s' for `%s'\n", |
||||
match, strings[index]); |
||||
} |
||||
} |
||||
fprintf(search_dat, "\t%lf\n", bench_end(&search_start)); |
||||
|
||||
zix_patree_free(patree); |
||||
zix_ampatree_free(ampatree); |
||||
zix_trie_free(trie); |
||||
zix_hash_free(zhash); |
||||
g_hash_table_unref(hash); |
||||
} |
||||
|
||||
fclose(insert_dat); |
||||
fclose(search_dat); |
||||
|
||||
fprintf(stderr, "Wrote dict_insert.txt dict_search.txt\n"); |
||||
|
||||
return 0; |
||||
} |
@ -1,218 +0,0 @@
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
Copyright 2011-2014 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include "test_malloc.h" |
||||
#include "zix/hash.h" |
||||
|
||||
static bool expect_failure = false; |
||||
|
||||
static const char* strings[] = { |
||||
"one", "two", "three", "four", "five", "six", "seven", "eight", |
||||
"2one", "2two", "2three", "2four", "2five", "2six", "2seven", "2eight", |
||||
"3one", "3two", "3three", "3four", "3five", "3six", "3seven", "3eight", |
||||
"4one", "4two", "4three", "4four", "4five", "4six", "4seven", "4eight", |
||||
"5one", "5two", "5three", "5four", "5five", "5six", "5seven", "5eight", |
||||
"6one", "6two", "6three", "6four", "6five", "6six", "6seven", "6eight", |
||||
"7one", "7two", "7three", "7four", "7five", "7six", "7seven", "7eight", |
||||
"8one", "8two", "8three", "8four", "8five", "8six", "8seven", "8eight", |
||||
"9one", "9two", "9three", "9four", "9five", "9six", "9seven", "9eight", |
||||
"Aone", "Atwo", "Athree", "Afour", "Afive", "Asix", "Aseven", "Aeight", |
||||
"Bone", "Btwo", "Bthree", "Bfour", "Bfive", "Bsix", "Bseven", "Beight", |
||||
"Cone", "Ctwo", "Cthree", "Cfour", "Cfive", "Csix", "Cseven", "Ceight", |
||||
"Done", "Dtwo", "Dthree", "Dfour", "Dfive", "Dsix", "Dseven", "Deight", |
||||
}; |
||||
|
||||
static int |
||||
test_fail(const char* fmt, ...) |
||||
{ |
||||
if (expect_failure) { |
||||
return 0; |
||||
} |
||||
va_list args; |
||||
va_start(args, fmt); |
||||
fprintf(stderr, "error: "); |
||||
vfprintf(stderr, fmt, args); |
||||
va_end(args); |
||||
return 1; |
||||
} |
||||
|
||||
static unsigned n_checked = 0; |
||||
|
||||
static void |
||||
check(void* value, void* user_data) |
||||
{ |
||||
if (strlen(*(const char*const*)value) >= 3) { |
||||
++n_checked; |
||||
} else { |
||||
fprintf(stderr, "ERROR: %s\n", (const char*)value); |
||||
} |
||||
} |
||||
|
||||
static uint32_t |
||||
string_ptr_hash(const void* value) |
||||
{ |
||||
// Trusty old DJB hash
|
||||
const char* str = *(const char*const*)value; |
||||
unsigned h = 5381; |
||||
for (const char* s = str; *s != '\0'; ++s) { |
||||
h = (h << 5) + h + *s; // h = h * 33 + c
|
||||
} |
||||
return h; |
||||
} |
||||
|
||||
static bool |
||||
string_ptr_equal(const void* a, const void* b) |
||||
{ |
||||
return !strcmp(*(const char*const*)a, *(const char*const*)b); |
||||
} |
||||
|
||||
static int |
||||
stress(void) |
||||
{ |
||||
ZixHash* hash = zix_hash_new( |
||||
string_ptr_hash, string_ptr_equal, sizeof(const char*)); |
||||
if (!hash) { |
||||
return test_fail("Failed to allocate hash\n"); |
||||
} |
||||
|
||||
const size_t n_strings = sizeof(strings) / sizeof(const char*); |
||||
|
||||
// Insert each string
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
const void* inserted = NULL; |
||||
ZixStatus st = zix_hash_insert(hash, &strings[i], &inserted); |
||||
if (st) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} else if (*(const void*const*)inserted != strings[i]) { |
||||
return test_fail("Corrupt insertion %s != %s\n", |
||||
strings[i], *(const char*const*)inserted); |
||||
} |
||||
} |
||||
|
||||
// Ensure hash size is correct
|
||||
if (zix_hash_size(hash) != n_strings) { |
||||
return test_fail("Hash size %zu != %zu\n", |
||||
zix_hash_size(hash), n_strings); |
||||
} |
||||
|
||||
//zix_hash_print_dot(hash, stdout);
|
||||
|
||||
// Attempt to insert each string again
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
const void* inserted = NULL; |
||||
ZixStatus st = zix_hash_insert(hash, &strings[i], &inserted); |
||||
if (st != ZIX_STATUS_EXISTS) { |
||||
return test_fail("Double inserted `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
// Search for each string
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
const char*const* match = (const char*const*)zix_hash_find( |
||||
hash, &strings[i]); |
||||
if (!match) { |
||||
return test_fail("Failed to find `%s'\n", strings[i]); |
||||
} |
||||
if (*match != strings[i]) { |
||||
return test_fail("Bad match for `%s': `%s'\n", strings[i], match); |
||||
} |
||||
} |
||||
|
||||
// Try some false matches
|
||||
const char* not_indexed[] = { |
||||
"ftp://example.org/not-there-at-all", |
||||
"http://example.org/foobar", |
||||
"http://", |
||||
"http://otherdomain.com" |
||||
}; |
||||
const size_t n_not_indexed = sizeof(not_indexed) / sizeof(char*); |
||||
for (size_t i = 0; i < n_not_indexed; ++i) { |
||||
const char*const* match = (const char*const*)zix_hash_find( |
||||
hash, ¬_indexed[i]); |
||||
if (match) { |
||||
return test_fail("Unexpectedly found `%s'\n", not_indexed[i]); |
||||
} |
||||
} |
||||
|
||||
// Remove strings
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
// Remove string
|
||||
ZixStatus st = zix_hash_remove(hash, &strings[i]); |
||||
if (st) { |
||||
return test_fail("Failed to remove `%s'\n", strings[i]); |
||||
} |
||||
|
||||
// Ensure second removal fails
|
||||
st = zix_hash_remove(hash, &strings[i]); |
||||
if (st != ZIX_STATUS_NOT_FOUND) { |
||||
return test_fail("Unexpectedly removed `%s' twice\n", strings[i]); |
||||
} |
||||
|
||||
// Check to ensure remaining strings are still present
|
||||
for (size_t j = i + 1; j < n_strings; ++j) { |
||||
const char*const* match = (const char*const*)zix_hash_find( |
||||
hash, &strings[j]); |
||||
if (!match) { |
||||
return test_fail("Failed to find `%s' after remove\n", strings[j]); |
||||
} |
||||
if (*match != strings[j]) { |
||||
return test_fail("Bad match for `%s' after remove\n", strings[j]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Insert each string again (to check non-empty desruction)
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
ZixStatus st = zix_hash_insert(hash, &strings[i], NULL); |
||||
if (st) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
// Check key == value (and test zix_hash_foreach)
|
||||
zix_hash_foreach(hash, check, NULL); |
||||
if (n_checked != n_strings) { |
||||
return test_fail("Check failed\n"); |
||||
} |
||||
|
||||
zix_hash_free(hash); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int |
||||
main(int argc, char** argv) |
||||
{ |
||||
if (stress()) { |
||||
return 1; |
||||
} |
||||
|
||||
const size_t total_n_allocs = test_malloc_get_n_allocs(); |
||||
printf("Testing 0 ... %zu failed allocations\n", total_n_allocs); |
||||
expect_failure = true; |
||||
for (size_t i = 0; i < total_n_allocs; ++i) { |
||||
test_malloc_reset(i); |
||||
stress(); |
||||
} |
||||
|
||||
test_malloc_reset((size_t)-1); |
||||
|
||||
return 0; |
||||
} |
@ -1,28 +0,0 @@
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
Copyright 2012 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#define ZIX_INLINE |
||||
|
||||
#include "zix/hash.c" |
||||
#include "zix/hash.h" |
||||
#include "zix/tree.c" |
||||
#include "zix/tree.h" |
||||
|
||||
int |
||||
main(void) |
||||
{ |
||||
return 0; |
||||
} |
@ -1,115 +0,0 @@
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
Copyright 2011 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include "zix/patree.h" |
||||
|
||||
static const char* strings[] = { |
||||
"http://example.org/foo", |
||||
"http://example.org/bar", |
||||
"http://example.org/baz", |
||||
"http://example.net/foo", |
||||
"http://example.net/bar", |
||||
"http://example.net/baz", |
||||
"http://drobilla.net/", |
||||
"http://drobilla.net/software/zix", |
||||
"http://www.gbengasesan.com/blog", |
||||
"http://www.gbengasesan.com", |
||||
"http://echo.jpl.nasa.gov/~lance/delta_v/delta_v.rendezvous.html", |
||||
"http://echo.jpl.nasa.gov/asteroids/1986da/1986DA.html", |
||||
"http://echo.jpl.nasa.gov/", |
||||
"http://echo.jpl.nasa.gov/asteroids/1620_Geographos/geographos.html", |
||||
"http://echo.jpl.nasa.gov/~ostro/KY26/", |
||||
"http://echo.jpl.nasa.gov/~ostro/KY26/JPL_press_release.text", |
||||
"http://echo.jpl.nasa.gov", |
||||
"http://echo.jpl.nasa.gov/asteroids/4179_Toutatis/toutatis.html", |
||||
"http://echo.jpl.nasa.gov/asteroids/4769_Castalia/cast01.html", |
||||
"http://echo.jpl.nasa.gov/publications/review_abs.html", |
||||
}; |
||||
|
||||
static int |
||||
test_fail(const char* fmt, ...) |
||||
{ |
||||
va_list args; |
||||
va_start(args, fmt); |
||||
fprintf(stderr, "error: "); |
||||
vfprintf(stderr, fmt, args); |
||||
va_end(args); |
||||
return 1; |
||||
} |
||||
|
||||
int |
||||
main(int argc, char** argv) |
||||
{ |
||||
ZixPatree* patree = zix_patree_new(); |
||||
|
||||
const size_t n_strings = sizeof(strings) / sizeof(char*); |
||||
|
||||
// Insert each string
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
ZixStatus st = zix_patree_insert(patree, strings[i], strlen(strings[i])); |
||||
if (st) { |
||||
return test_fail("Failed to insert `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
FILE* dot_file = fopen("patree.dot", "w"); |
||||
zix_patree_print_dot(patree, dot_file); |
||||
fclose(dot_file); |
||||
|
||||
// Attempt to insert each string again
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
ZixStatus st = zix_patree_insert(patree, strings[i], strlen(strings[i])); |
||||
if (st != ZIX_STATUS_EXISTS) { |
||||
return test_fail("Double inserted `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
// Search for each string
|
||||
for (size_t i = 0; i < n_strings; ++i) { |
||||
const char* match = NULL; |
||||
ZixStatus st = zix_patree_find(patree, strings[i], &match); |
||||
if (st) { |
||||
return test_fail("Failed to find `%s'\n", strings[i]); |
||||
} |
||||
if (match != strings[i]) { |
||||
return test_fail("Bad match for `%s'\n", strings[i]); |
||||
} |
||||
} |
||||
|
||||
// Try some false matches
|
||||
const char* not_indexed[] = { |
||||
"ftp://example.org/not-there-at-all", |
||||
"http://example.org/foobar", |
||||
"http://", |
||||
"http://otherdomain.com" |
||||
}; |
||||
const size_t n_not_indexed = sizeof(not_indexed) / sizeof(char*); |
||||
for (size_t i = 0; i < n_not_indexed; ++i) { |
||||
const char* match = NULL; |
||||
ZixStatus st = zix_patree_find(patree, not_indexed[i], &match); |
||||
if (st != ZIX_STATUS_NOT_FOUND) { |
||||
return test_fail("Unexpectedly found `%s'\n", not_indexed[i]); |
||||
} |
||||
} |
||||
|
||||
zix_patree_free(patree); |
||||
|
||||
return 0; |
||||
} |
@ -1,228 +0,0 @@
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
Copyright 2011 David Robillard <http://drobilla.net>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
||||
purpose with or without fee is hereby granted, provided that the above |
||||
copyright notice and this permission notice appear in all copies. |
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <limits.h> |
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "zix/ring.h" |
||||
#include "zix/thread.h" |
||||
|
||||
#define MSG_SIZE 20 |
||||
|
||||
ZixRing* ring = 0; |
||||
unsigned n_writes = 0; |
||||
bool read_error = false; |
||||
|
||||
static int |
||||
failure(const char* fmt, ...) |
||||
{ |
||||
va_list args; |
||||
va_start(args, fmt); |
||||
fprintf(stderr, "error: "); |
||||
vfprintf(stderr, fmt, args); |
||||
va_end(args); |
||||
return 1; |
||||
} |
||||
|
||||