v3.23.1: the PLI dictionary defaults and the PLI codec tag fixes
An unconfigured PLI dictionary answered result-ok with no data object,
which confuses applications that expect data. The dictionary now has a
base layer of sensible defaults for the qualifiers the pinned ETSI specs
define (TS 102 223 8.x, tags per TS 101 220 V18.3.0 Table 7.23):
- location as the test network 001/01 + LAC 0000 (8.19),
- the classic test IMEI 490154203237518 as F-padded BCD (8.20) and its
IMEISV (8.74),
- language 'en' (8.45), Timing Advance (2E/AE), E-UTRAN (8.61; UTRAN +
E-UTRAN for the multiple-technology qualifier 0E),
- automatic search mode (8.75), a full battery (8.76).
An override set through /api/pli-dict wins, and clearing a field restores
its default (the PWA's Save re-renders the effective values; the GET returns
the override or the default for the full qualifier set). The date/time
qualifier stays empty so the host clock keeps answering it; the
3GPP/3GPP2-specific qualifiers (NMR, ESN, MEID, CSG/HNB, WLAN, slices,
CAG, ...) stay empty - the ETSI specs define no contents for them, and a
fabricated object would mislead the application more than no answer.
Verifying the values against the pinned tag table exposed pre-existing bugs
in the PWA's PLI inline codecs, fixed here:
- Timing Advance used C6 (a 3GPP2 tag) -> 2E/AE;
- IMEISV used 94 (the IMEI tag) -> 62/E2;
- Network Search Mode used AD (the Language tag) -> 65/E5, and its labels
were swapped ('00' Manual / '01' Automatic per 8.75);
- the battery field was a percentage where 8.76 is an enum ('00' very low
... '04' full, 'FE'/'FF');
- encImeiPli padded the odd 15th digit with 0 instead of F (TS 124 008).
Docs: help EN/RU, api.md, the guide. Tests: the defaults + the resolution
order (Python), the HTTP endpoint's defaults/override/clearing, the codec
tags/labels and a server-defaults drift guard (Node). 846 frontend +
829 Python; sw cache simple-v414.
This commit is contained in:
@@ -115,6 +115,57 @@ if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
|
||||
class PliDictHttpTests(unittest.TestCase):
|
||||
"""The PLI dictionary's defaults, overrides and clearing (v3.23.1)."""
|
||||
|
||||
def setUp(self):
|
||||
self.server = _build_http_server('127.0.0.1', 0, PysimHandler)
|
||||
self.server.log_requests = False
|
||||
self.server.app = None
|
||||
threading.Thread(target=self.server.serve_forever, daemon=True).start()
|
||||
self.port = self.server.server_address[1]
|
||||
|
||||
def tearDown(self):
|
||||
self.server.shutdown()
|
||||
self.server.server_close()
|
||||
|
||||
def _req(self, method, path, body=None):
|
||||
data = json.dumps(body).encode() if body is not None else None
|
||||
req = urllib.request.Request(
|
||||
'http://127.0.0.1:%d%s' % (self.port, path), data=data,
|
||||
headers={'Content-Type': 'application/json'}, method=method)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=5) as res:
|
||||
return res.status, json.loads(res.read() or b'{}')
|
||||
except urllib.error.HTTPError as e:
|
||||
return e.code, json.loads(e.read() or b'{}')
|
||||
|
||||
def test_defaults_overrides_and_clearing(self):
|
||||
import pysim_simple_server.server as srv
|
||||
try:
|
||||
status, resp = self._req('GET', '/api/pli-dict')
|
||||
self.assertEqual(status, 200, resp)
|
||||
self.assertEqual(resp['00'], '930500F1100000')
|
||||
self.assertEqual(resp['0A'], '630104')
|
||||
self.assertEqual(resp['03'], '') # the host clock answers it
|
||||
self.assertEqual(resp['02'], '') # no default
|
||||
status, resp = self._req('POST', '/api/pli-dict',
|
||||
{'01': '94080000000000000000'})
|
||||
self.assertEqual(status, 200, resp)
|
||||
self.assertEqual(resp['01'], '94080000000000000000')
|
||||
self.assertEqual(srv._PLI_DATA.get(0x01), '94080000000000000000')
|
||||
# clearing the field restores the default
|
||||
status, resp = self._req('POST', '/api/pli-dict', {'01': ''})
|
||||
self.assertEqual(status, 200, resp)
|
||||
self.assertEqual(resp['01'], srv.PLI_DEFAULTS[0x01])
|
||||
self.assertNotIn(0x01, srv._PLI_DATA)
|
||||
# a bad value is ignored
|
||||
status, resp = self._req('POST', '/api/pli-dict', {'01': 'ZZ'})
|
||||
self.assertEqual(resp['01'], srv.PLI_DEFAULTS[0x01])
|
||||
finally:
|
||||
srv._PLI_DATA.pop(0x01, None)
|
||||
|
||||
|
||||
class CardFreeGetTests(unittest.TestCase):
|
||||
"""Cached GETs must answer while the card lock is held.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user