filesystem: add unit tests for encoder/decoder methods

Lets add test vectors for the per-record/per-file encode/decode of
our various classes for the Elementary Files.

We keep the test vectors as class variables of the respective EF-classes
to ensure implementation and test vectors are next to each other.

The test classes then iterate over all EF subclasses and execute the
decode/encode functions using the test vectors from the class variables.

Change-Id: I02d884547f4982e0b8ed7ef21b8cda75237942e2
Related: OS#4963
diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py
index 4125f4a..3edc6e3 100644
--- a/pySim/ts_31_102.py
+++ b/pySim/ts_31_102.py
@@ -539,6 +539,7 @@
 
 # TS 31.102 Section 4.2.6
 class EF_HPPLMN(TransparentEF):
+    _test_de_encode = [ ( '05', 5 ) ]
     def __init__(self, fid='6f31', sfid=0x12, name='EF.HPPLMN', size=(1, 1),
                  desc='Higher Priority PLMN search period'):
         super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size)
@@ -595,7 +596,17 @@
 
 # TS 31.103 Section 4.2.7 - *not* the same as DF.GSM/EF.ECC!
 class EF_ECC(LinFixedEF):
-    cc_construct = Rpad(BcdAdapter(Rpad(Bytes(3))), pattern='f')
+    _test_de_encode = [
+        ( '19f1ff01', { "call_code": "911f",
+                        "service_category": { "police": True, "ambulance": False, "fire_brigade": False,
+                                              "marine_guard": False, "mountain_rescue": False,
+                                              "manual_ecall": False, "automatic_ecall": False } } ),
+        ( '19f3ff02', { "call_code": "913f",
+                        "service_category": { "police": False, "ambulance": True, "fire_brigade": False,
+                                              "marine_guard": False, "mountain_rescue": False,
+                                              "manual_ecall": False, "automatic_ecall": False } } ),
+    ]
+    cc_construct = BcdAdapter(Rpad(Bytes(3)))
     category_construct = FlagsEnum(Byte, police=1, ambulance=2, fire_brigade=3, marine_guard=4,
                                    mountain_rescue=5, manual_ecall=6, automatic_ecall=7)
     alpha_construct = GsmStringAdapter(Rpad(GreedyBytes))
@@ -633,12 +644,28 @@
 
 # TS 31.102 Section 4.2.17
 class EF_LOCI(TransparentEF):
+    _test_de_encode = [
+        ( '47d1264a62f21037211e00',
+          { "tmsi": "47d1264a", "lai": { "mcc_mnc": "262f01", "lac": "3721" },
+            "rfu": 30, "lu_status": 0 } ),
+    ]
     def __init__(self, fid='6f7e', sfid=0x0b, name='EF.LOCI', desc='Location information', size=(11, 11)):
         super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size)
         Lai = Struct('mcc_mnc'/BcdAdapter(Bytes(3)), 'lac'/HexAdapter(Bytes(2)))
         self._construct = Struct('tmsi'/HexAdapter(Bytes(4)), 'lai'/Lai, 'rfu'/Int8ub, 'lu_status'/Int8ub)
+
 # TS 31.102 Section 4.2.18
 class EF_AD(TransparentEF):
+    _test_de_encode = [
+        ( '00000002', { "ms_operation_mode": "normal",
+                        "additional_info": { "ciphering_indicator": False, "csg_display_control": False,
+                                             "prose_services": False, "extended_drx": False },
+                        "rfu": 0, "mnc_len": 2, "extensions": b'' } ),
+        ( '01000102', { "ms_operation_mode": "normal_and_specific_facilities",
+                        "additional_info": { "ciphering_indicator": True, "csg_display_control": False,
+                                             "prose_services": False, "extended_drx": False },
+                        "rfu": 0, "mnc_len": 2, "extensions": b'' } ),
+    ]
     class OP_MODE(enum.IntEnum):
         normal = 0x00
         type_approval = 0x80
@@ -739,6 +766,9 @@
 
 # TS 31.102 Section 4.2.51
 class EF_START_HFN(TransparentEF):
+    _test_de_encode = [
+        ( 'f00000f00000', { "start_cs": 15728640, "start_ps": 15728640 } ),
+    ]
     def __init__(self, fid='6f5b', sfid=0x0f, name='EF.START-HFN', size=(6, 6),
                  desc='Initialisation values for Hyperframe number', **kwargs):
         super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
@@ -746,6 +776,9 @@
 
 # TS 31.102 Section 4.2.52
 class EF_THRESHOLD(TransparentEF):
+    _test_de_encode = [
+        ( 'f01000', { "max_start": 15732736 } ),
+    ]
     def __init__(self, fid='6f5c', sfid=0x10, name='EF.THRESHOLD', size=(3, 3),
                  desc='Maximum value of START', **kwargs):
         super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
@@ -820,6 +853,9 @@
 
 # TS 31.102 Section 4.2.85
 class EF_EHPLMNPI(TransparentEF):
+    _test_de_encode = [
+        ( '02', { "presentation_ind": "display_all" } ),
+    ]
     def __init__(self, fid='6fdb', sfid=None, name='EF.EHPLMNPI', size=(1, 1),
                  desc='Equivalent HPLMN Presentation Indication', **kwargs):
         super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
@@ -905,6 +941,10 @@
 
 # TS 31.102 Section 4.2.96
 class EF_PWS(TransparentEF):
+    _test_de_encode = [
+        ( '00', { "pws_configuration": { "ignore_pws_in_hplmn_and_equivalent": False,
+                                         "ignore_pws_in_vplmn": False } } ),
+    ]
     def __init__(self, fid='6fec', sfid=None, name='EF.PWS', desc='Public Warning System', size=(1, 1), **kwargs):
         super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
         pws_config = FlagsEnum(
@@ -973,6 +1013,10 @@
 
 # TS 31.102 Section 4.4.11.7
 class EF_UAC_AIC(TransparentEF):
+    _test_de_encode = [
+        ( '03', { "uac_access_id_config": { "multimedia_priority_service": True,
+                                            "mission_critical_service": True } } ),
+    ]
     def __init__(self, fid='4f06', sfid=0x06, name='EF.UAC_AIC', size=(4, 4),
                  desc='UAC Access Identities Configuration', **kwargs):
         super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)