fix(aprs): do not tell a mistyped passcode it is in receive-only mode
The previous commit derived "wants receive-only" from AprsPasscode.canTransmit, which is a boolean over four cases. Both a deliberate -1 and a mistyped passcode return false, so fixing the mis-diagnosis in one direction introduced it in the other: measured against the shipped algorithm, three entries - a passcode off by one digit, an arbitrary number, and a non-numeric entry - were all told they were connected in receive-only mode, when what they needed to hear was that the passcode does not match the callsign. classify already distinguishes these; only its ReceiveOnly case counts as a deliberate choice. A test now pins the distinction, including the fact that all four entries are equally unable to transmit - which is exactly why the boolean was not enough. Found by probe before review, not by the suite, which had no test for the reporter's use of this and still does not.
This commit is contained in:
1 parent
eb66a77cae
commit
0208a577c4
2 files changed
+32
-4
No files matched your search
@@ -127,10 +127,13 @@ class AprsReporter(
|
|||||||
}
|
}
|
||||||
val packetLine = (beacon as AprsBeacon.Result.Line).text
|
val packetLine = (beacon as AprsBeacon.Result.Line).text
|
||||||
|
|
||||||
// Receive-only is a deliberate choice, not a mistake, and has to be carried through:
|
// Receive-only is a deliberate choice and has to be told apart from a typo, because
|
||||||
// it logs in with -1 exactly as a wrong passcode does, and the server answers
|
// both log in with -1 and the server answers "unverified" to each. Classifying rather
|
||||||
// "unverified" to both.
|
// than asking canTransmit: that collapses ReceiveOnly and Mismatch into one boolean,
|
||||||
val wantsReceiveOnly = !AprsPasscode.canTransmit(cfg.callsign, cfg.passcode)
|
// so a mistyped passcode would be told it is in receive-only mode - the same
|
||||||
|
// mis-diagnosis as before, pointing the other way.
|
||||||
|
val wantsReceiveOnly =
|
||||||
|
AprsPasscode.classify(cfg.callsign, cfg.passcode) is AprsPasscode.Entry.ReceiveOnly
|
||||||
val c = client ?: AprsIsClient(
|
val c = client ?: AprsIsClient(
|
||||||
host = cfg.server,
|
host = cfg.server,
|
||||||
port = cfg.port,
|
port = cfg.port,
|
||||||
|
|||||||
@@ -64,6 +64,31 @@ class AprsPasscodeTest {
|
|||||||
assertEquals(AprsPasscode.RECEIVE_ONLY, AprsPasscode.loginValue(callsign, wrong))
|
assertEquals(AprsPasscode.RECEIVE_ONLY, AprsPasscode.loginValue(callsign, wrong))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The three-way distinction the reporter depends on, and why it must not use canTransmit for
|
||||||
|
* it: that collapses a deliberate receive-only choice and a typo into one boolean. Telling an
|
||||||
|
* operator who mistyped their passcode that they are in receive-only mode is the same
|
||||||
|
* mis-diagnosis as telling a deliberate receive-only user their passcode is wrong, pointing
|
||||||
|
* the other way.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
fun `a deliberate receive-only entry is distinguishable from a typo`() {
|
||||||
|
val deliberate = AprsPasscode.classify(callsign, "-1")
|
||||||
|
val blank = AprsPasscode.classify(callsign, "")
|
||||||
|
val typo = AprsPasscode.classify(callsign, (correct + 1).toString())
|
||||||
|
val garbage = AprsPasscode.classify(callsign, "abcde")
|
||||||
|
|
||||||
|
assertTrue(deliberate is AprsPasscode.Entry.ReceiveOnly)
|
||||||
|
assertTrue(blank is AprsPasscode.Entry.ReceiveOnly)
|
||||||
|
assertFalse("a typo must not read as receive-only", typo is AprsPasscode.Entry.ReceiveOnly)
|
||||||
|
assertFalse("garbage must not read as receive-only", garbage is AprsPasscode.Entry.ReceiveOnly)
|
||||||
|
|
||||||
|
// All four are equally unable to transmit, which is why the boolean is not enough.
|
||||||
|
for (entry in listOf("-1", "", (correct + 1).toString(), "abcde")) {
|
||||||
|
assertFalse(AprsPasscode.canTransmit(callsign, entry))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `something that is not a number is its own case`() {
|
fun `something that is not a number is its own case`() {
|
||||||
assertEquals(AprsPasscode.Entry.NotANumber, AprsPasscode.classify(callsign, "abcde"))
|
assertEquals(AprsPasscode.Entry.NotANumber, AprsPasscode.classify(callsign, "abcde"))
|
||||||
|
|||||||
Reference in new issue
Block a user