Files
simple/tests/test_tr_results.py
T
catarrh e0dfc1032e v3.23.5: the TERMINAL RESPONSE result list and its spec corrections
The step editor's result select (the expect's respond, the proactive-drain's
respond/first) offered five symbolic values with no hex.  It now offers the
full TS 102 223 v18.3.0 8.12.0 list (00-3F), labelled '<hex> - <alias>' (or
'<hex> - <spec name>'), plus a manual hex entry, and an optional
additional-information byte for the general result (83 02 <result> <info>,
default 00; the 8.12.2 terminal-problem values are suggested through a
datalist).

The script aliases were corrected to the spec: refused 03->22,
not_understood 04->32, modified 06->07, no_response 22->12 - a stored script
using one of them now answers with the corrected value; no_response stays
accepted for compatibility but is no longer offered by the editor.

The server's TR decode tables (_RESULT_NAMES_BASIC/_GENERAL, a GSM 11.14
mix displayed in the proactive log) are replaced by the spec table plus the
8.12.2 additional-information names; the dcs field parses as hex (0A used to
be refused and 10 read as decimal 10); the drain summary's 22 label is fixed.

The result labels are not translated (spec text); the unused RU keys were
removed.  Shared fixture frontend/tests/tr_results.json, drift-guarded by
both suites.  855 frontend + 838 Python; sw cache simple-v418.
2026-10-07 16:43:22 +03:00

90 lines
4.0 KiB
Python

#!/usr/bin/env python3
"""TERMINAL RESPONSE results (TS 102 223 v18.3.0 8.12.0/8.12.2) against the
SHARED fixture `frontend/tests/tr_results.json`: the Node suite asserts the
same file against the PWA's own tables, this suite asserts it against
`testscript.py`, so neither implementation can drift alone. Also pins the
corrected script aliases (the v3.23.5 review), the hex parsing of the
`dcs`/`additional_info` fields and the scripted TR's general result."""
import json
import pathlib
import sys
import unittest
PROJECTS = pathlib.Path(__file__).resolve().parents[2]
PY_SIM = PROJECTS / 'pysim'
if str(PY_SIM) not in sys.path:
sys.path.insert(0, str(PY_SIM))
import pysim_simple_server.server as S
import pysim_simple_server.testscript as T
FIXTURE = (pathlib.Path(__file__).resolve().parents[1]
/ 'frontend' / 'tests' / 'tr_results.json')
class TrResults(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.data = json.loads(FIXTURE.read_text(encoding='utf-8'))
def test_the_shared_result_table(self):
want = {r['v']: r['name'] for r in self.data['results']}
self.assertEqual(T.TR_RESULTS, want)
# the proactive log's decode uses the same table (a spec name, not the
# old GSM 11.14 mix)
self.assertEqual(S._tr_result_name(0x03), want['03'])
self.assertEqual(S._tr_result_name(0x20), want['20'])
def test_the_shared_additional_info_table(self):
want = {a['v']: a['name'] for a in self.data['additional_info']}
self.assertEqual(T.TR_RESULT_ADD_INFO, want)
def test_the_shared_aliases(self):
want = {k: int(v, 16) for k, v in self.data['aliases'].items()}
self.assertEqual(T.RESULT_NAMES, want)
def test_the_corrected_aliases(self):
# the v3.23.5 review: these four carried legacy (GSM 11.14) values
self.assertEqual(T.RESULT_NAMES['refused'], 0x22)
self.assertEqual(T.RESULT_NAMES['not_understood'], 0x32)
self.assertEqual(T.RESULT_NAMES['modified'], 0x07)
self.assertEqual(T.RESULT_NAMES['no_response'], 0x12)
# the common ones were already right
self.assertEqual(T.RESULT_NAMES['ok'], 0x00)
self.assertEqual(T.RESULT_NAMES['cancel'], 0x10)
self.assertEqual(T.RESULT_NAMES['timeout'], 0x12)
def test_the_tr_decode_names(self):
self.assertEqual(S._tr_result_name(0x22), 'User did not accept the proactive command')
self.assertIsNone(S._tr_result_name(0x99))
self.assertEqual(S._tr_result_add_info_name(0x20, 0x04), 'No service')
self.assertEqual(S._tr_result_add_info_name(0x21, 0x00), 'No specific cause can be given')
self.assertIsNone(S._tr_result_add_info_name(0x10, 0x04))
def test_the_respond_normalises_the_additional_info(self):
out = T.normalise_respond({'result': 'refused', 'additional_info': '0A'})
self.assertEqual(out['result'], 0x22)
self.assertEqual(out['additional_info'], 0x0A)
out = T.normalise_respond({'result': '00', 'additional_info': 4})
self.assertEqual(out['additional_info'], 4)
out = T.normalise_respond({'result': 'ok'})
self.assertNotIn('additional_info', out)
with self.assertRaises(T.ScriptError):
T.normalise_respond({'result': 'ok', 'additional_info': 'zz'})
def test_the_dcs_field_parses_as_hex(self):
# '0A' used to be refused and '10' read as decimal 10 (= 0x0A)
self.assertEqual(T.normalise_respond({'result': 'ok', 'text': 'A', 'dcs': '0A'})['dcs'], 0x0A)
self.assertEqual(T.normalise_respond({'result': 'ok', 'text': 'A', 'dcs': '10'})['dcs'], 0x10)
def test_the_scripted_tr_carries_the_additional_info(self):
tr = T.build_tr(1, 0x21, 0x81, 0x82, {'result': 0x20, 'additional_info': 0x04})
self.assertIn(bytes([0x83, 0x02, 0x20, 0x04]), tr)
tr = T.build_tr(1, 0x21, 0x81, 0x82, {'result': 0x00})
self.assertIn(bytes([0x83, 0x02, 0x00, 0x00]), tr)
if __name__ == '__main__':
unittest.main()