mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-16 07:07:13 +02:00
Integrate MaxmindDB module.
This commit is contained in:
31
module/Vendor/MaxmindDB/t/Makefile.am
vendored
Normal file
31
module/Vendor/MaxmindDB/t/Makefile.am
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
include $(top_srcdir)/common.mk
|
||||
|
||||
all-local:
|
||||
cd libtap && $(MAKE) $(AM_MAKEFLAGS) all
|
||||
clean-local:
|
||||
cd libtap && $(MAKE) $(AM_MAKEFLAGS) clean
|
||||
|
||||
AM_LDFLAGS = $(top_builddir)/src/libmaxminddb.la
|
||||
CFLAGS += -I$(top_srcdir)/src
|
||||
|
||||
noinst_LTLIBRARIES = libmmdbtest.la
|
||||
libmmdbtest_la_SOURCES = maxminddb_test_helper.c maxminddb_test_helper.h
|
||||
|
||||
EXTRA_DIST = compile_c++_t.pl external_symbols_t.pl mmdblookup_t.pl \
|
||||
libtap/COPYING libtap/INSTALL libtap/Makefile libtap/README.md \
|
||||
libtap/tap.c libtap/tap.h maxmind-db
|
||||
|
||||
check_PROGRAMS = \
|
||||
bad_pointers_t bad_databases_t basic_lookup_t data_entry_list_t \
|
||||
data-pool-t data_types_t dump_t get_value_t get_value_pointer_bug_t \
|
||||
ipv4_start_cache_t ipv6_lookup_in_ipv4_t metadata_t metadata_pointers_t \
|
||||
no_map_get_value_t read_node_t threads_t version_t
|
||||
|
||||
data_pool_t_LDFLAGS = $(AM_LDFLAGS) -lm
|
||||
data_pool_t_SOURCES = data-pool-t.c ../src/data-pool.c
|
||||
|
||||
threads_t_CFLAGS = $(CFLAGS) -pthread
|
||||
|
||||
TESTS = $(check_PROGRAMS) compile_c++_t.pl external_symbols_t.pl mmdblookup_t.pl
|
||||
|
||||
LDADD = libmmdbtest.la libtap/libtap.a
|
67
module/Vendor/MaxmindDB/t/bad_databases_t.c
vendored
Normal file
67
module/Vendor/MaxmindDB/t/bad_databases_t.c
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// This test currently does not work on Windows as nftw is
|
||||
// not available.
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <ftw.h>
|
||||
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
int test_read(const char *path, const struct stat *UNUSED(
|
||||
sbuf), int flags, struct FTW *UNUSED(ftw))
|
||||
{
|
||||
// Check if path is a regular file)
|
||||
if (flags != FTW_F) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MMDB_s *mmdb = (MMDB_s *)calloc(1, sizeof(MMDB_s));
|
||||
|
||||
if (NULL == mmdb) {
|
||||
BAIL_OUT("could not allocate memory for our MMDB_s struct");
|
||||
}
|
||||
|
||||
int status = MMDB_open(path, MMDB_MODE_MMAP, mmdb);
|
||||
|
||||
if (status != MMDB_SUCCESS) {
|
||||
ok(1, "received error when opening %s", path);
|
||||
free(mmdb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gai_error, mmdb_error;
|
||||
MMDB_lookup_string(mmdb, "1.1.1.1", &gai_error, &mmdb_error);
|
||||
if (gai_error != 0) {
|
||||
BAIL_OUT("could not parse IP address");
|
||||
}
|
||||
|
||||
cmp_ok(mmdb_error, "!=", MMDB_SUCCESS, "opening %s returned an error",
|
||||
path);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *test_db_dir;
|
||||
#ifdef _WIN32
|
||||
test_db_dir = "./t/maxmind-db/bad-data";
|
||||
#else
|
||||
char cwd[500];
|
||||
char *UNUSED(tmp) = getcwd(cwd, 500);
|
||||
|
||||
if (strcmp(basename(cwd), "t") == 0) {
|
||||
test_db_dir = "./maxmind-db/bad-data";
|
||||
} else {
|
||||
test_db_dir = "./t/maxmind-db/bad-data";
|
||||
}
|
||||
#endif
|
||||
plan(NO_PLAN);
|
||||
if (nftw(test_db_dir, test_read, 10, FTW_PHYS) != 0) {
|
||||
BAIL_OUT("nftw failed");
|
||||
}
|
||||
done_testing();
|
||||
}
|
53
module/Vendor/MaxmindDB/t/bad_pointers_t.c
vendored
Normal file
53
module/Vendor/MaxmindDB/t/bad_pointers_t.c
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-broken-pointers-24.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
{
|
||||
const char *ip = "1.1.1.16";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status = MMDB_get_value(&result.entry, &entry_data, NULL);
|
||||
|
||||
cmp_ok(
|
||||
status, "==", MMDB_INVALID_DATA_ERROR,
|
||||
"MMDB_get_value returns MMDB_INVALID_DATA_ERROR for bad pointer in data section");
|
||||
|
||||
MMDB_entry_data_list_s *entry_data_list;
|
||||
status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
|
||||
|
||||
cmp_ok(
|
||||
status, "==", MMDB_INVALID_DATA_ERROR,
|
||||
"MMDB_get_entry_data_list returns MMDB_INVALID_DATA_ERROR for bad pointer in data section");
|
||||
|
||||
MMDB_free_entry_data_list(entry_data_list);
|
||||
}
|
||||
|
||||
{
|
||||
const char *ip = "1.1.1.32";
|
||||
|
||||
int gai_error, mmdb_error;
|
||||
MMDB_lookup_result_s UNUSED(result) =
|
||||
MMDB_lookup_string(mmdb, ip, &gai_error, &mmdb_error);
|
||||
|
||||
cmp_ok(
|
||||
mmdb_error, "==", MMDB_CORRUPT_SEARCH_TREE_ERROR,
|
||||
"MMDB_lookup_string sets mmdb_error to MMDB_CORRUPT_SEARCH_TREE_ERROR when a search tree record points outside the data section");
|
||||
}
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
207
module/Vendor/MaxmindDB/t/basic_lookup_t.c
vendored
Normal file
207
module/Vendor/MaxmindDB/t/basic_lookup_t.c
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
static void test_big_lookup(void);
|
||||
|
||||
/* These globals are gross but it's the easiest way to mix calling
|
||||
* for_all_modes() and for_all_record_sizes() */
|
||||
static int Current_Mode;
|
||||
static const char *Current_Mode_Description;
|
||||
|
||||
void test_one_result(MMDB_s *mmdb, MMDB_lookup_result_s result,
|
||||
const char *ip, const char *expect,
|
||||
const char *function, const char *filename,
|
||||
const char *mode_desc)
|
||||
{
|
||||
int is_ok = ok(result.found_entry,
|
||||
"got a result for an IP in the database - %s - %s - %s - %s",
|
||||
function, ip, filename, mode_desc);
|
||||
|
||||
if (!is_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(&result, MMDB_DATA_TYPE_UTF8_STRING, "result{ip}", "ip", NULL);
|
||||
|
||||
char *string = mmdb_strndup(data.utf8_string, data.data_size);
|
||||
|
||||
char *real_expect;
|
||||
if (mmdb->metadata.ip_version == 4 || strncmp(expect, "::", 2) == 0) {
|
||||
real_expect = mmdb_strndup(expect, strlen(expect));
|
||||
} else {
|
||||
// When looking up IPv4 addresses in a mixed DB the result will be
|
||||
// something like "::1.2.3.4", not just "1.2.3.4".
|
||||
int maxlen = strlen(expect) + 3;
|
||||
real_expect = malloc(maxlen);
|
||||
snprintf(real_expect, maxlen, "::%s", expect);
|
||||
}
|
||||
|
||||
is(string, real_expect,
|
||||
"found expected result for ip key - %s - %s - %s - %s", function, ip,
|
||||
filename, mode_desc);
|
||||
|
||||
free(real_expect);
|
||||
free(string);
|
||||
}
|
||||
|
||||
void test_one_ip(MMDB_s *mmdb, const char *ip, const char *expect,
|
||||
const char *filename, const char *mode_desc)
|
||||
{
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
test_one_result(mmdb, result, ip, expect, "MMDB_lookup_string", filename,
|
||||
mode_desc);
|
||||
|
||||
result = lookup_sockaddr_ok(mmdb, ip, filename, mode_desc);
|
||||
test_one_result(mmdb, result, ip, expect, "MMDB_lookup_addrinfo", filename,
|
||||
mode_desc);
|
||||
}
|
||||
|
||||
void run_ipX_tests(const char *filename, const char **missing_ips,
|
||||
int missing_ips_length, const char *pairs[][2],
|
||||
int pairs_rows)
|
||||
{
|
||||
const char *path = test_database_path(filename);
|
||||
int mode = Current_Mode;
|
||||
const char *mode_desc = Current_Mode_Description;
|
||||
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
char desc_suffix[500];
|
||||
snprintf(desc_suffix, 500, "%s - %s", filename, mode_desc);
|
||||
|
||||
for (int i = 0; i < missing_ips_length; i++) {
|
||||
const char *ip = missing_ips[i];
|
||||
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
ok(
|
||||
!result.found_entry,
|
||||
"no result entry struct returned for IP address not in the database (string lookup) - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
|
||||
result = lookup_sockaddr_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
ok(
|
||||
!result.found_entry,
|
||||
"no result entry struct returned for IP address not in the database (ipv4 lookup) - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
}
|
||||
|
||||
for (int i = 0; i < pairs_rows; i += 1) {
|
||||
const char *ip_to_lookup = pairs[i][0];
|
||||
const char *expect = pairs[i][1];
|
||||
|
||||
test_one_ip(mmdb, ip_to_lookup, expect, filename, mode_desc);
|
||||
}
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
void run_ipv4_tests(int UNUSED(
|
||||
record_size), const char *filename, const char *UNUSED(
|
||||
ignored))
|
||||
{
|
||||
const char *pairs[9][2] = {
|
||||
{ "1.1.1.1", "1.1.1.1" },
|
||||
{ "1.1.1.2", "1.1.1.2" },
|
||||
{ "1.1.1.3", "1.1.1.2" },
|
||||
{ "1.1.1.7", "1.1.1.4" },
|
||||
{ "1.1.1.9", "1.1.1.8" },
|
||||
{ "1.1.1.15", "1.1.1.8" },
|
||||
{ "1.1.1.17", "1.1.1.16" },
|
||||
{ "1.1.1.31", "1.1.1.16" },
|
||||
{ "1.1.1.32", "1.1.1.32" },
|
||||
};
|
||||
|
||||
const char *missing[1] = { "2.3.4.5" };
|
||||
run_ipX_tests(filename, missing, 1, pairs, 9);
|
||||
}
|
||||
|
||||
void run_ipv6_tests(int UNUSED(
|
||||
record_size), const char *filename, const char *UNUSED(
|
||||
ignored))
|
||||
{
|
||||
const char *pairs[9][2] = {
|
||||
{ "::1:ffff:ffff", "::1:ffff:ffff" },
|
||||
{ "::2:0:0", "::2:0:0" },
|
||||
{ "::2:0:1a", "::2:0:0" },
|
||||
{ "::2:0:40", "::2:0:40" },
|
||||
{ "::2:0:4f", "::2:0:40" },
|
||||
{ "::2:0:50", "::2:0:50" },
|
||||
{ "::2:0:52", "::2:0:50" },
|
||||
{ "::2:0:58", "::2:0:58" },
|
||||
{ "::2:0:59", "::2:0:58" },
|
||||
};
|
||||
|
||||
const char *missing[2] = { "2.3.4.5", "::abcd" };
|
||||
run_ipX_tests(filename, missing, 2, pairs, 9);
|
||||
}
|
||||
|
||||
void all_record_sizes(int mode, const char *description)
|
||||
{
|
||||
const char *ipv4_filename_fmts[] = {
|
||||
"MaxMind-DB-test-ipv4-%i.mmdb",
|
||||
"MaxMind-DB-test-mixed-%i.mmdb"
|
||||
};
|
||||
|
||||
Current_Mode = mode;
|
||||
Current_Mode_Description = description;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for_all_record_sizes(ipv4_filename_fmts[i], &run_ipv4_tests);
|
||||
}
|
||||
|
||||
const char *ipv6_filename_fmts[] = {
|
||||
"MaxMind-DB-test-ipv6-%i.mmdb",
|
||||
"MaxMind-DB-test-mixed-%i.mmdb"
|
||||
};
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for_all_record_sizes(ipv6_filename_fmts[i], &run_ipv6_tests);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_big_lookup(void)
|
||||
{
|
||||
const char *const db_filename = "GeoIP2-Precision-Enterprise-Test.mmdb";
|
||||
const char *const db_path = test_database_path(db_filename);
|
||||
ok(db_path != NULL, "got database path");
|
||||
|
||||
MMDB_s * const mmdb = open_ok(db_path, MMDB_MODE_MMAP, "mmap mode");
|
||||
ok(mmdb != NULL, "opened MMDB");
|
||||
free((char *)db_path);
|
||||
|
||||
int gai_err = 0, mmdb_err = 0;
|
||||
const char *const ip_address = "81.2.69.160";
|
||||
MMDB_lookup_result_s result = MMDB_lookup_string(mmdb, ip_address, &gai_err,
|
||||
&mmdb_err);
|
||||
ok(gai_err == 0, "no getaddrinfo error");
|
||||
ok(mmdb_err == MMDB_SUCCESS, "no error from maxminddb library");
|
||||
ok(result.found_entry, "found IP");
|
||||
|
||||
MMDB_entry_data_list_s *entry_data_list = NULL;
|
||||
ok(
|
||||
MMDB_get_entry_data_list(&result.entry,
|
||||
&entry_data_list) == MMDB_SUCCESS,
|
||||
"successfully looked up entry data list"
|
||||
);
|
||||
ok(entry_data_list != NULL, "got an entry_data_list");
|
||||
|
||||
MMDB_free_entry_data_list(entry_data_list);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&all_record_sizes);
|
||||
test_big_lookup();
|
||||
done_testing();
|
||||
}
|
107
module/Vendor/MaxmindDB/t/compile_c++_t.pl
vendored
Normal file
107
module/Vendor/MaxmindDB/t/compile_c++_t.pl
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Cwd qw( abs_path );
|
||||
use FindBin qw( $Bin );
|
||||
|
||||
eval <<'EOF';
|
||||
use Test::More 0.88;
|
||||
use File::Temp qw( tempdir );
|
||||
use IPC::Run3 qw( run3 );
|
||||
EOF
|
||||
|
||||
if ($@) {
|
||||
print
|
||||
"1..0 # skip all tests skipped - these tests need the Test::More 0.88, File::Temp, and IPC::Run3 modules:\n";
|
||||
print "$@";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $test_db = "$Bin/maxmind-db/test-data/GeoIP2-City-Test.mmdb";
|
||||
|
||||
my $cpp_code = <<"EOF";
|
||||
#include <maxminddb.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *fname = "$test_db";
|
||||
MMDB_s mmdb;
|
||||
return MMDB_open(fname, MMDB_MODE_MMAP, &mmdb);
|
||||
}
|
||||
EOF
|
||||
|
||||
my $tempdir = tempdir(CLEANUP => 1 );
|
||||
|
||||
my $file = "$tempdir/open.cpp";
|
||||
open my $fh, '>', $file or die $!;
|
||||
print {$fh} $cpp_code or die $!;
|
||||
close $fh or die $!;
|
||||
|
||||
my $exe = "$tempdir/open";
|
||||
|
||||
my $include_dir = abs_path("$Bin/../include");
|
||||
my $lib_dir = abs_path("$Bin/../src/.libs");
|
||||
|
||||
my $cxx = $ENV{CXX} || 'c++';
|
||||
_test_cmd(
|
||||
[ $cxx, $file, "-I$include_dir", "-L$lib_dir", "-lmaxminddb", "-o$exe" ],
|
||||
qr/^$/,
|
||||
q{},
|
||||
0,
|
||||
'compile C++ program which links against libmaxminddb',
|
||||
);
|
||||
|
||||
# DYLD_LIBRARY_PATH is for Mac OS X
|
||||
$ENV{LD_LIBRARY_PATH} = $ENV{DYLD_LIBRARY_PATH} = $lib_dir;
|
||||
|
||||
_test_cmd(
|
||||
[$exe],
|
||||
qr/^$/,
|
||||
q{},
|
||||
0,
|
||||
'compiled C++ program executes without errors'
|
||||
);
|
||||
|
||||
done_testing();
|
||||
|
||||
sub _test_cmd {
|
||||
my $cmd = shift;
|
||||
my $expect_stdout = shift;
|
||||
my $expect_stderr = shift;
|
||||
my $expect_status = shift;
|
||||
my $desc = shift;
|
||||
|
||||
my $stdout;
|
||||
my $stderr;
|
||||
run3(
|
||||
$cmd,
|
||||
\undef,
|
||||
\$stdout,
|
||||
\$stderr,
|
||||
);
|
||||
|
||||
my $exit_status = $? >> 8;
|
||||
|
||||
# We don't need to retest that the help output shows up for all errors
|
||||
if ( defined $expect_stdout ) {
|
||||
like(
|
||||
$stdout,
|
||||
$expect_stdout,
|
||||
"stdout for @{$cmd}"
|
||||
);
|
||||
}
|
||||
|
||||
if ( ref $expect_stderr ) {
|
||||
like( $stderr, $expect_stderr, "stderr for @{$cmd}" );
|
||||
}
|
||||
else {
|
||||
is( $stderr, $expect_stderr, "stderr for @{$cmd}" );
|
||||
}
|
||||
|
||||
is(
|
||||
$exit_status, $expect_status,
|
||||
"exit status was $expect_status for @{$cmd}"
|
||||
);
|
||||
}
|
374
module/Vendor/MaxmindDB/t/data-pool-t.c
vendored
Normal file
374
module/Vendor/MaxmindDB/t/data-pool-t.c
vendored
Normal file
@ -0,0 +1,374 @@
|
||||
#include <assert.h>
|
||||
#include <data-pool.h>
|
||||
#include <inttypes.h>
|
||||
#include "libtap/tap.h"
|
||||
#include <math.h>
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
static void test_data_pool_new(void);
|
||||
static void test_data_pool_destroy(void);
|
||||
static void test_data_pool_alloc(void);
|
||||
static void test_data_pool_to_list(void);
|
||||
static bool create_and_check_list(size_t const,
|
||||
size_t const);
|
||||
static void check_block_count(MMDB_entry_data_list_s const *const,
|
||||
size_t const);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
test_data_pool_new();
|
||||
test_data_pool_destroy();
|
||||
test_data_pool_alloc();
|
||||
test_data_pool_to_list();
|
||||
done_testing();
|
||||
}
|
||||
|
||||
static void test_data_pool_new(void)
|
||||
{
|
||||
{
|
||||
MMDB_data_pool_s *const pool = data_pool_new(0);
|
||||
ok(!pool, "size 0 is not valid");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_data_pool_s *const pool = data_pool_new(SIZE_MAX - 10);
|
||||
ok(!pool, "very large size is not valid");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_data_pool_s *const pool = data_pool_new(512);
|
||||
ok(pool != NULL, "size 512 is valid");
|
||||
cmp_ok(pool->size, "==", 512, "size is 512");
|
||||
cmp_ok(pool->used, "==", 0, "used size is 0");
|
||||
data_pool_destroy(pool);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_data_pool_destroy(void)
|
||||
{
|
||||
{
|
||||
data_pool_destroy(NULL);
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_data_pool_s *const pool = data_pool_new(512);
|
||||
ok(pool != NULL, "created pool");
|
||||
data_pool_destroy(pool);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_data_pool_alloc(void)
|
||||
{
|
||||
{
|
||||
MMDB_data_pool_s *const pool = data_pool_new(1);
|
||||
ok(pool != NULL, "created pool");
|
||||
cmp_ok(pool->used, "==", 0, "used size starts at 0");
|
||||
|
||||
MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
|
||||
ok(entry1 != NULL, "allocated first entry");
|
||||
// Arbitrary so that we can recognize it.
|
||||
entry1->entry_data.offset = (uint32_t)123;
|
||||
|
||||
cmp_ok(pool->size, "==", 1, "size is still 1");
|
||||
cmp_ok(pool->used, "==", 1, "used size is 1 after taking one");
|
||||
|
||||
MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool);
|
||||
ok(entry2 != NULL, "got another entry");
|
||||
ok(entry1 != entry2, "second entry is different from first entry");
|
||||
|
||||
cmp_ok(pool->size, "==", 2, "size is 2 (new block)");
|
||||
cmp_ok(pool->used, "==", 1, "used size is 1 in current block");
|
||||
|
||||
ok(entry1->entry_data.offset == 123,
|
||||
"accessing the original entry's memory is ok");
|
||||
|
||||
data_pool_destroy(pool);
|
||||
}
|
||||
|
||||
{
|
||||
size_t const initial_size = 10;
|
||||
MMDB_data_pool_s *const pool = data_pool_new(initial_size);
|
||||
ok(pool != NULL, "created pool");
|
||||
|
||||
MMDB_entry_data_list_s *entry1 = NULL;
|
||||
for (size_t i = 0; i < initial_size; i++) {
|
||||
MMDB_entry_data_list_s *const entry = data_pool_alloc(pool);
|
||||
ok(entry != NULL, "got an entry");
|
||||
// Give each a unique number so we can check it.
|
||||
entry->entry_data.offset = (uint32_t)i;
|
||||
if (i == 0) {
|
||||
entry1 = entry;
|
||||
}
|
||||
}
|
||||
|
||||
cmp_ok(pool->size, "==", initial_size, "size is the initial size");
|
||||
cmp_ok(pool->used, "==", initial_size, "used size is as expected");
|
||||
|
||||
MMDB_entry_data_list_s *const entry = data_pool_alloc(pool);
|
||||
ok(entry != NULL, "got an entry");
|
||||
entry->entry_data.offset = (uint32_t)initial_size;
|
||||
|
||||
cmp_ok(pool->size, "==", initial_size * 2,
|
||||
"size is the initial size*2");
|
||||
cmp_ok(pool->used, "==", 1, "used size is as expected");
|
||||
|
||||
MMDB_entry_data_list_s *const list = data_pool_to_list(pool);
|
||||
|
||||
MMDB_entry_data_list_s *element = list;
|
||||
for (size_t i = 0; i < initial_size + 1; i++) {
|
||||
ok(
|
||||
element->entry_data.offset == (uint32_t)i,
|
||||
"found offset %" PRIu32 ", should have %zu",
|
||||
element->entry_data.offset,
|
||||
i
|
||||
);
|
||||
element = element->next;
|
||||
}
|
||||
|
||||
ok(entry1->entry_data.offset == (uint32_t)0,
|
||||
"accessing entry1's original memory is ok after growing the pool");
|
||||
|
||||
data_pool_destroy(pool);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_data_pool_to_list(void)
|
||||
{
|
||||
{
|
||||
size_t const initial_size = 16;
|
||||
MMDB_data_pool_s *const pool = data_pool_new(initial_size);
|
||||
ok(pool != NULL, "created pool");
|
||||
|
||||
MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
|
||||
ok(entry1 != NULL, "got an entry");
|
||||
|
||||
MMDB_entry_data_list_s *const list_one_element
|
||||
= data_pool_to_list(pool);
|
||||
ok(list_one_element != NULL, "got a list");
|
||||
ok(list_one_element == entry1,
|
||||
"list's first element is the first we retrieved");
|
||||
ok(list_one_element->next == NULL, "list is one element in size");
|
||||
|
||||
MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool);
|
||||
ok(entry2 != NULL, "got another entry");
|
||||
|
||||
MMDB_entry_data_list_s *const list_two_elements
|
||||
= data_pool_to_list(pool);
|
||||
ok(list_two_elements != NULL, "got a list");
|
||||
ok(list_two_elements == entry1,
|
||||
"list's first element is the first we retrieved");
|
||||
ok(list_two_elements->next != NULL, "list has a second element");
|
||||
|
||||
MMDB_entry_data_list_s *const second_element = list_two_elements->next;
|
||||
ok(second_element == entry2,
|
||||
"second item in list is second we retrieved");
|
||||
ok(second_element->next == NULL, "list ends with the second element");
|
||||
|
||||
data_pool_destroy(pool);
|
||||
}
|
||||
|
||||
{
|
||||
size_t const initial_size = 1;
|
||||
MMDB_data_pool_s *const pool = data_pool_new(initial_size);
|
||||
ok(pool != NULL, "created pool");
|
||||
|
||||
MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
|
||||
ok(entry1 != NULL, "got an entry");
|
||||
|
||||
MMDB_entry_data_list_s *const list_one_element
|
||||
= data_pool_to_list(pool);
|
||||
ok(list_one_element != NULL, "got a list");
|
||||
ok(list_one_element == entry1,
|
||||
"list's first element is the first we retrieved");
|
||||
ok(list_one_element->next == NULL, "list ends with this element");
|
||||
|
||||
data_pool_destroy(pool);
|
||||
}
|
||||
|
||||
{
|
||||
size_t const initial_size = 2;
|
||||
MMDB_data_pool_s *const pool = data_pool_new(initial_size);
|
||||
ok(pool != NULL, "created pool");
|
||||
|
||||
MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool);
|
||||
ok(entry1 != NULL, "got an entry");
|
||||
|
||||
MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool);
|
||||
ok(entry2 != NULL, "got an entry");
|
||||
ok(entry1 != entry2, "second entry is different from the first");
|
||||
|
||||
MMDB_entry_data_list_s *const list_element1 = data_pool_to_list(pool);
|
||||
ok(list_element1 != NULL, "got a list");
|
||||
ok(list_element1 == entry1,
|
||||
"list's first element is the first we retrieved");
|
||||
|
||||
MMDB_entry_data_list_s *const list_element2 = list_element1->next;
|
||||
ok(list_element2 == entry2,
|
||||
"second element is the second we retrieved");
|
||||
ok(list_element2->next == NULL, "list ends with this element");
|
||||
|
||||
data_pool_destroy(pool);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill one block save for one spot");
|
||||
ok(
|
||||
create_and_check_list(3, 2),
|
||||
"fill one block save for one spot"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill one block");
|
||||
ok(
|
||||
create_and_check_list(3, 3),
|
||||
"fill one block"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill one block and use one spot in the next block");
|
||||
ok(
|
||||
create_and_check_list(3, 3 + 1),
|
||||
"fill one block and use one spot in the next block"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill two blocks save for one spot");
|
||||
ok(
|
||||
create_and_check_list(3, 3 + 3 * 2 - 1),
|
||||
"fill two blocks save for one spot"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill two blocks");
|
||||
ok(
|
||||
create_and_check_list(3, 3 + 3 * 2),
|
||||
"fill two blocks"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill two blocks and use one spot in the next");
|
||||
ok(
|
||||
create_and_check_list(3, 3 + 3 * 2 + 1),
|
||||
"fill two blocks and use one spot in the next"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill three blocks save for one spot");
|
||||
ok(
|
||||
create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2 - 1),
|
||||
"fill three blocks save for one spot"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
diag("starting test: fill three blocks");
|
||||
ok(
|
||||
create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2),
|
||||
"fill three blocks"
|
||||
);
|
||||
}
|
||||
|
||||
// It would be nice to have a larger number of these, but it's expensive to
|
||||
// run many. We currently hardcode what this will be anyway, so varying
|
||||
// this is not very interesting.
|
||||
size_t const initial_sizes[] = { 1, 2, 32, 64, 128, 256 };
|
||||
|
||||
size_t const max_element_count = 4096;
|
||||
|
||||
for (size_t i = 0; i < sizeof(initial_sizes) / sizeof(initial_sizes[0]);
|
||||
i++) {
|
||||
size_t const initial_size = initial_sizes[i];
|
||||
|
||||
for (size_t element_count = 0; element_count < max_element_count;
|
||||
element_count++) {
|
||||
assert(create_and_check_list(initial_size, element_count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use assert() rather than libtap as libtap is significantly slower and we run
|
||||
// this frequently.
|
||||
static bool create_and_check_list(size_t const initial_size,
|
||||
size_t const element_count)
|
||||
{
|
||||
MMDB_data_pool_s *const pool = data_pool_new(initial_size);
|
||||
assert(pool != NULL);
|
||||
|
||||
assert(pool->used == 0);
|
||||
|
||||
// Hold on to the pointers as we initially see them so that we can check
|
||||
// they are still valid after building the list.
|
||||
MMDB_entry_data_list_s **const entry_array
|
||||
= calloc(element_count, sizeof(MMDB_entry_data_list_s *));
|
||||
assert(entry_array != NULL);
|
||||
|
||||
for (size_t i = 0; i < element_count; i++) {
|
||||
MMDB_entry_data_list_s *const entry = data_pool_alloc(pool);
|
||||
assert(entry != NULL);
|
||||
|
||||
entry->entry_data.offset = (uint32_t)i;
|
||||
|
||||
entry_array[i] = entry;
|
||||
}
|
||||
|
||||
MMDB_entry_data_list_s *const list = data_pool_to_list(pool);
|
||||
|
||||
if (element_count == 0) {
|
||||
assert(list == NULL);
|
||||
data_pool_destroy(pool);
|
||||
free(entry_array);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(list != NULL);
|
||||
|
||||
MMDB_entry_data_list_s *element = list;
|
||||
for (size_t i = 0; i < element_count; i++) {
|
||||
assert(element->entry_data.offset == (uint32_t)i);
|
||||
|
||||
assert(element == entry_array[i]);
|
||||
|
||||
element = element->next;
|
||||
}
|
||||
assert(element == NULL);
|
||||
|
||||
check_block_count(list, initial_size);
|
||||
|
||||
data_pool_destroy(pool);
|
||||
free(entry_array);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use assert() rather than libtap as libtap is significantly slower and we run
|
||||
// this frequently.
|
||||
static void check_block_count(MMDB_entry_data_list_s const *const list,
|
||||
size_t const initial_size)
|
||||
{
|
||||
size_t got_block_count = 0;
|
||||
size_t got_element_count = 0;
|
||||
|
||||
MMDB_entry_data_list_s const *element = list;
|
||||
while (element) {
|
||||
got_element_count++;
|
||||
|
||||
if (element->pool) {
|
||||
got_block_count++;
|
||||
}
|
||||
|
||||
element = element->next;
|
||||
}
|
||||
|
||||
// Because <number of elements> = <initial size> * 2^(number of blocks)
|
||||
double const a = ceil((double)got_element_count / (double)initial_size);
|
||||
double const b = log2(a);
|
||||
size_t const expected_block_count = ((size_t)b) + 1;
|
||||
|
||||
assert(got_block_count == expected_block_count);
|
||||
}
|
353
module/Vendor/MaxmindDB/t/data_entry_list_t.c
vendored
Normal file
353
module/Vendor/MaxmindDB/t/data_entry_list_t.c
vendored
Normal file
@ -0,0 +1,353 @@
|
||||
#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;
|
||||
cmp_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;
|
||||
cmp_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;
|
||||
cmp_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();
|
||||
}
|
439
module/Vendor/MaxmindDB/t/data_types_t.c
vendored
Normal file
439
module/Vendor/MaxmindDB/t/data_types_t.c
vendored
Normal file
@ -0,0 +1,439 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void test_all_data_types(MMDB_lookup_result_s *result, const char *ip,
|
||||
const char *UNUSED(filename), const char *mode_desc)
|
||||
{
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "utf8_string field for %s - %s", ip,
|
||||
mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UTF8_STRING, description,
|
||||
"utf8_string", NULL);
|
||||
const char *string = mmdb_strndup(data.utf8_string, data.data_size);
|
||||
// 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(string, expect, "got expected utf8_string value");
|
||||
|
||||
free((char *)string);
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "double field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_DOUBLE, description, "double", NULL);
|
||||
|
||||
compare_double(data.double_value, 42.123456);
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "float field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_FLOAT, description, "float", NULL);
|
||||
|
||||
compare_float(data.float_value, 1.1F);
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "bytes field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_BYTES, description, "bytes", NULL);
|
||||
uint8_t expect[] = { 0x00, 0x00, 0x00, 0x2a };
|
||||
ok(memcmp((uint8_t *)data.bytes, expect, 4) == 0,
|
||||
"bytes field has expected value");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint16 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT16, description, "uint16", NULL);
|
||||
uint16_t expect = 100;
|
||||
ok(data.uint16 == expect, "uint16 field is 100");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint32 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "uint32", NULL);
|
||||
uint32_t expect = 1 << 28;
|
||||
cmp_ok(data.uint32, "==", expect, "uint32 field is 2**28");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "int32 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_INT32, description, "int32", NULL);
|
||||
int32_t expect = 1 << 28;
|
||||
expect *= -1;
|
||||
cmp_ok(data.int32, "==", expect, "int32 field is -(2**28)");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint64 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT64, description, "uint64", NULL);
|
||||
uint64_t expect = 1;
|
||||
expect <<= 60;
|
||||
cmp_ok(data.uint64, "==", expect, "uint64 field is 2**60");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint128 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT128, description, "uint128",
|
||||
NULL);
|
||||
#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(data.uint128, expect, 16) == 0, "uint128 field is 2**120");
|
||||
#else
|
||||
mmdb_uint128_t expect = 1;
|
||||
expect <<= 120;
|
||||
cmp_ok(data.uint128, "==", expect, "uint128 field is 2**120");
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "boolean field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_BOOLEAN, description, "boolean",
|
||||
NULL);
|
||||
cmp_ok(data.boolean, "==", true, "boolean field is true");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "array field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_ARRAY, description, "array", NULL);
|
||||
ok(data.data_size == 3, "array field has 3 elements");
|
||||
|
||||
snprintf(description, 500, "array[0] for %s - %s", ip, mode_desc);
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "array", "0",
|
||||
NULL);
|
||||
ok(data.uint32 == 1, "array[0] is 1");
|
||||
|
||||
snprintf(description, 500, "array[1] for %s - %s", ip, mode_desc);
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "array", "1",
|
||||
NULL);
|
||||
ok(data.uint32 == 2, "array[1] is 1");
|
||||
|
||||
snprintf(description, 500, "array[2] for %s - %s", ip, mode_desc);
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "array", "2",
|
||||
NULL);
|
||||
ok(data.uint32 == 3, "array[2] is 1");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "map field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_MAP, description, "map", NULL);
|
||||
ok(data.data_size == 1, "map field has 1 element");
|
||||
|
||||
snprintf(description, 500, "map{mapX} for %s - %s", ip, mode_desc);
|
||||
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_MAP, description, "map", "mapX",
|
||||
NULL);
|
||||
ok(data.data_size == 2, "map{mapX} field has 2 elements");
|
||||
|
||||
snprintf(description, 500, "map{mapX}{utf8_stringX} for %s - %s", ip,
|
||||
mode_desc);
|
||||
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UTF8_STRING, description, "map",
|
||||
"mapX", "utf8_stringX", NULL);
|
||||
const char *string = mmdb_strndup(data.utf8_string, data.data_size);
|
||||
is(string, "hello", "map{mapX}{utf8_stringX} is 'hello'");
|
||||
free((char *)string);
|
||||
|
||||
snprintf(description, 500, "map{mapX}{arrayX} for %s - %s", ip,
|
||||
mode_desc);
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_ARRAY, description, "map", "mapX",
|
||||
"arrayX", NULL);
|
||||
ok(data.data_size == 3, "map{mapX}{arrayX} field has 3 elements");
|
||||
|
||||
snprintf(description, 500, "map{mapX}{arrayX}[0] for %s - %s", ip,
|
||||
mode_desc);
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "map", "mapX",
|
||||
"arrayX", "0", NULL);
|
||||
ok(data.uint32 == 7, "map{mapX}{arrayX}[0] is 7");
|
||||
|
||||
snprintf(description, 500, "map{mapX}{arrayX}[1] for %s - %s", ip,
|
||||
mode_desc);
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "map", "mapX",
|
||||
"arrayX", "1", NULL);
|
||||
ok(data.uint32 == 8, "map{mapX}{arrayX}[1] is 8");
|
||||
|
||||
snprintf(description, 500, "map{mapX}{arrayX}[2] for %s - %s", ip,
|
||||
mode_desc);
|
||||
data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "map", "mapX",
|
||||
"arrayX", "2", NULL);
|
||||
ok(data.uint32 == 9, "map{mapX}{arrayX}[2] is 9");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_all_data_types_as_zero(MMDB_lookup_result_s *result, const char *ip,
|
||||
const char *UNUSED(
|
||||
filename), const char *mode_desc)
|
||||
{
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "utf8_string field for %s - %s", ip,
|
||||
mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UTF8_STRING, description,
|
||||
"utf8_string", NULL);
|
||||
is(data.utf8_string, "", "got expected utf8_string value (NULL)");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "double field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_DOUBLE, description, "double", NULL);
|
||||
|
||||
compare_double(data.double_value, 0.0);
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "float field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_FLOAT, description, "float", NULL);
|
||||
|
||||
compare_float(data.float_value, 0.0F);
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "bytes field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_BYTES, description, "bytes", NULL);
|
||||
ok(data.data_size == 0, "bytes field data_size is 0");
|
||||
/* In C does it makes sense to write something like this?
|
||||
uint8_t expect[0] = {};
|
||||
ok(memcmp(data.bytes, expect, 0) == 0, "got expected bytes value (NULL)"); */
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint16 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT16, description, "uint16", NULL);
|
||||
uint16_t expect = 0;
|
||||
ok(data.uint16 == expect, "uint16 field is 0");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint32 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT32, description, "uint32", NULL);
|
||||
uint32_t expect = 0;
|
||||
cmp_ok(data.uint32, "==", expect, "uint32 field is 0");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "int32 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_INT32, description, "int32", NULL);
|
||||
int32_t expect = 0;
|
||||
expect *= -1;
|
||||
cmp_ok(data.int32, "==", expect, "int32 field is 0");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint64 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT64, description, "uint64", NULL);
|
||||
uint64_t expect = 0;
|
||||
cmp_ok(data.uint64, "==", expect, "uint64 field is 0");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "uint128 field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_UINT128, description, "uint128",
|
||||
NULL);
|
||||
#if MMDB_UINT128_IS_BYTE_ARRAY
|
||||
uint8_t expect[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
ok(memcmp(data.uint128, expect, 16) == 0, "uint128 field is 0");
|
||||
#else
|
||||
mmdb_uint128_t expect = 0;
|
||||
cmp_ok(data.uint128, "==", expect, "uint128 field is 0");
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "boolean field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_BOOLEAN, description, "boolean",
|
||||
NULL);
|
||||
cmp_ok(data.boolean, "==", false, "boolean field is false");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "array field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_ARRAY, description, "array", NULL);
|
||||
ok(data.data_size == 0, "array field has 0 elements");
|
||||
}
|
||||
|
||||
{
|
||||
char description[500];
|
||||
snprintf(description, 500, "map field for %s - %s", ip, mode_desc);
|
||||
|
||||
MMDB_entry_data_s data =
|
||||
data_ok(result, MMDB_DATA_TYPE_MAP, description, "map", NULL);
|
||||
ok(data.data_size == 0, "map field has 0 elements");
|
||||
}
|
||||
}
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-decoder.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
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);
|
||||
|
||||
{
|
||||
const char *ip = "not an ip";
|
||||
|
||||
int gai_error, mmdb_error;
|
||||
MMDB_lookup_result_s result =
|
||||
MMDB_lookup_string(mmdb, ip, &gai_error, &mmdb_error);
|
||||
|
||||
cmp_ok(gai_error, "==", EAI_NONAME,
|
||||
"MMDB_lookup populates getaddrinfo error properly - %s", ip);
|
||||
|
||||
ok(!result.found_entry,
|
||||
"no result entry struct returned for invalid IP address '%s'", ip);
|
||||
}
|
||||
|
||||
{
|
||||
const char *ip = "e900::";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
ok(
|
||||
!result.found_entry,
|
||||
"no result entry struct returned for IP address not in the database - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
}
|
||||
|
||||
{
|
||||
const char *ip = "::1.1.1.1";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
ok(
|
||||
result.found_entry,
|
||||
"got a result entry struct for IP address in the database - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
|
||||
cmp_ok(
|
||||
result.entry.offset, ">", 0,
|
||||
"result.entry.offset > 0 for address in the database - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
|
||||
test_all_data_types(&result, ip, filename, mode_desc);
|
||||
}
|
||||
|
||||
{
|
||||
const char *ip = "::4.5.6.7";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
ok(
|
||||
result.found_entry,
|
||||
"got a result entry struct for IP address in the database - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
|
||||
cmp_ok(
|
||||
result.entry.offset, ">", 0,
|
||||
"result.entry.offset > 0 for address in the database - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
|
||||
test_all_data_types(&result, ip, filename, mode_desc);
|
||||
}
|
||||
|
||||
{
|
||||
const char *ip = "::0.0.0.0";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
ok(
|
||||
result.found_entry,
|
||||
"got a result entry struct for IP address in the database - %s - %s - %s",
|
||||
ip, filename, mode_desc);
|
||||
|
||||
test_all_data_types_as_zero(&result, ip, filename, mode_desc);
|
||||
}
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
103
module/Vendor/MaxmindDB/t/dump_t.c
vendored
Normal file
103
module/Vendor/MaxmindDB/t/dump_t.c
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
#ifdef HAVE_OPEN_MEMSTREAM
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-decoder.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const char *ip = "1.1.1.1";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
MMDB_entry_data_list_s *entry_data_list;
|
||||
int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
|
||||
|
||||
ok(MMDB_SUCCESS == status,
|
||||
"MMDB_get_entry_data_list is successful");
|
||||
|
||||
char *dump_output;
|
||||
size_t dump_size;
|
||||
FILE *stream = open_memstream(&dump_output, &dump_size);
|
||||
status = MMDB_dump_entry_data_list(stream, entry_data_list, 0);
|
||||
fclose(stream);
|
||||
MMDB_free_entry_data_list(entry_data_list);
|
||||
|
||||
ok(MMDB_SUCCESS == status,
|
||||
"MMDB_dump_entry_data_list is successful - %s",
|
||||
mode_desc);
|
||||
|
||||
cmp_ok(dump_size, ">", 0, "MMDB_dump produced output - %s", mode_desc);
|
||||
|
||||
char *expect[] = {
|
||||
"{",
|
||||
" \"array\": ",
|
||||
" [",
|
||||
" 1 <uint32>",
|
||||
" 2 <uint32>",
|
||||
" 3 <uint32>",
|
||||
" ]",
|
||||
" \"boolean\": ",
|
||||
" true <boolean>",
|
||||
" \"bytes\": ",
|
||||
" 0000002A <bytes>",
|
||||
" \"double\": ",
|
||||
" 42.123456 <double>",
|
||||
" \"float\": ",
|
||||
" 1.100000 <float>",
|
||||
" \"int32\": ",
|
||||
" -268435456 <int32>",
|
||||
" \"map\": ",
|
||||
" {",
|
||||
" \"mapX\": ",
|
||||
" {",
|
||||
" \"arrayX\": ",
|
||||
" [",
|
||||
" 7 <uint32>",
|
||||
" 8 <uint32>",
|
||||
" 9 <uint32>",
|
||||
" ]",
|
||||
" \"utf8_stringX\": ",
|
||||
" \"hello\" <utf8_string>",
|
||||
" }",
|
||||
" }",
|
||||
" \"uint128\": ",
|
||||
" 0x01000000000000000000000000000000 <uint128>",
|
||||
" \"uint16\": ",
|
||||
" 100 <uint16>",
|
||||
" \"uint32\": ",
|
||||
" 268435456 <uint32>",
|
||||
" \"uint64\": ",
|
||||
" 1152921504606846976 <uint64>",
|
||||
" \"utf8_string\": ",
|
||||
" \"unicode! ☯ - ♫\" <utf8_string>",
|
||||
"}"
|
||||
};
|
||||
|
||||
for (int i = 0; i < 42; i++) {
|
||||
ok((strstr(dump_output, expect[i]) != NULL),
|
||||
"dump output contains expected line (%s) - %s", expect[i],
|
||||
mode_desc);
|
||||
}
|
||||
|
||||
free(dump_output);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
||||
#else
|
||||
int main(void)
|
||||
{
|
||||
plan(SKIP_ALL, "This test requires the open_memstream() function");
|
||||
}
|
||||
#endif
|
106
module/Vendor/MaxmindDB/t/external_symbols_t.pl
vendored
Normal file
106
module/Vendor/MaxmindDB/t/external_symbols_t.pl
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin qw( $Bin );
|
||||
|
||||
_skip_tests_if_required_modules_are_not_present();
|
||||
_skip_tests_if_nm_is_not_present();
|
||||
_test_libs_external_symbols();
|
||||
|
||||
done_testing();
|
||||
|
||||
sub _skip_tests_if_required_modules_are_not_present {
|
||||
eval <<'EOF';
|
||||
use Test::More 0.88;
|
||||
use IPC::Run3 qw( run3 );
|
||||
EOF
|
||||
|
||||
if ($@) {
|
||||
print
|
||||
"1..0 # skip all tests skipped - these tests need the Test::More 0.88, IPC::Run3 modules:\n";
|
||||
print "$@";
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub _skip_tests_if_nm_is_not_present {
|
||||
run3(
|
||||
[ 'nm', '-V' ],
|
||||
\undef,
|
||||
\undef,
|
||||
\undef,
|
||||
);
|
||||
|
||||
my $exit_status = $? >> 8;
|
||||
if ($exit_status) {
|
||||
print
|
||||
"1..0 # skipp all tests skipped - this test requires the command line utility `nm`.\n";
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub _test_libs_external_symbols {
|
||||
my @libs = _libs_to_test();
|
||||
|
||||
if (@libs) {
|
||||
for my $lib (@libs) {
|
||||
_test_lib_external_symbols($lib);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fail('No libs were found to test');
|
||||
}
|
||||
}
|
||||
|
||||
sub _libs_to_test {
|
||||
my $lib_dir = "$Bin/../src/.libs";
|
||||
opendir my $dh, $lib_dir
|
||||
or die "Failed to open the lib dir at $lib_dir for reading: $!\n";
|
||||
my @libs = map { $lib_dir . q{/} . $_ }
|
||||
grep { $_ =~ m/\.so$/ } readdir $dh;
|
||||
closedir $dh;
|
||||
|
||||
return @libs;
|
||||
}
|
||||
|
||||
sub _test_lib_external_symbols {
|
||||
my $lib = shift;
|
||||
|
||||
my $stdout;
|
||||
my $stderr;
|
||||
run3(
|
||||
[ 'nm', '-g', '--defined-only', $lib ],
|
||||
\undef,
|
||||
\$stdout,
|
||||
\$stderr,
|
||||
);
|
||||
|
||||
my $exit_status = $? >> 8;
|
||||
ok( !$exit_status, 'nm returned a non-error status' )
|
||||
or diag($stderr);
|
||||
|
||||
my @external_symbols = _extract_external_symbols($stdout);
|
||||
is_deeply(
|
||||
[ grep { $_ !~ m/^MMDB_/ } @external_symbols ],
|
||||
[],
|
||||
"$lib exports only MMDB_ symbols"
|
||||
);
|
||||
}
|
||||
|
||||
sub _extract_external_symbols {
|
||||
my $nm_output = shift;
|
||||
|
||||
my @lines = split /\r\n|\r|\n/, $nm_output;
|
||||
|
||||
my @external_symbols;
|
||||
for my $line (@lines) {
|
||||
my @fields = split /\s+/, $line;
|
||||
die "Unexpected nm output for line $line\n"
|
||||
if @fields != 3;
|
||||
push @external_symbols, $fields[2];
|
||||
}
|
||||
|
||||
return @external_symbols;
|
||||
}
|
66
module/Vendor/MaxmindDB/t/get_value_pointer_bug_t.c
vendored
Normal file
66
module/Vendor/MaxmindDB/t/get_value_pointer_bug_t.c
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
#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 = mmdb_strndup(entry_data.utf8_string, entry_data.data_size);
|
||||
if (!string) {
|
||||
ok(0, "mmdb_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();
|
||||
}
|
313
module/Vendor/MaxmindDB/t/get_value_t.c
vendored
Normal file
313
module/Vendor/MaxmindDB/t/get_value_t.c
vendored
Normal file
@ -0,0 +1,313 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void test_array_0_result(int status, MMDB_entry_data_s entry_data,
|
||||
char *function)
|
||||
{
|
||||
cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"status for %s() is MMDB_SUCCESS - array[0]", function);
|
||||
ok(entry_data.has_data, "found a value for array[0]");
|
||||
cmp_ok(entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
|
||||
"returned entry type is uint32 - array[0]");
|
||||
cmp_ok(entry_data.uint32, "==", 1, "entry value is 1 - array[0]");
|
||||
}
|
||||
|
||||
void test_array_2_result(int status, MMDB_entry_data_s entry_data,
|
||||
char *function)
|
||||
{
|
||||
cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"status for %s() is MMDB_SUCCESS - array[2]", function);
|
||||
ok(entry_data.has_data, "found a value for array[2]");
|
||||
cmp_ok(entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
|
||||
"returned entry type is uint32 - array[2]");
|
||||
cmp_ok(entry_data.uint32, "==", 3, "entry value is 3 - array[2]");
|
||||
}
|
||||
|
||||
void test_array_minus_3_result(int status, MMDB_entry_data_s entry_data,
|
||||
char *function)
|
||||
{
|
||||
cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"status for %s() is MMDB_SUCCESS - array[-3]", function);
|
||||
ok(entry_data.has_data, "found a value for array[-3]");
|
||||
cmp_ok(entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
|
||||
"returned entry type is uint32 - array[-3]");
|
||||
cmp_ok(entry_data.uint32, "==", 1, "entry value is 1 - array[-3]");
|
||||
}
|
||||
|
||||
void test_array_minus_1_result(int status, MMDB_entry_data_s entry_data,
|
||||
char *function)
|
||||
{
|
||||
cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"status for %s() is MMDB_SUCCESS - array[-1]", function);
|
||||
ok(entry_data.has_data, "found a value for array[-1]");
|
||||
cmp_ok(entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
|
||||
"returned entry type is uint32 - array[-1]");
|
||||
cmp_ok(entry_data.uint32, "==", 3, "entry value is 3 - array[-1]");
|
||||
}
|
||||
|
||||
|
||||
int call_vget_value(MMDB_entry_s *entry, MMDB_entry_data_s *entry_data, ...)
|
||||
{
|
||||
va_list keys;
|
||||
va_start(keys, entry_data);
|
||||
|
||||
int status = MMDB_vget_value(entry, entry_data, keys);
|
||||
|
||||
va_end(keys);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void test_simple_structure(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-decoder.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const char *ip = "1.1.1.1";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] = { "array", "0", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_array_0_result(status, entry_data, "MMDB_aget_value");
|
||||
|
||||
status = MMDB_get_value(&result.entry, &entry_data, "array", "0", NULL);
|
||||
test_array_0_result(status, entry_data, "MMDB_get_value");
|
||||
|
||||
status =
|
||||
call_vget_value(&result.entry, &entry_data, "array", "0", NULL);
|
||||
test_array_0_result(status, entry_data, "MMDB_vget_value");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] = { "array", "2", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_array_2_result(status, entry_data, "MMDB_aget_value");
|
||||
|
||||
status = MMDB_get_value(&result.entry, &entry_data, "array", "2", NULL);
|
||||
test_array_2_result(status, entry_data, "MMDB_get_value");
|
||||
|
||||
status =
|
||||
call_vget_value(&result.entry, &entry_data, "array", "2", NULL);
|
||||
test_array_2_result(status, entry_data, "MMDB_vget_value");
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status = MMDB_get_value(&result.entry, &entry_data, "array", "zero",
|
||||
NULL);
|
||||
cmp_ok(status, "==", MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR,
|
||||
"MMDB_get_value() returns error on non-integer array index");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] = { "array", "-1", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_array_minus_1_result(status, entry_data, "MMDB_aget_value");
|
||||
|
||||
status =
|
||||
MMDB_get_value(&result.entry, &entry_data, "array", "-1", NULL);
|
||||
test_array_minus_1_result(status, entry_data, "MMDB_get_value");
|
||||
|
||||
status =
|
||||
call_vget_value(&result.entry, &entry_data, "array", "-1", NULL);
|
||||
test_array_minus_1_result(status, entry_data, "MMDB_vget_value");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] = { "array", "-3", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_array_minus_3_result(status, entry_data, "MMDB_aget_value");
|
||||
|
||||
status =
|
||||
MMDB_get_value(&result.entry, &entry_data, "array", "-3", NULL);
|
||||
test_array_minus_3_result(status, entry_data, "MMDB_get_value");
|
||||
|
||||
status =
|
||||
call_vget_value(&result.entry, &entry_data, "array", "-3", NULL);
|
||||
test_array_minus_3_result(status, entry_data, "MMDB_vget_value");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status = MMDB_get_value(&result.entry, &entry_data, "array", "-4",
|
||||
NULL);
|
||||
cmp_ok(status, "==", MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR,
|
||||
"MMDB_get_value() returns error on too large negative integer");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status =
|
||||
MMDB_get_value(&result.entry, &entry_data, "array",
|
||||
"-18446744073709551616",
|
||||
NULL);
|
||||
cmp_ok(status, "==", MMDB_INVALID_LOOKUP_PATH_ERROR,
|
||||
"MMDB_get_value() returns error on integer smaller than LONG_MIN");
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status =
|
||||
MMDB_get_value(&result.entry, &entry_data, "array",
|
||||
"18446744073709551616",
|
||||
NULL);
|
||||
cmp_ok(status, "==", MMDB_INVALID_LOOKUP_PATH_ERROR,
|
||||
"MMDB_get_value() returns error on integer larger than LONG_MAX");
|
||||
}
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
void test_complex_map_a_result(int status, MMDB_entry_data_s entry_data,
|
||||
char *function)
|
||||
{
|
||||
cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"status for %s() is MMDB_SUCCESS - map1{map2}{array}[0]{map3}{a}",
|
||||
function);
|
||||
ok(entry_data.has_data,
|
||||
"found a value for map1{map2}{array}[0]{map3}{a}");
|
||||
cmp_ok(entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
|
||||
"returned entry type is uint32 - map1{map2}{array}[0]{map3}{a}");
|
||||
cmp_ok(entry_data.uint32, "==", 1,
|
||||
"entry value is 1 - map1{map2}{array}[0]{map3}{a}");
|
||||
}
|
||||
|
||||
void test_complex_map_c_result(int status, MMDB_entry_data_s entry_data,
|
||||
char *function)
|
||||
{
|
||||
cmp_ok(
|
||||
status, "==", MMDB_SUCCESS,
|
||||
"status for %s() is MMDB_SUCCESS - map1{map2}{array}[0]{map3}{c}",
|
||||
function);
|
||||
ok(entry_data.has_data,
|
||||
"found a value for map1{map2}{array}[0]{map3}{c}");
|
||||
cmp_ok(entry_data.type, "==", MMDB_DATA_TYPE_UINT32,
|
||||
"returned entry type is uint32 - map1{map2}{array}[0]{map3}{c}");
|
||||
cmp_ok(entry_data.uint32, "==", 3,
|
||||
"entry value is 3 - map1{map2}{array}[0]{map3}{c}");
|
||||
}
|
||||
|
||||
void test_no_result(int status, MMDB_entry_data_s entry_data, char *function,
|
||||
char *path_description)
|
||||
{
|
||||
cmp_ok(status, "==", MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR,
|
||||
"status for %s() is MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR - %s",
|
||||
function, path_description);
|
||||
ok(!entry_data.has_data, "did not find a value for %s", path_description);
|
||||
}
|
||||
|
||||
void test_nested_structure(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-nested.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const char *ip = "1.1.1.1";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] =
|
||||
{ "map1", "map2", "array", "0", "map3", "a", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_complex_map_a_result(status, entry_data, "MMDB_aget_value");
|
||||
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"map1", "map2", "array", "0", "map3", "a",
|
||||
NULL);
|
||||
test_complex_map_a_result(status, entry_data, "MMDB_get_value");
|
||||
|
||||
status = call_vget_value(&result.entry, &entry_data,
|
||||
"map1", "map2", "array", "0", "map3", "a",
|
||||
NULL);
|
||||
test_complex_map_a_result(status, entry_data, "MMDB_vget_value");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] =
|
||||
{ "map1", "map2", "array", "0", "map3", "c", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_complex_map_c_result(status, entry_data, "MMDB_aget_value");
|
||||
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"map1", "map2", "array", "0", "map3", "c",
|
||||
NULL);
|
||||
test_complex_map_c_result(status, entry_data, "MMDB_get_value");
|
||||
|
||||
status = call_vget_value(&result.entry, &entry_data,
|
||||
"map1", "map2", "array", "0", "map3", "c",
|
||||
NULL);
|
||||
test_complex_map_c_result(status, entry_data, "MMDB_vget_value");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] =
|
||||
{ "map1", "map42", "array", "0", "map3", "c", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_no_result(status, entry_data, "MMDB_aget_value",
|
||||
"map1{map42}{array}[0]{map3}{c}");
|
||||
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"map1", "map42", "array", "0", "map3", "c",
|
||||
NULL);
|
||||
test_no_result(status, entry_data, "MMDB_get_value",
|
||||
"map1{map42}{array}[0]{map3}{c}");
|
||||
|
||||
status = call_vget_value(&result.entry, &entry_data,
|
||||
"map1", "map42", "array", "0", "map3", "c",
|
||||
NULL);
|
||||
test_no_result(status, entry_data, "MMDB_vget_value",
|
||||
"map1{map42}{array}[0]{map3}{c}");
|
||||
}
|
||||
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
const char *lookup_path[] =
|
||||
{ "map1", "map2", "array", "9", "map3", "c", NULL };
|
||||
int status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
|
||||
test_no_result(status, entry_data, "MMDB_aget_value",
|
||||
"map1{map42}{array}[9]{map3}{c}");
|
||||
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"map1", "map2", "array", "9", "map3", "c",
|
||||
NULL);
|
||||
test_no_result(status, entry_data, "MMDB_get_value",
|
||||
"map1{map42}{array}[9]{map3}{c}");
|
||||
|
||||
status = call_vget_value(&result.entry, &entry_data,
|
||||
"map1", "map2", "array", "9", "map3", "c",
|
||||
NULL);
|
||||
test_no_result(status, entry_data, "MMDB_vget_value",
|
||||
"map1{map42}{array}[9]{map3}{c}");
|
||||
}
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
test_simple_structure(mode, mode_desc);
|
||||
test_nested_structure(mode, mode_desc);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
36
module/Vendor/MaxmindDB/t/ipv4_start_cache_t.c
vendored
Normal file
36
module/Vendor/MaxmindDB/t/ipv4_start_cache_t.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void test_one_ip(MMDB_s *mmdb, const char *ip, const char *filename,
|
||||
const char *mode_desc)
|
||||
{
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
ok(
|
||||
result.found_entry,
|
||||
"got a result for an IPv4 address included in a larger-than-IPv4 subnet - %s - %s",
|
||||
ip, mode_desc);
|
||||
|
||||
data_ok(&result, MMDB_DATA_TYPE_UTF8_STRING, "string value for IP", NULL);
|
||||
}
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-no-ipv4-search-tree.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
test_one_ip(mmdb, "1.1.1.1", filename, mode_desc);
|
||||
test_one_ip(mmdb, "255.255.255.255", filename, mode_desc);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
48
module/Vendor/MaxmindDB/t/ipv6_lookup_in_ipv4_t.c
vendored
Normal file
48
module/Vendor/MaxmindDB/t/ipv6_lookup_in_ipv4_t.c
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-ipv4-28.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const char *ip = "::abcd";
|
||||
int gai_error, mmdb_error;
|
||||
MMDB_lookup_result_s UNUSED(result) =
|
||||
MMDB_lookup_string(mmdb, ip, &gai_error, &mmdb_error);
|
||||
|
||||
cmp_ok(
|
||||
mmdb_error, "==", MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR,
|
||||
"MMDB_lookup_string sets mmdb_error to MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR when we try to look up an IPv6 address in an IPv4-only database");
|
||||
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_INET6,
|
||||
.ai_flags = AI_NUMERICHOST
|
||||
};
|
||||
|
||||
struct addrinfo *addresses;
|
||||
gai_error = getaddrinfo("2001:db8:85a3:0:0:8a2e:370:7334", NULL,
|
||||
&hints, &addresses);
|
||||
if (gai_error) {
|
||||
BAIL_OUT("getaddrinfo failed: %s", gai_strerror(gai_error));
|
||||
}
|
||||
|
||||
mmdb_error = 0;
|
||||
MMDB_lookup_sockaddr(mmdb, addresses->ai_addr, &mmdb_error);
|
||||
|
||||
cmp_ok(
|
||||
mmdb_error, "==", MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR,
|
||||
"MMDB_lookup_sockaddr sets mmdb_error to MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR when we try to look up an IPv6 address in an IPv4-only database");
|
||||
|
||||
freeaddrinfo(addresses);
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
232
module/Vendor/MaxmindDB/t/maxminddb_test_helper.c
vendored
Normal file
232
module/Vendor/MaxmindDB/t/maxminddb_test_helper.c
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "maxminddb.h"
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void for_all_record_sizes(const char *filename_fmt,
|
||||
void (*tests)(int record_size, const char *filename,
|
||||
const char *description))
|
||||
{
|
||||
int sizes[] = { 24, 28, 32 };
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int size = sizes[i];
|
||||
|
||||
char filename[500];
|
||||
snprintf(filename, 500, filename_fmt, size);
|
||||
|
||||
char description[14];
|
||||
snprintf(description, 14, "%i bit record", size);
|
||||
|
||||
tests(size, filename, description);
|
||||
}
|
||||
}
|
||||
|
||||
void for_all_modes(void (*tests)(int mode, const char *description))
|
||||
{
|
||||
tests(MMDB_MODE_MMAP, "mmap mode");
|
||||
}
|
||||
|
||||
const char *test_database_path(const char *filename)
|
||||
{
|
||||
char cwd[500];
|
||||
char *UNUSED(tmp) = getcwd(cwd, 500);
|
||||
|
||||
char *test_db_dir;
|
||||
#ifdef _WIN32
|
||||
test_db_dir = "./t/maxmind-db/test-data";
|
||||
#else
|
||||
if (strcmp(basename(cwd), "t") == 0) {
|
||||
test_db_dir = "./maxmind-db/test-data";
|
||||
} else {
|
||||
test_db_dir = "./t/maxmind-db/test-data";
|
||||
}
|
||||
#endif
|
||||
|
||||
char *path = malloc(500);
|
||||
assert(NULL != path);
|
||||
|
||||
snprintf(path, 500, "%s/%s", test_db_dir, filename);
|
||||
|
||||
return (const char *)path;
|
||||
}
|
||||
|
||||
const char *dup_entry_string_or_bail(MMDB_entry_data_s entry_data)
|
||||
{
|
||||
const char *string = mmdb_strndup(entry_data.utf8_string, entry_data.data_size);
|
||||
if (NULL == string) {
|
||||
BAIL_OUT("mmdb_strndup failed");
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
MMDB_s *open_ok(const char *db_file, int mode, const char *mode_desc)
|
||||
{
|
||||
if (0 != access(db_file, R_OK)) {
|
||||
BAIL_OUT(
|
||||
"could not read the specified file - %s\nIf you are in a git checkout try running 'git submodule update --init'",
|
||||
db_file);
|
||||
}
|
||||
|
||||
MMDB_s *mmdb = (MMDB_s *)calloc(1, sizeof(MMDB_s));
|
||||
|
||||
if (NULL == mmdb) {
|
||||
BAIL_OUT("could not allocate memory for our MMDB_s struct");
|
||||
}
|
||||
|
||||
int status = MMDB_open(db_file, mode, mmdb);
|
||||
|
||||
int is_ok = ok(MMDB_SUCCESS == status, "open %s status is success - %s",
|
||||
db_file, mode_desc);
|
||||
|
||||
if (!is_ok) {
|
||||
diag("open status code = %d (%s)", status, MMDB_strerror(status));
|
||||
free(mmdb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
is_ok = ok(mmdb->file_size > 0,
|
||||
"mmdb struct has been set for %s - %s",
|
||||
db_file, mode_desc);
|
||||
|
||||
if (!is_ok) {
|
||||
free(mmdb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mmdb;
|
||||
}
|
||||
|
||||
MMDB_lookup_result_s lookup_string_ok(MMDB_s *mmdb, const char *ip,
|
||||
const char *file, const char *mode_desc)
|
||||
{
|
||||
int gai_error, mmdb_error;
|
||||
MMDB_lookup_result_s result =
|
||||
MMDB_lookup_string(mmdb, ip, &gai_error, &mmdb_error);
|
||||
|
||||
test_lookup_errors(gai_error, mmdb_error, "MMDB_lookup_string", ip, file,
|
||||
mode_desc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MMDB_lookup_result_s lookup_sockaddr_ok(MMDB_s *mmdb, const char *ip,
|
||||
const char *file, const char *mode_desc)
|
||||
{
|
||||
int ai_flags = AI_NUMERICHOST;
|
||||
struct addrinfo hints = {
|
||||
.ai_socktype = SOCK_STREAM
|
||||
};
|
||||
struct addrinfo *addresses = NULL;
|
||||
|
||||
if (ip[0] == ':') {
|
||||
hints.ai_flags = ai_flags;
|
||||
#if defined AI_V4MAPPED && !defined __FreeBSD__
|
||||
hints.ai_flags |= AI_V4MAPPED;
|
||||
#endif
|
||||
hints.ai_family = AF_INET6;
|
||||
} else {
|
||||
hints.ai_flags = ai_flags;
|
||||
hints.ai_family = AF_INET;
|
||||
}
|
||||
|
||||
int gai_error = getaddrinfo(ip, NULL, &hints, &addresses);
|
||||
|
||||
int mmdb_error = 0;
|
||||
MMDB_lookup_result_s result = { .found_entry = false };
|
||||
if (gai_error == 0) {
|
||||
result = MMDB_lookup_sockaddr(mmdb, addresses->ai_addr, &mmdb_error);
|
||||
}
|
||||
if (NULL != addresses) {
|
||||
freeaddrinfo(addresses);
|
||||
}
|
||||
|
||||
test_lookup_errors(gai_error, mmdb_error, "MMDB_lookup_sockaddr", ip, file,
|
||||
mode_desc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void test_lookup_errors(int gai_error, int mmdb_error,
|
||||
const char *function, const char *ip,
|
||||
const char *file, const char *mode_desc)
|
||||
{
|
||||
|
||||
int is_ok = ok(0 == gai_error,
|
||||
"no getaddrinfo error in call to %s for %s - %s - %s",
|
||||
function, ip, file, mode_desc);
|
||||
|
||||
if (!is_ok) {
|
||||
diag("error from call to getaddrinfo for %s - %s",
|
||||
ip, gai_strerror(gai_error));
|
||||
}
|
||||
|
||||
is_ok = ok(0 == mmdb_error,
|
||||
"no MMDB error in call to %s for %s - %s - %s",
|
||||
function, ip, file, mode_desc);
|
||||
|
||||
if (!is_ok) {
|
||||
diag("MMDB error - %s", MMDB_strerror(mmdb_error));
|
||||
}
|
||||
}
|
||||
|
||||
MMDB_entry_data_s data_ok(MMDB_lookup_result_s *result, uint32_t expect_type,
|
||||
const char *description, ...)
|
||||
{
|
||||
va_list keys;
|
||||
va_start(keys, description);
|
||||
|
||||
MMDB_entry_data_s data;
|
||||
int status = MMDB_vget_value(&result->entry, &data, keys);
|
||||
|
||||
va_end(keys);
|
||||
|
||||
if (cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"no error from call to MMDB_vget_value - %s", description)) {
|
||||
|
||||
if (!cmp_ok(data.type, "==", expect_type,
|
||||
"got the expected data type - %s", description)) {
|
||||
|
||||
diag(" data type value is %i but expected %i", data.type,
|
||||
expect_type);
|
||||
}
|
||||
} else {
|
||||
diag(" error from MMDB_vget_value - %s", MMDB_strerror(status));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void compare_double(double got, double expect)
|
||||
{
|
||||
double diff = fabs(got - expect);
|
||||
int is_ok = ok(diff < 0.01, "double value was approximately %2.6f", expect);
|
||||
if (!is_ok) {
|
||||
diag(" got %2.6f but expected %2.6f (diff = %2.6f)",
|
||||
got, expect, diff);
|
||||
}
|
||||
}
|
||||
|
||||
void compare_float(float got, float expect)
|
||||
{
|
||||
float diff = fabsf(got - expect);
|
||||
int is_ok = ok(diff < 0.01, "float value was approximately %2.1f", expect);
|
||||
if (!is_ok) {
|
||||
diag(" got %2.4f but expected %2.1f (diff = %2.1f)",
|
||||
got, expect, diff);
|
||||
}
|
||||
}
|
66
module/Vendor/MaxmindDB/t/maxminddb_test_helper.h
vendored
Normal file
66
module/Vendor/MaxmindDB/t/maxminddb_test_helper.h
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/* Some test files may require something newer */
|
||||
#if !defined(_GNU_SOURCE) && !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "maxminddb.h"
|
||||
#include "maxminddb-compat-util.h"
|
||||
#include "libtap/tap.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#define R_OK 4
|
||||
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER && _MSC_VER < 1900)
|
||||
/* _snprintf has security issues, but I don't think it is worth
|
||||
worrying about for the unit tests. */
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifndef MMDB_TEST_HELPER_C
|
||||
#define MMDB_TEST_HELPER_C (1)
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
|
||||
#else
|
||||
# define UNUSED
|
||||
#endif
|
||||
|
||||
#define MAX_DESCRIPTION_LENGTH 500
|
||||
|
||||
extern void for_all_record_sizes(const char *filename_fmt,
|
||||
void (*tests)(int record_size,
|
||||
const char *filename,
|
||||
const char *description));
|
||||
extern void for_all_modes(void (*tests)(int mode, const char *description));
|
||||
extern const char *test_database_path(const char *filename);
|
||||
extern const char *dup_entry_string_or_bail(MMDB_entry_data_s entry_data);
|
||||
extern MMDB_s *open_ok(const char *db_file, int mode, const char *mode_desc);
|
||||
extern MMDB_lookup_result_s lookup_string_ok(MMDB_s *mmdb, const char *ip,
|
||||
const char *file,
|
||||
const char *mode_desc);
|
||||
extern MMDB_lookup_result_s lookup_sockaddr_ok(MMDB_s *mmdb, const char *ip,
|
||||
const char *file,
|
||||
const char *mode_desc);
|
||||
extern void test_lookup_errors(int gai_error, int mmdb_error,
|
||||
const char *function, const char *ip,
|
||||
const char *file, const char *mode_desc);
|
||||
extern MMDB_entry_data_s data_ok(MMDB_lookup_result_s *result,
|
||||
uint32_t expect_type,
|
||||
const char *description, ...);
|
||||
extern void compare_double(double got, double expect);
|
||||
extern void compare_float(float got, float expect);
|
||||
|
||||
#endif
|
32
module/Vendor/MaxmindDB/t/metadata_pointers_t.c
vendored
Normal file
32
module/Vendor/MaxmindDB/t/metadata_pointers_t.c
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-metadata-pointers.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
char *repeated_string = "Lots of pointers in metadata";
|
||||
|
||||
is(mmdb->metadata.database_type, repeated_string,
|
||||
"decoded pointer database_type");
|
||||
|
||||
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;
|
||||
is(description, repeated_string, "%s description", language);
|
||||
}
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
226
module/Vendor/MaxmindDB/t/metadata_t.c
vendored
Normal file
226
module/Vendor/MaxmindDB/t/metadata_t.c
vendored
Normal file
@ -0,0 +1,226 @@
|
||||
#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();
|
||||
}
|
158
module/Vendor/MaxmindDB/t/mmdblookup_t.pl
vendored
Normal file
158
module/Vendor/MaxmindDB/t/mmdblookup_t.pl
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin qw( $Bin );
|
||||
|
||||
eval <<'EOF';
|
||||
use Test::More 0.88;
|
||||
use IPC::Run3 qw( run3 );
|
||||
EOF
|
||||
|
||||
if ($@) {
|
||||
print
|
||||
"1..0 # skip all tests skipped - these tests need the Test::More 0.88, IPC::Run3 and Test::Output modules:\n";
|
||||
print "$@";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $mmdblookup = "$Bin/../bin/mmdblookup";
|
||||
my $test_data_dir = "$Bin/maxmind-db/test-data";
|
||||
|
||||
{
|
||||
ok( -x $mmdblookup, 'mmdblookup script is executable' );
|
||||
}
|
||||
|
||||
for my $arg (qw( -h -? --help )) {
|
||||
_test_stdout(
|
||||
[$arg],
|
||||
qr{mmdblookup --file.+This application accepts the following options:}s,
|
||||
0,
|
||||
"help output from $arg"
|
||||
);
|
||||
}
|
||||
|
||||
_test_both(
|
||||
[],
|
||||
qr{mmdblookup --file.+This application accepts the following options:}s,
|
||||
qr{ERROR: You must provide a filename with --file},
|
||||
1,
|
||||
"help output with no CLI options"
|
||||
);
|
||||
|
||||
_test_stderr(
|
||||
[qw( --file foo )],
|
||||
qr{ERROR: You must provide an IP address with --ip},
|
||||
1,
|
||||
'error when no --ip is given'
|
||||
);
|
||||
|
||||
_test_stdout(
|
||||
[qw( --version )],
|
||||
qr/mmdblookup version \d+\.\d+\.\d+/,
|
||||
0,
|
||||
'output for --version'
|
||||
);
|
||||
|
||||
_test_stdout(
|
||||
['--file', "$test_data_dir/GeoIP2-City-Test.mmdb", '--ip', '2.125.160.216'],
|
||||
qr/"en"\s*:\s*"Boxford"/,
|
||||
0,
|
||||
'output for 2.125.160.216'
|
||||
);
|
||||
|
||||
_test_stdout(
|
||||
['--file', "$test_data_dir/GeoIP2-City-Test.mmdb", '--ip', '2.125.160.216', '--verbose'],
|
||||
qr/Database metadata.+"en"\s*:\s*"Boxford"/s,
|
||||
0,
|
||||
'verbose output for 2.125.160.216'
|
||||
);
|
||||
|
||||
_test_stdout(
|
||||
['--file', "$test_data_dir/GeoIP2-City-Test.mmdb", '--ip', '2.125.160.216', qw( location latitude )],
|
||||
qr/^\s*51\.750000 <double>\s*$/s,
|
||||
0,
|
||||
'output for 2.125.160.216 with lookup path'
|
||||
);
|
||||
|
||||
_test_stderr(
|
||||
[ qw( --file this/path/better/not/exist.mmdb --ip 1.2.3.4 ) ],
|
||||
qr{Can't open this/path/better/not/exist.mmdb}s,
|
||||
2,
|
||||
'error for file that does not exist'
|
||||
);
|
||||
|
||||
_test_stderr(
|
||||
['--file', "$test_data_dir/GeoIP2-City-Test.mmdb", '--ip', 'not-an-ip-address' ],
|
||||
qr{Error from call to getaddrinfo for not-an-ip-address}s,
|
||||
3,
|
||||
'error for bad IP address'
|
||||
);
|
||||
|
||||
_test_stderr(
|
||||
['--file', "$test_data_dir/GeoIP2-City-Test.mmdb", '--ip', '10.2.3.4' ],
|
||||
qr{\QCould not find an entry for this IP address (10.2.3.4)}s,
|
||||
6,
|
||||
'error for bad PI address'
|
||||
);
|
||||
|
||||
done_testing();
|
||||
|
||||
sub _test_stdout {
|
||||
my $args = shift;
|
||||
my $expect_stdout = shift;
|
||||
my $expect_status = shift;
|
||||
my $desc = shift;
|
||||
|
||||
_test_both( $args, $expect_stdout, q{}, $expect_status, $desc );
|
||||
}
|
||||
|
||||
sub _test_stderr {
|
||||
my $args = shift;
|
||||
my $expect_stderr = shift;
|
||||
my $expect_status = shift;
|
||||
my $desc = shift;
|
||||
|
||||
_test_both( $args, undef, $expect_stderr, $expect_status, $desc );
|
||||
}
|
||||
|
||||
sub _test_both {
|
||||
my $args = shift;
|
||||
my $expect_stdout = shift;
|
||||
my $expect_stderr = shift;
|
||||
my $expect_status = shift;
|
||||
my $desc = shift;
|
||||
|
||||
my $stdout;
|
||||
my $stderr;
|
||||
run3(
|
||||
[ $mmdblookup, @{$args} ],
|
||||
\undef,
|
||||
\$stdout,
|
||||
\$stderr,
|
||||
);
|
||||
|
||||
my $exit_status = $? >> 8;
|
||||
|
||||
# We don't need to retest that the help output shows up for all errors
|
||||
if ( defined $expect_stdout ) {
|
||||
like(
|
||||
$stdout,
|
||||
$expect_stdout,
|
||||
"stdout for mmdblookup @{$args}"
|
||||
);
|
||||
}
|
||||
|
||||
if ( ref $expect_stderr ) {
|
||||
like( $stderr, $expect_stderr, "stderr for mmdblookup @{$args}" );
|
||||
}
|
||||
else {
|
||||
is( $stderr, $expect_stderr, "stderr for mmdblookup @{$args}" );
|
||||
}
|
||||
|
||||
is(
|
||||
$exit_status, $expect_status,
|
||||
"exit status was $expect_status for mmdblookup @{$args}"
|
||||
);
|
||||
}
|
32
module/Vendor/MaxmindDB/t/no_map_get_value_t.c
vendored
Normal file
32
module/Vendor/MaxmindDB/t/no_map_get_value_t.c
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-string-value-entries.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const char *ip = "1.1.1.1";
|
||||
MMDB_lookup_result_s result =
|
||||
lookup_string_ok(mmdb, ip, filename, mode_desc);
|
||||
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status = MMDB_get_value(&result.entry, &entry_data, NULL);
|
||||
|
||||
cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"status for MMDB_get_value() is MMDB_SUCCESS");
|
||||
ok(entry_data.has_data, "found a value when varargs list is just NULL");
|
||||
cmp_ok(entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
|
||||
"returned entry type is utf8_string");
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
157
module/Vendor/MaxmindDB/t/read_node_t.c
vendored
Normal file
157
module/Vendor/MaxmindDB/t/read_node_t.c
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
void test_entry_data(MMDB_s *mmdb, MMDB_entry_s *entry, uint32_t node_number,
|
||||
char * node_record)
|
||||
{
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status =
|
||||
MMDB_get_value(entry, &entry_data, "ip",
|
||||
NULL);
|
||||
cmp_ok(status, "==", MMDB_SUCCESS,
|
||||
"successful data lookup for node");
|
||||
cmp_ok(
|
||||
entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
|
||||
"returned entry type is UTF8_STRING for %s record of node %i",
|
||||
node_record, node_number);
|
||||
}
|
||||
|
||||
void run_read_node_tests(MMDB_s *mmdb, const uint32_t tests[][5],
|
||||
int test_count,
|
||||
uint8_t record_size)
|
||||
{
|
||||
for (int i = 0; i < test_count; i++) {
|
||||
uint32_t node_number = tests[i][0];
|
||||
MMDB_search_node_s node;
|
||||
int status = MMDB_read_node(mmdb, node_number, &node);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
cmp_ok(node.left_record, "==", tests[i][1],
|
||||
"left record for node %i is %i - %i bit DB",
|
||||
node_number, tests[i][1], record_size);
|
||||
cmp_ok(node.left_record_type, "==", tests[i][2],
|
||||
"left record type for node %i is %i", node_number,
|
||||
tests[i][2]);
|
||||
if (node.left_record_type == MMDB_RECORD_TYPE_DATA) {
|
||||
test_entry_data(mmdb, &node.left_record_entry, node_number,
|
||||
"left");
|
||||
}
|
||||
|
||||
cmp_ok(node.right_record, "==", tests[i][3],
|
||||
"right record for node %i is %i - %i bit DB",
|
||||
node_number, tests[i][3], record_size);
|
||||
cmp_ok(node.right_record_type, "==", tests[i][4],
|
||||
"right record type for node %i is %i", node_number,
|
||||
tests[i][4]);
|
||||
|
||||
if (node.right_record_type == MMDB_RECORD_TYPE_DATA) {
|
||||
test_entry_data(mmdb, &node.right_record_entry, node_number,
|
||||
"right");
|
||||
}
|
||||
} else {
|
||||
diag("call to MMDB_read_node for node %i failed - %i bit DB",
|
||||
node_number,
|
||||
record_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run_24_bit_record_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-mixed-24.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const uint32_t tests[7][5] = {
|
||||
{ 0, 1, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY },
|
||||
{ 80, 81, MMDB_RECORD_TYPE_SEARCH_NODE, 197,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE, },
|
||||
{ 96, 97, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, },
|
||||
{ 103, 242, MMDB_RECORD_TYPE_EMPTY, 104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE, },
|
||||
{ 127, 242, MMDB_RECORD_TYPE_EMPTY, 315,
|
||||
MMDB_RECORD_TYPE_DATA, },
|
||||
{ 132, 329, MMDB_RECORD_TYPE_DATA, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, },
|
||||
{ 241, 96, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, }
|
||||
};
|
||||
run_read_node_tests(mmdb, tests, 7, 24);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
void run_28_bit_record_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-mixed-28.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const uint32_t tests[7][5] = {
|
||||
{ 0, 1, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY },
|
||||
{ 80, 81, MMDB_RECORD_TYPE_SEARCH_NODE, 197,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE, },
|
||||
{ 96, 97, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, },
|
||||
{ 103, 242, MMDB_RECORD_TYPE_EMPTY, 104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE, },
|
||||
{ 127, 242, MMDB_RECORD_TYPE_EMPTY, 315,
|
||||
MMDB_RECORD_TYPE_DATA, },
|
||||
{ 132, 329, MMDB_RECORD_TYPE_DATA, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, },
|
||||
{ 241, 96, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, }
|
||||
};
|
||||
run_read_node_tests(mmdb, tests, 7, 28);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
void run_32_bit_record_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-mixed-32.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const uint32_t tests[7][5] = {
|
||||
{ 0, 1, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY },
|
||||
{ 80, 81, MMDB_RECORD_TYPE_SEARCH_NODE, 197,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE, },
|
||||
{ 96, 97, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, },
|
||||
{ 103, 242, MMDB_RECORD_TYPE_EMPTY, 104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE, },
|
||||
{ 127, 242, MMDB_RECORD_TYPE_EMPTY, 315,
|
||||
MMDB_RECORD_TYPE_DATA, },
|
||||
{ 132, 329, MMDB_RECORD_TYPE_DATA, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, },
|
||||
{ 241, 96, MMDB_RECORD_TYPE_SEARCH_NODE, 242,
|
||||
MMDB_RECORD_TYPE_EMPTY, }
|
||||
};
|
||||
|
||||
run_read_node_tests(mmdb, tests, 7, 32);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
run_24_bit_record_tests(mode, mode_desc);
|
||||
run_28_bit_record_tests(mode, mode_desc);
|
||||
run_32_bit_record_tests(mode, mode_desc);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
}
|
196
module/Vendor/MaxmindDB/t/threads_t.c
vendored
Normal file
196
module/Vendor/MaxmindDB/t/threads_t.c
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct thread_arg {
|
||||
int thread_id;
|
||||
MMDB_s *mmdb;
|
||||
const char *ip_to_lookup;
|
||||
} thread_arg_s;
|
||||
|
||||
typedef struct test_result {
|
||||
const char *ip_looked_up;
|
||||
int lookup_string_gai_error;
|
||||
int lookup_string_mmdb_error;
|
||||
int found_entry;
|
||||
int get_value_status;
|
||||
int data_type_ok;
|
||||
char *data_value;
|
||||
} test_result_s;
|
||||
|
||||
void test_one_ip(MMDB_s *mmdb, const char *ip, test_result_s *test_result)
|
||||
{
|
||||
|
||||
test_result->ip_looked_up = ip;
|
||||
|
||||
int gai_error = 0;
|
||||
int mmdb_error = 0;
|
||||
MMDB_lookup_result_s result =
|
||||
MMDB_lookup_string(mmdb, ip, &gai_error, &mmdb_error);
|
||||
|
||||
test_result->lookup_string_gai_error = gai_error;
|
||||
if (gai_error) {
|
||||
return;
|
||||
}
|
||||
|
||||
test_result->lookup_string_mmdb_error = mmdb_error;
|
||||
if (mmdb_error) {
|
||||
return;
|
||||
}
|
||||
|
||||
test_result->found_entry = result.found_entry;
|
||||
if (!result.found_entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
MMDB_entry_data_s data;
|
||||
int status = MMDB_get_value(&result.entry, &data, "ip", NULL);
|
||||
|
||||
test_result->get_value_status = status;
|
||||
if (status) {
|
||||
return;
|
||||
}
|
||||
|
||||
test_result->data_type_ok = data.type == MMDB_DATA_TYPE_UTF8_STRING;
|
||||
if (!test_result->data_type_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
test_result->data_value = mmdb_strndup(data.utf8_string, data.data_size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *run_one_thread(void *arg)
|
||||
{
|
||||
thread_arg_s *thread_arg = (thread_arg_s *)arg;
|
||||
|
||||
MMDB_s *mmdb = thread_arg->mmdb;
|
||||
const char *ip = thread_arg->ip_to_lookup;
|
||||
|
||||
test_result_s *result = malloc(sizeof(test_result_s));
|
||||
test_one_ip(mmdb, ip, result);
|
||||
|
||||
pthread_exit((void *)result);
|
||||
}
|
||||
|
||||
void process_result(test_result_s *result, const char *expect,
|
||||
const char *mode_desc)
|
||||
{
|
||||
int is_ok;
|
||||
is_ok =
|
||||
ok(!result->lookup_string_gai_error, "no getaddrinfo error for %s - %s",
|
||||
result->ip_looked_up, mode_desc);
|
||||
if (!is_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_ok = ok(!result->lookup_string_mmdb_error, "no mmdb error for %s - %s",
|
||||
result->ip_looked_up, mode_desc);
|
||||
if (!is_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_ok = ok(result->found_entry, "got a result for %s in the database - %s",
|
||||
result->ip_looked_up, mode_desc);
|
||||
if (!is_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_ok =
|
||||
ok(!result->get_value_status,
|
||||
"no error from MMDB_get_value for %s - %s",
|
||||
result->ip_looked_up,
|
||||
mode_desc);
|
||||
if (!is_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_ok = ok(result->data_type_ok,
|
||||
"MMDB_get_value found a utf8_string at 'ip' key for %s - %s",
|
||||
result->ip_looked_up, mode_desc);
|
||||
if (!is_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(result->data_value, expect,
|
||||
"found expected result for 'ip' key for %s - %s",
|
||||
result->ip_looked_up, mode_desc);
|
||||
}
|
||||
|
||||
void run_ipX_tests(MMDB_s *mmdb, const char *pairs[][2], int pairs_rows,
|
||||
int mode, const char *mode_desc)
|
||||
{
|
||||
pthread_t threads[pairs_rows];
|
||||
struct thread_arg thread_args[pairs_rows];
|
||||
|
||||
for (int i = 0; i < pairs_rows; i += 1) {
|
||||
thread_args[i].thread_id = i;
|
||||
thread_args[i].mmdb = mmdb;
|
||||
thread_args[i].ip_to_lookup = pairs[i][0];
|
||||
|
||||
int error = pthread_create(&threads[i], NULL, run_one_thread,
|
||||
&thread_args[i]);
|
||||
if (error) {
|
||||
BAIL_OUT("pthread_create failed");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < pairs_rows; i += 1) {
|
||||
void *thread_return;
|
||||
int error = pthread_join(threads[i], &thread_return);
|
||||
if (error) {
|
||||
BAIL_OUT("pthread_join failed");
|
||||
}
|
||||
|
||||
test_result_s *test_result = (test_result_s *)thread_return;
|
||||
if (NULL != test_result) {
|
||||
process_result(test_result, pairs[i][1], mode_desc);
|
||||
if (test_result->data_type_ok) {
|
||||
free(test_result->data_value);
|
||||
}
|
||||
free(test_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run_tests(int mode, const char *mode_desc)
|
||||
{
|
||||
const char *filename = "MaxMind-DB-test-mixed-32.mmdb";
|
||||
const char *path = test_database_path(filename);
|
||||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free((void *)path);
|
||||
|
||||
const char *pairs[18][2] = {
|
||||
{ "1.1.1.1", "::1.1.1.1" },
|
||||
{ "1.1.1.2", "::1.1.1.2" },
|
||||
{ "1.1.1.3", "::1.1.1.2" },
|
||||
{ "1.1.1.7", "::1.1.1.4" },
|
||||
{ "1.1.1.9", "::1.1.1.8" },
|
||||
{ "1.1.1.15", "::1.1.1.8" },
|
||||
{ "1.1.1.17", "::1.1.1.16" },
|
||||
{ "1.1.1.31", "::1.1.1.16" },
|
||||
{ "1.1.1.32", "::1.1.1.32" },
|
||||
{ "::1:ffff:ffff", "::1:ffff:ffff" },
|
||||
{ "::2:0:0", "::2:0:0" },
|
||||
{ "::2:0:1a", "::2:0:0" },
|
||||
{ "::2:0:40", "::2:0:40" },
|
||||
{ "::2:0:4f", "::2:0:40" },
|
||||
{ "::2:0:50", "::2:0:50" },
|
||||
{ "::2:0:52", "::2:0:50" },
|
||||
{ "::2:0:58", "::2:0:58" },
|
||||
{ "::2:0:59", "::2:0:58" },
|
||||
};
|
||||
|
||||
run_ipX_tests(mmdb, pairs, 18, mode, mode_desc);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
free(mmdb);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(NO_PLAN);
|
||||
for_all_modes(&run_tests);
|
||||
done_testing();
|
||||
pthread_exit(NULL);
|
||||
}
|
10
module/Vendor/MaxmindDB/t/version_t.c
vendored
Normal file
10
module/Vendor/MaxmindDB/t/version_t.c
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
#include "maxminddb_test_helper.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const char *version = MMDB_lib_version();
|
||||
if (ok((version != NULL), "MMDB_lib_version exists")) {
|
||||
is(version, PACKAGE_VERSION, "version is " PACKAGE_VERSION);
|
||||
}
|
||||
done_testing();
|
||||
}
|
Reference in New Issue
Block a user