1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
#!perl
# SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
use 5.014;
use warnings;
use utf8;
use Test::More;
use File::Spec::Functions qw(catfile);
use IP::Geolocation::MMDB;
use Math::BigInt 1.999806;
my $version = IP::Geolocation::MMDB::libmaxminddb_version;
# Check if the module was linked against the wrong library version.
if ($version =~ m{^(0|1\.[01])\.}) {
plan skip_all => "libmaxminddb $version is too old";
}
diag 'libmaxminddb version is ' . $version;
ok !eval { IP::Geolocation::MMDB->new },
'constructor without "file" parameter dies';
ok !eval { IP::Geolocation::MMDB->new(file => 'nonexistent') },
'constructor with non-existing file dies';
my $file = catfile(qw(t data Test-City.mmdb));
# Ensure that the module is subclassable by using an empty subclass.
@MaxMind::DB::Reader::ISA = qw(IP::Geolocation::MMDB);
my $reader = new_ok 'MaxMind::DB::Reader' => [file => $file];
can_ok $reader,
qw(get getcc record_for_address iterate_search_tree metadata file);
is $reader->file, $file, 'file matches';
ok !eval { $reader->get('-1') }, 'invalid ip address throws exception';
ok !$reader->record_for_address('127.0.0.1'), 'no data for localhost';
my $uint64 = Math::BigInt->new('4702394921427289928');
my $uint128 = Math::BigInt->new('86743875649080753100636639643044826960');
my $r = $reader->get('176.9.54.163');
isa_ok $r, 'HASH';
is $reader->getcc('176.9.54.163'), 'DE', 'IPv4 address is in Germany';
my ($s, $prefix_length) = $reader->get('176.9.54.163');
is_deeply $r, $s, 'data matches';
cmp_ok $prefix_length, '==', 16, 'IPv4 prefix length is 16';
SKIP:
{
skip 'IPv6 tests on Windows', 3 if $^O eq 'MSWin32';
isa_ok $reader->record_for_address('2a01:4f8:150:74ab::2'), 'HASH';
is $reader->getcc('2a01:4f8:150:74ab::2'), 'DE',
'IPv6 address is in Germany';
my (undef, $prefix_length) = $reader->get('2a01:4f8:150:74ab::2');
cmp_ok $prefix_length, '==', 32, 'IPv6 prefix length is 32';
}
is_deeply $r->{x_array}, [-1, 0, 1], 'array matches';
is_deeply $r->{x_map}, {red => 160, green => 32, blue => 240}, 'map matches';
ok $r->{x_boolean}, 'boolean is true';
is $r->{x_bytes}, pack('W*', ord 'A' .. ord 'Z'), 'bytes match';
cmp_ok $r->{x_double}, '>', 0.0, 'double is greater than zero';
cmp_ok $r->{x_float}, '<', 0.0, 'float is less than zero';
is $r->{x_int32}, -12500413, 'int32 matches';
is $r->{x_uint16}, 16706, 'uint16 matches';
is $r->{x_uint32}, 1094861636, 'uint32 matches';
is $r->{x_uint64}, $uint64, 'uint64 matches';
is $r->{x_uint128}, $uint128, 'uint128 matches';
is $r->{x_utf8_string}, 'Фалькенштайн', 'utf8_string matches';
my $m = $reader->metadata;
can_ok $m, qw(
binary_format_major_version binary_format_minor_version build_epoch
database_type languages description ip_version node_count record_size
);
cmp_ok $m->binary_format_major_version, '>=', 0, 'major version is set';
cmp_ok $m->binary_format_minor_version, '>=', 0, 'minor version is set';
cmp_ok $m->build_epoch, '>=', 0, 'build_epoch is set';
isnt $m->database_type, q{}, 'database type is not empty';
isa_ok $m->languages, 'ARRAY';
isa_ok $m->description, 'HASH';
cmp_ok $m->ip_version, '>=', 0, 'ip_version is set';
cmp_ok $m->node_count, '>=', 0, 'node_count is set';
cmp_ok $m->record_size, '>=', 0, 'record_size is set';
my %data_for;
sub data_callback {
my ($numeric_ip, $prefix_length, $data) = @_;
my $address = $numeric_ip->as_hex . '/' . $prefix_length;
$data_for{$address} = $data;
return;
}
my %children_for;
sub node_callback {
my ($node_number, $left_node_number, $right_node_number) = @_;
$children_for{$node_number} = [$left_node_number, $right_node_number];
return;
}
$reader->iterate_search_tree(\&data_callback, \&node_callback);
cmp_ok scalar keys %data_for, '>', 0, 'data_callback was called';
cmp_ok scalar keys %children_for, '>', 0, 'node_callback was called';
ok exists $children_for{0}, 'node 0 exists';
isnt $children_for{0}->[0], $children_for{0}->[1], 'children differ';
my $ipv4_data = $data_for{'0xffffb0090000/112'};
my $ipv6_data = $data_for{'0x2a0104f8000000000000000000000000/32'};
ok defined $ipv4_data, 'IPv4 data exists';
ok defined $ipv6_data, 'IPv6 data exists';
ok exists $ipv4_data->{city}, 'city key exists';
ok exists $ipv6_data->{country}, 'country key exists';
done_testing;
|