1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00

Update MaxmindDB to current git.

This commit is contained in:
Sandu Liviu Catalin 2021-08-22 20:15:19 +03:00
parent 0008869ddd
commit 69a4d305a5
40 changed files with 2291 additions and 1912 deletions

View File

@ -41,6 +41,6 @@ jobs:
- uses: actions/checkout@v2
with:
submodules: true
- run: cmake -DBUILD_TESTING=ON -V .
- run: cmake -DBUILD_TESTING=ON .
- run: cmake --build .
- run: ctest -V .

View File

@ -1,3 +1,4 @@
*.a
*.la
*.lo
*.o
@ -25,13 +26,11 @@
/man
/missing
/src/libmaxminddb.pc
/src/libmaxminddb.a
/src/test-data-pool
/t/*.log
/t/*.trs
/t/*_t
/t/*-t
/t/libtap.a
/test-driver
\#*\#
aclocal.m4

View File

@ -1,78 +0,0 @@
#
# based on uncrustify config file for the linux kernel
#
code_width = 80
indent_case_brace = 4
indent_columns = 4
indent_label = 2 # pos: absolute col, neg: relative column
indent_with_tabs = 0
#
# inter-symbol newlines
#
nl_brace_else = remove # "} else" vs "} \n else" - cuddle else
nl_brace_while = remove # "} while" vs "} \n while" - cuddle while
nl_do_brace = remove # "do {" vs "do \n {"
nl_else_brace = remove # "else {" vs "else \n {"
nl_enum_brace = remove # "enum {" vs "enum \n {"
nl_fcall_brace = remove # "list_for_each() {" vs "list_for_each()\n{"
nl_fdef_brace = force # "int foo() {" vs "int foo()\n{"
nl_for_brace = remove # "for () {" vs "for () \n {"
nl_func_var_def_blk = 0 # don't add newlines after a block of var declarations
nl_if_brace = remove # "if () {" vs "if () \n {"
nl_multi_line_define = true
nl_struct_brace = remove # "struct {" vs "struct \n {"
nl_switch_brace = remove # "switch () {" vs "switch () \n {"
nl_union_brace = remove # "union {" vs "union \n {"
nl_while_brace = remove # "while () {" vs "while () \n {"
#
# Source code modifications
#
mod_full_brace_do = force # "do a--; while ();" vs "do { a--; } while ();"
mod_full_brace_for = force # "for () a--;" vs "for () { a--; }"
mod_full_brace_if = force # "if (a) a--;" vs "if (a) { a--; }"
mod_full_brace_nl = 3 # don't remove if more than 3 newlines
mod_full_brace_while = force # "while (a) a--;" vs "while (a) { a--; }"
mod_paren_on_return = remove # "return 1;" vs "return (1);"
#
# inter-character spacing options
#
sp_after_cast = remove # "(int) a" vs "(int)a"
sp_after_comma = force
sp_after_sparen = force # "if () {" vs "if (){"
sp_arith = force
sp_assign = force
sp_assign = force
sp_before_comma = remove
sp_before_ptr_star = force # "char *foo" vs "char* foo
sp_before_sparen = force # "if (" vs "if("
sp_between_ptr_star = remove # "char * *foo" vs "char **foo"
sp_bool = force
sp_compare = force
sp_func_call_paren = remove # "foo (" vs "foo("
sp_func_def_paren = remove # "int foo (){" vs "int foo(){"
sp_func_proto_paren = remove # "int foo ();" vs "int foo();"
sp_inside_braces = force # "{ 1 }" vs "{1}"
sp_inside_braces_enum = force # "{ 1 }" vs "{1}"
sp_inside_braces_struct = force # "{ 1 }" vs "{1}"
sp_inside_sparen = remove
sp_paren_brace = force
sp_sizeof_paren = remove # "sizeof (int)" vs "sizeof(int)"
#
# Aligning stuff
#
align_enum_equ_span = 4 # '=' in enum definition
align_nl_cont = true
align_on_tabstop = FALSE # align on tabstops
align_right_cmt_span = 3
align_struct_init_span = 1
align_struct_init_span = 3 # align stuff in a structure init '= { }'
align_var_def_star_style = 2 # void *foo;
align_var_struct_span = 0
align_with_tabs = FALSE # use tabs to align

View File

@ -1,12 +1,18 @@
cmake_minimum_required (VERSION 3.7)
cmake_minimum_required (VERSION 3.9)
project(maxminddb
LANGUAGES C
VERSION 1.5.0
VERSION 1.6.0
)
set(MAXMINDDB_SOVERSION 0.0.7)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS OFF)
if (WIN32)
option(MSVC_STATIC_RUNTIME "When ON the library will be built by using MT/MTd run-time libraries" OFF)
endif()
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
option(BUILD_TESTING "Build test programs" OFF)
option(BUILD_TESTING "Build test programs" ON)
include(CheckTypeSize)
check_type_size("unsigned __int128" UINT128)
@ -30,7 +36,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
endif()
configure_file(${PROJECT_SOURCE_DIR}/include/maxminddb_config.h.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/include/maxminddb_config.h)
${PROJECT_SOURCE_DIR}/include/maxminddb_config.h)
add_library(maxminddb
src/maxminddb.c
@ -52,13 +58,27 @@ endif()
if(WIN32)
target_link_libraries(maxminddb ws2_32)
if(BUILD_SHARED_LIBS)
set_target_properties(maxminddb PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
if(MSVC_STATIC_RUNTIME)
# On MSVC, when MSVC_STATIC_RUNTIME is ON, MT (Release) and MTd (Debug)
# run-time libraries will be used instead of MD/MDd. The default is OFF so
# MD/MDd are used when nothing related is passed.
#
# Adapted from https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#make-override-files
set(CMAKE_USER_MAKE_RULES_OVERRIDE
${CMAKE_CURRENT_SOURCE_DIR}/c_flag_overrides.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX
${CMAKE_CURRENT_SOURCE_DIR}/cxx_flag_overrides.cmake)
endif()
endif()
set(CMAKE_SHARED_LIBRARY_PREFIX lib)
set(CMAKE_STATIC_LIBRARY_PREFIX lib)
target_include_directories(maxminddb PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include)
target_include_directories(maxminddb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_include_directories(maxminddb PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
set(MAXMINDB_HEADERS
include/maxminddb.h
@ -66,17 +86,14 @@ set(MAXMINDB_HEADERS
)
set_target_properties(maxminddb PROPERTIES PUBLIC_HEADER "${MAXMINDB_HEADERS}")
#install(TARGETS maxminddb
# EXPORT maxminddb
# ARCHIVE DESTINATION lib
# PUBLIC_HEADER DESTINATION include/
#)
install(TARGETS maxminddb
EXPORT maxminddb)
# This is required to work with FetchContent
#install(EXPORT maxminddb
# FILE maxminddb-config.cmake
# NAMESPACE maxminddb::
# DESTINATION lib/cmake/maxminddb)
install(EXPORT maxminddb
FILE maxminddb-config.cmake
NAMESPACE maxminddb::
DESTINATION lib/cmake/maxminddb)
# We always want to build mmdblookup
add_subdirectory(bin)

View File

@ -1,3 +1,44 @@
## 1.7.0
* `FD_CLOEXEC` is now set on platforms that do not support `O_CLOEXEC`.
Reported by rittneje. GitHub #273.
* When building with Visual Studio, you may now build a static runtime with
CMake by setting `MSVC_STATIC_RUNTIME` to `ON`. Pull request by Rafael
Santiago. GitHub #269.
* The CMake build now works on iOS. Pull request by SpaceIm. GitHub #271.
## 1.6.0 - 2021-04-29
* This release includes several improvements to the CMake build. In
particular:
* C99 support is now properly enabled, fixing builds on older `gcc`
versions. Pull request by Jan Včelák. GitHub #257.
* `CMAKE_SHARED_LIBRARY_PREFIX` and `CMAKE_STATIC_LIBRARY_PREFIX` are
no longer explicitly set and now use the default values for the platform.
Pull request by Jan Včelák. GitHub #258.
* `target_include_directories` now works as expected. Pull request by Jan
Včelák. GitHub #259.
* DLLs are now installed on Windows when `libmaxminddb` is built as a
shared library. Pull request by Jan Včelák. GitHub #261.
* When built as a dynamic library on Windows, all symbols are now exported.
Pull request by Jan Včelák. GitHub #262.
## 1.5.2 - 2021-02-18
* With `libmaxminddb` on Windows and `mmdblookup` generally, there were
instances where the return value of `calloc` was not checked, which could
lead to issues in low memory situations or when resource limits had been
set. Reported by cve-reporting. GitHub #252.
## 1.5.1 - 2021-02-18
* The formatting of the manpages has been improved and the script that
generates them now supports `lowdown` in addition to `pandoc`. Pull request
by Faidon Liambotis. GitHub #248.
## 1.5.0 - 2021-01-05
* A CMake build script has been added for Windows builds. The Visual

View File

@ -1,4 +1,4 @@
Copyright 2013-2014 MaxMind, Inc.
Copyright 2013-2021 MaxMind, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,7 +1,6 @@
# Releasing this library
We release by uploading the tarball to GitHub, uploading Ubuntu PPAs, and by
updating the Homebrew recipe for this library.
We release by uploading the tarball to GitHub and uploading Ubuntu PPAs.
## Creating the release tarball
You may want to refer to the section about prerequisites.
@ -9,9 +8,12 @@ You may want to refer to the section about prerequisites.
* Check whether there are any open issues to fix while you're doing this.
* Update `Changes.md` to include specify the new version, today's date, and
list relevant changes. Commit this.
* Create a new branch off of the latest `main` for the release.
* Run `./dev-bin/release.sh` to update various files in the distro, our
GitHub pages, and creates a GitHub release with the tarball.
* Check the release looks good on both GitHub and launchpad.net.
* Make a pull request against `main` with the changes from the release
script.
## PPA
@ -27,9 +29,16 @@ configurations different than Greg's machine.
Check whether any new Ubuntu versions need to be listed in this script
before running it.
You should run it from `master`.
You should run it from `main`.
## Homebrew
## Homebrew (optional)
Releasing to Homebrew is no longer required as the formulas are easily
updated by the end-user using a built-in feature in the tool. These
directions remain in case there is a more significant change to the
build process that may require a non-trivial update to the formula or
in the case where we want the Homebrew version updated promptly for
some reason.
* Go to https://github.com/Homebrew/homebrew-core/edit/master/Formula/libmaxminddb.rb
* Edit the file to update the url and sha256. You can get the sha256 for the

View File

@ -68,7 +68,8 @@ You can clone this repository and build it by running:
$ git clone --recursive https://github.com/maxmind/libmaxminddb
After cloning, run `./bootstrap` from the `libmaxminddb` directory and then
follow the instructions for installing from a named release tarball as described above.
follow the instructions for installing from a named release tarball as
described above.
## Using CMake
@ -80,6 +81,11 @@ work.
$ ctest -V .
$ cmake --build . --target install
When building with Visual Studio, you may build a multithreaded (MT/MTd)
runtime library, using the `MSVC_STATIC_RUNTIME` setting:
$ cmake -DMSVC_STATIC_RUNTIME=ON -DBUILD_SHARED_LIBS=OFF ..
## On Ubuntu via PPA
MaxMind provides a PPA for recent version of Ubuntu. To add the PPA to your
@ -120,6 +126,8 @@ Use `make safedist` to check the resulting tarball.
# Copyright and License
Copyright 2013-2021 MaxMind, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

View File

@ -8,6 +8,6 @@ if(NOT WIN32)
install(
TARGETS mmdblookup
RUNTIME DESTINATION bin
DESTINATION bin
)
endif()

View File

@ -23,11 +23,8 @@
#include <unistd.h>
#endif
#define LOCAL static
LOCAL void usage(char *program, int exit_code, const char *error);
LOCAL const char **get_options(
int argc,
static void usage(char *program, int exit_code, const char *error);
static const char **get_options(int argc,
char **argv,
char **mmdb_file,
char **ip_address,
@ -36,24 +33,24 @@ LOCAL const char **get_options(
int *lookup_path_length,
int *const thread_count,
char **const ip_file);
LOCAL MMDB_s open_or_die(const char *fname);
LOCAL void dump_meta(MMDB_s *mmdb);
LOCAL bool lookup_from_file(MMDB_s *const mmdb,
static MMDB_s open_or_die(const char *fname);
static void dump_meta(MMDB_s *mmdb);
static bool lookup_from_file(MMDB_s *const mmdb,
char const *const ip_file,
bool const dump);
LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address,
static int lookup_and_print(MMDB_s *mmdb,
const char *ip_address,
const char **lookup_path,
int lookup_path_length,
bool verbose);
LOCAL int benchmark(MMDB_s *mmdb, int iterations);
LOCAL MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr);
LOCAL void random_ipv4(char *ip);
static int benchmark(MMDB_s *mmdb, int iterations);
static MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr);
static void random_ipv4(char *ip);
#ifndef _WIN32
// These aren't with the automatically generated prototypes as we'd lose the
// enclosing macros.
static bool start_threaded_benchmark(
MMDB_s *const mmdb,
static bool start_threaded_benchmark(MMDB_s *const mmdb,
int const thread_count,
int const iterations);
static long double get_time(void);
@ -61,8 +58,7 @@ static void *thread(void *arg);
#endif
#ifdef _WIN32
int wmain(int argc, wchar_t **wargv)
{
int wmain(int argc, wchar_t **wargv) {
// Convert our argument list from UTF-16 to UTF-8.
char **argv = (char **)calloc(argc, sizeof(char *));
if (!argv) {
@ -72,11 +68,11 @@ int wmain(int argc, wchar_t **wargv)
for (int i = 0; i < argc; i++) {
int utf8_width;
char *utf8_string;
utf8_width = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0,
NULL, NULL);
utf8_width =
WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, NULL);
if (utf8_width < 1) {
fprintf(stderr, "WideCharToMultiByte() failed: %d\n",
GetLastError());
fprintf(
stderr, "WideCharToMultiByte() failed: %d\n", GetLastError());
exit(1);
}
utf8_string = calloc(utf8_width, sizeof(char));
@ -84,17 +80,17 @@ int wmain(int argc, wchar_t **wargv)
fprintf(stderr, "calloc(): %s\n", strerror(errno));
exit(1);
}
if (WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, utf8_string,
utf8_width, NULL, NULL) < 1) {
fprintf(stderr, "WideCharToMultiByte() failed: %d\n",
GetLastError());
if (WideCharToMultiByte(
CP_UTF8, 0, wargv[i], -1, utf8_string, utf8_width, NULL, NULL) <
1) {
fprintf(
stderr, "WideCharToMultiByte() failed: %d\n", GetLastError());
exit(1);
}
argv[i] = utf8_string;
}
#else // _WIN32
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
#endif // _WIN32
char *mmdb_file = NULL;
char *ip_address = NULL;
@ -104,9 +100,15 @@ int main(int argc, char **argv)
int thread_count = 0;
char *ip_file = NULL;
const char **lookup_path =
get_options(argc, argv, &mmdb_file, &ip_address, &verbose, &iterations,
&lookup_path_length, &thread_count, &ip_file);
const char **lookup_path = get_options(argc,
argv,
&mmdb_file,
&ip_address,
&verbose,
&iterations,
&lookup_path_length,
&thread_count,
&ip_file);
MMDB_s mmdb = open_or_die(mmdb_file);
@ -131,13 +133,13 @@ int main(int argc, char **argv)
}
if (0 == iterations) {
exit(lookup_and_print(&mmdb, ip_address, lookup_path,
lookup_path_length, verbose));
exit(lookup_and_print(
&mmdb, ip_address, lookup_path, lookup_path_length, verbose));
}
free((void *)lookup_path);
srand( (int)time(NULL) );
srand((int)time(NULL));
#ifndef _WIN32
if (thread_count > 0) {
@ -153,13 +155,13 @@ int main(int argc, char **argv)
exit(benchmark(&mmdb, iterations));
}
LOCAL void usage(char *program, int exit_code, const char *error)
{
static void usage(char *program, int exit_code, const char *error) {
if (NULL != error) {
fprintf(stderr, "\n *ERROR: %s\n", error);
}
char *usage = "\n"
char *usage =
"\n"
" %s --file /path/to/file.mmdb --ip 1.2.3.4 [path to lookup]\n"
"\n"
" This application accepts the following options:\n"
@ -168,7 +170,8 @@ LOCAL void usage(char *program, int exit_code, const char *error)
"\n"
" --ip (-i) The IP address to look up. Required.\n"
"\n"
" --verbose (-v) Turns on verbose output. Specifically, this causes this\n"
" --verbose (-v) Turns on verbose output. Specifically, this "
"causes this\n"
" application to output the database metadata.\n"
"\n"
" --version Print the program's version number and exit.\n"
@ -188,7 +191,8 @@ LOCAL void usage(char *program, int exit_code, const char *error)
" \"cities\": [ \"Berlin\", \"Frankfurt\" ]\n"
" }\n"
"\n"
" You could look up just the English name by calling mmdblookup with a lookup path of:\n"
" You could look up just the English name by calling mmdblookup with "
"a lookup path of:\n"
"\n"
" mmdblookup --file ... --ip ... names en\n"
"\n"
@ -198,7 +202,8 @@ LOCAL void usage(char *program, int exit_code, const char *error)
"\n"
" Array numbering begins with zero (0).\n"
"\n"
" If you do not provide a path to lookup, all of the information for a given IP\n"
" If you do not provide a path to lookup, all of the information for "
"a given IP\n"
" will be shown.\n"
"\n";
@ -206,8 +211,7 @@ LOCAL void usage(char *program, int exit_code, const char *error)
exit(exit_code);
}
LOCAL const char **get_options(
int argc,
static const char **get_options(int argc,
char **argv,
char **mmdb_file,
char **ip_address,
@ -215,35 +219,32 @@ LOCAL const char **get_options(
int *iterations,
int *lookup_path_length,
int *const thread_count,
char **const ip_file)
{
char **const ip_file) {
static int help = 0;
static int version = 0;
while (1) {
static struct option options[] = {
{ "file", required_argument, 0, 'f' },
{ "ip", required_argument, 0, 'i' },
{ "verbose", no_argument, 0, 'v' },
{ "version", no_argument, 0, 'n' },
{ "benchmark", required_argument, 0, 'b' },
{"file", required_argument, 0, 'f'},
{"ip", required_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'n'},
{"benchmark", required_argument, 0, 'b'},
#ifndef _WIN32
{ "threads", required_argument, 0, 't' },
{"threads", required_argument, 0, 't'},
#endif
{ "ip-file", required_argument, 0, 'I' },
{ "help", no_argument, 0, 'h' },
{ "?", no_argument, 0, 1 },
{ 0, 0, 0, 0 }
};
{"ip-file", required_argument, 0, 'I'},
{"help", no_argument, 0, 'h'},
{"?", no_argument, 0, 1},
{0, 0, 0, 0}};
int opt_index;
#ifdef _WIN32
char const * const optstring = "f:i:b:I:vnh?";
char const *const optstring = "f:i:b:I:vnh?";
#else
char const * const optstring = "f:i:b:t:I:vnh?";
char const *const optstring = "f:i:b:t:I:vnh?";
#endif
int opt_char = getopt_long(argc, argv, optstring, options,
&opt_index);
int opt_char = getopt_long(argc, argv, optstring, options, &opt_index);
if (-1 == opt_char) {
break;
@ -295,6 +296,10 @@ LOCAL const char **get_options(
const char **lookup_path =
calloc((argc - optind) + 1, sizeof(const char *));
if (!lookup_path) {
fprintf(stderr, "calloc(): %s\n", strerror(errno));
exit(1);
}
int i;
for (i = 0; i < argc - optind; i++) {
lookup_path[i] = argv[i + optind];
@ -305,14 +310,13 @@ LOCAL const char **get_options(
return lookup_path;
}
LOCAL MMDB_s open_or_die(const char *fname)
{
static MMDB_s open_or_die(const char *fname) {
MMDB_s mmdb;
int status = MMDB_open(fname, MMDB_MODE_MMAP, &mmdb);
if (MMDB_SUCCESS != status) {
fprintf(stderr, "\n Can't open %s - %s\n", fname,
MMDB_strerror(status));
fprintf(
stderr, "\n Can't open %s - %s\n", fname, MMDB_strerror(status));
if (MMDB_IO_ERROR == status) {
fprintf(stderr, " IO error: %s\n", strerror(errno));
@ -326,8 +330,7 @@ LOCAL MMDB_s open_or_die(const char *fname)
return mmdb;
}
LOCAL void dump_meta(MMDB_s *mmdb)
{
static void dump_meta(MMDB_s *mmdb) {
const char *meta_dump = "\n"
" Database metadata\n"
" Node count: %i\n"
@ -342,7 +345,8 @@ LOCAL void dump_meta(MMDB_s *mmdb)
const time_t epoch = (const time_t)mmdb->metadata.build_epoch;
strftime(date, 40, "%F %T UTC", gmtime(&epoch));
fprintf(stdout, meta_dump,
fprintf(stdout,
meta_dump,
mmdb->metadata.node_count,
mmdb->metadata.record_size,
mmdb->metadata.ip_version,
@ -362,7 +366,8 @@ LOCAL void dump_meta(MMDB_s *mmdb)
fprintf(stdout, " Description:\n");
for (size_t i = 0; i < mmdb->metadata.description.count; i++) {
fprintf(stdout, " %s: %s\n",
fprintf(stdout,
" %s: %s\n",
mmdb->metadata.description.descriptions[i]->language,
mmdb->metadata.description.descriptions[i]->description);
}
@ -381,10 +386,9 @@ LOCAL void dump_meta(MMDB_s *mmdb)
//
// In addition to being useful for comparisons, this function provides a way to
// have a more deterministic set of lookups for benchmarking.
LOCAL bool lookup_from_file(MMDB_s *const mmdb,
static bool lookup_from_file(MMDB_s *const mmdb,
char const *const ip_file,
bool const dump)
{
bool const dump) {
FILE *const fh = fopen(ip_file, "r");
if (!fh) {
fprintf(stderr, "fopen(): %s: %s\n", ip_file, strerror(errno));
@ -392,7 +396,7 @@ LOCAL bool lookup_from_file(MMDB_s *const mmdb,
}
clock_t const clock_start = clock();
char buf[1024] = { 0 };
char buf[1024] = {0};
// I'd normally use uint64_t, but support for it is optional in C99.
unsigned long long i = 0;
while (1) {
@ -429,10 +433,11 @@ LOCAL bool lookup_from_file(MMDB_s *const mmdb,
}
MMDB_entry_data_list_s *entry_data_list = NULL;
int const status = MMDB_get_entry_data_list(&result.entry,
&entry_data_list);
int const status =
MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (status != MMDB_SUCCESS) {
fprintf(stderr, "MMDB_get_entry_data_list(): %s\n",
fprintf(stderr,
"MMDB_get_entry_data_list(): %s\n",
MMDB_strerror(status));
fclose(fh);
MMDB_free_entry_data_list(entry_data_list);
@ -447,10 +452,11 @@ LOCAL bool lookup_from_file(MMDB_s *const mmdb,
if (dump) {
fprintf(stdout, "%s:\n", buf);
int const status = MMDB_dump_entry_data_list(stderr,
entry_data_list, 0);
int const status =
MMDB_dump_entry_data_list(stderr, entry_data_list, 0);
if (status != MMDB_SUCCESS) {
fprintf(stderr, "MMDB_dump_entry_data_list(): %s\n",
fprintf(stderr,
"MMDB_dump_entry_data_list(): %s\n",
MMDB_strerror(status));
fclose(fh);
MMDB_free_entry_data_list(entry_data_list);
@ -467,16 +473,18 @@ LOCAL bool lookup_from_file(MMDB_s *const mmdb,
fprintf(
stdout,
"Looked up %llu addresses in %.2f seconds. %.2f lookups per second.\n",
i, seconds, i / seconds);
i,
seconds,
i / seconds);
return true;
}
LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address,
static int lookup_and_print(MMDB_s *mmdb,
const char *ip_address,
const char **lookup_path,
int lookup_path_length,
bool verbose)
{
bool verbose) {
MMDB_lookup_result_s result = lookup_or_die(mmdb, ip_address);
MMDB_entry_data_list_s *entry_data_list = NULL;
@ -484,38 +492,32 @@ LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address,
int exit_code = 0;
if (verbose) {
fprintf(
stdout,
"\n Record prefix length: %d\n",
result.netmask
);
fprintf(stdout, "\n Record prefix length: %d\n", result.netmask);
}
if (result.found_entry) {
int status;
if (lookup_path_length) {
MMDB_entry_data_s entry_data;
status = MMDB_aget_value(&result.entry, &entry_data,
lookup_path);
status = MMDB_aget_value(&result.entry, &entry_data, lookup_path);
if (MMDB_SUCCESS == status) {
if (entry_data.offset) {
MMDB_entry_s entry =
{ .mmdb = mmdb, .offset = entry_data.offset };
status = MMDB_get_entry_data_list(&entry,
&entry_data_list);
MMDB_entry_s entry = {.mmdb = mmdb,
.offset = entry_data.offset};
status = MMDB_get_entry_data_list(&entry, &entry_data_list);
} else {
fprintf(
stdout,
"\n No data was found at the lookup path you provided\n\n");
fprintf(stdout,
"\n No data was found at the lookup path you "
"provided\n\n");
}
}
} else {
status = MMDB_get_entry_data_list(&result.entry,
&entry_data_list);
status = MMDB_get_entry_data_list(&result.entry, &entry_data_list);
}
if (MMDB_SUCCESS != status) {
fprintf(stderr, "Got an error looking up the entry data - %s\n",
fprintf(stderr,
"Got an error looking up the entry data - %s\n",
MMDB_strerror(status));
exit_code = 5;
goto end;
@ -533,7 +535,7 @@ LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address,
exit_code = 6;
}
end:
end:
MMDB_free_entry_data_list(entry_data_list);
MMDB_close(mmdb);
free((void *)lookup_path);
@ -541,8 +543,7 @@ LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address,
return exit_code;
}
LOCAL int benchmark(MMDB_s *mmdb, int iterations)
{
static int benchmark(MMDB_s *mmdb, int iterations) {
char ip_address[16];
int exit_code = 0;
@ -556,11 +557,12 @@ LOCAL int benchmark(MMDB_s *mmdb, int iterations)
if (result.found_entry) {
int status = MMDB_get_entry_data_list(&result.entry,
&entry_data_list);
int status =
MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (MMDB_SUCCESS != status) {
fprintf(stderr, "Got an error looking up the entry data - %s\n",
fprintf(stderr,
"Got an error looking up the entry data - %s\n",
MMDB_strerror(status));
exit_code = 5;
MMDB_free_entry_data_list(entry_data_list);
@ -573,19 +575,20 @@ LOCAL int benchmark(MMDB_s *mmdb, int iterations)
time = clock() - time;
double seconds = ((double)time / CLOCKS_PER_SEC);
fprintf(
stdout,
"\n Looked up %i addresses in %.2f seconds. %.2f lookups per second.\n\n",
iterations, seconds, iterations / seconds);
fprintf(stdout,
"\n Looked up %i addresses in %.2f seconds. %.2f lookups per "
"second.\n\n",
iterations,
seconds,
iterations / seconds);
end:
end:
MMDB_close(mmdb);
return exit_code;
}
LOCAL MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr)
{
static MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr) {
int gai_error, mmdb_error;
MMDB_lookup_result_s result =
MMDB_lookup_string(mmdb, ipstr, &gai_error, &mmdb_error);
@ -604,7 +607,8 @@ LOCAL MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr)
}
if (MMDB_SUCCESS != mmdb_error) {
fprintf(stderr, "\n Got an error from the maxminddb library: %s\n\n",
fprintf(stderr,
"\n Got an error from the maxminddb library: %s\n\n",
MMDB_strerror(mmdb_error));
exit(4);
}
@ -612,15 +616,19 @@ LOCAL MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr)
return result;
}
LOCAL void random_ipv4(char *ip)
{
static void random_ipv4(char *ip) {
// rand() is perfectly fine for this use case
// coverity[dont_call]
int ip_int = rand();
uint8_t *bytes = (uint8_t *)&ip_int;
snprintf(ip, 16, "%u.%u.%u.%u",
*bytes, *(bytes + 1), *(bytes + 2), *(bytes + 3));
snprintf(ip,
16,
"%u.%u.%u.%u",
*bytes,
*(bytes + 1),
*(bytes + 2),
*(bytes + 3));
}
#ifndef _WIN32
@ -631,13 +639,11 @@ struct thread_info {
int iterations;
};
static bool start_threaded_benchmark(
MMDB_s *const mmdb,
static bool start_threaded_benchmark(MMDB_s *const mmdb,
int const thread_count,
int const iterations)
{
struct thread_info *const tinfo = calloc(thread_count,
sizeof(struct thread_info));
int const iterations) {
struct thread_info *const tinfo =
calloc(thread_count, sizeof(struct thread_info));
if (!tinfo) {
fprintf(stderr, "calloc(): %s\n", strerror(errno));
return false;
@ -685,16 +691,18 @@ static bool start_threaded_benchmark(
rate = total_ips / elapsed;
}
fprintf(
stdout,
"Looked up %llu addresses using %d threads in %.2Lf seconds. %.2Lf lookups per second.\n",
total_ips, thread_count, elapsed, rate);
fprintf(stdout,
"Looked up %llu addresses using %d threads in %.2Lf seconds. %.2Lf "
"lookups per second.\n",
total_ips,
thread_count,
elapsed,
rate);
return true;
}
static long double get_time(void)
{
static long double get_time(void) {
// clock_gettime() is not present on OSX until 10.12.
#ifdef HAVE_CLOCK_GETTIME
struct timespec tp = {
@ -720,15 +728,14 @@ static long double get_time(void)
#endif
}
static void *thread(void *arg)
{
static void *thread(void *arg) {
const struct thread_info *const tinfo = arg;
if (!tinfo) {
fprintf(stderr, "thread(): %s\n", strerror(EINVAL));
return NULL;
}
char ip_address[16] = { 0 };
char ip_address[16] = {0};
for (int i = 0; i < tinfo->iterations; i++) {
memset(ip_address, 0, 16);
@ -740,10 +747,11 @@ static void *thread(void *arg)
}
MMDB_entry_data_list_s *entry_data_list = NULL;
int const status = MMDB_get_entry_data_list(&result.entry,
&entry_data_list);
int const status =
MMDB_get_entry_data_list(&result.entry, &entry_data_list);
if (status != MMDB_SUCCESS) {
fprintf(stderr, "MMDB_get_entry_data_list(): %s\n",
fprintf(stderr,
"MMDB_get_entry_data_list(): %s\n",
MMDB_strerror(status));
MMDB_free_entry_data_list(entry_data_list);
return NULL;

View File

@ -0,0 +1,7 @@
if(MSVC)
set(CMAKE_C_FLAGS_DEBUG_INIT "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
set(CMAKE_C_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1 /D NDEBUG")
set(CMAKE_C_FLAGS_RELEASE_INIT "/MT /O2 /Ob2 /D NDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
endif()

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.63])
AC_INIT([libmaxminddb], [1.5.0], [support@maxmind.com])
AC_INIT([libmaxminddb], [1.6.0], [support@maxmind.com])
AC_CONFIG_SRCDIR([include/maxminddb.h])
AC_CONFIG_HEADERS([config.h include/maxminddb_config.h])

View File

@ -0,0 +1,6 @@
if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG_INIT "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1")
set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1 /D NDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "/MT /O2 /Ob2 /D NDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
endif()

View File

@ -0,0 +1,15 @@
#!/bin/sh
format="clang-format -i -style=file"
for dir in bin include src t; do
c_files=`find $dir -maxdepth 1 -name '*.c'`
if [ "$c_files" != "" ]; then
$format $dir/*.c;
fi
h_files=`find $dir -maxdepth 1 -name '*.h'`
if [ "$h_files" != "" ]; then
$format $dir/*.h;
fi
done

View File

@ -7,53 +7,75 @@ use autodie qw( :all );
use FindBin qw( $Bin );
use File::Path qw( mkpath );
use File::Slurp qw( edit_file read_file write_file );
use File::Temp qw( tempdir );
use File::Slurp qw( edit_file read_file );
use File::Which qw( which );
sub main {
my $target = shift || "$Bin/..";
my $pandoc = which('pandoc')
or die
"\n You must install pandoc in order to generate the man pages.\n\n";
my @translators = qw ( lowdown pandoc );
my $translator;
foreach my $p (@translators) {
if ( defined which($p) ) {
$translator = $p;
last;
}
}
unless ( defined $translator ) {
die "\n You must install one of "
. join( ', ', @translators )
. " in order to generate the man pages.\n\n";
}
_make_man( $target, 'libmaxminddb', 3 );
_make_man( $translator, $target, 'libmaxminddb', 3 );
_make_lib_man_links($target);
_make_man( $target, 'mmdblookup', 1 );
_make_man( $translator, $target, 'mmdblookup', 1 );
}
sub _make_man {
my $translator = shift;
my $target = shift;
my $name = shift;
my $section = shift;
my $input = "$Bin/../doc/$name.md";
my $man_dir = "$target/man/man$section";
mkpath($man_dir);
my $output = "$man_dir/$name.$section";
my $tempdir = tempdir( CLEANUP => 1 );
my $markdown = <<"EOF";
% $name($section)
EOF
$markdown .= read_file("$Bin/../doc/$name.md");
my $tempfile = "$tempdir/$name.$section.md";
write_file( $tempfile, $markdown );
my $man_file = "$man_dir/$name.$section";
system( qw( pandoc -s -t man ), $tempfile, '-o', $man_file );
_fix_indentation($man_file);
if ( $translator eq 'pandoc' ) {
system(
'pandoc',
'-s',
'-f', 'markdown_mmd+backtick_code_blocks',
'-t', 'man',
'-M', "title:$name",
'-M', "section:$section",
$input,
'-o', $output,
);
_pandoc_postprocess($output);
}
elsif ( $translator eq 'lowdown' ) {
system(
'lowdown',
'-s',
'--out-no-smarty',
'-Tman',
'-M', "title:$name",
'-M', "section:$section",
$input,
'-o', $output,
);
}
}
sub _make_lib_man_links {
my $target = shift;
my $header = read_file("$Bin/../include/maxminddb.h");
for my $proto ( $header =~ /^ *extern.+?(\w+)\(/gsm ) {
for my $proto ( $header =~ /^ *extern.+?(MMDB_\w+)\(/gsm ) {
open my $fh, '>', "$target/man/man3/$proto.3";
print {$fh} ".so man3/libmaxminddb.3\n";
close $fh;
@ -62,12 +84,13 @@ sub _make_lib_man_links {
# AFAICT there's no way to control the indentation depth for code blocks with
# Pandoc.
sub _fix_indentation {
sub _pandoc_postprocess {
my $file = shift;
edit_file(
sub {
s/^\.IP\n\.nf/.IP "" 4\n.nf/gm;
s/(Automatically generated by Pandoc)(.+)$/$1/m;
},
$file
);

View File

@ -4,7 +4,7 @@ set -e
set -x
set -u
DISTS=( artful zesty xenial trusty precise )
DISTS=( groovy focal bionic xenial trusty )
VERSION=$(perl -MFile::Slurp::Tiny=read_file -MDateTime <<EOF
use v5.16;

View File

@ -1,19 +0,0 @@
#!/bin/sh
uncrustify="uncrustify -c .uncrustify.cfg --replace --no-backup"
# We indent each thing twice because uncrustify is not idempotent - in some
# cases it will flip-flop between two indentation styles.
for dir in bin include src t; do
c_files=`find $dir -maxdepth 1 -name '*.c'`
if [ "$c_files" != "" ]; then
$uncrustify $dir/*.c;
$uncrustify $dir/*.c;
fi
h_files=`find $dir -maxdepth 1 -name '*.h'`
if [ "$h_files" != "" ]; then
$uncrustify $dir/*.h;
$uncrustify $dir/*.h;
fi
done

View File

@ -28,7 +28,7 @@ extern "C" {
#include <winsock2.h>
#include <ws2tcpip.h>
/* libmaxminddb package version from configure */
#define PACKAGE_VERSION "1.5.0"
#define PACKAGE_VERSION "1.6.0"
typedef ADDRESS_FAMILY sa_family_t;
@ -87,7 +87,7 @@ typedef ADDRESS_FAMILY sa_family_t;
#if !(MMDB_UINT128_IS_BYTE_ARRAY)
#if MMDB_UINT128_USING_MODE
typedef unsigned int mmdb_uint128_t __attribute__ ((__mode__(TI)));
typedef unsigned int mmdb_uint128_t __attribute__((__mode__(TI)));
#else
typedef unsigned __int128 mmdb_uint128_t;
#endif
@ -139,7 +139,8 @@ typedef struct MMDB_entry_data_s {
uint32_t type;
} MMDB_entry_data_s;
/* This is the return type when someone asks for all the entry data in a map or array */
/* This is the return type when someone asks for all the entry data in a map or
* array */
typedef struct MMDB_entry_data_list_s {
MMDB_entry_data_s entry_data;
struct MMDB_entry_data_list_s *next;
@ -213,14 +214,14 @@ typedef struct MMDB_search_node_s {
MMDB_entry_s right_record_entry;
} MMDB_search_node_s;
extern int MMDB_open(const char *const filename, uint32_t flags,
MMDB_s *const mmdb);
extern int
MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb);
extern MMDB_lookup_result_s MMDB_lookup_string(const MMDB_s *const mmdb,
const char *const ipstr,
int *const gai_error,
int *const mmdb_error);
extern MMDB_lookup_result_s MMDB_lookup_sockaddr(
const MMDB_s *const mmdb,
extern MMDB_lookup_result_s
MMDB_lookup_sockaddr(const MMDB_s *const mmdb,
const struct sockaddr *const sockaddr,
int *const mmdb_error);
extern int MMDB_read_node(const MMDB_s *const mmdb,
@ -237,13 +238,15 @@ extern int MMDB_aget_value(MMDB_entry_s *const start,
const char *const *const path);
extern int MMDB_get_metadata_as_entry_data_list(
const MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list);
extern int MMDB_get_entry_data_list(
MMDB_entry_s *start, MMDB_entry_data_list_s **const entry_data_list);
extern void MMDB_free_entry_data_list(
MMDB_entry_data_list_s *const entry_data_list);
extern int
MMDB_get_entry_data_list(MMDB_entry_s *start,
MMDB_entry_data_list_s **const entry_data_list);
extern void
MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list);
extern void MMDB_close(MMDB_s *const mmdb);
extern const char *MMDB_lib_version(void);
extern int MMDB_dump_entry_data_list(FILE *const stream,
extern int
MMDB_dump_entry_data_list(FILE *const stream,
MMDB_entry_data_list_s *const entry_data_list,
int indent);
extern const char *MMDB_strerror(int error_code);

View File

@ -9,8 +9,7 @@ static bool can_multiply(size_t const, size_t const, size_t const);
// Allocate an MMDB_data_pool_s. It initially has space for size
// MMDB_entry_data_list_s structs.
MMDB_data_pool_s *data_pool_new(size_t const size)
{
MMDB_data_pool_s *data_pool_new(size_t const size) {
MMDB_data_pool_s *const pool = calloc(1, sizeof(MMDB_data_pool_s));
if (!pool) {
return NULL;
@ -40,8 +39,7 @@ MMDB_data_pool_s *data_pool_new(size_t const size)
// the given max. max will typically be SIZE_MAX.
//
// We want to know if we'll wrap around.
static bool can_multiply(size_t const max, size_t const m, size_t const n)
{
static bool can_multiply(size_t const max, size_t const m, size_t const n) {
if (m == 0) {
return false;
}
@ -50,8 +48,7 @@ static bool can_multiply(size_t const max, size_t const m, size_t const n)
}
// Clean up the data pool.
void data_pool_destroy(MMDB_data_pool_s *const pool)
{
void data_pool_destroy(MMDB_data_pool_s *const pool) {
if (!pool) {
return;
}
@ -65,8 +62,7 @@ void data_pool_destroy(MMDB_data_pool_s *const pool)
// Claim a new struct from the pool. Doing this may cause the pool's size to
// grow.
MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const pool)
{
MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const pool) {
if (!pool) {
return NULL;
}
@ -115,8 +111,7 @@ MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const pool)
// Turn the structs in the array-like pool into a linked list.
//
// Before calling this function, the list isn't linked up.
MMDB_entry_data_list_s *data_pool_to_list(MMDB_data_pool_s *const pool)
{
MMDB_entry_data_list_s *data_pool_to_list(MMDB_data_pool_s *const pool) {
if (!pool) {
return NULL;
}
@ -154,22 +149,16 @@ MMDB_entry_data_list_s *data_pool_to_list(MMDB_data_pool_s *const pool)
static void test_can_multiply(void);
int main(void)
{
int main(void) {
plan(NO_PLAN);
test_can_multiply();
done_testing();
}
static void test_can_multiply(void)
{
{
ok(can_multiply(SIZE_MAX, 1, SIZE_MAX), "1*SIZE_MAX is ok");
}
static void test_can_multiply(void) {
{ ok(can_multiply(SIZE_MAX, 1, SIZE_MAX), "1*SIZE_MAX is ok"); }
{
ok(!can_multiply(SIZE_MAX, 2, SIZE_MAX), "2*SIZE_MAX is not ok");
}
{ ok(!can_multiply(SIZE_MAX, 2, SIZE_MAX), "2*SIZE_MAX is not ok"); }
{
ok(can_multiply(SIZE_MAX, 10240, sizeof(MMDB_entry_data_list_s)),

View File

@ -43,8 +43,7 @@
* SUCH DAMAGE.
*/
static void *
mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len)
{
mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len) {
register char *cur, *last;
const char *cl = (const char *)l;
const char *cs = (const char *)s;
@ -97,9 +96,7 @@ mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len)
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static size_t
mmdb_strnlen(const char *s, size_t maxlen)
{
static size_t mmdb_strnlen(const char *s, size_t maxlen) {
size_t len;
for (len = 0; len < maxlen; len++, s++) {
@ -138,9 +135,7 @@ mmdb_strnlen(const char *s, size_t maxlen)
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static char *
mmdb_strdup(const char *str)
{
static char *mmdb_strdup(const char *str) {
size_t len;
char *copy;
@ -151,9 +146,7 @@ mmdb_strdup(const char *str)
return (copy);
}
static char *
mmdb_strndup(const char *str, size_t n)
{
static char *mmdb_strndup(const char *str, size_t n) {
size_t len;
char *copy;

File diff suppressed because it is too large Load Diff

View File

@ -8,9 +8,10 @@
#include "maxminddb_test_helper.h"
int test_read(const char *path, const struct stat *UNUSED(
sbuf), int flags, struct FTW *UNUSED(ftw))
{
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;
@ -36,16 +37,15 @@ int test_read(const char *path, const struct stat *UNUSED(
BAIL_OUT("could not parse IP address");
}
cmp_ok(mmdb_error, "!=", MMDB_SUCCESS, "opening %s returned an error",
path);
cmp_ok(
mmdb_error, "!=", MMDB_SUCCESS, "opening %s returned an error", path);
MMDB_close(mmdb);
free(mmdb);
return 0;
}
int main(void)
{
int main(void) {
char *test_db_dir;
#ifdef _WIN32
test_db_dir = "../t/maxmind-db/bad-data";

View File

@ -1,7 +1,6 @@
#include "maxminddb_test_helper.h"
void run_tests(int mode, const char *mode_desc)
{
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);
@ -15,16 +14,20 @@ void run_tests(int mode, const char *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");
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");
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);
}
@ -36,17 +39,19 @@ void run_tests(int mode, const char *mode_desc)
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");
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)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -7,14 +7,19 @@ static void test_big_lookup(void);
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)
{
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);
function,
ip,
filename,
mode_desc);
if (!is_ok) {
return;
@ -33,35 +38,45 @@ void test_one_result(MMDB_s *mmdb, MMDB_lookup_result_s result,
// something like "::1.2.3.4", not just "1.2.3.4".
int maxlen = strlen(expect) + 3;
real_expect = malloc(maxlen);
if (!real_expect) {
BAIL_OUT("could not allocate memory");
}
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);
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)
{
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);
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);
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)
{
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;
@ -78,17 +93,21 @@ void run_ipX_tests(const char *filename, const char **missing_ips,
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);
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);
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) {
@ -102,52 +121,47 @@ void run_ipX_tests(const char *filename, const char **missing_ips,
free(mmdb);
}
void run_ipv4_tests(int UNUSED(
record_size), const char *filename, const char *UNUSED(
ignored))
{
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" },
{"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" };
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))
{
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" },
{"::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" };
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"
};
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;
@ -156,40 +170,35 @@ void all_record_sizes(int mode, const char *description)
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"
};
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)
{
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");
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);
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(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);
@ -198,8 +207,7 @@ static void test_big_lookup(void)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&all_record_sizes);
test_big_lookup();

View File

@ -1,21 +1,19 @@
#include "libtap/tap.h"
#include "maxminddb_test_helper.h"
#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 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)
{
int main(void) {
plan(NO_PLAN);
test_data_pool_new();
test_data_pool_destroy();
@ -24,8 +22,7 @@ int main(void)
done_testing();
}
static void test_data_pool_new(void)
{
static void test_data_pool_new(void) {
{
MMDB_data_pool_s *const pool = data_pool_new(0);
ok(!pool, "size 0 is not valid");
@ -45,11 +42,8 @@ static void test_data_pool_new(void)
}
}
static void test_data_pool_destroy(void)
{
{
data_pool_destroy(NULL);
}
static void test_data_pool_destroy(void) {
{ data_pool_destroy(NULL); }
{
MMDB_data_pool_s *const pool = data_pool_new(512);
@ -58,8 +52,7 @@ static void test_data_pool_destroy(void)
}
}
static void test_data_pool_alloc(void)
{
static void test_data_pool_alloc(void) {
{
MMDB_data_pool_s *const pool = data_pool_new(1);
ok(pool != NULL, "created pool");
@ -109,20 +102,18 @@ static void test_data_pool_alloc(void)
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->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,
ok(element->entry_data.offset == (uint32_t)i,
"found offset %" PRIu32 ", should have %zu",
element->entry_data.offset,
i
);
i);
element = element->next;
}
@ -133,8 +124,7 @@ static void test_data_pool_alloc(void)
}
}
static void test_data_pool_to_list(void)
{
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);
@ -143,8 +133,8 @@ static void test_data_pool_to_list(void)
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);
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");
@ -153,8 +143,8 @@ static void test_data_pool_to_list(void)
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);
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");
@ -176,8 +166,8 @@ static void test_data_pool_to_list(void)
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);
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");
@ -213,72 +203,54 @@ static void test_data_pool_to_list(void)
{
diag("starting test: fill one block save for one spot");
ok(
create_and_check_list(3, 2),
"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"
);
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 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"
);
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"
);
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"
);
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"
);
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"
);
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 initial_sizes[] = {1, 2, 32, 64, 128, 256};
size_t const max_element_count = 4096;
@ -296,8 +268,7 @@ static void test_data_pool_to_list(void)
// 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)
{
size_t const element_count) {
MMDB_data_pool_s *const pool = data_pool_new(initial_size);
assert(pool != NULL);
@ -305,8 +276,8 @@ static bool create_and_check_list(size_t const initial_size,
// 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 *));
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++) {
@ -349,8 +320,7 @@ static bool create_and_check_list(size_t const initial_size,
// 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 const initial_size) {
size_t got_block_count = 0;
size_t got_element_count = 0;

View File

@ -1,57 +1,68 @@
#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 *
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,
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,
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,
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,
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,
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 *
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,
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 *
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,
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 };
uint8_t expect[] = {0x00, 0x00, 0x00, 0x2a};
ok(memcmp(bytes, expect, 4) == 0, "got expected value for bytes key");
@ -60,12 +71,13 @@ MMDB_entry_data_list_s *test_bytes_value(MMDB_entry_data_list_s
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 *
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,
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);
@ -73,12 +85,13 @@ MMDB_entry_data_list_s *test_double_value(MMDB_entry_data_list_s
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 *
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,
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);
@ -86,64 +99,79 @@ MMDB_entry_data_list_s *test_float_value(MMDB_entry_data_list_s
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 *
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,
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,
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 *
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,
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,
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,
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,
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,
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 *
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,
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,
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);
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);
@ -158,16 +186,22 @@ MMDB_entry_data_list_s *test_mapX_key_value_pair(MMDB_entry_data_list_s
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 *
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,
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,
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,
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);
@ -175,9 +209,13 @@ MMDB_entry_data_list_s *test_map_value(MMDB_entry_data_list_s *entry_data_list)
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,
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,
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);
@ -186,17 +224,32 @@ MMDB_entry_data_list_s *test_map_value(MMDB_entry_data_list_s *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 *
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,
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 };
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
@ -208,12 +261,13 @@ MMDB_entry_data_list_s *test_uint128_value(MMDB_entry_data_list_s
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 *
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,
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");
@ -221,12 +275,13 @@ MMDB_entry_data_list_s *test_uint16_value(MMDB_entry_data_list_s
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 *
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,
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");
@ -234,12 +289,13 @@ MMDB_entry_data_list_s *test_uint32_value(MMDB_entry_data_list_s
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 *
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,
cmp_ok(value->entry_data.type,
"==",
MMDB_DATA_TYPE_UINT64,
"'uint64' key's value is an uint64");
uint64_t expect = 1;
expect <<= 60;
@ -248,18 +304,35 @@ MMDB_entry_data_list_s *test_uint64_value(MMDB_entry_data_list_s
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 *
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,
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 };
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");
@ -268,8 +341,7 @@ MMDB_entry_data_list_s *test_utf8_string_value(MMDB_entry_data_list_s
return entry_data_list;
}
void run_tests(int mode, const char *description)
{
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);
@ -286,15 +358,19 @@ void run_tests(int mode, const char *description)
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");
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,
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,
cmp_ok(entry_data_list->entry_data.data_size,
"==",
12,
"first map in entry data list has 12 k/v pairs");
while (1) {
@ -304,7 +380,9 @@ void run_tests(int mode, const char *description)
break;
}
cmp_ok(key->entry_data.type, "==", MMDB_DATA_TYPE_UTF8_STRING,
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);
@ -345,8 +423,7 @@ void run_tests(int mode, const char *description)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,21 +1,40 @@
#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)
{
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);
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);
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 };
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);
@ -47,7 +66,7 @@ void test_all_data_types(MMDB_lookup_result_s *result, const char *ip,
MMDB_entry_data_s data =
data_ok(result, MMDB_DATA_TYPE_BYTES, description, "bytes", NULL);
uint8_t expect[] = { 0x00, 0x00, 0x00, 0x2a };
uint8_t expect[] = {0x00, 0x00, 0x00, 0x2a};
ok(memcmp((uint8_t *)data.bytes, expect, 4) == 0,
"bytes field has expected value");
}
@ -98,12 +117,25 @@ void test_all_data_types(MMDB_lookup_result_s *result, const char *ip,
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);
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 };
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;
@ -116,9 +148,8 @@ void test_all_data_types(MMDB_lookup_result_s *result, const char *ip,
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);
MMDB_entry_data_s data = data_ok(
result, MMDB_DATA_TYPE_BOOLEAN, description, "boolean", NULL);
cmp_ok(data.boolean, "==", true, "boolean field is true");
}
@ -131,21 +162,18 @@ void test_all_data_types(MMDB_lookup_result_s *result, const char *ip,
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);
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);
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);
data = data_ok(
result, MMDB_DATA_TYPE_UINT32, description, "array", "2", NULL);
ok(data.uint32 == 3, "array[2] is 1");
}
@ -159,64 +187,99 @@ void test_all_data_types(MMDB_lookup_result_s *result, const char *ip,
snprintf(description, 500, "map{mapX} for %s - %s", ip, mode_desc);
data =
data_ok(result, MMDB_DATA_TYPE_MAP, description, "map", "mapX",
NULL);
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,
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);
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);
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,
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);
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,
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);
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,
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);
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)
{
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);
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);
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)");
}
@ -249,7 +312,8 @@ void test_all_data_types_as_zero(MMDB_lookup_result_s *result, const char *ip,
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)"); */
ok(memcmp(data.bytes, expect, 0) == 0, "got expected bytes value
(NULL)"); */
}
{
@ -297,12 +361,25 @@ void test_all_data_types_as_zero(MMDB_lookup_result_s *result, const char *ip,
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);
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 };
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;
@ -314,9 +391,8 @@ void test_all_data_types_as_zero(MMDB_lookup_result_s *result, const char *ip,
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);
MMDB_entry_data_s data = data_ok(
result, MMDB_DATA_TYPE_BOOLEAN, description, "boolean", NULL);
cmp_ok(data.boolean, "==", false, "boolean field is false");
}
@ -339,8 +415,7 @@ void test_all_data_types_as_zero(MMDB_lookup_result_s *result, const char *ip,
}
}
void run_tests(int mode, const char *mode_desc)
{
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);
@ -360,11 +435,15 @@ void run_tests(int mode, const char *mode_desc)
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);
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);
"no result entry struct returned for invalid IP address '%s'",
ip);
}
{
@ -372,10 +451,12 @@ void run_tests(int mode, const char *mode_desc)
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);
ok(!result.found_entry,
"no result entry struct returned for IP address not in the database "
"- %s - %s - %s",
ip,
filename,
mode_desc);
}
{
@ -383,15 +464,21 @@ void run_tests(int mode, const char *mode_desc)
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);
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);
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);
}
@ -401,15 +488,21 @@ void run_tests(int mode, const char *mode_desc)
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);
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);
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);
}
@ -419,10 +512,12 @@ void run_tests(int mode, const char *mode_desc)
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);
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);
}
@ -431,8 +526,7 @@ void run_tests(int mode, const char *mode_desc)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -2,8 +2,7 @@
#include "maxminddb_test_helper.h"
#ifdef HAVE_OPEN_MEMSTREAM
void run_tests(int mode, const char *mode_desc)
{
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);
@ -16,8 +15,7 @@ void run_tests(int mode, const char *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");
ok(MMDB_SUCCESS == status, "MMDB_get_entry_data_list is successful");
char *dump_output;
size_t dump_size;
@ -32,8 +30,7 @@ void run_tests(int mode, const char *mode_desc)
cmp_ok(dump_size, ">", 0, "MMDB_dump produced output - %s", mode_desc);
char *expect[] = {
"{",
char *expect[] = {"{",
" \"array\": ",
" [",
" 1 <uint32>",
@ -74,12 +71,12 @@ void run_tests(int mode, const char *mode_desc)
" 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],
"dump output contains expected line (%s) - %s",
expect[i],
mode_desc);
}
@ -89,15 +86,13 @@ void run_tests(int mode, const char *mode_desc)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();
}
#else
int main(void)
{
int main(void) {
plan(SKIP_ALL, "This test requires the open_memstream() function");
}
#endif

View File

@ -14,15 +14,20 @@
* 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)
{
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);
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 =
@ -31,16 +36,16 @@ void test_one_ip(MMDB_s *mmdb, const char *filename, const char *mode_desc,
ok(0, "mmdb_strndup() call failed");
exit(1);
}
if (!ok(strcmp(string,
country_code) == 0, "iso_code is %s", country_code)) {
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)
{
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);
@ -59,8 +64,7 @@ void run_tests(int mode, const char *mode_desc)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,52 +1,70 @@
#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);
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,
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);
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,
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);
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,
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);
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,
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, ...)
{
int call_vget_value(MMDB_entry_s *entry, MMDB_entry_data_s *entry_data, ...) {
va_list keys;
va_start(keys, entry_data);
@ -57,8 +75,7 @@ int call_vget_value(MMDB_entry_s *entry, MMDB_entry_data_s *entry_data, ...)
return status;
}
void test_simple_structure(int mode, const char *mode_desc)
{
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);
@ -70,7 +87,7 @@ void test_simple_structure(int mode, const char *mode_desc)
{
MMDB_entry_data_s entry_data;
const char *lookup_path[] = { "array", "0", NULL };
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");
@ -84,7 +101,7 @@ void test_simple_structure(int mode, const char *mode_desc)
{
MMDB_entry_data_s entry_data;
const char *lookup_path[] = { "array", "2", NULL };
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");
@ -96,18 +113,19 @@ void test_simple_structure(int mode, const char *mode_desc)
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,
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 };
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");
@ -122,7 +140,7 @@ void test_simple_structure(int mode, const char *mode_desc)
{
MMDB_entry_data_s entry_data;
const char *lookup_path[] = { "array", "-3", NULL };
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");
@ -137,30 +155,33 @@ void test_simple_structure(int mode, const char *mode_desc)
{
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,
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,
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,
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");
}
@ -168,46 +189,58 @@ void test_simple_structure(int mode, const char *mode_desc)
free(mmdb);
}
void test_complex_map_a_result(int status, MMDB_entry_data_s entry_data,
char *function)
{
cmp_ok(status, "==", MMDB_SUCCESS,
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,
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,
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,
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,
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,
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,
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);
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)
{
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);
@ -219,79 +252,139 @@ void test_nested_structure(int mode, const char *mode_desc)
{
MMDB_entry_data_s entry_data;
const char *lookup_path[] =
{ "map1", "map2", "array", "0", "map3", "a", NULL };
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",
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",
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 };
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",
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",
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 };
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",
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",
status = MMDB_get_value(&result.entry,
&entry_data,
"map1",
"map42",
"array",
"0",
"map3",
"c",
NULL);
test_no_result(status, entry_data, "MMDB_get_value",
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",
status = call_vget_value(&result.entry,
&entry_data,
"map1",
"map42",
"array",
"0",
"map3",
"c",
NULL);
test_no_result(status, entry_data, "MMDB_vget_value",
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 };
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",
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",
status = MMDB_get_value(&result.entry,
&entry_data,
"map1",
"map2",
"array",
"9",
"map3",
"c",
NULL);
test_no_result(status, entry_data, "MMDB_get_value",
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",
status = call_vget_value(&result.entry,
&entry_data,
"map1",
"map2",
"array",
"9",
"map3",
"c",
NULL);
test_no_result(status, entry_data, "MMDB_vget_value",
test_no_result(status,
entry_data,
"MMDB_vget_value",
"map1{map42}{array}[9]{map3}{c}");
}
@ -299,14 +392,12 @@ void test_nested_structure(int mode, const char *mode_desc)
free(mmdb);
}
void run_tests(int mode, const char *mode_desc)
{
void run_tests(int mode, const char *mode_desc) {
test_simple_structure(mode, mode_desc);
test_nested_structure(mode, mode_desc);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,21 +1,22 @@
#include "maxminddb_test_helper.h"
void test_one_ip(MMDB_s *mmdb, const char *ip, const char *filename,
const char *mode_desc)
{
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);
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)
{
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);
@ -28,8 +29,7 @@ void run_tests(int mode, const char *mode_desc)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,7 +1,6 @@
#include "maxminddb_test_helper.h"
void run_tests(int mode, const char *mode_desc)
{
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);
@ -12,18 +11,18 @@ void run_tests(int mode, const char *mode_desc)
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");
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 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);
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));
}
@ -31,17 +30,19 @@ void run_tests(int mode, const char *mode_desc)
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");
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)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -18,10 +18,10 @@
#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 };
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];
@ -35,13 +35,11 @@ void for_all_record_sizes(const char *filename_fmt,
}
}
void for_all_modes(void (*tests)(int mode, const char *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)
{
const char *test_database_path(const char *filename) {
char *test_db_dir;
#ifdef _WIN32
test_db_dir = "../t/maxmind-db/test-data";
@ -64,10 +62,9 @@ const char *test_database_path(const char *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);
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");
}
@ -75,11 +72,10 @@ const char *dup_entry_string_or_bail(MMDB_entry_data_s entry_data)
return string;
}
MMDB_s *open_ok(const char *db_file, int mode, const char *mode_desc)
{
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'",
BAIL_OUT("could not read the specified file - %s\nIf you are in a git "
"checkout try running 'git submodule update --init'",
db_file);
}
@ -91,8 +87,10 @@ MMDB_s *open_ok(const char *db_file, int mode, const char *mode_desc)
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);
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));
@ -102,7 +100,8 @@ MMDB_s *open_ok(const char *db_file, int mode, const char *mode_desc)
is_ok = ok(mmdb->file_size > 0,
"mmdb struct has been set for %s - %s",
db_file, mode_desc);
db_file,
mode_desc);
if (!is_ok) {
free(mmdb);
@ -112,26 +111,26 @@ MMDB_s *open_ok(const char *db_file, int mode, const char *mode_desc)
return mmdb;
}
MMDB_lookup_result_s lookup_string_ok(MMDB_s *mmdb, const char *ip,
const char *file, const char *mode_desc)
{
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);
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)
{
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 hints = {.ai_socktype = SOCK_STREAM};
struct addrinfo *addresses = NULL;
if (ip[0] == ':') {
@ -148,7 +147,7 @@ MMDB_lookup_result_s lookup_sockaddr_ok(MMDB_s *mmdb, const char *ip,
int gai_error = getaddrinfo(ip, NULL, &hints, &addresses);
int mmdb_error = 0;
MMDB_lookup_result_s result = { .found_entry = false };
MMDB_lookup_result_s result = {.found_entry = false};
if (gai_error == 0) {
result = MMDB_lookup_sockaddr(mmdb, addresses->ai_addr, &mmdb_error);
}
@ -156,38 +155,48 @@ MMDB_lookup_result_s lookup_sockaddr_ok(MMDB_s *mmdb, const char *ip,
freeaddrinfo(addresses);
}
test_lookup_errors(gai_error, mmdb_error, "MMDB_lookup_sockaddr", ip, file,
mode_desc);
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)
{
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);
function,
ip,
file,
mode_desc);
if (!is_ok) {
diag("error from call to getaddrinfo for %s - %s",
ip, gai_strerror(gai_error));
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);
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, ...)
{
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);
@ -196,13 +205,20 @@ MMDB_entry_data_s data_ok(MMDB_lookup_result_s *result, uint32_t expect_type,
va_end(keys);
if (cmp_ok(status, "==", MMDB_SUCCESS,
"no error from call to MMDB_vget_value - %s", description)) {
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)) {
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,
diag(" data type value is %i but expected %i",
data.type,
expect_type);
}
} else {
@ -212,22 +228,20 @@ MMDB_entry_data_s data_ok(MMDB_lookup_result_s *result, uint32_t expect_type,
return data;
}
void compare_double(double got, double expect)
{
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);
diag(
" got %2.6f but expected %2.6f (diff = %2.6f)", got, expect, diff);
}
}
void compare_float(float got, float expect)
{
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);
diag(
" got %2.4f but expected %2.1f (diff = %2.1f)", got, expect, diff);
}
}

View File

@ -6,12 +6,12 @@
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include "libtap/tap.h"
#include "maxminddb-compat-util.h"
#include "maxminddb.h"
#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>
@ -33,9 +33,9 @@
#define MMDB_TEST_HELPER_C (1)
#ifdef __GNUC__
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#define UNUSED(x) UNUSED_##x __attribute__((__unused__))
#else
# define UNUSED
#define UNUSED
#endif
#define MAX_DESCRIPTION_LENGTH 500
@ -48,18 +48,24 @@ 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,
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,
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 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, ...);
const char *description,
...);
extern void compare_double(double got, double expect);
extern void compare_float(float got, float expect);

View File

@ -1,7 +1,6 @@
#include "maxminddb_test_helper.h"
void run_tests(int mode, const char *mode_desc)
{
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);
@ -9,7 +8,8 @@ void run_tests(int mode, const char *mode_desc)
char *repeated_string = "Lots of pointers in metadata";
is(mmdb->metadata.database_type, repeated_string,
is(mmdb->metadata.database_type,
repeated_string,
"decoded pointer database_type");
for (uint16_t i = 0; i < mmdb->metadata.description.count; i++) {
@ -24,8 +24,7 @@ void run_tests(int mode, const char *mode_desc)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,38 +1,63 @@
#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",
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",
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",
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);
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",
cmp_ok(mmdb->metadata.binary_format_major_version,
"==",
2,
"binary_format_major_version is 2 - %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",
cmp_ok(mmdb->metadata.binary_format_minor_version,
"==",
0,
"binary_format_minor_version is 0 - %s",
mode_desc);
cmp_ok(mmdb->metadata.description.count, "==", 2,
"found 2 descriptions - %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;
@ -45,34 +70,45 @@ void test_metadata(MMDB_s *mmdb, const char *mode_desc)
ok(1, "found zh description");
is(description, "Test Database Chinese", "zh description");
} else {
ok(0, "found unknown description in unexpected language - %s",
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);
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 *
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,
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,
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,
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,
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");
@ -81,36 +117,41 @@ MMDB_entry_data_list_s *test_languages_value(MMDB_entry_data_list_s
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 *
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,
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,
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_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,
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);
const char *description = dup_entry_string_or_bail(value->entry_data);
if (strcmp(key_name, "en") == 0) {
is(description, "Test Database",
is(description,
"Test Database",
"en description == 'Test Database'");
} else if (strcmp(key_name, "zh") == 0) {
is(description, "Test Database Chinese",
is(description,
"Test Database Chinese",
"zh description == 'Test Database Chinese'");
} else {
ok(0, "unknown key found in description map - %s", key_name);
@ -123,63 +164,70 @@ MMDB_entry_data_list_s *test_description_value(
return entry_data_list;
}
void test_metadata_as_data_entry_list(MMDB_s * mmdb,
const char *mode_desc)
{
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);
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",
cmp_ok(status,
"==",
MMDB_SUCCESS,
"get metadata as data_entry_list - %s",
mode_desc);
cmp_ok(first->entry_data.data_size, "==", 9,
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;
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,
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;
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;
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;
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,
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,
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;
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;
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);
@ -188,8 +236,7 @@ void test_metadata_as_data_entry_list(MMDB_s * mmdb,
} 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);
ok(0, "unknown key found in metadata map - %s", key_name);
}
free((void *)key_name);
@ -198,8 +245,7 @@ void test_metadata_as_data_entry_list(MMDB_s * mmdb,
MMDB_free_entry_data_list(first);
}
void run_tests(int mode, const char *mode_desc)
{
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);
@ -218,8 +264,7 @@ void run_tests(int mode, const char *mode_desc)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,7 +1,6 @@
#include "maxminddb_test_helper.h"
void run_tests(int mode, const char *mode_desc)
{
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);
@ -14,18 +13,21 @@ void run_tests(int mode, const char *mode_desc)
MMDB_entry_data_s entry_data;
int status = MMDB_get_value(&result.entry, &entry_data, NULL);
cmp_ok(status, "==", MMDB_SUCCESS,
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,
cmp_ok(entry_data.type,
"==",
MMDB_DATA_TYPE_UTF8_STRING,
"returned entry type is utf8_string");
MMDB_close(mmdb);
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,50 +1,64 @@
#include "maxminddb_test_helper.h"
void test_entry_data(MMDB_s *mmdb, MMDB_entry_s *entry, uint32_t node_number,
char * node_record)
{
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,
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);
node_record,
node_number);
}
void run_read_node_tests(MMDB_s *mmdb, const uint32_t tests[][5],
void run_read_node_tests(MMDB_s *mmdb,
const uint32_t tests[][5],
int test_count,
uint8_t record_size)
{
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],
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,
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");
test_entry_data(
mmdb, &node.left_record_entry, node_number, "left");
}
cmp_ok(node.right_record, "==", tests[i][3],
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,
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");
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",
@ -54,87 +68,168 @@ void run_read_node_tests(MMDB_s *mmdb, const uint32_t tests[][5],
}
}
void run_24_bit_record_tests(int mode, const char *mode_desc)
{
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, }
};
{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)
{
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, }
};
{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)
{
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, }
};
{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);
@ -142,15 +237,13 @@ void run_32_bit_record_tests(int mode, const char *mode_desc)
free(mmdb);
}
void run_tests(int mode, const char *mode_desc)
{
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)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -17,8 +17,7 @@ typedef struct test_result {
char *data_value;
} test_result_s;
void test_one_ip(MMDB_s *mmdb, const char *ip, test_result_s *test_result)
{
void test_one_ip(MMDB_s *mmdb, const char *ip, test_result_s *test_result) {
test_result->ip_looked_up = ip;
@ -60,44 +59,50 @@ void test_one_ip(MMDB_s *mmdb, const char *ip, test_result_s *test_result)
return;
}
void *run_one_thread(void *arg)
{
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));
if (!result) {
BAIL_OUT("could not allocate memory");
}
test_one_ip(mmdb, ip, result);
pthread_exit((void *)result);
}
void process_result(test_result_s *result, const char *expect,
const char *mode_desc)
{
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);
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);
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);
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,
is_ok = ok(!result->get_value_status,
"no error from MMDB_get_value for %s - %s",
result->ip_looked_up,
mode_desc);
@ -107,19 +112,24 @@ void process_result(test_result_s *result, const char *expect,
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);
result->ip_looked_up,
mode_desc);
if (!is_ok) {
return;
}
is(result->data_value, expect,
is(result->data_value,
expect,
"found expected result for 'ip' key for %s - %s",
result->ip_looked_up, mode_desc);
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)
{
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];
@ -128,8 +138,8 @@ void run_ipX_tests(MMDB_s *mmdb, const char *pairs[][2], int pairs_rows,
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]);
int error =
pthread_create(&threads[i], NULL, run_one_thread, &thread_args[i]);
if (error) {
BAIL_OUT("pthread_create failed");
}
@ -153,32 +163,31 @@ void run_ipX_tests(MMDB_s *mmdb, const char *pairs[][2], int pairs_rows,
}
}
void run_tests(int mode, const char *mode_desc)
{
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" },
{"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);
@ -187,8 +196,7 @@ void run_tests(int mode, const char *mode_desc)
free(mmdb);
}
int main(void)
{
int main(void) {
plan(NO_PLAN);
for_all_modes(&run_tests);
done_testing();

View File

@ -1,7 +1,6 @@
#include "maxminddb_test_helper.h"
int main(void)
{
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);