Blob Blame History Raw
#include "maxminddb_test_helper.h"

/* This test exercises a bug found in MMDB_get_value for certain types of
 * nested data structures which contain pointers. See
 * https://github.com/maxmind/libmaxminddb/issues/2 and
 * https://github.com/maxmind/libmaxminddb/issues/3.
 *
 * There is also the potential for a similar bug when looking up a value by
 * path in an array. This is not tested (yet) as we don't have the right test
 * data for it.
 *
 * These tests are somewhat fragile since they depend on a specific data
 * layout in the database. Ideally the test would check that this layout
 * exists before checking to see if the lookups are correct.
 */

void test_one_ip(MMDB_s *mmdb, const char *filename, const char *mode_desc,
                 char *ip, char *country_code)
{
    MMDB_lookup_result_s result =
        lookup_string_ok(mmdb, ip, filename, mode_desc);

    MMDB_entry_data_s entry_data =
        data_ok(&result, MMDB_DATA_TYPE_UTF8_STRING, "country{iso_code}",
                "country", "iso_code", NULL);

    if (ok(entry_data.has_data, "found data for country{iso_code}")) {
        char *string = strndup(entry_data.utf8_string, entry_data.data_size);
        if (!string) {
            ok(0, "strndup() call failed");
            exit(1);
        }
        if (!ok(strcmp(string,
                       country_code) == 0, "iso_code is %s", country_code)) {
            diag("  value is %s", string);
        }
        free(string);
    }
}

void run_tests(int mode, const char *mode_desc)
{
    const char *filename = "GeoIP2-City-Test.mmdb";
    const char *path = test_database_path(filename);
    MMDB_s *mmdb = open_ok(path, mode, mode_desc);
    free((void *)path);

    /* This exercises a bug where the entire top-level value is a pointer to
     * another part of the data section. */
    test_one_ip(mmdb, filename, mode_desc, "2001:218::", "JP");
    /* This exercises a bug where one subnet's data shares part of the data
    * with another subnet - in this case it is the "country" key (and others)
    * in the top level map. We are testing that the "country" key's value is
    * handled correctly. The value _should_ be a pointer to another map. */
    test_one_ip(mmdb, filename, mode_desc, "81.2.69.160", "GB");

    MMDB_close(mmdb);
    free(mmdb);
}

int main(void)
{
    plan(NO_PLAN);
    for_all_modes(&run_tests);
    done_testing();
}