v3.28.4: the Custom-mode FCI editor + the shared ADM pattern
The profile rule editor rendered the same "FCI hex (raw SELECT response)" field for Exact and Custom, although the custom check never reads `fciHex` (it compares the data objects against the card's live FCI) - so the field looked like an expectation it was not. - The raw-FCI field and its decoded preview are exact-mode-only now; the Custom mode shows just its data-object editor. - Switching a rule to Custom seeds the data objects from its captured FCI when the list is empty (the same all-'value' seeding a captured profile gets); the "load from the captured FCI" link refills an emptied list, and a rule without a captured FCI still starts empty for manual rows. From the v3.28.3 review: the ADM's byte-pair rule now lives in one place, presets.ADM_PATTERN, used by /api/verify-adm and the outfile import - two literals could drift and an imported ADM could silently become unverifiable. The RU help's ADM wording is "4-16 hex-цифр (чётное число)". Docs: help EN/RU, the repo AGENTS. Tests: the mode switch (seed / keep / no FCI / switch-away), the field-gating source pin, the pattern's shape and the both-users pin. 917 frontend + 927 Python; sw cache simple-v442.
This commit is contained in:
@@ -9,6 +9,7 @@ without silently destroying it.
|
||||
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
@@ -610,5 +611,24 @@ class StoreInfoTests(unittest.TestCase):
|
||||
self.assertEqual(presets.default_path().parent.name, '.pysim-simple-server')
|
||||
|
||||
|
||||
class AdmPatternTests(unittest.TestCase):
|
||||
"""The ADM's shared shape (v3.28.3 review): one constant, used by both the
|
||||
outfile import and /api/verify-adm - two literals would drift and an
|
||||
imported ADM could silently become unverifiable."""
|
||||
|
||||
def test_the_pattern_is_byte_pairs_of_4_to_16_digits(self):
|
||||
for ok in ('1234', '3632333239463337', 'CFA3DD9C6B7F0F8C', '1a2b'):
|
||||
self.assertIsNotNone(re.fullmatch(presets.ADM_PATTERN, ok.upper()), ok)
|
||||
for bad in ('123', '12345', 'AB' * 9, 'ZZZZ', ''):
|
||||
self.assertIsNone(re.fullmatch(presets.ADM_PATTERN, bad), bad)
|
||||
|
||||
def test_both_users_reference_the_constant(self):
|
||||
root = pathlib.Path(__file__).resolve().parents[1]
|
||||
for rel in ('pysim_simple_server/outfile.py', 'pysim_simple_server/server.py'):
|
||||
src = (root / rel).read_text(encoding='utf-8')
|
||||
self.assertIn('presets.ADM_PATTERN', src)
|
||||
self.assertNotIn(r"'(?:[0-9A-F]{2}){2,8}'", src)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user