Improved hash-map tests.

This commit is contained in:
LoRd_MuldeR 2022-11-30 18:03:42 +01:00
parent cb898fc8a6
commit 58fdfcb573
8 changed files with 297 additions and 47 deletions

View File

@ -3,7 +3,7 @@ SUBDIRS := libhashset example test
BUILD_ALL := $(patsubst %,build\:%,$(SUBDIRS)) BUILD_ALL := $(patsubst %,build\:%,$(SUBDIRS))
CLEAN_ALL := $(patsubst %,clean\:%,$(SUBDIRS)) CLEAN_ALL := $(patsubst %,clean\:%,$(SUBDIRS))
.PHONY: all clean $(BUILD_ALL) $(CLEAN_ALL) .PHONY: all test clean $(BUILD_ALL) $(CLEAN_ALL)
all: $(BUILD_ALL) all: $(BUILD_ALL)
@ -14,3 +14,6 @@ $(BUILD_ALL):
$(CLEAN_ALL): $(CLEAN_ALL):
$(MAKE) -C $(patsubst clean:%,%,$@) clean $(MAKE) -C $(patsubst clean:%,%,$@) clean
test: $(BUILD_ALL)
$(MAKE) -C test test

View File

@ -1,16 +1,22 @@
SUBDIRS := hash-set SUBDIRS := hash-set hash-map
BUILD_ALL := $(patsubst %,build\:%,$(SUBDIRS)) BUILD_ALL := $(patsubst %,build\:%,$(SUBDIRS))
CLEAN_ALL := $(patsubst %,clean\:%,$(SUBDIRS)) CLEAN_ALL := $(patsubst %,clean\:%,$(SUBDIRS))
TESTS_ALL := $(patsubst %,rtest\:%,$(SUBDIRS))
.PHONY: all clean $(BUILD_ALL) $(CLEAN_ALL) .PHONY: all clean test $(BUILD_ALL) $(CLEAN_ALL) $(TESTS_ALL)
all: $(BUILD_ALL) all: $(BUILD_ALL)
clean: $(CLEAN_ALL) clean: $(CLEAN_ALL)
test: $(TESTS_ALL)
$(BUILD_ALL): $(BUILD_ALL):
$(MAKE) -C $(patsubst build:%,%,$@) $(MAKE) -C $(patsubst build:%,%,$@)
$(CLEAN_ALL): $(CLEAN_ALL):
$(MAKE) -C $(patsubst clean:%,%,$@) clean $(MAKE) -C $(patsubst clean:%,%,$@) clean
$(TESTS_ALL):
$(MAKE) -C $(patsubst rtest:%,%,$@) test

View File

@ -10,7 +10,7 @@ ALL_PATH := $(SRC_PATH) $(BIN_PATH)
BIN_FILE := $(BIN_PATH)/test-hash-set$(EXE_SUFFIX) BIN_FILE := $(BIN_PATH)/test-hash-set$(EXE_SUFFIX)
SRC_FILE := $(wildcard $(SRC_PATH)/*.c) SRC_FILE := $(wildcard $(SRC_PATH)/*.c)
.PHONY: all build clean .PHONY: all build clean test
all: clean build all: clean build
@ -24,3 +24,6 @@ $(ALL_PATH):
clean: clean:
rm -vf $(BIN_FILE) rm -vf $(BIN_FILE)
test: build
./$(BIN_FILE)

View File

@ -35,6 +35,8 @@ int main(void)
} }
RUN_TEST_CASE(1); RUN_TEST_CASE(1);
RUN_TEST_CASE(2);
RUN_TEST_CASE(3);
hash_map_destroy64(hash_set); hash_map_destroy64(hash_set);
puts("Tests completed successfully."); puts("Tests completed successfully.");

View File

@ -12,7 +12,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#define TEST_COUNT 4 #define TEST_COUNT 3
/* ========================================================================= */ /* ========================================================================= */
/* Utilities */ /* Utilities */
@ -41,28 +41,35 @@ while(0)
int test_function_1(hash_map64_t *const hash_set) int test_function_1(hash_map64_t *const hash_set)
{ {
size_t r, j, cursor, capacity, valid, deleted, limit; size_t r, j, cursor, capacity, valid, deleted, limit;
uint64_t key, value; uint64_t key, value, *test_data;
uint8_t spinner = 0U, *test1, *test2; uint8_t spinner = 0U, *test_key1, *test_key2;
random_t random; random_t random;
random_init(&random); random_init(&random);
test1 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t)); test_key1 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t));
if (!test1) if (!test_key1)
{ {
abort(); /*malloc has failed!*/ abort(); /*malloc has failed!*/
} }
test2 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t)); test_key2 = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t));
if (!test2) if (!test_key2)
{
abort(); /*malloc has failed!*/
}
test_data = (uint64_t*) malloc(TEST_SIZE * sizeof(uint64_t));
if (!test_data)
{ {
abort(); /*malloc has failed!*/ abort(); /*malloc has failed!*/
} }
for (r = 0U; r < 64U; ++r) for (r = 0U; r < 64U; ++r)
{ {
memset(test1, 0, TEST_SIZE * sizeof(uint8_t)); memset(test_key1, 0, TEST_SIZE * sizeof(uint8_t));
memset(test2, 0, TEST_SIZE * sizeof(uint8_t)); memset(test_key2, 0, TEST_SIZE * sizeof(uint8_t));
memset(test_data, 0, TEST_SIZE * sizeof(uint64_t));
for (j = 0U; j < TEST_SIZE / 3U; ++j) for (j = 0U; j < TEST_SIZE / 3U; ++j)
{ {
@ -71,15 +78,167 @@ int test_function_1(hash_map64_t *const hash_set)
{ {
rnd = random_next(&random) % TEST_SIZE; rnd = random_next(&random) % TEST_SIZE;
} }
while (test1[rnd]); while (test_key1[rnd]);
INVERT(test1[rnd]); INVERT(test_key1[rnd]);
} }
for (j = 0U; j < TEST_SIZE; ++j) for (j = 0U; j < TEST_SIZE; ++j)
{ {
if (test1[j]) if (test_key1[j])
{ {
const errno_t error = hash_map_insert64(hash_set, j, 0U); const errno_t error = hash_map_insert64(hash_set, j, test_data[j] = random_next(&random));
if (error)
{
printf("Insert operation has failed! (error: %d)\n", error);
return EXIT_FAILURE;
}
if (!(++spinner & 0x0F))
{
PRINT_SET_INFO(1);
}
}
}
for (j = 0U; j < TEST_SIZE; ++j)
{
const errno_t error = hash_map_contains64(hash_set, j);
if (error != (test_key1[j] ? 0 : ENOENT))
{
printf("Contains operation has failed! (error: %d)\n", error);
return EXIT_FAILURE;
}
}
cursor = 0U;
while (!hash_map_iterate64(hash_set, &cursor, &key, &value))
{
if ((!test_key1[key]) || test_key2[key])
{
puts("Iteration error has been detected!");
return EXIT_FAILURE;
}
INVERT(test_key2[key]);
}
for (j = 0U; j < TEST_SIZE; ++j)
{
if (test_key1[j] != test_key2[j])
{
puts("Iteration error has been detected!");
return EXIT_FAILURE;
}
}
for (j = 0U; j < TEST_SIZE; ++j)
{
if (test_key1[j])
{
if (!hash_map_get64(hash_set, j, &value))
{
if (value != test_data[j])
{
puts("Value mismatch has been detected!");
return EXIT_FAILURE;
}
}
else
{
puts("Failed to retrieve the value!");
return EXIT_FAILURE;
}
}
}
for (j = 0U; j < TEST_SIZE; ++j)
{
if (test_key1[j])
{
const errno_t error = hash_map_remove64(hash_set, j);
if (error)
{
printf("Remove operation has failed! (error: %d)\n", error);
return EXIT_FAILURE;
}
if (!(++spinner & 0x0F))
{
PRINT_SET_INFO(1);
}
}
}
for (j = 0U; j < TEST_SIZE; ++j)
{
const errno_t error = hash_map_contains64(hash_set, j);
if (error != ENOENT)
{
printf("Contains operation has failed! (error: %d)\n", error);
return EXIT_FAILURE;
}
}
if (hash_map_size64(hash_set) != 0U)
{
puts("Invalid size!");
return EXIT_FAILURE;
}
}
free(test_key1);
free(test_key2);
free(test_data);
PRINT_SET_INFO(1);
puts("---------");
return EXIT_SUCCESS;
}
/* ========================================================================= */
/* TEST #2 */
/* ========================================================================= */
int test_function_2(hash_map64_t *const hash_set)
{
size_t r, j, capacity, valid, deleted, limit;
uint64_t value, *test_val;
uint8_t spinner = 0U, *test_key;
random_t random;
random_init(&random);
test_key = (uint8_t*) malloc(TEST_SIZE * sizeof(uint8_t));
if (!test_key)
{
abort(); /*malloc has failed!*/
}
test_val = (uint64_t*) malloc(TEST_SIZE * sizeof(uint64_t));
if (!test_val)
{
abort(); /*malloc has failed!*/
}
for (r = 0U; r < 64U; ++r)
{
memset(test_key, 0, TEST_SIZE * sizeof(uint8_t));
memset(test_val, 0, TEST_SIZE * sizeof(uint64_t));
for (j = 0U; j < TEST_SIZE / 3U; ++j)
{
size_t rnd;
do
{
rnd = random_next(&random) % TEST_SIZE;
}
while (test_key[rnd]);
INVERT(test_key[rnd]);
}
for (j = 0U; j < TEST_SIZE; ++j)
{
if (test_key[j])
{
const errno_t error = hash_map_insert64(hash_set, j, test_val[j] = random_next(&random));
if (error) if (error)
{ {
printf("Insert operation has failed! (error: %d)\n", error); printf("Insert operation has failed! (error: %d)\n", error);
@ -92,34 +251,14 @@ int test_function_1(hash_map64_t *const hash_set)
} }
} }
cursor = 0U;
while (!hash_map_iterate64(hash_set, &cursor, &key, &value))
{
if ((!test1[key]) || test2[key])
{
puts("Iteration error has been detected!");
return EXIT_FAILURE;
}
INVERT(test2[key]);
}
for (j = 0U; j < TEST_SIZE; ++j) for (j = 0U; j < TEST_SIZE; ++j)
{ {
if (test1[j] != test2[j]) if (test_key[j])
{ {
puts("Iteration error has been detected!"); const errno_t error = hash_map_insert64(hash_set, j, test_val[j] = random_next(&random));
return EXIT_FAILURE; if (error != EEXIST)
}
}
for (j = 0U; j < TEST_SIZE; ++j)
{ {
if (test1[j]) printf("Insert operation has failed! (error: %d)\n", error);
{
const errno_t error = hash_map_remove64(hash_set, j);
if (error)
{
printf("Remove operation has failed! (error: %d)\n", error);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!(++spinner & 0x0F)) if (!(++spinner & 0x0F))
@ -129,18 +268,110 @@ int test_function_1(hash_map64_t *const hash_set)
} }
} }
if (hash_map_size64(hash_set) != 0U) for (j = 0U; j < TEST_SIZE; ++j)
{ {
puts("Invalid size!"); if (test_key[j])
{
if (!hash_map_get64(hash_set, j, &value))
{
if (value != test_val[j])
{
puts("Value mismatch has been detected!");
return EXIT_FAILURE;
}
}
else
{
puts("Failed to retrieve the value!");
return EXIT_FAILURE;
}
}
}
if (hash_map_clear64(hash_set))
{
puts("Failed to clear the map!");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
free(test1); free(test_key);
free(test2); free(test_val);
PRINT_SET_INFO(2); PRINT_SET_INFO(2);
puts("---------"); puts("---------");
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* ========================================================================= */
/* TEST #3 */
/* ========================================================================= */
#define VALUE(X) (((X) ^ UINT64_C(0xB7E151628AED2A6A)) * UINT64_C(65599))
int test_function_3(hash_map64_t *const hash_set)
{
size_t r, cursor, capacity, valid, deleted, limit;
uint8_t spinner = 0U;
clock_t last_update = clock();
uint64_t key, value;
random_t random;
random_init(&random);
for (r = 0U; r < 3U; ++r)
{
for (;;)
{
const uint64_t rnd = random_next(&random) & UINT64_C(0x1FFFFFFFFFFFFFF);
const errno_t error = hash_map_insert64(hash_set, rnd, VALUE(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! [0x%016" PRIX64 "]\n", rnd);
cursor = 0U;
while (!hash_map_iterate64(hash_set, &cursor, &key, &value))
{
if (value != VALUE(key))
{
puts("Value mismatch has been detected!");
return EXIT_FAILURE;
}
}
puts("Value verification successful.");
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_map_clear64(hash_set))
{
puts("Clear operation has failed!");
return EXIT_FAILURE;
}
}
PRINT_SET_INFO(3);
puts("---------");
return EXIT_SUCCESS;
}

View File

@ -9,5 +9,7 @@
#include <hash_map.h> #include <hash_map.h>
int test_function_1(hash_map64_t *const hash_set); int test_function_1(hash_map64_t *const hash_set);
int test_function_2(hash_map64_t *const hash_set);
int test_function_3(hash_map64_t *const hash_set);
#endif /*_TEST_TESTS_INCLUDED*/ #endif /*_TEST_TESTS_INCLUDED*/

View File

@ -10,7 +10,7 @@ ALL_PATH := $(SRC_PATH) $(BIN_PATH)
BIN_FILE := $(BIN_PATH)/test-hash-set$(EXE_SUFFIX) BIN_FILE := $(BIN_PATH)/test-hash-set$(EXE_SUFFIX)
SRC_FILE := $(wildcard $(SRC_PATH)/*.c) SRC_FILE := $(wildcard $(SRC_PATH)/*.c)
.PHONY: all build clean .PHONY: all build clean test
all: clean build all: clean build
@ -24,3 +24,6 @@ $(ALL_PATH):
clean: clean:
rm -vf $(BIN_FILE) rm -vf $(BIN_FILE)
test: build
./$(BIN_FILE)

View File

@ -314,7 +314,7 @@ int test_function_3(hash_set64_t *const hash_set)
else else
{ {
PRINT_SET_INFO(3); PRINT_SET_INFO(3);
printf("Collision detected! [%016" PRIx64 "]\n", rnd); printf("Collision detected! [0x%016" PRIX64 "]\n", rnd);
break; break;
} }
} }