v3.19.2: the three-status-words disambiguation (envelope SW vs por.sw)

The script author read por.sw as the envelope SW, so a por.sw expectation
on an applet's own TAR failed with (none).

- docs/test-scripts.md: a 'The three status words (envelope SW / PoR
  status / R-APDU SW)' table in the authoring section - where each one
  comes from, the script field and the report row - plus a cross-reference
  from the por check paragraph; help EN/RU 8.9 points at it.
- a failed por.sw check on a response_type: 'raw' decode carries the check
  detail 'the response is application data - an applet's own TAR has no
  R-APDU SW; assert it with data' (the PWA renders check details).
- the runner's log prints APP DATA=<hex> (no R-APDU SW) for application
  responses instead of the misleading R-APDU SW=(none) data=...; the
  compact/scripting lines are unchanged.
- the step editor's custom-PoR block gets a one-line hint about the same.
Tests: 821 frontend + 730 Python; sw cache simple-v391.
This commit is contained in:
2026-10-04 22:19:58 +03:00
parent 14c43f37b3
commit 78bc91d297
9 changed files with 88 additions and 22 deletions
+23 -10
View File
@@ -34,7 +34,7 @@ from osmocom.tlv import BER_TLV_IE
from osmocom.utils import rpad
VERSION = '3.19.1'
VERSION = '3.19.2'
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
@@ -5839,9 +5839,14 @@ def _por_check_results(spec, por, level, prefix='PoR'):
actual or '(none)', level))
if 'sw' in spec:
actual = str((por.get('decoded') or {}).get('last_status_word') or '')
checks.append(_test_check_result(
prefix + ' SW', testscript.match_value(spec['sw'], actual),
spec['sw']['value'], actual or '(none)', level))
ok = testscript.match_value(spec['sw'], actual)
detail = None
if not ok and por.get('response_type') == 'raw':
detail = ("the response is application data - an applet's own TAR "
"has no R-APDU SW; assert it with 'data'")
checks.append(_test_check_result(prefix + ' SW', ok,
spec['sw']['value'], actual or '(none)',
level, detail=detail))
if 'data' in spec:
actual = str((por.get('decoded') or {}).get('last_response_data') or '')
checks.append(_test_check_result(
@@ -6024,9 +6029,13 @@ def _test_run_scp80(server, step, ctx):
_test_log('PoR[inline] status=%s TAR=%s CNTR=%s%s raw=%s'
% (por.get('response_status'), por.get('tar'),
por.get('cntr'), extra, por.get('raw') or data))
_test_log('R-APDU SW=%s data=%s'
% (dec.get('last_status_word') or '(none)',
dec.get('last_response_data') or '(none)'))
if por.get('response_type') == 'raw':
_test_log('APP DATA=%s (no R-APDU SW)'
% (dec.get('last_response_data') or '(none)'))
else:
_test_log('R-APDU SW=%s data=%s'
% (dec.get('last_status_word') or '(none)',
dec.get('last_response_data') or '(none)'))
elif data:
_test_log('PoR[inline] undecodable raw=%s' % data)
else:
@@ -6284,9 +6293,13 @@ def _test_run_expect(server, step, pending, ctx=None):
_test_log('PoR[sms-submit] status=%s TAR=%s CNTR=%s raw=%s'
% (por.get('response_status'), por.get('tar'),
por.get('cntr'), por.get('raw') or '(none)'))
_test_log('R-APDU SW=%s data=%s'
% (dec.get('last_status_word') or '(none)',
dec.get('last_response_data') or '(none)'))
if por.get('response_type') == 'raw':
_test_log('APP DATA=%s (no R-APDU SW)'
% (dec.get('last_response_data') or '(none)'))
else:
_test_log('R-APDU SW=%s data=%s'
% (dec.get('last_status_word') or '(none)',
dec.get('last_response_data') or '(none)'))
else:
_test_log('PoR[sms-submit] none (no decodable PDU or no scp80 '
'context)')