File: mmdb.t

package info (click to toggle)
libip-geolocation-mmdb-perl 1.013-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 184 kB
  • sloc: perl: 192; makefile: 3
file content (132 lines) | stat: -rw-r--r-- 4,471 bytes parent folder | download
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;