aboutsummaryrefslogtreecommitdiff
path: root/tests/managers/thl/test_ipinfo.py
blob: 47b17120dddffc5de7b75cd18bcd2f9facfadcd6 (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from collections.abc import Callable
from typing import TYPE_CHECKING

import faker

from generalresearch.managers.thl.ipinfo import (
    GeoIpInfoManager,
    IPGeonameManager,
    IPInformationManager,
)
from generalresearch.models.thl.ipinfo import (
    GeoIPInformation,
    IPGeoname,
    IPInformation,
)

if TYPE_CHECKING:
    from generalresearch.pg_helper import PostgresConfig
    from generalresearch.redis_helper import RedisConfig

fake = faker.Faker()


class TestIPGeonameManager:

    def test_init(
        self, thl_web_rr: PostgresConfig, ip_geoname_manager: IPGeonameManager
    ):

        instance = IPGeonameManager(pg_config=thl_web_rr)
        assert isinstance(instance, IPGeonameManager)
        assert isinstance(ip_geoname_manager, IPGeonameManager)

    def test_create(
        self,
        ip_geoname_factory: Callable[..., IPGeoname],
        ip_geoname_manager: IPGeonameManager,
    ):

        instance = ip_geoname_factory()
        assert isinstance(instance, IPGeoname)

        res = ip_geoname_manager.fetch_geoname_ids(filter_ids=[instance.geoname_id])
        assert res[0].model_dump_json() == instance.model_dump_json()


class TestIPInformationManager:

    def test_init(
        self, thl_web_rr: PostgresConfig, ip_information_manager: IPInformationManager
    ):
        instance = IPInformationManager(pg_config=thl_web_rr)
        assert isinstance(instance, IPInformationManager)
        assert isinstance(ip_information_manager, IPInformationManager)

    def test_create(
        self,
        ip_geoname_factory: Callable[..., IPGeoname],
        ip_information_manager: IPInformationManager,
    ):
        instance = ip_geoname_factory()
        assert isinstance(instance, IPInformation)

        res = ip_information_manager.fetch_ip_information(filter_ips=[instance.ip])
        assert res[0].model_dump_json() == instance.model_dump_json()

    def test_prefetch_geoname(
        self,
        ip_information: IPInformation,
        ip_geoname: IPGeoname,
        thl_web_rr: PostgresConfig,
    ):
        assert isinstance(ip_information, IPInformation)

        assert ip_information.geoname_id == ip_geoname.geoname_id
        assert ip_information.geoname is None

        ip_information.prefetch_geoname(pg_config=thl_web_rr)
        assert isinstance(ip_information.geoname, IPGeoname)


class TestGeoIpInfoManager:
    def test_init(
        self,
        thl_web_rr: PostgresConfig,
        thl_redis_config: RedisConfig,
        geoipinfo_manager: GeoIpInfoManager,
    ):
        instance = GeoIpInfoManager(pg_config=thl_web_rr, redis_config=thl_redis_config)
        assert isinstance(instance, GeoIpInfoManager)
        assert isinstance(geoipinfo_manager, GeoIpInfoManager)

    def test_multi(
        self,
        ip_information_factory: Callable[..., IPInformation],
        ip_geoname: IPGeoname,
        geoipinfo_manager: GeoIpInfoManager,
    ):
        ip = fake.ipv4_public()
        ip_information_factory(ip=ip, geoname=ip_geoname)
        ips = [ip]

        # This only looks up in redis. They don't exist yet
        res = geoipinfo_manager.get_cache_multi(ip_addresses=ips)
        assert res == {ip: None}

        # Looks up in redis, if not exists, looks in mysql, then sets
        #   the caches that didn't exist.
        res = geoipinfo_manager.get_multi(ip_addresses=ips)
        assert res[ip] is not None

        ip2 = fake.ipv4_public()
        ip_information_factory(ip=ip2, geoname=ip_geoname)
        ips = [ip, ip2]
        res = geoipinfo_manager.get_cache_multi(ip_addresses=ips)
        assert res[ip] is not None
        assert res[ip2] is None
        res = geoipinfo_manager.get_multi(ip_addresses=ips)
        assert res[ip] is not None
        assert res[ip2] is not None
        res = geoipinfo_manager.get_cache_multi(ip_addresses=ips)
        assert res[ip] is not None
        assert res[ip2] is not None

    def test_multi_ipv6(
        self,
        ip_information_factory: Callable[..., IPInformation],
        ip_geoname: IPGeoname,
        geoipinfo_manager: GeoIpInfoManager,
    ):
        ip = fake.ipv6()
        # Make another IP that will be in the same /64 block.
        ip2 = ip[:-1] + "a" if ip[-1] != "a" else ip[:-1] + "b"
        ip_information_factory(ip=ip, geoname=ip_geoname)
        ips = [ip, ip2]
        print(f"{ips=}")

        # This only looks up in redis. They don't exist yet
        res = geoipinfo_manager.get_cache_multi(ip_addresses=ips)
        assert res == {ip: None, ip2: None}

        # Looks up in redis, if not exists, looks in mysql, then sets
        #   the caches that didn't exist.
        res = geoipinfo_manager.get_multi(ip_addresses=ips)

        res1 = res[ip]
        assert isinstance(res1, GeoIPInformation)
        assert res1.ip == ip
        assert res1.lookup_prefix == "/64"

        res2 = res[ip2]
        assert isinstance(res2, GeoIPInformation)
        assert res2.ip == ip2
        assert res2.lookup_prefix == "/64"
        # they should be the same basically, except for the ip

    def test_doesnt_exist(self, geoipinfo_manager: GeoIpInfoManager):
        ip = fake.ipv4_public()
        res = geoipinfo_manager.get_multi(ip_addresses=[ip])
        assert res == {ip: None}