Improved hash-map tests.
This commit is contained in:
parent
cb898fc8a6
commit
58fdfcb573
5
Makefile
5
Makefile
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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.");
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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*/
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user