Added KMLTrackExporterTest.

Part of #2383.
This commit is contained in:
Dennis Guse
2026-09-12 19:43:54 +02:00
parent d5e83cf057
commit 7505e6d693
3 changed files with 321 additions and 1 deletions
@@ -0,0 +1,131 @@
package de.dennisguse.opentracks.io.file.exporter;
import static org.junit.Assert.assertEquals;
import android.content.Context;
import android.content.Intent;
import android.os.Looper;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.GrantPermissionRule;
import androidx.test.rule.ServiceTestRule;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import de.dennisguse.opentracks.TestUtil;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.importer.ExportImportTest;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@RunWith(JUnit4.class)
public class KMLTrackExporterTest {
@Rule
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS);
@Rule
public GrantPermissionRule mGrantPermissionRule = TestUtil.createGrantPermissionRule();
private static final Context context = ApplicationProvider.getApplicationContext();
@BeforeClass
public static void preSetUp() {
// Prepare looper for Android's message queue
if (Looper.myLooper() == null) Looper.prepare();
PreferencesUtils.resetPreferences(context, true);
}
@Test
public void twoTrack_with_oneMarker() throws TimeoutException, IOException {
// given
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
.getService();
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
final Track.Id trackIdOne;
{ // first track
trackPointCreator.setClock("2020-02-02T02:02:02Z");
trackIdOne = service.startNewTrack();
Position position = ExportImportTest.sendLocation(trackPointCreator, "2020-02-02T02:02:03Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 1f);
contentProviderUtils.insertMarker(
new Marker(
null,
trackIdOne,
"Marker 1",
"Marker 1 desc",
"Marker 1 typeLocalized",
position,
null
));
service.endCurrentTrack();
}
final Track.Id trackIdTwo;
{ // second track
trackPointCreator.setClock("2022-02-02T02:02:02Z");
trackIdTwo = service.startNewTrack();
Position position = ExportImportTest.sendLocation(trackPointCreator, "2022-02-02T02:02:03Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 1f);
contentProviderUtils.insertMarker(
new Marker(
null,
trackIdTwo,
"Marker 2",
"Marker 2 desc",
"Marker 2 typeLocalized",
position,
null
));
service.endCurrentTrack();
}
// when
TrackExporter exporter = TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.createTrackExporter(context, new ContentProviderUtils(context));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
exporter.writeTrack(
List.of(contentProviderUtils.getTrack(trackIdOne), contentProviderUtils.getTrack(trackIdTwo)),
outputStream
);
// then
try (InputStream inputStreamExpected = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml23_twotracks)) {
String expectation = new String(inputStreamExpected.readAllBytes(), StandardCharsets.UTF_8);
String expectationAdjusted = expectation
.replace("ece162fb-d614-4431-9d33-eb20f8ee8e1d", contentProviderUtils.getTrack(trackIdOne).uuid().toString())
.replace("6712f4ca-3456-4739-841a-9e62760cc447", contentProviderUtils.getTrack(trackIdTwo).uuid().toString());
assertEquals(expectationAdjusted, outputStream.toString());
}
}
}
@@ -127,6 +127,7 @@ public class ExportImportTest {
@Before
public void fileSetup() throws IOException, TimeoutException {
//TODO Replace with a ByteArrayOutputStream instead of storing a file?
tmpFile = File.createTempFile("test", "test", context.getFilesDir());
tmpFileUri = Uri.fromFile(tmpFile);
@@ -769,7 +770,8 @@ public class ExportImportTest {
sensorManager.getAltitudeChangeHandler().setAggregator(aggregatorBarometer);
}
public static void sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, double altitude, Float altitudeGain) {
//TODO Use return value (for markers)
public static Position sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, double altitude, Float altitudeGain) {
Location location = new Location("mock");
location.setLatitude(latitude);
location.setLongitude(longitude);
@@ -782,5 +784,7 @@ public class ExportImportTest {
trackPointCreator.setClock(time);
trackPointCreator.getSensorManager().getGpsHandler().onDataReceived(location);
return Position.of(location, Instant.parse(time));
}
}
+185
View File
@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.3"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:opentracks="http://opentracksapp.com/xmlschemas/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/kml/2.3 http://schemas.opengis.net/kml/2.3/ogckml23.xsd
http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
<Document>
<open>1</open>
<visibility>1</visibility>
<name><![CDATA[2020-02-02T03:02+01]]></name>
<atom:generator><![CDATA[OpenTracks]]></atom:generator>
<Style id="track">
<LineStyle><color>7f0000ff</color><width>4</width></LineStyle>
<IconStyle>
<scale>1.3</scale>
<Icon />
</IconStyle>
</Style>
<Style id="waypoint"><IconStyle>
<Icon />
</IconStyle></Style>
<Schema id="schema">
<SimpleArrayField name="speed" type="float">
<displayName><![CDATA[Speed (m/s)]]></displayName>
</SimpleArrayField>
<SimpleArrayField name="power" type="float">
<displayName><![CDATA[Power (W)]]></displayName>
</SimpleArrayField>
<SimpleArrayField name="cadence" type="float">
<displayName><![CDATA[Cadence (rpm)]]></displayName>
</SimpleArrayField>
<SimpleArrayField name="heartrate" type="float">
<displayName><![CDATA[Heart rate (bpm)]]></displayName>
</SimpleArrayField>
<SimpleArrayField name="temperature" type="float">
<displayName><![CDATA[Temperature (Celsius)]]></displayName>
</SimpleArrayField>
</Schema>
<Folder>
<name><![CDATA[2020-02-02T03:02+01 Markers]]></name>
<open>1</open>
<Placemark>
<name><![CDATA[Marker 1]]></name>
<description><![CDATA[Marker 1 desc]]></description>
<TimeStamp><when>2020-02-02T03:02:03+01:00</when></TimeStamp>
<styleUrl>#waypoint</styleUrl>
<ExtendedData>
<Data name="type"><value><![CDATA[Marker 1 typeLocalized]]></value></Data>
</ExtendedData>
<Point>
<coordinates>14.001456,3.123456,1020.25</coordinates>
</Point>
</Placemark>
</Folder>
<Folder>
<name><![CDATA[2022-02-02T03:02+01 Markers]]></name>
<open>1</open>
<Placemark>
<name><![CDATA[Marker 2]]></name>
<description><![CDATA[Marker 2 desc]]></description>
<TimeStamp><when>2022-02-02T03:02:03+01:00</when></TimeStamp>
<styleUrl>#waypoint</styleUrl>
<ExtendedData>
<Data name="type"><value><![CDATA[Marker 2 typeLocalized]]></value></Data>
</ExtendedData>
<Point>
<coordinates>14.001456,3.123456,1020.25</coordinates>
</Point>
</Placemark>
</Folder>
<Folder id="tracks">
<name>Tracks</name>
<open>1</open>
<Placemark>
<name><![CDATA[2020-02-02T03:02+01]]></name>
<description><![CDATA[]]></description>
<opentracks:trackid>ece162fb-d614-4431-9d33-eb20f8ee8e1d</opentracks:trackid>
<styleUrl>#track</styleUrl>
<ExtendedData>
<Data name="activityType"><value><![CDATA[unknown]]></value></Data>
</ExtendedData>
<ExtendedData>
<Data name="type"><value><![CDATA[unknown]]></value></Data>
</ExtendedData>
<MultiTrack>
<altitudeMode>absolute</altitudeMode>
<interpolate>1</interpolate>
<Track>
<when>2020-02-02T03:02:02+01:00</when>
<coord/>
<when>2020-02-02T03:02:03+01:00</when>
<coord>14.001456 3.123456 1020.25</coord>
<when>2020-02-02T03:02:03+01:00</when>
<coord/>
<ExtendedData>
<SchemaData schemaUrl="#schema">
<SimpleArrayData name="trackpoint_type">
<value>SEGMENT_START_MANUAL</value>
<value>TRACKPOINT</value>
<value>SEGMENT_END_MANUAL</value>
</SimpleArrayData>
<SimpleArrayData name="speed">
<value />
<value>15</value>
<value />
</SimpleArrayData>
<SimpleArrayData name="elevation_gain">
<value />
<value>1</value>
<value>1</value>
</SimpleArrayData>
<SimpleArrayData name="elevation_loss">
<value />
<value>1</value>
<value>1</value>
</SimpleArrayData>
<SimpleArrayData name="accuracy_horizontal">
<value />
<value>10</value>
<value />
</SimpleArrayData>
</SchemaData>
</ExtendedData>
</Track>
</MultiTrack>
</Placemark>
<Placemark>
<name><![CDATA[2022-02-02T03:02+01]]></name>
<description><![CDATA[]]></description>
<opentracks:trackid>6712f4ca-3456-4739-841a-9e62760cc447</opentracks:trackid>
<styleUrl>#track</styleUrl>
<ExtendedData>
<Data name="activityType"><value><![CDATA[unknown]]></value></Data>
</ExtendedData>
<ExtendedData>
<Data name="type"><value><![CDATA[unknown]]></value></Data>
</ExtendedData>
<MultiTrack>
<altitudeMode>absolute</altitudeMode>
<interpolate>1</interpolate>
<Track>
<when>2022-02-02T03:02:02+01:00</when>
<coord/>
<when>2022-02-02T03:02:03+01:00</when>
<coord>14.001456 3.123456 1020.25</coord>
<when>2022-02-02T03:02:03+01:00</when>
<coord/>
<ExtendedData>
<SchemaData schemaUrl="#schema">
<SimpleArrayData name="trackpoint_type">
<value>SEGMENT_START_MANUAL</value>
<value>TRACKPOINT</value>
<value>SEGMENT_END_MANUAL</value>
</SimpleArrayData>
<SimpleArrayData name="speed">
<value />
<value>15</value>
<value />
</SimpleArrayData>
<SimpleArrayData name="elevation_gain">
<value />
<value>1</value>
<value>1</value>
</SimpleArrayData>
<SimpleArrayData name="elevation_loss">
<value />
<value>1</value>
<value>1</value>
</SimpleArrayData>
<SimpleArrayData name="accuracy_horizontal">
<value />
<value>10</value>
<value />
</SimpleArrayData>
</SchemaData>
</ExtendedData>
</Track>
</MultiTrack>
</Placemark>
</Folder>
</Document>
</kml>