v3.18.0: the semantic event action for test scripts
The other-applet batch: a test script can send the common event downloads semantically instead of raw hex. - events.py: server-side mirrors of the PWA's event forms for Location status (0x03), Access technology change (0x0B), Network rejection (0x12 - the LA/RA/TA object selected by the registration group, the extended EMM cause and the extended information object) and Data connection status change (0x1D - status/type/TI plus the optional cause, host-clock 8.39 date-time, location information, access technology, APN and PDP/PDN/PDU type). Fields are validated before the run (a bad value is a script error, not a step failure); `src` overrides the device-identities source (default terminal, matching the Phone forms). - The engine gains the `event` action kind; the runner builds and sends it. The PWA's action-kind list stays in sync (drift-guarded - the guard itself caught its own regex bug on the first run). - Byte parity: the vectors are generated from the PWA's own builders and pinned in tests/test_events.py; the frontend suites assert the same values. PLMN and SCTS helpers are mirrored too. - The Phone tab's event form shows the built "Event data (hex)" (updated as the fields change), so every event without a builder can be used through the raw `envelope` action. - The test-step editor offers the event select + a JSON fields textarea; malformed JSON refuses the save with a clear message. - docs/test-scripts.md (the semantic-event table, an event example, the format stamp), docs/api.md and help EN/RU updated. Tests: 812 frontend + 717 Python; sw cache simple-v381.
This commit is contained in:
@@ -23,6 +23,8 @@ import re
|
||||
|
||||
import gsm0338 # registers the 'gsm03.38' codec (the default alphabet coding)
|
||||
|
||||
from pysim_simple_server import events
|
||||
|
||||
__all__ = [
|
||||
'ScriptError', 'ACTION_KINDS', 'FAIL_LEVELS', 'POR_CHECKS', 'RESULT_NAMES',
|
||||
'normalise_script', 'normalise_step', 'normalise_respond',
|
||||
@@ -30,8 +32,8 @@ __all__ = [
|
||||
'pack_gsm7',
|
||||
]
|
||||
|
||||
ACTION_KINDS = ('envelope', 'menu-select', 'file-write', 'file-read', 'apdu',
|
||||
'scp80', 'status')
|
||||
ACTION_KINDS = ('envelope', 'event', 'menu-select', 'file-write', 'file-read',
|
||||
'apdu', 'scp80', 'status')
|
||||
FAIL_LEVELS = ('error', 'warning')
|
||||
POR_CHECKS = ('none', 'ok', 'any')
|
||||
|
||||
@@ -218,6 +220,31 @@ def _normalise_params(kind, p):
|
||||
raise ScriptError('envelope: event is required')
|
||||
return {'event': _int(p['event'], 'envelope event', 0, 255),
|
||||
'data': _data_hex(p.get('data'), 'envelope data', allow_empty=True)}
|
||||
if kind == 'event':
|
||||
# The semantic event download: the builder owns the field set and the
|
||||
# byte layout (events.py mirrors the PWA's forms for the supported
|
||||
# events; every other event uses the raw `envelope` action).
|
||||
code = events.resolve_event(p.get('event'))
|
||||
if code is None:
|
||||
raise ScriptError('event: a supported event name or a hex byte is '
|
||||
'required (supported: %s)'
|
||||
% ', '.join('%s/0x%02X' % (events.event_name(c), c)
|
||||
for c in sorted(events.BUILDERS)))
|
||||
raw = p.get('fields')
|
||||
if raw is not None and not isinstance(raw, dict):
|
||||
raise ScriptError('event: fields must be an object')
|
||||
try:
|
||||
fields = events.normalise(code, raw or {})
|
||||
except events.EventError as e:
|
||||
raise ScriptError('event 0x%02X: %s' % (code, e))
|
||||
out = {'event': code, 'fields': fields}
|
||||
src = str(p.get('src') or '').strip().upper()
|
||||
if src:
|
||||
if not re.fullmatch(r'[0-9A-F]{2}', src):
|
||||
raise ScriptError('event: src must be one hex byte '
|
||||
'(82 terminal / 83 network)')
|
||||
out['src'] = src
|
||||
return out
|
||||
if kind == 'menu-select':
|
||||
# The item is named by its id, or by its text - the id varies with the
|
||||
# applet's install parameters, so a script can match the text the card
|
||||
|
||||
Reference in New Issue
Block a user