#include "maxminddb_test_helper.h"
MMDB_entry_data_list_s *test_array_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *array = entry_data_list = entry_data_list->next;
cmp_ok(array->entry_data.type, "==", MMDB_DATA_TYPE_ARRAY,
"'array' key's value is an array");
cmp_ok(array->entry_data.data_size, "==", 3,
"'array' key's value has 3 elements");
MMDB_entry_data_list_s *idx0 = entry_data_list = entry_data_list->next;
cmp_ok(idx0->entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
"first array entry is a UINT32");
cmp_ok(idx0->entry_data.uint32, "==", 1, "first array entry value is 1");
MMDB_entry_data_list_s *idx1 = entry_data_list = entry_data_list->next;
cmp_ok(idx1->entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
"second array entry is a UINT32");
cmp_ok(idx1->entry_data.uint32, "==", 2, "second array entry value is 2");
MMDB_entry_data_list_s *idx2 = entry_data_list = entry_data_list->next;
cmp_ok(idx2->entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
"third array entry is a UINT32");
cmp_ok(idx2->entry_data.uint32, "==", 3, "third array entry value is 3");
return entry_data_list;
}
MMDB_entry_data_list_s *test_boolean_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_BOOLEAN,
"'boolean' key's value is a boolean");
ok(value->entry_data.boolean, "'boolean' key's value is true");
return entry_data_list;
}
MMDB_entry_data_list_s *test_bytes_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_BYTES,
"'bytes' key's value is bytes");
uint8_t *bytes = malloc(value->entry_data.data_size);
if (NULL == bytes) {
BAIL_OUT("malloc failed");
}
memcpy(bytes, value->entry_data.bytes, value->entry_data.data_size);
uint8_t expect[] = { 0x00, 0x00, 0x00, 0x2a };
ok(memcmp(bytes, expect, 4) == 0, "got expected value for bytes key");
free((void *)bytes);
return entry_data_list;
}
MMDB_entry_data_list_s *test_double_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_DOUBLE,
"'double' key's value is a double");
compare_double(value->entry_data.double_value, 42.123456);
return entry_data_list;
}
MMDB_entry_data_list_s *test_float_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_FLOAT,
"'float' key's value is a float");
compare_float(value->entry_data.float_value, 1.1F);
return entry_data_list;
}
MMDB_entry_data_list_s *test_int32_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_INT32,
"'int32' key's value is an int32");
int32_t expect = 1 << 28;
expect *= -1;
cmp_ok(value->entry_data.int32, "==", expect,
"got expected value for int32 key");
return entry_data_list;
}
MMDB_entry_data_list_s *test_arrayX_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *arrayX = entry_data_list = entry_data_list->next;
cmp_ok(arrayX->entry_data.type, "==", MMDB_DATA_TYPE_ARRAY,
"'map{mapX}{arrayX}' key's value is an array");
cmp_ok(arrayX->entry_data.data_size, "==", 3,
"'map{mapX}{arrayX}' key's value has 3 elements");
MMDB_entry_data_list_s *idx0 = entry_data_list = entry_data_list->next;
cmp_ok(idx0->entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
"first array entry is a UINT32");
cmp_ok(idx0->entry_data.uint32, "==", 7, "first array entry value is 7");
MMDB_entry_data_list_s *idx1 = entry_data_list = entry_data_list->next;
cmp_ok(idx1->entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
"second array entry is a UINT32");
cmp_ok(idx1->entry_data.uint32, "==", 8, "second array entry value is 8");
MMDB_entry_data_list_s *idx2 = entry_data_list = entry_data_list->next;
cmp_ok(idx2->entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
"third array entry is a UINT32");
cmp_ok(idx2->entry_data.uint32, "==", 9, "third array entry value is 9");
return entry_data_list;
}
MMDB_entry_data_list_s *test_mapX_key_value_pair(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *mapX_key = entry_data_list = entry_data_list->next;
cmp_ok(mapX_key->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
"found a map key in 'map{mapX}'");
const char *mapX_key_name = dup_entry_string_or_bail(mapX_key->entry_data);
if (strcmp(mapX_key_name, "utf8_stringX") == 0) {
MMDB_entry_data_list_s *mapX_value =
entry_data_list = entry_data_list->next;
cmp_ok(mapX_value->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
"'map{mapX}{utf8_stringX}' type is utf8_string");
const char *utf8_stringX_value = dup_entry_string_or_bail(
mapX_value->entry_data);
ok(strcmp(utf8_stringX_value, "hello") == 0,
"map{mapX}{utf8_stringX} value is 'hello'");
free((void *)utf8_stringX_value);
} else if (strcmp(mapX_key_name, "arrayX") == 0) {
entry_data_list = test_arrayX_value(entry_data_list);
} else {
ok(0, "unknown key found in map{mapX} - %s", mapX_key_name);
}
free((void *)mapX_key_name);
return entry_data_list;
}
MMDB_entry_data_list_s *test_map_value(MMDB_entry_data_list_s *entry_data_list)
{
MMDB_entry_data_list_s *map = entry_data_list = entry_data_list->next;
cmp_ok(map->entry_data.type, "==", MMDB_DATA_TYPE_MAP,
"'map' key's value is a map");
cmp_ok(map->entry_data.data_size, "==", 1,
"'map' key's value has 1 key/value pair");
MMDB_entry_data_list_s *map_key_1 = entry_data_list = entry_data_list->next;
cmp_ok(map_key_1->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
"found a map key in 'map'");
const char *map_key_1_name =
dup_entry_string_or_bail(map_key_1->entry_data);
ok(strcmp(map_key_1_name, "mapX") == 0, "key name is mapX");
free((void *)map_key_1_name);
MMDB_entry_data_list_s *mapX = entry_data_list = entry_data_list->next;
cmp_ok(mapX->entry_data.type, "==", MMDB_DATA_TYPE_MAP,
"'map{mapX}' key's value is a map");
cmp_ok(mapX->entry_data.data_size, "==", 2,
"'map' key's value has 2 key/value pairs");
entry_data_list = test_mapX_key_value_pair(entry_data_list);
entry_data_list = test_mapX_key_value_pair(entry_data_list);
return entry_data_list;
}
MMDB_entry_data_list_s *test_uint128_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_UINT128,
"'uint128' key's value is an uint128");
#if MMDB_UINT128_IS_BYTE_ARRAY
uint8_t expect[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ok(memcmp(value->entry_data.uint128, expect, 16) == 0,
"uint128 field is 2**120");
#else
mmdb_uint128_t expect = 1;
expect <<= 120;
ok(value->entry_data.uint128 == expect, "uint128 field is 2**120");
#endif
return entry_data_list;
}
MMDB_entry_data_list_s *test_uint16_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_UINT16,
"'uint16' key's value is an uint16");
uint16_t expect = 100;
ok(value->entry_data.uint16 == expect, "uint16 field is 100");
return entry_data_list;
}
MMDB_entry_data_list_s *test_uint32_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
"'uint32' key's value is an uint32");
uint32_t expect = 1 << 28;
ok(value->entry_data.uint32 == expect, "uint32 field is 100");
return entry_data_list;
}
MMDB_entry_data_list_s *test_uint64_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_UINT64,
"'uint64' key's value is an uint64");
uint64_t expect = 1;
expect <<= 60;
ok(value->entry_data.uint64 == expect, "uint64 field is 2**60");
return entry_data_list;
}
MMDB_entry_data_list_s *test_utf8_string_value(MMDB_entry_data_list_s
*entry_data_list)
{
MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next;
cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
"'utf8_string' key's value is a string");
const char *utf8_string = dup_entry_string_or_bail(value->entry_data);
// This is hex for "unicode! ☯ - ♫" as bytes
char expect[19] =
{ 0x75, 0x6e, 0x69, 0x63, 0x6f, 0x64, 0x65, 0x21, 0x20, 0xe2, 0x98,
0xaf, 0x20, 0x2d, 0x20, 0xe2, 0x99, 0xab, 0x00 };
is(utf8_string, expect, "got expected value for utf8_string key");
free((void *)utf8_string);
return entry_data_list;
}
void run_tests(int mode, const char *description)
{
const char *filename = "MaxMind-DB-test-decoder.mmdb";
const char *path = test_database_path(filename);
MMDB_s *mmdb = open_ok(path, mode, description);
free((void *)path);
char *ip = "1.1.1.1";
MMDB_lookup_result_s result =
lookup_string_ok(mmdb, ip, filename, description);
MMDB_entry_data_list_s *entry_data_list, *first;
int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (MMDB_SUCCESS != status) {
BAIL_OUT("MMDB_get_entry_data_list failed with %s",
MMDB_strerror(status));
} else {
cmp_ok(status, "==", MMDB_SUCCESS,
"MMDB_get_entry_data_list succeeded");
}
first = entry_data_list;
cmp_ok(entry_data_list->entry_data.type, "==", MMDB_DATA_TYPE_MAP,
"first entry in entry data list is a map");
cmp_ok(entry_data_list->entry_data.data_size, "==", 12,
"first map in entry data list has 12 k/v pairs");
while (1) {
MMDB_entry_data_list_s *key = entry_data_list = entry_data_list->next;
if (!key) {
break;
}
cmp_ok(key->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
"found a map key");
const char *key_name = dup_entry_string_or_bail(key->entry_data);
if (strcmp(key_name, "array") == 0) {
entry_data_list = test_array_value(entry_data_list);
} else if (strcmp(key_name, "boolean") == 0) {
entry_data_list = test_boolean_value(entry_data_list);
} else if (strcmp(key_name, "bytes") == 0) {
entry_data_list = test_bytes_value(entry_data_list);
} else if (strcmp(key_name, "double") == 0) {
entry_data_list = test_double_value(entry_data_list);
} else if (strcmp(key_name, "float") == 0) {
entry_data_list = test_float_value(entry_data_list);
} else if (strcmp(key_name, "int32") == 0) {
entry_data_list = test_int32_value(entry_data_list);
} else if (strcmp(key_name, "map") == 0) {
entry_data_list = test_map_value(entry_data_list);
} else if (strcmp(key_name, "uint128") == 0) {
entry_data_list = test_uint128_value(entry_data_list);
} else if (strcmp(key_name, "uint16") == 0) {
entry_data_list = test_uint16_value(entry_data_list);
} else if (strcmp(key_name, "uint32") == 0) {
entry_data_list = test_uint32_value(entry_data_list);
} else if (strcmp(key_name, "uint64") == 0) {
entry_data_list = test_uint64_value(entry_data_list);
} else if (strcmp(key_name, "utf8_string") == 0) {
entry_data_list = test_utf8_string_value(entry_data_list);
} else {
ok(0, "unknown key found in map - %s", key_name);
}
free((void *)key_name);
}
MMDB_free_entry_data_list(first);
MMDB_close(mmdb);
free(mmdb);
}
int main(void)
{
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();
}