#include "maxminddb_test_helper.h" void test_metadata(MMDB_s *mmdb, const char *mode_desc) { cmp_ok(mmdb->metadata.node_count, "==", 37, "node_count is 37 - %s", mode_desc); cmp_ok(mmdb->metadata.record_size, "==", 24, "record_size is 24 - %s", mode_desc); cmp_ok(mmdb->metadata.ip_version, "==", 4, "ip_version is 4 - %s", mode_desc); is(mmdb->metadata.database_type, "Test", "database_type is Test - %s", mode_desc); // 2013-07-01T00:00:00Z uint64_t expect_epoch = 1372636800; int is_ok = cmp_ok(mmdb->metadata.build_epoch, ">=", expect_epoch, "build_epoch > %lli", expect_epoch); if (!is_ok) { diag(" epoch is %lli", mmdb->metadata.build_epoch); } cmp_ok(mmdb->metadata.binary_format_major_version, "==", 2, "binary_format_major_version is 2 - %s", mode_desc); cmp_ok(mmdb->metadata.binary_format_minor_version, "==", 0, "binary_format_minor_version is 0 - %s", mode_desc); cmp_ok(mmdb->metadata.languages.count, "==", 2, "found 2 languages - %s", mode_desc); is(mmdb->metadata.languages.names[0], "en", "first language is en - %s", mode_desc); is(mmdb->metadata.languages.names[1], "zh", "second language is zh - %s", mode_desc); cmp_ok(mmdb->metadata.description.count, "==", 2, "found 2 descriptions - %s", mode_desc); for (uint16_t i = 0; i < mmdb->metadata.description.count; i++) { const char *language = mmdb->metadata.description.descriptions[i]->language; const char *description = mmdb->metadata.description.descriptions[i]->description; if (strncmp(language, "en", 2) == 0) { ok(1, "found en description"); is(description, "Test Database", "en description"); } else if (strncmp(language, "zh", 2) == 0) { ok(1, "found zh description"); is(description, "Test Database Chinese", "zh description"); } else { ok(0, "found unknown description in unexpected language - %s", language); } } cmp_ok(mmdb->full_record_byte_size, "==", 6, "full_record_byte_size is 6 - %s", mode_desc); } MMDB_entry_data_list_s *test_languages_value(MMDB_entry_data_list_s *entry_data_list) { MMDB_entry_data_list_s *languages = entry_data_list = entry_data_list->next; cmp_ok(languages->entry_data.type, "==", MMDB_DATA_TYPE_ARRAY, "'languages' key's value is an array"); cmp_ok(languages->entry_data.data_size, "==", 2, "'languages' key's value has 2 elements"); MMDB_entry_data_list_s *idx0 = entry_data_list = entry_data_list->next; cmp_ok(idx0->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING, "first array entry is a UTF8_STRING"); const char *lang0 = dup_entry_string_or_bail(idx0->entry_data); is(lang0, "en", "first language is en"); free((void *)lang0); MMDB_entry_data_list_s *idx1 = entry_data_list = entry_data_list->next; cmp_ok(idx1->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING, "second array entry is a UTF8_STRING"); const char *lang1 = dup_entry_string_or_bail(idx1->entry_data); is(lang1, "zh", "second language is zh"); free((void *)lang1); return entry_data_list; } MMDB_entry_data_list_s *test_description_value( MMDB_entry_data_list_s *entry_data_list) { MMDB_entry_data_list_s *description = entry_data_list = entry_data_list->next; cmp_ok(description->entry_data.type, "==", MMDB_DATA_TYPE_MAP, "'description' key's value is a map"); cmp_ok(description->entry_data.data_size, "==", 2, "'description' key's value has 2 key/value pairs"); for (int i = 0; i < 2; i++) { MMDB_entry_data_list_s *key = entry_data_list = entry_data_list->next; cmp_ok(key->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING, "found a map key in 'map'"); const char *key_name = dup_entry_string_or_bail(key->entry_data); MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; cmp_ok(value->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING, "map value is a UTF8_STRING"); const char *description = dup_entry_string_or_bail(value->entry_data); if (strcmp(key_name, "en") == 0) { is(description, "Test Database", "en description == 'Test Database'"); } else if (strcmp(key_name, "zh") == 0) { is(description, "Test Database Chinese", "zh description == 'Test Database Chinese'"); } else { ok(0, "unknown key found in description map - %s", key_name); } free((void *)key_name); free((void *)description); } return entry_data_list; } void test_metadata_as_data_entry_list(MMDB_s * mmdb, const char *mode_desc) { MMDB_entry_data_list_s *entry_data_list, *first; int status = MMDB_get_metadata_as_entry_data_list(mmdb, &entry_data_list); first = entry_data_list; cmp_ok(status, "==", MMDB_SUCCESS, "get metadata as data_entry_list - %s", mode_desc); cmp_ok(first->entry_data.data_size, "==", 9, "metadata map has 9 key/value 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, "node_count") == 0) { MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; cmp_ok(value->entry_data.uint32, "==", 37, "node_count == 37"); } else if (strcmp(key_name, "record_size") == 0) { MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; cmp_ok(value->entry_data.uint16, "==", 24, "record_size == 24"); } else if (strcmp(key_name, "ip_version") == 0) { MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; cmp_ok(value->entry_data.uint16, "==", 4, "ip_version == 4"); } else if (strcmp(key_name, "binary_format_major_version") == 0) { MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; cmp_ok(value->entry_data.uint16, "==", 2, "binary_format_major_version == 2"); } else if (strcmp(key_name, "binary_format_minor_version") == 0) { MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; cmp_ok(value->entry_data.uint16, "==", 0, "binary_format_minor_version == 0"); } else if (strcmp(key_name, "build_epoch") == 0) { MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; ok(value->entry_data.uint64 > 1373571901, "build_epoch > 1373571901"); } else if (strcmp(key_name, "database_type") == 0) { MMDB_entry_data_list_s *value = entry_data_list = entry_data_list->next; const char *type = dup_entry_string_or_bail(value->entry_data); is(type, "Test", "type == Test"); free((void *)type); } else if (strcmp(key_name, "languages") == 0) { entry_data_list = test_languages_value(entry_data_list); } else if (strcmp(key_name, "description") == 0) { entry_data_list = test_description_value(entry_data_list); } else { ok(0, "unknown key found in metadata map - %s", key_name); } free((void *)key_name); } MMDB_free_entry_data_list(first); } void run_tests(int mode, const char *mode_desc) { const char *file = "MaxMind-DB-test-ipv4-24.mmdb"; const char *path = test_database_path(file); MMDB_s *mmdb = open_ok(path, mode, mode_desc); // All of the remaining tests require an open mmdb if (NULL == mmdb) { diag("could not open %s - skipping remaining tests", path); return; } free((void *)path); test_metadata(mmdb, mode_desc); test_metadata_as_data_entry_list(mmdb, mode_desc); MMDB_close(mmdb); free(mmdb); } int main(void) { plan(NO_PLAN); for_all_modes(&run_tests); done_testing(); }