ui: FPLMN manual-selection clear and duplicate guard (v2.7.19)
Attaching to a PLMN listed in EF.FPLMN used to write successful locations anyway, i.e. it attached to a forbidden network. Per TS 23.122 a successful manual selection removes the entry, so the attach scenarios clear it first: - netsim.remove_fplmn() clears every occurrence of the PLMN (entries are not compacted; FFFFFF gaps stay); insert_fplmn() returns None when the PLMN is already listed, so roaming_denied no longer stores duplicates (the live card had '250-99, 250-99'). - clear_fplmn() step, called from write_real_locations() -> covers attach_eps, attach_2g and the sms_received location rewrite; the write is logged as a normal fplmn update_binary. - tests: remove_fplmn duplicates/absent/gaps; roaming_denied duplicate skip; attach clears both occurrences before the location writes; make_runner now copies FakeFileInfo so seeded data does not leak between tests. - help EN/RU and AGENTS updated.
This commit is contained in:
+50
-1
@@ -81,6 +81,20 @@ class BuilderTests(unittest.TestCase):
|
||||
self.assertEqual(netsim.fplmn_entries('FF' * 9),
|
||||
['FFFFFF', 'FFFFFF', 'FFFFFF'])
|
||||
self.assertEqual(netsim.fplmn_entries(''), [])
|
||||
# an already listed PLMN is never stored twice
|
||||
self.assertIsNone(netsim.insert_fplmn('00F110' + 'FF' * 9, '00F110'))
|
||||
self.assertIsNone(netsim.insert_fplmn('AABBCC00F110112233445566', '00F110'))
|
||||
|
||||
def test_fplmn_remove_clears_every_occurrence(self):
|
||||
# duplicates (the same VPLMN can be listed more than once) all go
|
||||
self.assertEqual(netsim.remove_fplmn('00F110' + '00F110' + 'FF' * 6, '00F110'),
|
||||
'FF' * 12)
|
||||
# gaps in other positions are preserved, the list is not compacted
|
||||
self.assertEqual(netsim.remove_fplmn('AABBCC00F110112233445566', '00F110'),
|
||||
'AABBCCFFFFFF112233445566')
|
||||
# not listed -> no write
|
||||
self.assertIsNone(netsim.remove_fplmn('AABBCC' + 'FF' * 9, '00F110'))
|
||||
self.assertIsNone(netsim.remove_fplmn('', '00F110'))
|
||||
|
||||
def test_parse_imsi_matches_the_pysim_vector(self):
|
||||
self.assertEqual(netsim.parse_imsi('082982608200002080'),
|
||||
@@ -263,7 +277,11 @@ FILES = {
|
||||
|
||||
|
||||
def make_runner(params=None, event_list=(3,), sleep=None):
|
||||
lchan = FakeLchan(dict(FILES))
|
||||
# Copy the file infos too: tests seed per-file data and must not leak it
|
||||
# into the next runner (FILES holds shared FakeFileInfo objects).
|
||||
files = {fid: FakeFileInfo(f.size, f.record_len, f.num, f.data)
|
||||
for fid, f in FILES.items()}
|
||||
lchan = FakeLchan(files)
|
||||
app = SimpleNamespace(rs=SimpleNamespace(lchan=[lchan]))
|
||||
srv = FakeSrv()
|
||||
runner = netsim.NetSimRunner(srv, app, params=params, event_list=event_list,
|
||||
@@ -321,6 +339,37 @@ class RunnerTests(unittest.TestCase):
|
||||
epsnsc = [w for w in lchan.writes if w[1] == '6FE4'][0][2]
|
||||
self.assertTrue(epsnsc.startswith('A0348001078120' + 'FF' * 32))
|
||||
|
||||
def test_roaming_denied_skips_a_duplicate_fplmn_entry(self):
|
||||
runner, lchan, srv = make_runner()
|
||||
lchan.files['6F7B'].data = '00F110' + 'FF' * 9
|
||||
out = runner.run('roaming_denied')
|
||||
self.assertTrue(out['success'])
|
||||
self.assertFalse(any(w[1] == '6F7B' for w in lchan.writes))
|
||||
self.assertTrue(any('already listed' in s.get('note', '')
|
||||
for s in out['steps']))
|
||||
|
||||
def test_attach_clears_every_fplmn_occurrence_first(self):
|
||||
runner, lchan, srv = make_runner()
|
||||
# the same VPLMN listed twice (older runs appended it again)
|
||||
lchan.files['6F7B'].data = '00F110' + '00F110' + 'FF' * 6
|
||||
out = runner.run('attach_eps')
|
||||
self.assertTrue(out['success'])
|
||||
fplmn = [w for w in lchan.writes if w[1] == '6F7B']
|
||||
self.assertEqual(len(fplmn), 1)
|
||||
self.assertEqual(fplmn[0][2], 'FF' * 12)
|
||||
# the clear happens before the successful location writes
|
||||
idx_fplmn = next(i for i, w in enumerate(lchan.writes) if w[1] == '6F7B')
|
||||
idx_loci = next(i for i, w in enumerate(lchan.writes) if w[1] == '6F7E')
|
||||
self.assertLess(idx_fplmn, idx_loci)
|
||||
for fid in ('6F7E', '6F73', '6FE3'):
|
||||
self.assertIn(fid, [w[1] for w in lchan.writes])
|
||||
|
||||
def test_attach_without_a_listed_plmn_writes_no_fplmn(self):
|
||||
runner, lchan, srv = make_runner()
|
||||
out = runner.run('attach_eps')
|
||||
self.assertTrue(out['success'])
|
||||
self.assertFalse(any(w[1] == '6F7B' for w in lchan.writes))
|
||||
|
||||
def test_roaming_denied_never_stores_the_home_plmn(self):
|
||||
runner, lchan, srv = make_runner()
|
||||
srv.net_state = {'files': {
|
||||
|
||||
Reference in New Issue
Block a user