diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt index 597946d6..4d59aef9 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt @@ -158,6 +158,12 @@ class DatabaseRepo( val all = nameToCatnum.filter { (localName, _) -> dataParser.matchesAmSatName(localName, keys) }.values.toSet() + // No local entry matches this AMSAT name (e.g. a brand-new + // satellite not yet in the local TLE, like TEVEL2/RS95S): + // skip it. Returning empty is correct — crashing here (via + // all.first()) aborted the WHOLE list update and kept the + // stale pre-whitelist FM list with all five ISS modules. + if (all.isEmpty()) return emptySet() if (all.size <= 1) return all val preferred = all.intersect(activeCatnums) if (preferred.isNotEmpty()) return preferred diff --git a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt index 14eac89c..d950a44b 100644 --- a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt +++ b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt @@ -244,6 +244,43 @@ class DatabaseRepoTest { assertEquals(setOf(25544), settingsRepo.amSatFm) } + @Test + fun `amsat fm list survives unknown satellite names and still disambiguates ISS`() = runTest(dispatcher) { + // Regression: AMSAT pages list satellites absent from the local TLE + // (TEVEL2-1..9, RS95S). resolvePerName used to crash on the empty + // match set (all.first()), aborting the WHOLE list update and keeping + // the stale pre-whitelist FM list with all five ISS modules. + val satnogsUrl = Sources.satelliteDataUrls.getValue("SatNOGS") + val localSource = FakeLocalSource() + val remoteSource = FakeRemoteSource().apply { + networkStreams[satnogsUrl] = { issModulesCsvStream() } + networkStreams[Sources.amSatLiveUrls.getValue("FM")] = { amsatFmPageWithUnknownStream() } + } + val settingsRepo = FakeSettingsRepo( + dataSources = DataSourcesSettings( + satelliteUrls = listOf(satnogsUrl), + transceiversUrls = emptyList() + ) + ).apply { amSatActive = setOf(25544) } + val repository = DatabaseRepo(dispatcher, dataParser, localSource, remoteSource, settingsRepo) + + repository.updateFromRemote() + + // No crash; ISS still collapses to the primary ZARYA (25544). + assertEquals(setOf(25544), settingsRepo.amSatFm) + } + + private fun amsatFmPageWithUnknownStream(): InputStream = """ + + + + + + + +
SatelliteUplinkDownlinkComment
ISS145.990 MHz437.800 MHz
TEVEL2-1 thru TEVEL2-9145.970 MHz436.400 MHz
RS95S(QMR-KWT-2)145.920 MHz436.950 MHz
+ """.trimIndent().byteInputStream() + private fun issModulesCsvStream(): InputStream = """ OBJECT_NAME,OBJECT_ID,EPOCH,MEAN_MOTION,ECCENTRICITY,INCLINATION,RA_OF_ASC_NODE,ARG_OF_PERICENTER,MEAN_ANOMALY,EPHEMERIS_TYPE,CLASSIFICATION_TYPE,NORAD_CAT_ID,ELEMENT_SET_NO,REV_AT_EPOCH,BSTAR,MEAN_MOTION_DOT,MEAN_MOTION_DDOT ISS (ZARYA),1998-067A,2021-11-16T12:28:09.322176,15.48582035,.0004694,51.6447,309.4881,203.6966,299.8876,0,U,25544,999,31220,.31985E-4,.1288E-4,0