package com.workshare.msnos.core.geo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.maxmind.geoip2.model.OmniResponse;
import com.maxmind.geoip2.record.City;
import com.maxmind.geoip2.record.Continent;
import com.maxmind.geoip2.record.Country;
import com.maxmind.geoip2.record.Subdivision;
import com.workshare.msnos.core.geo.Location.Match;
import com.workshare.msnos.core.geo.Location.Place;
@RunWith(PowerMockRunner.class)
@PrepareForTest({OmniResponse.class, Continent.class, City.class, Country.class, Subdivision.class, com.maxmind.geoip2.record.Location.class})
public class LocationTest {
public static final Continent NORTH_AMERICA = mockContinent("NA", "North America");
public static final Continent EUROPE = mockContinent("EU", "Europe");
public static final Country UNITED_STATES = mockCountry("US", "United States");
public static final Country CANADA = mockCountry("CA", "Canada");
public static final Subdivision NEW_YORK = mockRegion("NY","New York");
public static final City SYRACUSE = mock(City.class);
static {
when(SYRACUSE.getGeoNameId()).thenReturn(5116079);
when(SYRACUSE.getName()).thenReturn("Syracuse");
}
static {
when(EUROPE.getCode()).thenReturn("EU");
when(EUROPE.getName()).thenReturn("EUROPE");
}
@Before
public void setup() {
}
@Test
public void shouldCreateContinentRecord() {
Location location = new Location (response(NORTH_AMERICA));
assertEquals(Place.Type.CONTINENT, location.getContinent().getType());
assertEquals(NORTH_AMERICA.getCode(), location.getContinent().getCode());
assertEquals(NORTH_AMERICA.getName(), location.getContinent().getName());
}
@Test
public void shouldCreateCountryRecord() {
Location location = new Location (response(UNITED_STATES));
assertEquals(Place.Type.COUNTRY, location.getCountry().getType());
assertEquals(UNITED_STATES.getIsoCode(), location.getCountry().getCode());
assertEquals(UNITED_STATES.getName(), location.getCountry().getName());
}
@Test
public void shouldCreateRegionRecord() {
Location location = new Location (response(NEW_YORK));
assertEquals(Place.Type.REGION, location.getRegion().getType());
assertEquals(NEW_YORK.getIsoCode(), location.getRegion().getCode());
assertEquals(NEW_YORK.getName(), location.getRegion().getName());
}
@Test
public void shouldCreateCityRecord() {
Location location = new Location (response(SYRACUSE));
assertEquals(Place.Type.CITY, location.getCity().getType());
assertEquals(SYRACUSE.getGeoNameId().toString(), location.getCity().getCode());
assertEquals(SYRACUSE.getName(), location.getCity().getName());
}
@Test
public void shouldRecordGPSLocation() {
Location location = new Location (response(0.2, 0.5, 99));
assertEquals(0.2, location.getGPS().getLatitude(), 0.01);
assertEquals(0.5, location.getGPS().getLongitude(), 0.01);
assertEquals(99, location.getGPS().getAccuracy().intValue());
}
@Test
public void shouldNotMatchWithNowhere() {
Location america = new Location (response(NORTH_AMERICA));
Location nowhere = new Location (response());
Match match = america.match(nowhere);
assertEquals(0, match.value());
}
@Test
public void shouldNotMatchIfContinentDifferent() {
Location america = new Location (response(NORTH_AMERICA));
Location europe = new Location (response(EUROPE));
Match match = america.match(europe);
assertEquals(0, match.value());
}
@Test
public void shouldMatchByContinent() {
Location self = new Location (response(NORTH_AMERICA, null, null, null));
Location other = new Location (response(NORTH_AMERICA, UNITED_STATES, null, null));
Match match = self.match(other);
assertEquals(1, match.value());
}
@Test
public void shouldMatchByCountry() {
Location self = new Location (response(NORTH_AMERICA, UNITED_STATES, null, null));
Location other = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, null));
Match match = self.match(other);
assertEquals(3, match.value());
}
@Test
public void shouldMatchByRegion() {
Location self = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, null));
Location other = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, SYRACUSE));
Match match = self.match(other);
assertEquals(7, match.value());
}
@Test
public void shouldMatchByCity() {
Location self = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, SYRACUSE));
Location other = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, SYRACUSE));
Match match = self.match(other);
assertEquals(15, match.value());
}
@Test
public void shouldCalculatePrecisionWhenNowhere() {
assertEquals(0, Location.UNKNOWN.getPrecision());
}
@Test
public void shouldCalculatePrecisionCorrectly() {
Location continent = new Location (response(NORTH_AMERICA, null, null, null));
Location country = new Location (response(NORTH_AMERICA, UNITED_STATES, null, null));
Location region = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, null));
Location city = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, SYRACUSE));
assertTrue(country.getPrecision() > continent.getPrecision());
assertTrue(region.getPrecision() > country.getPrecision());
assertTrue(city.getPrecision() > region.getPrecision());
}
@Test
public void shouldComputeMostPreciseLocationAsNowherWhenNoNetworks() {
Location location = Location.computeMostPreciseLocation(null);
assertEquals(Location.UNKNOWN, location);
}
@Test
public void shouldNotMatchWhenOtherIsNull() {
Location self = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, SYRACUSE));
Match match = self.match(null);
assertEquals(0, match.value());
}
@Test
public void shouldToStringNicelyGoodLocation() {
Location loc = new Location (response(NORTH_AMERICA, UNITED_STATES, NEW_YORK, SYRACUSE));
assertEquals("North America, United States, New York, Syracuse", loc.toString());
}
@Test
public void shouldToStringNicelyDecentLocation() {
Location loc = new Location (response(NORTH_AMERICA, UNITED_STATES, null, null));
assertEquals("North America, United States", loc.toString());
}
@Test
public void shouldToStringNicelyUnknownLocation() {
Location loc = Location.UNKNOWN;
assertEquals("unknown", loc.toString());
}
private OmniResponse response(Continent continent) {
return response(continent, null, null, null);
}
private OmniResponse response(Country country) {
return response(null, country, null, null);
}
private OmniResponse response(Subdivision region) {
return response(null, null, region, null);
}
private OmniResponse response(City city) {
return response(null, null, null, city);
}
private OmniResponse response() {
return response(null, null, null, null);
}
private OmniResponse response(double latitude, double longitude, int accuracy) {
com.maxmind.geoip2.record.Location location = mock(com.maxmind.geoip2.record.Location.class);
when(location.getLatitude()).thenReturn(latitude);
when(location.getLongitude()).thenReturn(longitude);
when(location.getAccuracyRadius()).thenReturn(accuracy);
OmniResponse response = mock(OmniResponse.class);
when(response.getLocation()).thenReturn(location);
return response;
}
private OmniResponse response(Continent continent, Country country, Subdivision region, City city) {
OmniResponse response = mock(OmniResponse.class);
when(response.getContinent()).thenReturn(continent );
when(response.getCountry()).thenReturn(country);
when(response.getMostSpecificSubdivision()).thenReturn(region);
when(response.getCity()).thenReturn(city);
return response;
}
private static Continent mockContinent(String code, String name) {
Continent continent = mock(Continent.class);
when(continent.getCode()).thenReturn(code);
when(continent.getName()).thenReturn(name);
return continent;
}
private static Country mockCountry(String code, String name) {
Country country = mock(Country.class);
when(country.getIsoCode()).thenReturn(code);
when(country.getName()).thenReturn(name);
return country;
}
private static final Subdivision mockRegion(String code, String name) {
Subdivision region = mock(Subdivision.class);
when(region.getIsoCode()).thenReturn(code);
when(region.getName()).thenReturn(name);
return region;
}
}