Added unit tests for Map data type and fixed other issues
This commit is contained in:
340
tests/test_map.c
Normal file
340
tests/test_map.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Unit tests for Map data type
|
||||
*/
|
||||
|
||||
#define TEST(NAME) do { \
|
||||
printf("Running test_%s...", #NAME); \
|
||||
test_##NAME(); \
|
||||
printf(" PASSED\n"); \
|
||||
} while(0)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../src/map.h"
|
||||
|
||||
// Create a new map
|
||||
void test_map_new() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
assert(res.value.map != NULL);
|
||||
assert(map_size(res.value.map) == 0);
|
||||
assert(map_capacity(res.value.map) > 0);
|
||||
|
||||
map_destroy(res.value.map);
|
||||
}
|
||||
|
||||
// Add elements to map
|
||||
void test_map_add() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
int x = 42, y = 84;
|
||||
|
||||
map_result_t x_res = map_add(map, "key1", &x);
|
||||
assert(x_res.status == MAP_OK);
|
||||
assert(map_size(map) == 1);
|
||||
|
||||
map_result_t y_res = map_add(map, "key2", &y);
|
||||
assert(y_res.status == MAP_OK);
|
||||
assert(map_size(map) == 2);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Add multiple elements to the map
|
||||
void test_map_add_multiple() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
const int x = 0xB00B5;
|
||||
const char *y = "Hello";
|
||||
|
||||
map_result_t add_res = map_add(map, "x", (void*)&x);
|
||||
assert(add_res.status == MAP_OK);
|
||||
|
||||
add_res = map_add(map, "y", (void*)y);
|
||||
assert(add_res.status == MAP_OK);
|
||||
|
||||
assert(map_size(map) == 2);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Get map element
|
||||
void test_map_get() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
int val = 123;
|
||||
map_add(map, "test", &val);
|
||||
|
||||
map_result_t get_res = map_get(map, "test");
|
||||
assert(get_res.status == MAP_OK);
|
||||
assert(*(int*)get_res.value.element == 123);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Get non-existing key from map
|
||||
void test_map_get_invalid() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
map_result_t get_res = map_get(map, "boom");
|
||||
assert(get_res.status == MAP_ERR_NOT_FOUND);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Map with heterogeneous types
|
||||
void test_map_mixed() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
const int x = 0xB00B5;
|
||||
const char *y = "Hello";
|
||||
|
||||
map_add(map, "x", (void*)&x);
|
||||
map_add(map, "y", (void*)y);
|
||||
|
||||
map_result_t get_res = map_get(map, "x");
|
||||
assert(get_res.status == MAP_OK);
|
||||
|
||||
const int *val_x = (const int*)get_res.value.element;
|
||||
assert(*val_x == 0xB00B5);
|
||||
|
||||
get_res = map_get(map, "y");
|
||||
assert(get_res.status == MAP_OK);
|
||||
|
||||
const char *val_y = (const char*)get_res.value.element;
|
||||
assert(!strcmp(val_y, "Hello"));
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Update existing map key
|
||||
void test_map_update() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
const int x = 100, y = 200;
|
||||
|
||||
map_add(map, "key", (void*)&x);
|
||||
|
||||
map_result_t set_res = map_add(map, "key", (void*)&y);
|
||||
assert(set_res.status == MAP_OK);
|
||||
|
||||
map_result_t get_res = map_get(map, "key");
|
||||
const int *val = (const int*)get_res.value.element;
|
||||
|
||||
assert(*val == 200);
|
||||
assert(map_size(map) == 1);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Remove an element from map
|
||||
void test_map_remove() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
const int x = 10, y = 20;
|
||||
|
||||
map_add(map, "x", (void*)&x);
|
||||
map_add(map, "y", (void*)&y);
|
||||
|
||||
assert(map_size(map) == 2);
|
||||
|
||||
map_result_t rm_res = map_remove(map, "x");
|
||||
assert(rm_res.status == MAP_OK);
|
||||
assert(map_size(map) == 1);
|
||||
|
||||
// Check whether the 'x' and 'y' keysx is still there
|
||||
map_result_t get_res = map_get(map, "x");
|
||||
assert(get_res.status != MAP_OK);
|
||||
|
||||
get_res = map_get(map, "y");
|
||||
assert(get_res.status == MAP_OK);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Remove non-existing key from map
|
||||
void test_map_remove_invalid() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
map_result_t rm_res = map_remove(map, "boom");
|
||||
assert(rm_res.status != MAP_OK);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Clear the map
|
||||
void test_map_clear() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
int x = 10, y = 20, z = 30;
|
||||
|
||||
map_add(map, "x", (void*)&x);
|
||||
map_add(map, "y", (void*)&y);
|
||||
map_add(map, "z", (void*)&z);
|
||||
|
||||
assert(map_size(map) == 3);
|
||||
|
||||
map_result_t clear_res = map_clear(map);
|
||||
assert(clear_res.status == MAP_OK);
|
||||
assert(map_size(map) == 0);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Clear empty map
|
||||
void test_map_clear_empty() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
map_result_t clear_res = map_clear(map);
|
||||
assert(clear_res.status == MAP_OK);
|
||||
assert(map_size(map) == 0);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Multiple operations in sequence (add, update, delete and clear)
|
||||
void test_map_sequence() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
const int x = 0xB00B5;
|
||||
const char *y = "Hello";
|
||||
|
||||
// Add
|
||||
map_add(map, "x", (void*)&x);
|
||||
map_add(map, "y", (void*)&y);
|
||||
|
||||
assert(map_size(map) == 2);
|
||||
|
||||
// Update
|
||||
const int new_x = 0xC0FFEE;
|
||||
map_add(map, "x", (void*)&new_x);
|
||||
|
||||
map_result_t get_res = map_get(map, "x");
|
||||
assert(*(const int*)get_res.value.element == 0xC0FFEE);
|
||||
|
||||
// Delete
|
||||
map_remove(map, "y");
|
||||
assert(map_size(map) == 1);
|
||||
|
||||
// Clear
|
||||
map_clear(map);
|
||||
assert(map_size(map) == 0);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Test map with product data types
|
||||
typedef struct {
|
||||
char name[256];
|
||||
char surname[256];
|
||||
short age;
|
||||
} Person;
|
||||
|
||||
void test_map_struct() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
Person bob = { "Bob", "Miller", 23 };
|
||||
Person alice = { "Alice", "Davis", 21 };
|
||||
|
||||
map_add(map, "af94rt", &bob);
|
||||
map_add(map, "b910o5", &alice);
|
||||
|
||||
map_result_t get_res = map_get(map, "af94rt");
|
||||
assert(get_res.status == MAP_OK);
|
||||
|
||||
Person *retr = (Person*)get_res.value.element;
|
||||
assert(!strcmp(retr->name, "Bob"));
|
||||
assert(!strcmp(retr->surname, "Miller"));
|
||||
assert(retr->age == 23);
|
||||
|
||||
get_res = map_get(map, "b910o5");
|
||||
assert(get_res.status == MAP_OK);
|
||||
|
||||
retr = (Person*)get_res.value.element;
|
||||
assert(!strcmp(retr->name, "Alice"));
|
||||
assert(!strcmp(retr->surname, "Davis"));
|
||||
assert(retr->age == 21);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
// Test map capacity tracking
|
||||
void test_map_cap() {
|
||||
map_result_t res = map_new();
|
||||
|
||||
assert(res.status == MAP_OK);
|
||||
map_t *map = res.value.map;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
char key[16];
|
||||
snprintf(key, sizeof(key), "key%d", i);
|
||||
map_add(map, key, &i);
|
||||
}
|
||||
|
||||
assert(map_size(map) == 10);
|
||||
assert(map_capacity(map) >= 10);
|
||||
|
||||
map_destroy(map);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
printf("=== Running Map unit tests ===\n\n");
|
||||
|
||||
TEST(map_new);
|
||||
TEST(map_add);
|
||||
TEST(map_add_multiple);
|
||||
TEST(map_get);
|
||||
TEST(map_get_invalid);
|
||||
TEST(map_mixed);
|
||||
TEST(map_update);
|
||||
TEST(map_remove);
|
||||
TEST(map_remove_invalid);
|
||||
TEST(map_clear);
|
||||
TEST(map_clear_empty);
|
||||
TEST(map_sequence);
|
||||
TEST(map_struct);
|
||||
TEST(map_cap);
|
||||
|
||||
printf("\n=== All tests passed! ===\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user