From a93375e8ab26e7cb22c6ee7e4bf23bf2d6ed170d Mon Sep 17 00:00:00 2001 From: Nick Pope Date: Tue, 30 Mar 2021 11:52:12 +0100 Subject: [PATCH] Fixed #34305 -- Changed GeoIP2 tests to use MaxMind test databases. GEOIP_SETTINGS is removed from the global scope as this prevents modifications to the settings using @override_settings in tests. Additional improvements now that we have stable test databases include: - Made testing more comprehensive and improved coverage - Patched socket.gethostbyname() for whole test case - Added testing of non-free GeoIP2 databases Co-authored-by: Tom Forbes --- django/contrib/gis/geoip2.py | 19 +- .../data/geoip2/GeoIP2-City-Test.mmdb | Bin 0 -> 22430 bytes .../data/geoip2/GeoIP2-Country-Test.mmdb | Bin 0 -> 19628 bytes .../data/geoip2/GeoLite2-ASN-Test.mmdb | Bin 0 -> 12653 bytes .../data/geoip2/GeoLite2-City-Test.mmdb | Bin 0 -> 21117 bytes .../data/geoip2/GeoLite2-Country-Test.mmdb | Bin 0 -> 18041 bytes tests/gis_tests/data/geoip2/LICENSE | 4 + tests/gis_tests/data/geoip2/README | 3 + tests/gis_tests/test_geoip2.py | 262 ++++++++++-------- 9 files changed, 159 insertions(+), 129 deletions(-) create mode 100644 tests/gis_tests/data/geoip2/GeoIP2-City-Test.mmdb create mode 100644 tests/gis_tests/data/geoip2/GeoIP2-Country-Test.mmdb create mode 100644 tests/gis_tests/data/geoip2/GeoLite2-ASN-Test.mmdb create mode 100644 tests/gis_tests/data/geoip2/GeoLite2-City-Test.mmdb create mode 100644 tests/gis_tests/data/geoip2/GeoLite2-Country-Test.mmdb create mode 100644 tests/gis_tests/data/geoip2/LICENSE create mode 100644 tests/gis_tests/data/geoip2/README diff --git a/django/contrib/gis/geoip2.py b/django/contrib/gis/geoip2.py index 898f5d596d..5f49954209 100644 --- a/django/contrib/gis/geoip2.py +++ b/django/contrib/gis/geoip2.py @@ -25,19 +25,12 @@ __all__ = ["HAS_GEOIP2"] try: import geoip2.database -except ImportError: +except ImportError: # pragma: no cover HAS_GEOIP2 = False else: HAS_GEOIP2 = True __all__ += ["GeoIP2", "GeoIP2Exception"] -# Creating the settings dictionary with any settings, if needed. -GEOIP_SETTINGS = { - "GEOIP_PATH": getattr(settings, "GEOIP_PATH", None), - "GEOIP_CITY": getattr(settings, "GEOIP_CITY", "GeoLite2-City.mmdb"), - "GEOIP_COUNTRY": getattr(settings, "GEOIP_COUNTRY", "GeoLite2-Country.mmdb"), -} - class GeoIP2Exception(Exception): pass @@ -95,7 +88,7 @@ class GeoIP2: raise GeoIP2Exception("Invalid GeoIP caching option: %s" % cache) # Getting the GeoIP data path. - path = path or GEOIP_SETTINGS["GEOIP_PATH"] + path = path or getattr(settings, "GEOIP_PATH", None) if not path: raise GeoIP2Exception( "GeoIP path must be provided via parameter or the GEOIP_PATH setting." @@ -106,12 +99,16 @@ class GeoIP2: # Constructing the GeoIP database filenames using the settings # dictionary. If the database files for the GeoLite country # and/or city datasets exist, then try to open them. - country_db = path / (country or GEOIP_SETTINGS["GEOIP_COUNTRY"]) + country_db = path / ( + country or getattr(settings, "GEOIP_COUNTRY", "GeoLite2-Country.mmdb") + ) if country_db.is_file(): self._country = geoip2.database.Reader(str(country_db), mode=cache) self._country_file = country_db - city_db = path / (city or GEOIP_SETTINGS["GEOIP_CITY"]) + city_db = path / ( + city or getattr(settings, "GEOIP_CITY", "GeoLite2-City.mmdb") + ) if city_db.is_file(): self._city = geoip2.database.Reader(str(city_db), mode=cache) self._city_file = city_db diff --git a/tests/gis_tests/data/geoip2/GeoIP2-City-Test.mmdb b/tests/gis_tests/data/geoip2/GeoIP2-City-Test.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..3197ef122fa3522eb8b4e15ad0e6cf1e0e51e8a0 GIT binary patch literal 22430 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 an`rqi_r*?~G6S9xqzOeq?@Uj9@Bafz;CX8R literal 0 HcmV?d00001 diff --git a/tests/gis_tests/data/geoip2/GeoIP2-Country-Test.mmdb b/tests/gis_tests/data/geoip2/GeoIP2-Country-Test.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..d79c9933bb986e1ea01c7a6faebde862f1c1d4a7 GIT binary patch literal 19628 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 literal 0 HcmV?d00001 diff --git a/tests/gis_tests/data/geoip2/GeoLite2-ASN-Test.mmdb b/tests/gis_tests/data/geoip2/GeoLite2-ASN-Test.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..afa7e956e4cd55d4398ffb9d4805ad2dde507cf3 GIT binary patch literal 12653 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") - # No city database available, these calls should fail. - with self.assertRaises(GeoIP2Exception): - cntry_g.city("tmc.edu") + def test_bad_query(self): + g = GeoIP2(city="") - # Non-string query should raise TypeError - with self.assertRaises(TypeError): - cntry_g.country_code(17) - with self.assertRaises(TypeError): - cntry_g.country_name(GeoIP2) + functions = (g.city, g.geos, g.lat_lon, g.lon_lat) + msg = "Invalid GeoIP city data file: " + for function in functions: + with self.subTest(function=function.__qualname__): + with self.assertRaisesMessage(GeoIP2Exception, msg): + function("example.com") - @mock.patch("socket.gethostbyname") - def test03_country(self, gethostbyname): - "GeoIP country querying methods." - gethostbyname.return_value = "128.249.1.1" - g = GeoIP2(city="") + functions += (g.country, g.country_code, g.country_name) + values = (123, 123.45, b"", (), [], {}, set(), frozenset(), GeoIP2) + msg = "GeoIP query must be a string, not type" + for function, value in itertools.product(functions, values): + with self.subTest(function=function.__qualname__, type=type(value)): + with self.assertRaisesMessage(TypeError, msg): + function(value) - for query in (self.fqdn, self.addr): - self.assertEqual( - "US", - g.country_code(query), - "Failed for func country_code and query %s" % query, - ) - self.assertEqual( - "United States", - g.country_name(query), - "Failed for func country_name and query %s" % query, - ) - self.assertEqual( - {"country_code": "US", "country_name": "United States"}, - g.country(query), - ) + def test_country(self): + g = GeoIP2(city="") + for query in (self.fqdn, self.ipv4, self.ipv6): + with self.subTest(query=query): + self.assertEqual( + g.country(query), + { + "country_code": "GB", + "country_name": "United Kingdom", + }, + ) + self.assertEqual(g.country_code(query), "GB") + self.assertEqual(g.country_name(query), "United Kingdom") - @mock.patch("socket.gethostbyname") - def test04_city(self, gethostbyname): - "GeoIP city querying methods." - gethostbyname.return_value = "129.237.192.1" - g = GeoIP2(country="") + def test_city(self): + g = GeoIP2(country="") + for query in (self.fqdn, self.ipv4, self.ipv6): + with self.subTest(query=query): + self.assertEqual( + g.city(query), + { + "city": "Boxford", + "continent_code": "EU", + "continent_name": "Europe", + "country_code": "GB", + "country_name": "United Kingdom", + "dma_code": None, + "is_in_european_union": False, + "latitude": 51.75, + "longitude": -1.25, + "postal_code": "OX1", + "region": "ENG", + "time_zone": "Europe/London", + }, + ) - for query in (self.fqdn, self.addr): - # Country queries should still work. - self.assertEqual( - "US", - g.country_code(query), - "Failed for func country_code and query %s" % query, - ) - self.assertEqual( - "United States", - g.country_name(query), - "Failed for func country_name and query %s" % query, - ) - self.assertEqual( - {"country_code": "US", "country_name": "United States"}, - g.country(query), - ) + geom = g.geos(query) + self.assertIsInstance(geom, GEOSGeometry) + self.assertEqual(geom.srid, 4326) + self.assertEqual(geom.tuple, (-1.25, 51.75)) - # City information dictionary. - d = g.city(query) - self.assertEqual("NA", d["continent_code"]) - self.assertEqual("North America", d["continent_name"]) - self.assertEqual("US", d["country_code"]) - self.assertEqual("Lawrence", d["city"]) - self.assertEqual("KS", d["region"]) - self.assertEqual("America/Chicago", d["time_zone"]) - self.assertFalse(d["is_in_european_union"]) - geom = g.geos(query) - self.assertIsInstance(geom, GEOSGeometry) + self.assertEqual(g.lat_lon(query), (51.75, -1.25)) + self.assertEqual(g.lon_lat(query), (-1.25, 51.75)) + # Country queries should still work. + self.assertEqual( + g.country(query), + { + "country_code": "GB", + "country_name": "United Kingdom", + }, + ) + self.assertEqual(g.country_code(query), "GB") + self.assertEqual(g.country_name(query), "United Kingdom") - for e1, e2 in ( - geom.tuple, - g.lon_lat(query), - g.lat_lon(query), - ): - self.assertIsInstance(e1, float) - self.assertIsInstance(e2, float) - - def test06_ipv6_query(self): - "GeoIP can lookup IPv6 addresses." - g = GeoIP2() - d = g.city("2002:81ed:c9a5::81ed:c9a5") # IPv6 address for www.nhm.ku.edu - self.assertEqual("US", d["country_code"]) - self.assertEqual("Lawrence", d["city"]) - self.assertEqual("KS", d["region"]) + def test_not_found(self): + g1 = GeoIP2(city="") + g2 = GeoIP2(country="") + for function, query in itertools.product( + (g1.country, g2.city), ("127.0.0.1", "::1") + ): + with self.subTest(function=function.__qualname__, query=query): + msg = f"The address {query} is not in the database." + with self.assertRaisesMessage(geoip2.errors.AddressNotFoundError, msg): + function(query) def test_del(self): g = GeoIP2() @@ -162,8 +168,7 @@ class GeoIPTest(SimpleTestCase): self.assertIs(country._db_reader.closed, True) def test_repr(self): - path = settings.GEOIP_PATH - g = GeoIP2(path=path) + g = GeoIP2() meta = g._reader.metadata() version = "%s.%s" % ( meta.binary_format_major_version, @@ -181,26 +186,47 @@ class GeoIPTest(SimpleTestCase): ) self.assertEqual(repr(g), expected) - @mock.patch("socket.gethostbyname", return_value="expected") - def test_check_query(self, gethostbyname): + def test_check_query(self): g = GeoIP2() - self.assertEqual(g._check_query("127.0.0.1"), "127.0.0.1") - self.assertEqual( - g._check_query("2002:81ed:c9a5::81ed:c9a5"), "2002:81ed:c9a5::81ed:c9a5" - ) - self.assertEqual(g._check_query("invalid-ip-address"), "expected") + self.assertEqual(g._check_query(self.ipv4), self.ipv4) + self.assertEqual(g._check_query(self.ipv6), self.ipv6) + self.assertEqual(g._check_query(self.fqdn), self.ipv4) def test_coords_deprecation_warning(self): g = GeoIP2() msg = "GeoIP2.coords() is deprecated. Use GeoIP2.lon_lat() instead." with self.assertWarnsMessage(RemovedInDjango60Warning, msg): - e1, e2 = g.coords(self.fqdn) + e1, e2 = g.coords(self.ipv4) self.assertIsInstance(e1, float) self.assertIsInstance(e2, float) def test_open_deprecation_warning(self): msg = "GeoIP2.open() is deprecated. Use GeoIP2() instead." with self.assertWarnsMessage(RemovedInDjango60Warning, msg): - g = GeoIP2.open(settings.GEOIP_PATH, 0) + g = GeoIP2.open(settings.GEOIP_PATH, GeoIP2.MODE_AUTO) self.assertTrue(g._country) self.assertTrue(g._city) + + +@skipUnless(HAS_GEOIP2, "GeoIP2 is required.") +@override_settings( + GEOIP_CITY="GeoIP2-City-Test.mmdb", + GEOIP_COUNTRY="GeoIP2-Country-Test.mmdb", +) +class GeoIP2Test(GeoLite2Test): + """Non-free GeoIP2 databases are supported.""" + + +@skipUnless(HAS_GEOIP2, "GeoIP2 is required.") +class ErrorTest(SimpleTestCase): + def test_missing_path(self): + msg = "GeoIP path must be provided via parameter or the GEOIP_PATH setting." + with self.settings(GEOIP_PATH=None): + with self.assertRaisesMessage(GeoIP2Exception, msg): + GeoIP2() + + def test_unsupported_database(self): + msg = "Unable to recognize database edition: GeoLite2-ASN" + with self.settings(GEOIP_PATH=build_geoip_path("GeoLite2-ASN-Test.mmdb")): + with self.assertRaisesMessage(GeoIP2Exception, msg): + GeoIP2()