Clean up "test" and "example" projects.

This commit is contained in:
LoRd_MuldeR 2022-11-29 15:23:06 +01:00
parent 34c9d3a99c
commit 93a286563a
15 changed files with 602 additions and 513 deletions

View File

@ -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

View File

@ -39,6 +39,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\input.c" />
<ClCompile Include="src\main.c" />
</ItemGroup>
<ItemGroup>
@ -46,6 +47,9 @@
<Project>{8cf3bd19-28b1-435d-b719-e00b052dfc3a}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\input.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>

View File

@ -18,5 +18,13 @@
<ClCompile Include="src\main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\input.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\input.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

50
example/src/input.c Normal file
View File

@ -0,0 +1,50 @@
/******************************************************************************/
/* HashSet for C99, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* 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;
}

15
example/src/input.h Normal file
View File

@ -0,0 +1,15 @@
/******************************************************************************/
/* HashSet for C99, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
#ifndef _EXAMPLE_INPUT_INCLUDED
#define _EXAMPLE_INPUT_INCLUDED
#include <stdlib.h>
#include <stdint.h>
int have_more_items(const size_t offset);
uint64_t get_next_item(const size_t offset);
#endif /*_EXAMPLE_INPUT_INCLUDED*/

View File

@ -6,50 +6,7 @@
#include <hash_set.h>
#include <stdio.h>
#include <inttypes.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),
};
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 */

View File

@ -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))),)

View File

@ -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

View File

@ -40,12 +40,18 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\main.c" />
<ClCompile Include="src\random.c" />
<ClCompile Include="src\tests.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libhashset\libhashset.vcxproj">
<Project>{8cf3bd19-28b1-435d-b719-e00b052dfc3a}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\random.h" />
<ClInclude Include="src\tests.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>

View File

@ -18,5 +18,19 @@
<ClCompile Include="src\main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\random.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\tests.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\random.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\tests.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -3,457 +3,19 @@
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
#include <hash_set.h>
#include "tests.h"
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#ifndef _WIN32
# include <unistd.h>
#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 \
#define RUN_TEST_CASE(X) do \
{ \
if (!hash_set_info64(hash_set, &capacity, &valid, &deleted, &limit)) \
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;
}

39
test/src/random.c Normal file
View File

@ -0,0 +1,39 @@
/******************************************************************************/
/* HashSet for C99, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
#include "random.h"
#include <string.h>
#ifndef _WIN32
# include <unistd.h>
#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++];
}

22
test/src/random.h Normal file
View File

@ -0,0 +1,22 @@
/******************************************************************************/
/* HashSet for C99, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
#ifndef _TEST_RANDOM_INCLUDED
#define _TEST_RANDOM_INCLUDED
#include <stdlib.h>
#include <stdint.h>
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*/

411
test/src/tests.c Normal file
View File

@ -0,0 +1,411 @@
/******************************************************************************/
/* HashSet for C99, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
#include "tests.h"
#include "random.h"
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#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;
}

16
test/src/tests.h Normal file
View File

@ -0,0 +1,16 @@
/******************************************************************************/
/* HashSet for C99, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
#ifndef _TEST_TESTS_INCLUDED
#define _TEST_TESTS_INCLUDED
#include <hash_set.h>
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*/