package org.iilab.pb.location; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.NETWORK_PROVIDER; import static java.lang.System.currentTimeMillis; import static org.iilab.pb.common.Intents.LOCATION_UPDATE_ACTION; import static org.iilab.pb.location.LocationTestUtil.location; import static org.junit.Assert.assertEquals; @RunWith(RobolectricTestRunner.class) public class LocationUpdateReceiverTest { public static final float LESS_ACCURATE = 20.0f; public static final float ALMOST_SAME_AS_LESS_ACCURATE = 20.1f; public static final float VERY_LESS_ACCURATE = 50.0f; private static final float SIGNIFICANTLY_LESS_ACCURATE = 260f; private static final float MORE_ACCURATE = 0.60f; private LocationUpdateReceiver locationUpdateReceiver; private Context context; @Before public void setUp() throws InterruptedException { context = Robolectric.application; locationUpdateReceiver = new LocationUpdateReceiver() { public Location location; Location getCurrentBestLocation() { return location; } void setCurrentBestLocation(Location location) { this.location = location; } }; } @Test public void shouldReturnBestKnowLocation() { Location expectedLocation = location(NETWORK_PROVIDER, 10.0, 20.0, currentTimeMillis(), LESS_ACCURATE); locationUpdateReceiver.onReceive(context, getIntent(expectedLocation)); assertLocation(expectedLocation); } @Test public void shouldReturnSignificantlyLatestLocation() { Location oldLocation1 = location(NETWORK_PROVIDER, 12.0, 20.0, offsetCurrentTimeBy(-90), LESS_ACCURATE); Location oldLocation2 = location(NETWORK_PROVIDER, 10.0, 20.0, offsetCurrentTimeBy(-80), LESS_ACCURATE); Location newLocation = location(NETWORK_PROVIDER, 11.0, 20.0, currentTimeMillis(), LESS_ACCURATE); locationUpdateReceiver.onReceive(context, getIntent(oldLocation1)); locationUpdateReceiver.onReceive(context, getIntent(newLocation)); locationUpdateReceiver.onReceive(context, getIntent(oldLocation1)); locationUpdateReceiver.onReceive(context, getIntent(oldLocation2)); assertLocation(newLocation); } @Test public void shouldReturnMoreAccurateLocation() { Location oldLocation = location(NETWORK_PROVIDER, 12.0, 20.0, currentTimeMillis(), LESS_ACCURATE); Location newLocation = location(NETWORK_PROVIDER, 11.5, 20.0, offsetCurrentTimeBy(40), MORE_ACCURATE); Location newLocation1 = location(NETWORK_PROVIDER, 11.0, 20.0, offsetCurrentTimeBy(-20), LESS_ACCURATE); locationUpdateReceiver.onReceive(context, getIntent(oldLocation)); locationUpdateReceiver.onReceive(context, getIntent(newLocation)); locationUpdateReceiver.onReceive(context, getIntent(newLocation1)); assertLocation(newLocation); } @Test public void shouldReturnLocationWhichHasAlmostSameAccuracyAndRelativelyNew() { Location oldLocation = location(NETWORK_PROVIDER, 12.0, 20.0, currentTimeMillis(), LESS_ACCURATE); long time = offsetCurrentTimeBy(10); Location newLocation = location(NETWORK_PROVIDER, 12.0, 20.0, time, ALMOST_SAME_AS_LESS_ACCURATE); Location newLocationClone = location(NETWORK_PROVIDER, 12.0, 20.0, time, ALMOST_SAME_AS_LESS_ACCURATE); locationUpdateReceiver.onReceive(context, getIntent(oldLocation)); locationUpdateReceiver.onReceive(context, getIntent(newLocation)); locationUpdateReceiver.onReceive(context, getIntent(newLocationClone)); assertLocation(newLocation); } @Test public void shouldReturnLocationFromSameProviderAndNotSignificantlyAccurateButRelativelyNew() { Location oldLocation = location(NETWORK_PROVIDER, 12.0, 20.0, currentTimeMillis(), LESS_ACCURATE); Location lessAccurateButNewLocation = location(NETWORK_PROVIDER, 12.0, 20.0, offsetCurrentTimeBy(10), VERY_LESS_ACCURATE); Location diffMoreAccurateProviderLocation = location(GPS_PROVIDER, 12.0, 20.0, offsetCurrentTimeBy(20), VERY_LESS_ACCURATE - 10.0f); Location significantlyLessAccurateLocation = location(NETWORK_PROVIDER, 13.0, 20.0, offsetCurrentTimeBy(10), SIGNIFICANTLY_LESS_ACCURATE); locationUpdateReceiver.onReceive(context, getIntent(oldLocation)); locationUpdateReceiver.onReceive(context, getIntent(lessAccurateButNewLocation)); locationUpdateReceiver.onReceive(context, getIntent(diffMoreAccurateProviderLocation)); locationUpdateReceiver.onReceive(context, getIntent(significantlyLessAccurateLocation)); assertLocation(diffMoreAccurateProviderLocation); } private Intent getIntent(Location location) { Intent intent = new Intent(LOCATION_UPDATE_ACTION); intent.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); return intent; } private long offsetCurrentTimeBy(int seconds) { return currentTimeMillis() + (1000 * seconds); } private void assertLocation(Location expectedLocation) { Location actualLocation = locationUpdateReceiver.getCurrentBestLocation(); assertEquals(expectedLocation, actualLocation); } }