Run Unit Tests / nrf52-companion-smoke (push) Canceled after 0s
Run Unit Tests / nrf52-sensor-smoke (push) Canceled after 0s
Run Unit Tests / esp32-sensor-smoke (push) Canceled after 0s
Run Unit Tests / management-reports (push) Canceled after 0s
Run Unit Tests / stm32-companion-smoke (push) Canceled after 0s
Run Unit Tests / bootloader-version (push) Canceled after 0s
Run Unit Tests / test (push) Canceled after 0s
Run Unit Tests / hosted-doc-links (push) Canceled after 0s
Build and deploy Docs site to GitHub Pages / github-pages (push) Canceled after 0s
78 lines
4.2 KiB
Python
78 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Measure exact-text decoding of plausible manual Morse timing variations."""
|
|
from pathlib import Path
|
|
import unittest
|
|
from test_morse_tx import compile_run
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
class HumanMorseTimingTests(unittest.TestCase):
|
|
def test_actual_hil_sender_scheduler_decodes_human_variations_exactly(self):
|
|
code = (ROOT / "test/fixtures/morse_rx_hil_human.cpp").read_text(encoding="ascii")
|
|
output = compile_run(self, code, flags=("-DMESH_MORSE_HIL=1", "-DMESH_MORSE_MAX_WPM=240",
|
|
"-DMESH_MORSE_HIL_FAST_OFF_DEBOUNCE=1"))
|
|
rows = [line.split("\t") for line in output.splitlines()]
|
|
self.assertEqual(len(rows), 176)
|
|
unsupported = 0
|
|
for row in rows:
|
|
with self.subTest(wpm=row[0], sample_ms=row[1], timing=row[2]):
|
|
if row[:3] == ["240", "2", "spacing50"]:
|
|
# Experimental 5 ms dots at 2 ms RSSI sampling can bias the
|
|
# learned unit enough to confuse a 4.5-dot stretched letter
|
|
# gap with a word. Never claim this as an exact decode.
|
|
unsupported += 1
|
|
self.assertEqual(row[3], "FAIL")
|
|
self.assertEqual(row[4], "CQ DE TES T 73 SOS ")
|
|
else:
|
|
self.assertEqual(row[3], "PASS")
|
|
self.assertEqual(row[4], "CQ DE TEST 73 SOS ")
|
|
self.assertEqual(unsupported, 1)
|
|
|
|
def test_old_gap_thresholds_fail_tight_actual_sender_without_changing_marks(self):
|
|
code = (ROOT / "test/fixtures/morse_rx_hil_human.cpp").read_text(encoding="ascii")
|
|
source = (ROOT / "src/helpers/MorseRx.h").read_text(encoding="utf-8")
|
|
old = source.replace("gap * UnitScale >= uint32_t(gap_unit_q5) * 2UL",
|
|
"gap * 4UL * UnitScale >= uint32_t(gap_unit_q5) * 9UL").replace(
|
|
"gap * UnitScale >= uint32_t(gap_unit_q5) * 5UL",
|
|
"gap * 2UL * UnitScale >= uint32_t(gap_unit_q5) * 11UL")
|
|
self.assertNotEqual(source, old)
|
|
output = compile_run(self, code, flags=("-DMESH_MORSE_HIL=1", "-DMESH_MORSE_MAX_WPM=240",
|
|
"-DMESH_MORSE_HIL_FAST_OFF_DEBOUNCE=1"), headers={
|
|
"helpers/MorseRx.h": old,
|
|
"helpers/MorseTx.h": (ROOT / "src/helpers/MorseTx.h").read_text(encoding="utf-8")})
|
|
failures = {tuple(row[:2]): row[4] for line in output.splitlines()
|
|
if (row := line.split("\t"))[2:4] == ["tight_human", "FAIL"]}
|
|
for pair in (("25", "1"), ("25", "2"), ("120", "1"), ("120", "2")):
|
|
self.assertEqual(failures[pair], "CQ DE TEST 73 ?S ")
|
|
|
|
def actual_rows(self):
|
|
code = (ROOT / "test/fixtures/morse_rx_human.cpp").read_text(encoding="ascii")
|
|
output = compile_run(self, code)
|
|
rows = [line.split("\t") for line in output.splitlines()]
|
|
self.assertEqual(len(rows), 98)
|
|
return rows
|
|
|
|
def test_actual_decoder_supported_human_timing_is_exact_without_normalization(self):
|
|
rows = [row for row in self.actual_rows() if row[2] != "farnsworth_2_0"]
|
|
self.assertEqual(len(rows), 84)
|
|
failures = [row for row in rows if row[4] != "PASS" or row[5] != "CQ DE TEST 73 SOS "]
|
|
self.assertEqual(failures, [], "Strict human timing matrix failures:\n" +
|
|
"\n".join("\t".join(row) for row in failures))
|
|
|
|
def test_doubled_character_spacing_is_explicitly_unsupported_not_a_feature_pass(self):
|
|
# Without an explicit spacing hint, six dot units can denote either
|
|
# a stretched letter gap or a short word gap. Characterize that known
|
|
# ambiguity honestly; never count its spaced output as an exact decode.
|
|
rows = [row for row in self.actual_rows() if row[2] == "farnsworth_2_0"]
|
|
self.assertEqual(len(rows), 14)
|
|
for row in rows:
|
|
with self.subTest(wpm=row[0], sample_ms=row[1]):
|
|
self.assertEqual(row[4], "FAIL")
|
|
self.assertEqual(row[5], "C Q D E T E S T 7 3 S O S ")
|
|
self.assertNotEqual(row[5], "CQ DE TEST 73 SOS ")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|