diff --git a/example/Makefile b/example/Makefile index bc11336..e25089a 100644 --- a/example/Makefile +++ b/example/Makefile @@ -1,7 +1,7 @@ DUMPMACHINE := $(shell $(CC) -dumpmachine) ifneq ($(SANITIZE_ADDRESS),1) - XCFLAGS = -Ofast -DNDEBUG -s -static + XCFLAGS = -Ofast -flto -DNDEBUG -s -static ifneq ($(firstword $(filter x86_64-%,$(DUMPMACHINE))),) XCFLAGS += -march=x86-64 -mtune=nocona else ifneq ($(firstword $(filter i686-%,$(DUMPMACHINE))),) @@ -25,7 +25,7 @@ BIN_PATH := bin ALL_PATH := $(SRC_PATH) $(BIN_PATH) BIN_FILE := $(BIN_PATH)/hashset-example$(EXE_SUFFIX) -SRC_FILE := $(SRC_PATH)/main.c +SRC_FILE := $(wildcard $(SRC_PATH)/*.c) LIB_FILE := ../libhashset/lib/libhashset-1.a .PHONY: all build clean diff --git a/example/hashset-example.vcxproj b/example/hashset-example.vcxproj index 9a03fa9..f44c56a 100644 --- a/example/hashset-example.vcxproj +++ b/example/hashset-example.vcxproj @@ -39,6 +39,7 @@ + @@ -46,6 +47,9 @@ {8cf3bd19-28b1-435d-b719-e00b052dfc3a} + + + 16.0 Win32Proj diff --git a/example/hashset-example.vcxproj.filters b/example/hashset-example.vcxproj.filters index 0b7f47e..274df3c 100644 --- a/example/hashset-example.vcxproj.filters +++ b/example/hashset-example.vcxproj.filters @@ -18,5 +18,13 @@ Source Files + + Source Files + + + + + Header Files + \ No newline at end of file diff --git a/example/src/input.c b/example/src/input.c new file mode 100644 index 0000000..8e38d14 --- /dev/null +++ b/example/src/input.c @@ -0,0 +1,50 @@ +/******************************************************************************/ +/* HashSet for C99, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#include "input.h" + +#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0U])) + +/* ========================================================================= */ +/* I/O Functions */ +/* ========================================================================= */ + +static const uint64_t INPUT_DATA[] = +{ + UINT64_C(0xEC7D0A721D57EC50), UINT64_C(0x2D6A7AB6BF627C22), UINT64_C(0x4FDD65C766A875B3), UINT64_C(0x820325C26E55AADE), UINT64_C(0xDAAA501D96EEF99B), + UINT64_C(0x8144E2BD50513672), UINT64_C(0x292CE22A29D5DB2B), UINT64_C(0xBC6CF8B2053A5334), UINT64_C(0x6D1401A1D373E7D1), UINT64_C(0x24ADEDD753FA66AE), + UINT64_C(0xC10245EBF7AA2022), UINT64_C(0x023529AB3C7CD028), UINT64_C(0x36D2B9AC4939E5B6), UINT64_C(0xC03EBAFFF82F66AA), UINT64_C(0xF192D661B62529F8), + UINT64_C(0xB704F3B5D339E013), UINT64_C(0xA9FF1DACC3E51172), UINT64_C(0x56B07D81D1075239), UINT64_C(0xB1871C613F7AABE2), UINT64_C(0xA8EF994549F8FE4A), + UINT64_C(0xA57BB923C5253144), UINT64_C(0x00D86833851697B3), UINT64_C(0xDA9E46FDD32DC65D), UINT64_C(0x7ACB9C0ADDDFAB93), UINT64_C(0xB5B5850E76C843DB), + UINT64_C(0x3B6A7C89C7E81A5D), UINT64_C(0x4EB1262597175FCD), UINT64_C(0xB6FBE2171D1D7EA0), UINT64_C(0x081137EA1D536FC4), UINT64_C(0xE0445CD0FAD5C7DD), + UINT64_C(0x893007682A3BF169), UINT64_C(0xD0C19098FBD42472), UINT64_C(0xEDB93F32F0A49B30), UINT64_C(0x2EA9A358058AB291), UINT64_C(0x8DAEDB071BA37583), + UINT64_C(0x7D82157789453793), UINT64_C(0xBB2773CA12083932), UINT64_C(0x6303F020DEFC11A9), UINT64_C(0xD41F0AD15E0189DC), UINT64_C(0x19B057F06E39C89E), + UINT64_C(0x4253F25E0B30719C), UINT64_C(0x09463D8E5BA23234), UINT64_C(0x34D04E31976724AA), UINT64_C(0x4671121B954F5A79), UINT64_C(0xE92C10C3DB5D8D1B), + UINT64_C(0xE9CBC62D55911AE7), UINT64_C(0x2A1AB1C994DB788E), UINT64_C(0xC8C33ECF2C582D77), UINT64_C(0x5FA82FE6C15B629E), UINT64_C(0x466CEED23C511177), + UINT64_C(0x036D0870BAE19AE1), UINT64_C(0x6606CC0204159016), UINT64_C(0xD6238C8747BC5852), UINT64_C(0x223E4185F09E378F), UINT64_C(0xA9B3F004F76E5444), + UINT64_C(0x23C9471F9E0284DD), UINT64_C(0x8B8FD1A11AA899F1), UINT64_C(0x0AB371E3FC9D3B56), UINT64_C(0xAC2E67112F3A040D), UINT64_C(0x192A053B04315830), + UINT64_C(0x432D3397538C1F92), UINT64_C(0xE959C8CB414D0179), UINT64_C(0x2CBAD874DD3E7ED3), UINT64_C(0x27C1B56C45A07443), UINT64_C(0x985DCE41B814DB32), + UINT64_C(0x7D89DA5C4F0A66B3), UINT64_C(0x8BDD31E4EBE03149), UINT64_C(0xDE099239E444C693), UINT64_C(0x1ADD95B03AF163A0), UINT64_C(0x36CD32A83DE833F2), + UINT64_C(0xDF4A8C3B1DC66B09), UINT64_C(0xC29C92C5A077B9FE), UINT64_C(0x56950ECB370CBC27), UINT64_C(0x7FEAD937FCA475F1), UINT64_C(0x1E4AD443AD9D41EC), + UINT64_C(0x9A265C879D7E5872), UINT64_C(0x455AB983F8BA1441), UINT64_C(0x027C2ED163D11C29), UINT64_C(0xA7A7D23CAA6F4DC6), UINT64_C(0xEE7939920BE1E7BC), + UINT64_C(0x2AE02B16E28F02F6), UINT64_C(0xFE8A0CB4EB33DA1B), UINT64_C(0x8CCBF16F006BE241), UINT64_C(0x3371EF26F2850DAF), UINT64_C(0xC35EA57F39EA9E58), + UINT64_C(0x20977AD263FB0272), UINT64_C(0x29BBDD2B8DFCD944), UINT64_C(0x3EF8BD07A2CA3369), UINT64_C(0x64FC3600F0B37716), UINT64_C(0x53CBD741D2433E51), + UINT64_C(0x69459841B5CEE1AB), UINT64_C(0x170B6EBB26B0102C), UINT64_C(0xAF7D361D649AED05), UINT64_C(0x8843B951E1A79CA4), UINT64_C(0xCC0B139063D3EF0A), + UINT64_C(0x85CB5DBD53986A64), UINT64_C(0x7C66F5CD3E46FDB7), UINT64_C(0xE863F4436E8BD7F8), UINT64_C(0x82496CD067153344), UINT64_C(0x863F1F732CE3751E), +}; + +int have_more_items(const size_t offset) +{ + return offset < ARRAY_SIZE(INPUT_DATA); +} + +uint64_t get_next_item(const size_t offset) +{ + if (offset < ARRAY_SIZE(INPUT_DATA)) + { + return INPUT_DATA[offset]; + } + return 0U; +} diff --git a/example/src/input.h b/example/src/input.h new file mode 100644 index 0000000..3457a47 --- /dev/null +++ b/example/src/input.h @@ -0,0 +1,15 @@ +/******************************************************************************/ +/* HashSet for C99, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef _EXAMPLE_INPUT_INCLUDED +#define _EXAMPLE_INPUT_INCLUDED + +#include +#include + +int have_more_items(const size_t offset); +uint64_t get_next_item(const size_t offset); + +#endif /*_EXAMPLE_INPUT_INCLUDED*/ diff --git a/example/src/main.c b/example/src/main.c index 0920c9d..b9b4f85 100644 --- a/example/src/main.c +++ b/example/src/main.c @@ -6,50 +6,7 @@ #include #include #include - -#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0U])) - -/* ========================================================================= */ -/* I/O Functions */ -/* ========================================================================= */ - -static const uint64_t INPUT_DATA[] = -{ - UINT64_C(0xEC7D0A721D57EC50), UINT64_C(0x2D6A7AB6BF627C22), UINT64_C(0x4FDD65C766A875B3), UINT64_C(0x820325C26E55AADE), UINT64_C(0xDAAA501D96EEF99B), - UINT64_C(0x8144E2BD50513672), UINT64_C(0x292CE22A29D5DB2B), UINT64_C(0xBC6CF8B2053A5334), UINT64_C(0x6D1401A1D373E7D1), UINT64_C(0x24ADEDD753FA66AE), - UINT64_C(0xC10245EBF7AA2022), UINT64_C(0x023529AB3C7CD028), UINT64_C(0x36D2B9AC4939E5B6), UINT64_C(0xC03EBAFFF82F66AA), UINT64_C(0xF192D661B62529F8), - UINT64_C(0xB704F3B5D339E013), UINT64_C(0xA9FF1DACC3E51172), UINT64_C(0x56B07D81D1075239), UINT64_C(0xB1871C613F7AABE2), UINT64_C(0xA8EF994549F8FE4A), - UINT64_C(0xA57BB923C5253144), UINT64_C(0x00D86833851697B3), UINT64_C(0xDA9E46FDD32DC65D), UINT64_C(0x7ACB9C0ADDDFAB93), UINT64_C(0xB5B5850E76C843DB), - UINT64_C(0x3B6A7C89C7E81A5D), UINT64_C(0x4EB1262597175FCD), UINT64_C(0xB6FBE2171D1D7EA0), UINT64_C(0x081137EA1D536FC4), UINT64_C(0xE0445CD0FAD5C7DD), - UINT64_C(0x893007682A3BF169), UINT64_C(0xD0C19098FBD42472), UINT64_C(0xEDB93F32F0A49B30), UINT64_C(0x2EA9A358058AB291), UINT64_C(0x8DAEDB071BA37583), - UINT64_C(0x7D82157789453793), UINT64_C(0xBB2773CA12083932), UINT64_C(0x6303F020DEFC11A9), UINT64_C(0xD41F0AD15E0189DC), UINT64_C(0x19B057F06E39C89E), - UINT64_C(0x4253F25E0B30719C), UINT64_C(0x09463D8E5BA23234), UINT64_C(0x34D04E31976724AA), UINT64_C(0x4671121B954F5A79), UINT64_C(0xE92C10C3DB5D8D1B), - UINT64_C(0xE9CBC62D55911AE7), UINT64_C(0x2A1AB1C994DB788E), UINT64_C(0xC8C33ECF2C582D77), UINT64_C(0x5FA82FE6C15B629E), UINT64_C(0x466CEED23C511177), - UINT64_C(0x036D0870BAE19AE1), UINT64_C(0x6606CC0204159016), UINT64_C(0xD6238C8747BC5852), UINT64_C(0x223E4185F09E378F), UINT64_C(0xA9B3F004F76E5444), - UINT64_C(0x23C9471F9E0284DD), UINT64_C(0x8B8FD1A11AA899F1), UINT64_C(0x0AB371E3FC9D3B56), UINT64_C(0xAC2E67112F3A040D), UINT64_C(0x192A053B04315830), - UINT64_C(0x432D3397538C1F92), UINT64_C(0xE959C8CB414D0179), UINT64_C(0x2CBAD874DD3E7ED3), UINT64_C(0x27C1B56C45A07443), UINT64_C(0x985DCE41B814DB32), - UINT64_C(0x7D89DA5C4F0A66B3), UINT64_C(0x8BDD31E4EBE03149), UINT64_C(0xDE099239E444C693), UINT64_C(0x1ADD95B03AF163A0), UINT64_C(0x36CD32A83DE833F2), - UINT64_C(0xDF4A8C3B1DC66B09), UINT64_C(0xC29C92C5A077B9FE), UINT64_C(0x56950ECB370CBC27), UINT64_C(0x7FEAD937FCA475F1), UINT64_C(0x1E4AD443AD9D41EC), - UINT64_C(0x9A265C879D7E5872), UINT64_C(0x455AB983F8BA1441), UINT64_C(0x027C2ED163D11C29), UINT64_C(0xA7A7D23CAA6F4DC6), UINT64_C(0xEE7939920BE1E7BC), - UINT64_C(0x2AE02B16E28F02F6), UINT64_C(0xFE8A0CB4EB33DA1B), UINT64_C(0x8CCBF16F006BE241), UINT64_C(0x3371EF26F2850DAF), UINT64_C(0xC35EA57F39EA9E58), - UINT64_C(0x20977AD263FB0272), UINT64_C(0x29BBDD2B8DFCD944), UINT64_C(0x3EF8BD07A2CA3369), UINT64_C(0x64FC3600F0B37716), UINT64_C(0x53CBD741D2433E51), - UINT64_C(0x69459841B5CEE1AB), UINT64_C(0x170B6EBB26B0102C), UINT64_C(0xAF7D361D649AED05), UINT64_C(0x8843B951E1A79CA4), UINT64_C(0xCC0B139063D3EF0A), - UINT64_C(0x85CB5DBD53986A64), UINT64_C(0x7C66F5CD3E46FDB7), UINT64_C(0xE863F4436E8BD7F8), UINT64_C(0x82496CD067153344), UINT64_C(0x863F1F732CE3751E), -}; - -static int have_more_items(const size_t offset) -{ - return offset < ARRAY_SIZE(INPUT_DATA); -} - -static uint64_t get_next_item(const size_t offset) -{ - if (offset < ARRAY_SIZE(INPUT_DATA)) - { - return INPUT_DATA[offset]; - } - return 0U; -} +#include "input.h" /* ========================================================================= */ /* MAIN */ diff --git a/libhashset/Makefile b/libhashset/Makefile index 23d2b5a..256ed4a 100644 --- a/libhashset/Makefile +++ b/libhashset/Makefile @@ -1,7 +1,7 @@ DUMPMACHINE := $(shell $(CC) -dumpmachine) ifneq ($(SANITIZE_ADDRESS),1) - XCFLAGS = -Ofast -DNDEBUG + XCFLAGS = -Ofast -flto -DNDEBUG ifneq ($(firstword $(filter x86_64-%,$(DUMPMACHINE))),) XCFLAGS += -march=x86-64 -mtune=nocona else ifneq ($(firstword $(filter i686-%,$(DUMPMACHINE))),) diff --git a/test/Makefile b/test/Makefile index 82dc065..53680b3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ DUMPMACHINE := $(shell $(CC) -dumpmachine) ifneq ($(SANITIZE_ADDRESS),1) - XCFLAGS = -Ofast -DNDEBUG -s -static + XCFLAGS = -Ofast -flto -DNDEBUG -s -static ifneq ($(firstword $(filter x86_64-%,$(DUMPMACHINE))),) XCFLAGS += -march=x86-64 -mtune=nocona else ifneq ($(firstword $(filter i686-%,$(DUMPMACHINE))),) @@ -25,7 +25,7 @@ BIN_PATH := bin ALL_PATH := $(SRC_PATH) $(BIN_PATH) BIN_FILE := $(BIN_PATH)/hashset-test$(EXE_SUFFIX) -SRC_FILE := $(SRC_PATH)/main.c +SRC_FILE := $(wildcard $(SRC_PATH)/*.c) LIB_FILE := ../libhashset/lib/libhashset-1.a .PHONY: all build clean diff --git a/test/hashset-test.vcxproj b/test/hashset-test.vcxproj index 0867a52..90c1596 100644 --- a/test/hashset-test.vcxproj +++ b/test/hashset-test.vcxproj @@ -40,12 +40,18 @@ + + {8cf3bd19-28b1-435d-b719-e00b052dfc3a} + + + + 16.0 Win32Proj diff --git a/test/hashset-test.vcxproj.filters b/test/hashset-test.vcxproj.filters index 0b7f47e..100d11c 100644 --- a/test/hashset-test.vcxproj.filters +++ b/test/hashset-test.vcxproj.filters @@ -18,5 +18,19 @@ Source Files + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/test/src/main.c b/test/src/main.c index d558356..eb7754a 100644 --- a/test/src/main.c +++ b/test/src/main.c @@ -3,457 +3,19 @@ /* This work has been released under the CC0 1.0 Universal license! */ /******************************************************************************/ -#include - +#include "tests.h" #include #include -#include -#include -#include -#ifndef _WIN32 -# include -#endif - -#if defined(__GNUC__) -# define INLINE __inline__ -#elif defined(_MSC_VER) -# define INLINE __inline -#else -# define INLINE -#endif - -/* ========================================================================= */ -/* Utilities */ -/* ========================================================================= */ - -#define INVERT(X) do { (X) = (!(X)); } while(0) - -#define UNUSED(X) ((void)X) - -#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0U])) - -#ifdef _WIN32 -#define RtlGenRandom SystemFunction036 -#define getentropy(X,Y) (RtlGenRandom((X),(uint32_t)(Y)) ? 0 : (-1)) -unsigned char __stdcall RtlGenRandom(void *buffer, uint32_t length); -#endif - -typedef struct -{ - size_t offset; - uint64_t buffer[16U]; -} -random_t; - -static INLINE void random_init(random_t *const rnd) -{ - memset(rnd, 0, sizeof(random_t)); - rnd->offset = SIZE_MAX; -} - -static INLINE uint64_t random_next(random_t *const rnd) -{ - if (rnd->offset >= ARRAY_SIZE(rnd->buffer)) - { - rnd->offset = 0U; - if (getentropy(rnd->buffer, sizeof(rnd->buffer)) < 0) - { - abort(); - } - } - - return rnd->buffer[rnd->offset++]; -} - -#define PRINT_SET_INFO(X) do \ -{\ - if (!hash_set_info64(hash_set, &capacity, &valid, &deleted, &limit)) \ +#define RUN_TEST_CASE(X) do \ +{ \ + if (test_function_##X(hash_set) != EXIT_SUCCESS) \ { \ - fprintf(stdout, "[#%d] capacity: %010zu, valid: %010zu, deleted: %010zu, limit: %010zu\n", (X), capacity, valid, deleted, limit); \ - fflush(stdout); \ + goto failure; \ } \ } \ while(0) -/* ========================================================================= */ -/* TEST #1 */ -/* ========================================================================= */ - -#define MAXIMUM 425984U - -static int dump_callback(const size_t index, const char status, const uint64_t value) -{ -#ifndef NDEBUG - printf("%016zX: %c -> %016" PRIX64 "\n", index, status, value); -#else - UNUSED(index); UNUSED(status); UNUSED(value); -#endif - return 1; -} - -static int test_function_1(hash_set64_t *const hash_set) -{ - size_t r, capacity, valid, deleted, limit; - uint64_t i; - uint8_t spinner = 0U; - - for (r = 0U; r < 5U; ++r) - { - for (i = 0; i < MAXIMUM; ++i) - { - if ((i != 3167U) && (i != 9887U) && (i != 185903U) && (i != 387083U)) - { - const errno_t error = hash_set_insert64(hash_set, i); - if (error) - { - printf("Insert operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - } - if (!(++spinner & 0x0F)) - { - PRINT_SET_INFO(1); - } - } - - if (hash_set_size64(hash_set) != MAXIMUM - 4U) - { - puts("Invalid size!"); - return EXIT_FAILURE; - } - - for (i = 0; i < MAXIMUM; ++i) - { - if ((i != 3167U) && (i != 9887U) && (i != 387083U)) - { - const errno_t error = hash_set_insert64(hash_set, i); - if (error != ((i != 185903U) ? EEXIST : 0)) - { - printf("Insert operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - } - } - - if (hash_set_size64(hash_set) != MAXIMUM - 3U) - { - puts("Invalid size!"); - return EXIT_FAILURE; - } - - for (i = 0; i < MAXIMUM; ++i) - { - const errno_t error = hash_set_contains64(hash_set, i); - if (error != ((i != 3167U) && (i != 9887U) && (i != 387083U)) ? 0 : ENOENT) - { - printf("Contains operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - } - - if (hash_set_dump64(hash_set, dump_callback)) - { - puts("Dump operation has failed!"); - return EXIT_FAILURE; - } - - for (i = 0; i < MAXIMUM; ++i) - { - if ((i != 3167U) && (i != 9887U) && (i != 216263U) && (i != 387083U)) - { - const errno_t error = hash_set_remove64(hash_set, i); - if (error) - { - printf("Remove operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - } - if (!(++spinner & 0x0F)) - { - PRINT_SET_INFO(1); - } - } - - if (hash_set_size64(hash_set) != 1U) - { - puts("Invalid size!"); - return EXIT_FAILURE; - } - - for (i = 0; i < MAXIMUM; ++i) - { - const errno_t error = hash_set_contains64(hash_set, i); - if (error != ((i != 216263U) ? ENOENT : 0)) - { - printf("Contains operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - } - - if (!hash_set_remove64(hash_set, 9887U)) - { - puts("Final remove operation has failed!"); - return EXIT_FAILURE; - } - - if (hash_set_remove64(hash_set, 216263U)) - { - puts("Final remove operation has failed!"); - return EXIT_FAILURE; - } - - if (hash_set_size64(hash_set) != 0U) - { - puts("Invalid size!"); - return EXIT_FAILURE; - } - - PRINT_SET_INFO(1); - puts("---------"); - } - - return EXIT_SUCCESS; -} - -/* ========================================================================= */ -/* TEST #2 */ -/* ========================================================================= */ - -#define TEST_SIZE 499979U - -static int test_function_2(hash_set64_t *const hash_set) -{ - size_t r, j, capacity, valid, deleted, limit; - uint64_t value; - uint8_t spinner = 0U, *test1, *test2; - uintptr_t cursor; - - random_t random; - random_init(&random); - - test1 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t)); - if (!test1) - { - abort(); /*malloc has failed!*/ - } - - test2 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t)); - if (!test2) - { - abort(); /*malloc has failed!*/ - } - - for (r = 0U; r < 64U; ++r) - { - memset(test1, 0, TEST_SIZE * sizeof(uint8_t)); - memset(test2, 0, TEST_SIZE * sizeof(uint8_t)); - - for (j = 0U; j < TEST_SIZE / 3U; ++j) - { - size_t rnd; - do - { - rnd = random_next(&random) % TEST_SIZE; - } - while (test1[rnd]); - INVERT(test1[rnd]); - } - - for (j = 0U; j < TEST_SIZE; ++j) - { - if (test1[j]) - { - const errno_t error = hash_set_insert64(hash_set, j); - if (error) - { - printf("Insert operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - if (!(++spinner & 0x0F)) - { - PRINT_SET_INFO(2); - } - } - } - - cursor = 0U; - while (!hash_set_iterate64(hash_set, &cursor, &value)) - { - if ((!test1[value]) || test2[value]) - { - puts("Iteration error has been detected!"); - return EXIT_FAILURE; - } - INVERT(test2[value]); - } - - for (j = 0U; j < TEST_SIZE; ++j) - { - if (test1[j] != test2[j]) - { - puts("Iteration error has been detected!"); - return EXIT_FAILURE; - } - } - - for (j = 0U; j < TEST_SIZE; ++j) - { - if (test1[j]) - { - const errno_t error = hash_set_remove64(hash_set, j); - if (error) - { - printf("Remove operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - if (!(++spinner & 0x0F)) - { - PRINT_SET_INFO(2); - } - } - } - - if (hash_set_size64(hash_set) != 0U) - { - puts("Invalid size!"); - return EXIT_FAILURE; - } - } - - free(test1); - free(test2); - - PRINT_SET_INFO(2); - puts("---------"); - - return EXIT_SUCCESS; -} - -/* ========================================================================= */ -/* TEST #3 */ -/* ========================================================================= */ - -static int test_function_3(hash_set64_t *const hash_set) -{ - size_t r, capacity, valid, deleted, limit; - uint8_t spinner = 0U; - clock_t last_update = clock(); - - random_t random; - random_init(&random); - - for (r = 0U; r < 3U; ++r) - { - for (;;) - { - const uint64_t rnd = random_next(&random) & UINT64_C(0x3FFFFFFFFFFFFFF); - const errno_t error = hash_set_insert64(hash_set, rnd); - if (error) - { - if (error != EEXIST) - { - printf("Insert operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - else - { - PRINT_SET_INFO(3); - printf("Collision detected! [%016" PRIx64 "]\n", rnd); - break; - } - } - if (!(++spinner & 0x7F)) - { - const clock_t clock_now = clock(); - if ((clock_now < last_update) || (clock_now >= last_update + CLOCKS_PER_SEC)) - { - PRINT_SET_INFO(3); - last_update = clock_now; - } - } - } - - PRINT_SET_INFO(3); - - if (hash_set_clear64(hash_set)) - { - puts("Clear operation has failed!"); - return EXIT_FAILURE; - } - } - - PRINT_SET_INFO(3); - puts("---------"); - - return EXIT_SUCCESS; -} - -/* ========================================================================= */ -/* TEST #4 */ -/* ========================================================================= */ - -#define LIMIT (((uint64_t)UINT32_MAX) >> 2) - -static int test_function_4(hash_set64_t *const hash_set) -{ - size_t capacity, valid, deleted, limit; - uint64_t value; - uint8_t spinner = 0U; - clock_t last_update = clock(); - - for (value = 0U; value < LIMIT; ++value) - { - const errno_t error = hash_set_insert64(hash_set, value); - if (error) - { - PRINT_SET_INFO(4); - printf("Insert operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - if (!(++spinner & 0x7F)) - { - const clock_t clock_now = clock(); - if ((clock_now < last_update) || (clock_now >= last_update + CLOCKS_PER_SEC)) - { - PRINT_SET_INFO(4); - last_update = clock_now; - } - } - } - - for (value = 0U; value < LIMIT; ++value) - { - const errno_t error = hash_set_remove64(hash_set, value); - if (error) - { - PRINT_SET_INFO(4); - printf("Remove operation has failed! (error: %d)\n", error); - return EXIT_FAILURE; - } - if (!(++spinner & 0x7F)) - { - const clock_t clock_now = clock(); - if ((clock_now < last_update) || (clock_now >= last_update + CLOCKS_PER_SEC)) - { - PRINT_SET_INFO(4); - last_update = clock_now; - } - } - } - - if (hash_set_size64(hash_set) != 0U) - { - puts("Invalid size!"); - return EXIT_FAILURE; - } - - PRINT_SET_INFO(4); - puts("---------"); - - return EXIT_SUCCESS; -} - /* ========================================================================= */ /* MAIN */ /* ========================================================================= */ @@ -472,32 +34,17 @@ int main(void) return EXIT_FAILURE; } - if (test_function_1(hash_set) != EXIT_SUCCESS) - { - goto failure; - } - - if (test_function_2(hash_set) != EXIT_SUCCESS) - { - goto failure; - } - - if (test_function_3(hash_set) != EXIT_SUCCESS) - { - goto failure; - } - - if (test_function_4(hash_set) != EXIT_SUCCESS) - { - goto failure; - } + RUN_TEST_CASE(1); + RUN_TEST_CASE(2); + RUN_TEST_CASE(3); + RUN_TEST_CASE(4); hash_set_destroy64(hash_set); - puts("Test completed successfully."); + puts("Tests completed successfully."); return EXIT_SUCCESS; failure: hash_set_destroy64(hash_set); - puts("Something went wrong !!!"); + puts("\nSomething went wrong !!!"); return EXIT_FAILURE; } diff --git a/test/src/random.c b/test/src/random.c new file mode 100644 index 0000000..bd13c50 --- /dev/null +++ b/test/src/random.c @@ -0,0 +1,39 @@ +/******************************************************************************/ +/* HashSet for C99, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#include "random.h" +#include + +#ifndef _WIN32 +# include +#endif + +#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0U])) + +#ifdef _WIN32 +#define RtlGenRandom SystemFunction036 +#define getentropy(X,Y) (RtlGenRandom((X),(uint32_t)(Y)) ? 0 : (-1)) +unsigned char __stdcall RtlGenRandom(void* buffer, uint32_t length); +#endif + +void random_init(random_t *const rnd) +{ + memset(rnd, 0, sizeof(random_t)); + rnd->offset = SIZE_MAX; +} + +uint64_t random_next(random_t *const rnd) +{ + if (rnd->offset >= ARRAY_SIZE(rnd->buffer)) + { + rnd->offset = 0U; + if (getentropy(rnd->buffer, sizeof(rnd->buffer)) < 0) + { + abort(); + } + } + + return rnd->buffer[rnd->offset++]; +} diff --git a/test/src/random.h b/test/src/random.h new file mode 100644 index 0000000..f7b698b --- /dev/null +++ b/test/src/random.h @@ -0,0 +1,22 @@ +/******************************************************************************/ +/* HashSet for C99, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef _TEST_RANDOM_INCLUDED +#define _TEST_RANDOM_INCLUDED + +#include +#include + +typedef struct +{ + size_t offset; + uint64_t buffer[16U]; +} +random_t; + +void random_init(random_t *const rnd); +uint64_t random_next(random_t *const rnd); + +#endif /*_TEST_RANDOM_INCLUDED*/ diff --git a/test/src/tests.c b/test/src/tests.c new file mode 100644 index 0000000..1e0adbf --- /dev/null +++ b/test/src/tests.c @@ -0,0 +1,411 @@ +/******************************************************************************/ +/* HashSet for C99, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#include "tests.h" +#include "random.h" + +#include +#include +#include +#include +#include + +#define TEST_COUNT 4 + +/* ========================================================================= */ +/* Utilities */ +/* ========================================================================= */ + +#define UNUSED(X) ((void)X) + +#define INVERT(X) do { (X) = (!(X)); } while(0) + +#define PRINT_SET_INFO(X) do \ +{\ + if (!hash_set_info64(hash_set, &capacity, &valid, &deleted, &limit)) \ + { \ + fprintf(stdout, "[Test %d/%d] capacity: %010zu, valid: %010zu, deleted: %010zu, limit: %010zu\n", (X), TEST_COUNT, capacity, valid, deleted, limit); \ + fflush(stdout); \ + } \ +} \ +while(0) + +/* ========================================================================= */ +/* TEST #1 */ +/* ========================================================================= */ + +#define MAXIMUM 425984U + +static int dump_callback(const size_t index, const char status, const uint64_t value) +{ +#ifndef NDEBUG + printf("%016zX: %c -> %016" PRIX64 "\n", index, status, value); +#else + UNUSED(index); UNUSED(status); UNUSED(value); +#endif + return 1; +} + +int test_function_1(hash_set64_t *const hash_set) +{ + size_t r, capacity, valid, deleted, limit; + uint64_t i; + uint8_t spinner = 0U; + + for (r = 0U; r < 5U; ++r) + { + for (i = 0; i < MAXIMUM; ++i) + { + if ((i != 3167U) && (i != 9887U) && (i != 185903U) && (i != 387083U)) + { + const errno_t error = hash_set_insert64(hash_set, i); + if (error) + { + printf("Insert operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + } + if (!(++spinner & 0x0F)) + { + PRINT_SET_INFO(1); + } + } + + if (hash_set_size64(hash_set) != MAXIMUM - 4U) + { + puts("Invalid size!"); + return EXIT_FAILURE; + } + + for (i = 0; i < MAXIMUM; ++i) + { + if ((i != 3167U) && (i != 9887U) && (i != 387083U)) + { + const errno_t error = hash_set_insert64(hash_set, i); + if (error != ((i != 185903U) ? EEXIST : 0)) + { + printf("Insert operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + } + } + + if (hash_set_size64(hash_set) != MAXIMUM - 3U) + { + puts("Invalid size!"); + return EXIT_FAILURE; + } + + for (i = 0; i < MAXIMUM; ++i) + { + const errno_t error = hash_set_contains64(hash_set, i); + if (error != ((i != 3167U) && (i != 9887U) && (i != 387083U)) ? 0 : ENOENT) + { + printf("Contains operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + } + + if (hash_set_dump64(hash_set, dump_callback)) + { + puts("Dump operation has failed!"); + return EXIT_FAILURE; + } + + for (i = 0; i < MAXIMUM; ++i) + { + if ((i != 3167U) && (i != 9887U) && (i != 216263U) && (i != 387083U)) + { + const errno_t error = hash_set_remove64(hash_set, i); + if (error) + { + printf("Remove operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + } + if (!(++spinner & 0x0F)) + { + PRINT_SET_INFO(1); + } + } + + if (hash_set_size64(hash_set) != 1U) + { + puts("Invalid size!"); + return EXIT_FAILURE; + } + + for (i = 0; i < MAXIMUM; ++i) + { + const errno_t error = hash_set_contains64(hash_set, i); + if (error != ((i != 216263U) ? ENOENT : 0)) + { + printf("Contains operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + } + + if (!hash_set_remove64(hash_set, 9887U)) + { + puts("Final remove operation has failed!"); + return EXIT_FAILURE; + } + + if (hash_set_remove64(hash_set, 216263U)) + { + puts("Final remove operation has failed!"); + return EXIT_FAILURE; + } + + if (hash_set_size64(hash_set) != 0U) + { + puts("Invalid size!"); + return EXIT_FAILURE; + } + + PRINT_SET_INFO(1); + puts("---------"); + } + + return EXIT_SUCCESS; +} + +/* ========================================================================= */ +/* TEST #2 */ +/* ========================================================================= */ + +#define TEST_SIZE 499979U + +int test_function_2(hash_set64_t *const hash_set) +{ + size_t r, j, capacity, valid, deleted, limit; + uint64_t value; + uint8_t spinner = 0U, *test1, *test2; + uintptr_t cursor; + + random_t random; + random_init(&random); + + test1 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t)); + if (!test1) + { + abort(); /*malloc has failed!*/ + } + + test2 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t)); + if (!test2) + { + abort(); /*malloc has failed!*/ + } + + for (r = 0U; r < 64U; ++r) + { + memset(test1, 0, TEST_SIZE * sizeof(uint8_t)); + memset(test2, 0, TEST_SIZE * sizeof(uint8_t)); + + for (j = 0U; j < TEST_SIZE / 3U; ++j) + { + size_t rnd; + do + { + rnd = random_next(&random) % TEST_SIZE; + } + while (test1[rnd]); + INVERT(test1[rnd]); + } + + for (j = 0U; j < TEST_SIZE; ++j) + { + if (test1[j]) + { + const errno_t error = hash_set_insert64(hash_set, j); + if (error) + { + printf("Insert operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + if (!(++spinner & 0x0F)) + { + PRINT_SET_INFO(2); + } + } + } + + cursor = 0U; + while (!hash_set_iterate64(hash_set, &cursor, &value)) + { + if ((!test1[value]) || test2[value]) + { + puts("Iteration error has been detected!"); + return EXIT_FAILURE; + } + INVERT(test2[value]); + } + + for (j = 0U; j < TEST_SIZE; ++j) + { + if (test1[j] != test2[j]) + { + puts("Iteration error has been detected!"); + return EXIT_FAILURE; + } + } + + for (j = 0U; j < TEST_SIZE; ++j) + { + if (test1[j]) + { + const errno_t error = hash_set_remove64(hash_set, j); + if (error) + { + printf("Remove operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + if (!(++spinner & 0x0F)) + { + PRINT_SET_INFO(2); + } + } + } + + if (hash_set_size64(hash_set) != 0U) + { + puts("Invalid size!"); + return EXIT_FAILURE; + } + } + + free(test1); + free(test2); + + PRINT_SET_INFO(2); + puts("---------"); + + return EXIT_SUCCESS; +} + +/* ========================================================================= */ +/* TEST #3 */ +/* ========================================================================= */ + +int test_function_3(hash_set64_t *const hash_set) +{ + size_t r, capacity, valid, deleted, limit; + uint8_t spinner = 0U; + clock_t last_update = clock(); + + random_t random; + random_init(&random); + + for (r = 0U; r < 3U; ++r) + { + for (;;) + { + const uint64_t rnd = random_next(&random) & UINT64_C(0x3FFFFFFFFFFFFFF); + const errno_t error = hash_set_insert64(hash_set, rnd); + if (error) + { + if (error != EEXIST) + { + printf("Insert operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + else + { + PRINT_SET_INFO(3); + printf("Collision detected! [%016" PRIx64 "]\n", rnd); + break; + } + } + if (!(++spinner & 0x7F)) + { + const clock_t clock_now = clock(); + if ((clock_now < last_update) || (clock_now >= last_update + CLOCKS_PER_SEC)) + { + PRINT_SET_INFO(3); + last_update = clock_now; + } + } + } + + PRINT_SET_INFO(3); + + if (hash_set_clear64(hash_set)) + { + puts("Clear operation has failed!"); + return EXIT_FAILURE; + } + } + + PRINT_SET_INFO(3); + puts("---------"); + + return EXIT_SUCCESS; +} + +/* ========================================================================= */ +/* TEST #4 */ +/* ========================================================================= */ + +#define LIMIT (((uint64_t)UINT32_MAX) >> 2) + +int test_function_4(hash_set64_t *const hash_set) +{ + size_t capacity, valid, deleted, limit; + uint64_t value; + uint8_t spinner = 0U; + clock_t last_update = clock(); + + for (value = 0U; value < LIMIT; ++value) + { + const errno_t error = hash_set_insert64(hash_set, value); + if (error) + { + PRINT_SET_INFO(4); + printf("Insert operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + if (!(++spinner & 0x7F)) + { + const clock_t clock_now = clock(); + if ((clock_now < last_update) || (clock_now >= last_update + CLOCKS_PER_SEC)) + { + PRINT_SET_INFO(4); + last_update = clock_now; + } + } + } + + for (value = 0U; value < LIMIT; ++value) + { + const errno_t error = hash_set_remove64(hash_set, value); + if (error) + { + PRINT_SET_INFO(4); + printf("Remove operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; + } + if (!(++spinner & 0x7F)) + { + const clock_t clock_now = clock(); + if ((clock_now < last_update) || (clock_now >= last_update + CLOCKS_PER_SEC)) + { + PRINT_SET_INFO(4); + last_update = clock_now; + } + } + } + + if (hash_set_size64(hash_set) != 0U) + { + puts("Invalid size!"); + return EXIT_FAILURE; + } + + PRINT_SET_INFO(4); + puts("---------"); + + return EXIT_SUCCESS; +} diff --git a/test/src/tests.h b/test/src/tests.h new file mode 100644 index 0000000..9d6d7f7 --- /dev/null +++ b/test/src/tests.h @@ -0,0 +1,16 @@ +/******************************************************************************/ +/* HashSet for C99, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef _TEST_TESTS_INCLUDED +#define _TEST_TESTS_INCLUDED + +#include + +int test_function_1(hash_set64_t *const hash_set); +int test_function_2(hash_set64_t *const hash_set); +int test_function_3(hash_set64_t *const hash_set); +int test_function_4(hash_set64_t *const hash_set); + +#endif /*_TEST_TESTS_INCLUDED*/