summaryrefslogtreecommitdiff
path: root/android-app/app/src/test/kotlin/org/terst
diff options
context:
space:
mode:
Diffstat (limited to 'android-app/app/src/test/kotlin/org/terst')
-rw-r--r--android-app/app/src/test/kotlin/org/terst/nav/track/GpxRoundTripTest.kt83
-rw-r--r--android-app/app/src/test/kotlin/org/terst/nav/track/TrackSummaryTest.kt56
2 files changed, 139 insertions, 0 deletions
diff --git a/android-app/app/src/test/kotlin/org/terst/nav/track/GpxRoundTripTest.kt b/android-app/app/src/test/kotlin/org/terst/nav/track/GpxRoundTripTest.kt
new file mode 100644
index 0000000..7ed7ec7
--- /dev/null
+++ b/android-app/app/src/test/kotlin/org/terst/nav/track/GpxRoundTripTest.kt
@@ -0,0 +1,83 @@
+package org.terst.nav.track
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class GpxRoundTripTest {
+
+ private fun roundTrip(points: List<TrackPoint>): List<TrackPoint> {
+ val gpx = GpxSerializer.serialize(points, "Test Track")
+ return GpxParser.parse(gpx.byteInputStream())
+ }
+
+ @Test
+ fun `round-trip preserves lat and lon`() {
+ val pt = TrackPoint(lat = 37.8044, lon = -122.2712, sogKnots = 6.1, cogDeg = 247.0)
+ val result = roundTrip(listOf(pt)).first()
+ assertEquals(37.8044, result.lat, 0.00001)
+ assertEquals(-122.2712, result.lon, 0.00001)
+ }
+
+ @Test
+ fun `round-trip preserves sog and cog`() {
+ val pt = TrackPoint(lat = 0.0, lon = 0.0, sogKnots = 5.3, cogDeg = 183.0)
+ val result = roundTrip(listOf(pt)).first()
+ assertEquals(5.3, result.sogKnots, 0.001)
+ assertEquals(183.0, result.cogDeg, 0.001)
+ }
+
+ @Test
+ fun `round-trip preserves optional nav fields`() {
+ val pt = TrackPoint(
+ lat = 1.0, lon = 2.0, sogKnots = 4.0, cogDeg = 90.0,
+ depthMeters = 12.5, baroHpa = 1013.2, windSpeedKnots = 14.0,
+ windAngleDeg = 45.0, isTrueWind = true, waveHeightM = 1.2
+ )
+ val result = roundTrip(listOf(pt)).first()
+ assertEquals(12.5, result.depthMeters!!, 0.001)
+ assertEquals(1013.2, result.baroHpa!!, 0.001)
+ assertEquals(14.0, result.windSpeedKnots!!, 0.001)
+ assertEquals(45.0, result.windAngleDeg!!, 0.001)
+ assertTrue(result.isTrueWind)
+ assertEquals(1.2, result.waveHeightM!!, 0.001)
+ }
+
+ @Test
+ fun `round-trip with null optional fields leaves them null`() {
+ val pt = TrackPoint(lat = 0.0, lon = 0.0, sogKnots = 0.0, cogDeg = 0.0)
+ val result = roundTrip(listOf(pt)).first()
+ assertNull(result.depthMeters)
+ assertNull(result.baroHpa)
+ assertNull(result.windSpeedKnots)
+ }
+
+ @Test
+ fun `round-trip preserves multiple points in order`() {
+ val points = listOf(
+ TrackPoint(lat = 1.0, lon = 1.0, sogKnots = 1.0, cogDeg = 0.0, timestampMs = 1000L),
+ TrackPoint(lat = 2.0, lon = 2.0, sogKnots = 2.0, cogDeg = 90.0, timestampMs = 2000L),
+ TrackPoint(lat = 3.0, lon = 3.0, sogKnots = 3.0, cogDeg = 180.0, timestampMs = 3000L),
+ )
+ val result = roundTrip(points)
+ assertEquals(3, result.size)
+ assertEquals(1.0, result[0].lat, 0.00001)
+ assertEquals(2.0, result[1].lat, 0.00001)
+ assertEquals(3.0, result[2].lat, 0.00001)
+ }
+
+ @Test
+ fun `round-trip preserves timestamp`() {
+ val ts = 1712345678000L
+ val pt = TrackPoint(lat = 0.0, lon = 0.0, sogKnots = 0.0, cogDeg = 0.0, timestampMs = ts)
+ val result = roundTrip(listOf(pt)).first()
+ assertEquals(ts, result.timestampMs)
+ }
+
+ @Test
+ fun `track name with special chars is escaped`() {
+ val gpx = GpxSerializer.serialize(emptyList(), "Track & \"Fun\" <test>")
+ assertTrue(gpx.contains("Track &amp; &quot;Fun&quot; &lt;test&gt;"))
+ }
+}
diff --git a/android-app/app/src/test/kotlin/org/terst/nav/track/TrackSummaryTest.kt b/android-app/app/src/test/kotlin/org/terst/nav/track/TrackSummaryTest.kt
new file mode 100644
index 0000000..2daaf45
--- /dev/null
+++ b/android-app/app/src/test/kotlin/org/terst/nav/track/TrackSummaryTest.kt
@@ -0,0 +1,56 @@
+package org.terst.nav.track
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+class TrackSummaryTest {
+
+ private fun pt(lat: Double, lon: Double, sog: Double = 5.0, ts: Long = 0L) =
+ TrackPoint(lat = lat, lon = lon, sogKnots = sog, cogDeg = 0.0, timestampMs = ts)
+
+ @Test
+ fun `distance between two points one nm apart`() {
+ // 1 nautical mile north along the prime meridian ≈ 0.01667° latitude
+ val a = pt(0.0, 0.0, ts = 0L)
+ val b = pt(0.016667, 0.0, ts = 60_000L)
+ val s = summarise(listOf(a, b))
+ assertEquals(1.0, s.distanceNm, 0.01)
+ }
+
+ @Test
+ fun `duration is last minus first timestamp`() {
+ val points = listOf(pt(0.0, 0.0, ts = 1_000L), pt(0.0, 0.0, ts = 61_000L))
+ assertEquals(60_000L, summarise(points).durationMs)
+ }
+
+ @Test
+ fun `max sog picks highest value`() {
+ val points = listOf(pt(0.0, 0.0, sog = 4.0), pt(0.0, 0.0, sog = 9.2), pt(0.0, 0.0, sog = 6.0))
+ assertEquals(9.2, summarise(points).maxSogKt, 0.001)
+ }
+
+ @Test
+ fun `avg wind is null when no wind data`() {
+ val s = summarise(listOf(pt(0.0, 0.0)))
+ assertNull(s.avgWindKt)
+ }
+
+ @Test
+ fun `avg wind averages available readings`() {
+ val points = listOf(
+ TrackPoint(0.0, 0.0, 5.0, 0.0, windSpeedKnots = 10.0),
+ TrackPoint(0.0, 0.0, 5.0, 0.0, windSpeedKnots = 20.0),
+ )
+ assertEquals(15.0, summarise(points).avgWindKt!!, 0.001)
+ }
+
+ @Test
+ fun `avg wave height averages available readings`() {
+ val points = listOf(
+ TrackPoint(0.0, 0.0, 5.0, 0.0, waveHeightM = 1.0),
+ TrackPoint(0.0, 0.0, 5.0, 0.0, waveHeightM = 3.0),
+ )
+ assertEquals(2.0, summarise(points).avgWaveHeightM!!, 0.001)
+ }
+}