Skip to content

Commit

Permalink
Add a test for barometric height and some code simplification
Browse files Browse the repository at this point in the history
  • Loading branch information
simonpoole committed Sep 19, 2023
1 parent 55afe48 commit 7f751d7
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 82 deletions.
2 changes: 1 addition & 1 deletion src/androidTest/java/de/blau/android/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ public static void scrollTo(@NonNull String text, boolean fail) {
}
}
}

/**
* Scroll to a specific text
*
Expand Down
192 changes: 192 additions & 0 deletions src/androidTest/java/de/blau/android/gpx/GpxBarometerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package de.blau.android.gpx;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import de.blau.android.App;
import de.blau.android.Logic;
import de.blau.android.Main;
import de.blau.android.Map;
import de.blau.android.MockTileServer;
import de.blau.android.R;
import de.blau.android.SignalHandler;
import de.blau.android.TestUtils;
import de.blau.android.layer.LayerType;
import de.blau.android.prefs.AdvancedPrefDatabase;
import de.blau.android.prefs.Preferences;
import de.blau.android.resources.TileLayerDatabase;
import de.blau.android.services.TrackerService;
import okhttp3.mockwebserver.MockWebServer;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class GpxBarometerTest {

public static final int TIMEOUT = 180;

Main main = null;
UiDevice device = null;
Instrumentation instrumentation = null;
MockWebServer tileServer = null;
Preferences prefs = null;

/**
* Manual start of activity so that we can set up the monitor for main
*/
@Rule
public ActivityScenarioRule<Main> activityScenarioRule = new ActivityScenarioRule<>(Main.class);

/**
* Pre-test setup
*/
@Before
public void setup() {
instrumentation = InstrumentationRegistry.getInstrumentation();
device = UiDevice.getInstance(instrumentation);
// this sets the mock location permission
instrumentation.getUiAutomation().executeShellCommand("appops set de.blau.android android:mock_location allow");

prefs = App.getPreferences(instrumentation.getTargetContext());
prefs.setGpsDistance(0);
prefs.enableBarometricHeight(true); // this needs to be set before TrackerService is created

ActivityMonitor monitor = instrumentation.addMonitor(Main.class.getName(), null, false);
ActivityScenario.launch(Main.class);

main = (Main) instrumentation.waitForMonitorWithTimeout(monitor, 30000);
instrumentation.removeMonitor(monitor);

tileServer = MockTileServer.setupTileServer(main, "ersatz_background.mbt", true);

Logic logic = App.getLogic();
Map map = main.getMap();

App.getDelegator().reset(true);
try (AdvancedPrefDatabase db = new AdvancedPrefDatabase(main)) {
db.deleteLayer(LayerType.GPX, null);
}

TestUtils.grantPermissons(device);
TestUtils.dismissStartUpDialogs(device, main);
TestUtils.stopEasyEdit(main);
TestUtils.zoomToNullIsland(logic, map);
}

/**
* Post-test teardown
*/
@After
public void teardown() {
instrumentation.waitForIdleSync();
prefs.enableBarometricHeight(false);
try {
tileServer.close();
} catch (IOException | NullPointerException e) {
// ignore
}
if (main != null) {
try (AdvancedPrefDatabase db = new AdvancedPrefDatabase(main)) {
db.deleteLayer(LayerType.GPX, null);
}
TestUtils.stopEasyEdit(main);
main.deleteDatabase(TileLayerDatabase.DATABASE_NAME);
main.finish();
} else {
System.out.println("main is null");
}
}

/**
* Turn on using barometric height, calibrate default pressure at sea level to -100m
*/
// @SdkSuppress(minSdkVersion = 26)
@Test
public void recordWithBarometricElevation() {
Intent intent = new Intent(main, TrackerService.class);
intent.putExtra(TrackerService.CALIBRATE_KEY, true);
intent.putExtra(TrackerService.CALIBRATE_HEIGHT_KEY, -100);
main.bindService(intent, main, Context.BIND_AUTO_CREATE);

main.startService(intent);
//
TestUtils.setupMockLocation(main, Criteria.ACCURACY_FINE);
// wait for the trackerservice to start
// unluckily there doesn't seem to be any elegant way to do this
int retries = 0;
synchronized (device) {
while (main.getTracker() == null && retries < 60) {
try {
device.wait(1000);
} catch (InterruptedException e) {
// Ignore
}
retries++;
if (retries >= 60) {
fail("Tracker service didn't start");
}
}
}

TestUtils.zoomToLevel(device, main, 19);
TestUtils.clickButton(device, device.getCurrentPackageName() + ":id/follow", false);

ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("short.gpx");
Track track = new Track(main, false);
track.importFromGPX(is);

// set a different current location so that the first point always gets recorded
int trackSize = track.getTrackPoints().size();
TrackPoint startPoint = track.getTrackPoints().get(trackSize / 2);
Location loc = new Location(LocationManager.GPS_PROVIDER);
loc.setLatitude(startPoint.getLatitude());
loc.setLongitude(startPoint.getLongitude());
main.getTracker().updateLocation(loc);
TestUtils.sleep();
main.invalidateOptionsMenu();

GpxTest.clickGpsButton(device);
assertTrue(TestUtils.clickText(device, false, main.getString(R.string.menu_gps_start), false, false));
GpxTest.clickAwayTip(device, main);

final CountDownLatch signal = new CountDownLatch(1);
main.getTracker().getTrack().reset(); // clear out anything saved
TestUtils.injectLocation(main, track.getTrackPoints(), Criteria.ACCURACY_FINE, 1000, new SignalHandler(signal));
try {
signal.await(TIMEOUT, TimeUnit.SECONDS);
} catch (InterruptedException e) {
fail(e.getMessage());
}
GpxTest.clickGpsButton(device);
assertTrue(TestUtils.clickText(device, false, main.getString(R.string.menu_gps_pause), true, false));

TrackPoint recorded = main.getTracker().getTrack().getTrackPoints().get(1);
assertTrue(recorded.hasAltitude());
assertEquals(-105f, recorded.getAltitude(), 1f);
}
}
53 changes: 23 additions & 30 deletions src/androidTest/java/de/blau/android/gpx/GpxTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
Expand Down Expand Up @@ -68,9 +67,6 @@ public class GpxTest {
MockWebServer tileServer = null;
Preferences prefs = null;

/**
* Manual start of activity so that we can set up the monitor for main
*/
@Rule
public ActivityTestRule<Main> mActivityRule = new ActivityTestRule<>(Main.class);

Expand All @@ -87,11 +83,12 @@ public void setup() {
main = mActivityRule.getActivity();

tileServer = MockTileServer.setupTileServer(main, "ersatz_background.mbt", true);
prefs = new Preferences(main);
prefs = App.getPreferences(main);
Logic logic = App.getLogic();
logic.setPrefs(prefs);
Map map = main.getMap();
map.setPrefs(main, prefs);
prefs.enableBarometricHeight(false);

App.getDelegator().reset(true);
try (AdvancedPrefDatabase db = new AdvancedPrefDatabase(main)) {
Expand Down Expand Up @@ -136,20 +133,7 @@ public void recordSaveAndImportGpx() {
TestUtils.setupMockLocation(main, Criteria.ACCURACY_FINE);
// wait for the trackerservice to start
// unluckily there doesn't seem to be any elegant way to do this
int retries = 0;
synchronized (device) {
while (main.getTracker() == null && retries < 60) {
try {
device.wait(1000);
} catch (InterruptedException e) {
// Ignore
}
retries++;
if (retries >= 60) {
fail("Tracker service didn't start");
}
}
}
checkTracker();
// set min distance to 1m
prefs.setGpsDistance(0);

Expand Down Expand Up @@ -181,7 +165,7 @@ public void recordSaveAndImportGpx() {
try {
signal.await(TIMEOUT, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Assert.fail(e.getMessage());
fail(e.getMessage());
}
clickGpsButton(device);
assertTrue(TestUtils.clickText(device, false, main.getString(R.string.menu_gps_pause), true, false));
Expand Down Expand Up @@ -234,14 +218,9 @@ public void recordSaveAndImportGpx() {
}

/**
* Start recording, pause resume, clear
* Wait until the tracker is available
*/
// @SdkSuppress(minSdkVersion = 26)
@Test
public void recordPauseAndResume() {
TestUtils.setupMockLocation(main, Criteria.ACCURACY_FINE);
// wait for the trackerservice to start
// unluckily there doesn't seem to be any elegant way to do this
private void checkTracker() {
int retries = 0;
synchronized (device) {
while (main.getTracker() == null && retries < 60) {
Expand All @@ -256,6 +235,19 @@ public void recordPauseAndResume() {
}
}
}
}

/**
* Start recording, pause resume, clear
*/
// @SdkSuppress(minSdkVersion = 26)
@Test
public void recordPauseAndResume() {
TestUtils.setupMockLocation(main, Criteria.ACCURACY_FINE);
// wait for the trackerservice to start
// unluckily there doesn't seem to be any elegant way to do this
int retries = 0;
checkTracker();
// set min distance to 1m
prefs.setGpsDistance(0);

Expand Down Expand Up @@ -287,7 +279,7 @@ public void recordPauseAndResume() {
try {
signal.await(TIMEOUT, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Assert.fail(e.getMessage());
fail(e.getMessage());
}
clickGpsButton(device);
assertTrue(TestUtils.clickText(device, false, main.getString(R.string.menu_gps_pause), true, false));
Expand Down Expand Up @@ -358,11 +350,14 @@ public void importWayPoints() {
@Test
public void followNetworkLocation() {
TestUtils.setupMockLocation(main, Criteria.ACCURACY_COARSE);
checkTracker();
// set min distance to 1m
prefs.setGpsDistance(0);

TestUtils.zoomToLevel(device, main, 19);
TestUtils.clickButton(device, device.getCurrentPackageName() + ":id/follow", false);
assertTrue(main.getFollowGPS());

ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("20110513_121244-tp.gpx");
Track track = new Track(main, false);
Expand All @@ -371,8 +366,6 @@ public void followNetworkLocation() {
final CountDownLatch signal = new CountDownLatch(1);
TestUtils.injectLocation(main, track.getTrackPoints(), Criteria.ACCURACY_COARSE, 1000, new SignalHandler(signal));
TestUtils.sleep(TIMEOUT * 1000L);
clickGpsButton(device);
assertTrue(TestUtils.clickText(device, false, "Pause GPX track", true, false));
// compare roughly with last location
TrackPoint lastPoint = track.getTrackPoints().get(track.getTrackPoints().size() - 1);
ViewBox box = main.getMap().getViewBox();
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/de/blau/android/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2160,17 +2160,21 @@ public void onError(String message) {
tipKeys.add(R.string.tip_gpx_no_elevation_key);
tipMessageIds.add(R.string.tip_gpx_no_elevation);
}
Tip.showDialog(Main.this, tipKeys, tipMessageIds);
if (haveTracker && haveLocationProvider(getEnabledLocationProviders(), LocationManager.GPS_PROVIDER)) {
getTracker().startTracking();
setFollowGPS(true);
}
addGpxLayer();
mapLayout.post(() -> {
triggerMenuInvalidation();
Tip.showDialog(Main.this, tipKeys, tipMessageIds);
});
return true;
case R.id.menu_gps_pause:
if (haveTracker && haveLocationProvider(getEnabledLocationProviders(), LocationManager.GPS_PROVIDER)) {
getTracker().stopTracking(false);
}
mapLayout.post(() -> triggerMenuInvalidation());
return true;
case R.id.menu_gps_clear:
if (haveTracker) {
Expand Down Expand Up @@ -2745,7 +2749,6 @@ private void addGpxLayer() {
} else {
Log.e(DEBUG_TAG, "addGpxLayer tracker not available");
}
triggerMenuInvalidation();
}

/**
Expand Down Expand Up @@ -2928,6 +2931,7 @@ private List<String> getEnabledLocationProviders() {
* @param follow if true center on current location
*/
public synchronized void setFollowGPS(boolean follow) {
Log.d(DEBUG_TAG, "Set follow GPS " + follow);
if (followGPS != follow) {
followGPS = follow;
if (follow) {
Expand Down Expand Up @@ -4164,6 +4168,7 @@ public static void prepareRedownload() {
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(DEBUG_TAG, "Service " + name.getClassName() + " connected");
if (TrackerService.class.getCanonicalName().equals(name.getClassName())) {
Log.i(DEBUG_TAG, "Setting up tracker");
setTracker((((TrackerBinder) service).getService()));
map.setTracker(getTracker());
de.blau.android.layer.gpx.MapOverlay layer = (de.blau.android.layer.gpx.MapOverlay) map.getLayer(LayerType.GPX,
Expand Down Expand Up @@ -4193,6 +4198,7 @@ public void onServiceDisconnected(ComponentName name) {

@Override
public void onLocationChanged(Location location) {
Log.d(DEBUG_TAG, "follow " + followGPS + " " + location);
if (followGPS) {
ViewBox viewBox = map.getViewBox();
// ensure the view is zoomed in to at least the most zoomed-out
Expand Down
Loading

0 comments on commit 7f751d7

Please sign in to comment.