3838import  static  java .util .Map .entry ;
3939import  static  org .elasticsearch .ingest .geoip .GeoIpTestUtils .copyDatabase ;
4040import  static  org .elasticsearch .ingest .geoip .IpinfoIpDataLookups .parseAsn ;
41+ import  static  org .elasticsearch .ingest .geoip .IpinfoIpDataLookups .parseLocationDouble ;
4142import  static  org .hamcrest .Matchers .empty ;
4243import  static  org .hamcrest .Matchers .equalTo ;
4344import  static  org .hamcrest .Matchers .is ;
@@ -72,6 +73,10 @@ public void testDatabasePropertyInvariants() {
7273        // the second ASN variant database is like a specialization of the ASN database 
7374        assertThat (Sets .difference (Database .Asn .properties (), Database .AsnV2 .properties ()), is (empty ()));
7475        assertThat (Database .Asn .defaultProperties (), equalTo (Database .AsnV2 .defaultProperties ()));
76+ 
77+         // the second City variant database is like a version of the ordinary City database but lacking many fields 
78+         assertThat (Sets .difference (Database .CityV2 .properties (), Database .City .properties ()), is (empty ()));
79+         assertThat (Sets .difference (Database .CityV2 .defaultProperties (), Database .City .defaultProperties ()), is (empty ()));
7580    }
7681
7782    public  void  testParseAsn () {
@@ -88,6 +93,18 @@ public void testParseAsn() {
8893        assertThat (parseAsn ("anythingelse" ), nullValue ());
8994    }
9095
96+     public  void  testParseLocationDouble () {
97+         // expected case: "123.45" is 123.45 
98+         assertThat (parseLocationDouble ("123.45" ), equalTo (123.45 ));
99+         // defensive cases: null and empty becomes null, this is not expected fwiw 
100+         assertThat (parseLocationDouble (null ), nullValue ());
101+         assertThat (parseLocationDouble ("" ), nullValue ());
102+         // defensive cases: we strip whitespace 
103+         assertThat (parseLocationDouble ("  -123.45  " ), equalTo (-123.45 ));
104+         // bottom case: a non-parsable string is null 
105+         assertThat (parseLocationDouble ("anythingelse" ), nullValue ());
106+     }
107+ 
91108    public  void  testAsn () throws  IOException  {
92109        assumeFalse ("https://github.com/elastic/elasticsearch/issues/114266" , Constants .WINDOWS );
93110        Path  configDir  = tmpDir ;
@@ -100,7 +117,7 @@ public void testAsn() throws IOException {
100117
101118        // this is the 'free' ASN database (sample) 
102119        try  (DatabaseReaderLazyLoader  loader  = configDatabases .getDatabase ("ip_asn_sample.mmdb" )) {
103-             IpDataLookup  lookup  = new  IpinfoIpDataLookups .Asn (Set . of ( Database .Property . values () ));
120+             IpDataLookup  lookup  = new  IpinfoIpDataLookups .Asn (Database .AsnV2 . properties ( ));
104121            Map <String , Object > data  = lookup .getData (loader , "5.182.109.0" );
105122            assertThat (
106123                data ,
@@ -118,7 +135,7 @@ public void testAsn() throws IOException {
118135
119136        // this is the non-free or 'standard' ASN database (sample) 
120137        try  (DatabaseReaderLazyLoader  loader  = configDatabases .getDatabase ("asn_sample.mmdb" )) {
121-             IpDataLookup  lookup  = new  IpinfoIpDataLookups .Asn (Set . of ( Database .Property . values () ));
138+             IpDataLookup  lookup  = new  IpinfoIpDataLookups .Asn (Database .AsnV2 . properties ( ));
122139            Map <String , Object > data  = lookup .getData (loader , "23.53.116.0" );
123140            assertThat (
124141                data ,
@@ -185,7 +202,7 @@ public void testCountry() throws IOException {
185202
186203        // this is the 'free' Country database (sample) 
187204        try  (DatabaseReaderLazyLoader  loader  = configDatabases .getDatabase ("ip_country_sample.mmdb" )) {
188-             IpDataLookup  lookup  = new  IpinfoIpDataLookups .Country (Set . of ( Database .Property . values () ));
205+             IpDataLookup  lookup  = new  IpinfoIpDataLookups .Country (Database .Country . properties ( ));
189206            Map <String , Object > data  = lookup .getData (loader , "4.221.143.168" );
190207            assertThat (
191208                data ,
@@ -202,6 +219,74 @@ public void testCountry() throws IOException {
202219        }
203220    }
204221
222+     public  void  testGeolocation () throws  IOException  {
223+         assumeFalse ("https://github.com/elastic/elasticsearch/issues/114266" , Constants .WINDOWS );
224+         Path  configDir  = tmpDir ;
225+         copyDatabase ("ipinfo/ip_geolocation_sample.mmdb" , configDir .resolve ("ip_geolocation_sample.mmdb" ));
226+ 
227+         GeoIpCache  cache  = new  GeoIpCache (1000 ); // real cache to test purging of entries upon a reload 
228+         ConfigDatabases  configDatabases  = new  ConfigDatabases (configDir , cache );
229+         configDatabases .initialize (resourceWatcherService );
230+ 
231+         // this is the non-free or 'standard' Geolocation database (sample) 
232+         try  (DatabaseReaderLazyLoader  loader  = configDatabases .getDatabase ("ip_geolocation_sample.mmdb" )) {
233+             IpDataLookup  lookup  = new  IpinfoIpDataLookups .Geolocation (Database .CityV2 .properties ());
234+             Map <String , Object > data  = lookup .getData (loader , "2.124.90.182" );
235+             assertThat (
236+                 data ,
237+                 equalTo (
238+                     Map .ofEntries (
239+                         entry ("ip" , "2.124.90.182" ),
240+                         entry ("country_iso_code" , "GB" ),
241+                         entry ("region_name" , "England" ),
242+                         entry ("city_name" , "London" ),
243+                         entry ("timezone" , "Europe/London" ),
244+                         entry ("postal_code" , "E1W" ),
245+                         entry ("location" , Map .of ("lat" , 51.50853 , "lon" , -0.12574 ))
246+                     )
247+                 )
248+             );
249+         }
250+     }
251+ 
252+     public  void  testGeolocationInvariants () {
253+         assumeFalse ("https://github.com/elastic/elasticsearch/issues/114266" , Constants .WINDOWS );
254+         Path  configDir  = tmpDir ;
255+         copyDatabase ("ipinfo/ip_geolocation_sample.mmdb" , configDir .resolve ("ip_geolocation_sample.mmdb" ));
256+ 
257+         {
258+             final  Set <String > expectedColumns  = Set .of (
259+                 "network" ,
260+                 "city" ,
261+                 "region" ,
262+                 "country" ,
263+                 "postal_code" ,
264+                 "timezone" ,
265+                 "latitude" ,
266+                 "longitude" 
267+             );
268+ 
269+             Path  databasePath  = configDir .resolve ("ip_geolocation_sample.mmdb" );
270+             assertDatabaseInvariants (databasePath , (ip , row ) -> {
271+                 assertThat (row .keySet (), equalTo (expectedColumns ));
272+                 {
273+                     String  latitude  = (String ) row .get ("latitude" );
274+                     assertThat (latitude , equalTo (latitude .trim ()));
275+                     Double  parsed  = parseLocationDouble (latitude );
276+                     assertThat (parsed , notNullValue ());
277+                     assertThat (latitude , equalTo (Double .toString (parsed ))); // reverse it 
278+                 }
279+                 {
280+                     String  longitude  = (String ) row .get ("longitude" );
281+                     assertThat (longitude , equalTo (longitude .trim ()));
282+                     Double  parsed  = parseLocationDouble (longitude );
283+                     assertThat (parsed , notNullValue ());
284+                     assertThat (longitude , equalTo (Double .toString (parsed ))); // reverse it 
285+                 }
286+             });
287+         }
288+     }
289+ 
205290    private  static  void  assertDatabaseInvariants (final  Path  databasePath , final  BiConsumer <InetAddress , Map <String , Object >> rowConsumer ) {
206291        try  (Reader  reader  = new  Reader (pathToFile (databasePath ))) {
207292            Networks <?> networks  = reader .networks (Map .class );
0 commit comments