blob: 2eaaad1891f52bb51428122830dfda7b04599180 [file] [log] [blame]
Harald Welte865eea62023-01-27 19:26:12 +01001#!/usr/bin/env python3
2
3# (C) 2023 by Harald Welte <laforge@osmocom.org>
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18import unittest
19import logging
20
21from pySim.utils import *
22from pySim.filesystem import *
23
24import pySim.iso7816_4
25import pySim.ts_102_221
26import pySim.ts_102_222
27import pySim.ts_31_102
28import pySim.ts_31_103
29import pySim.ts_51_011
30import pySim.sysmocom_sja2
31import pySim.gsm_r
Harald Weltef9e2df12023-07-11 21:03:54 +020032import pySim.cdma_ruim
Harald Welte865eea62023-01-27 19:26:12 +010033
34def get_qualified_name(c):
35 """return the qualified (by module) name of a class."""
36 return "%s.%s" % (c.__module__, c.__name__)
37
38class LinFixed_Test(unittest.TestCase):
39 classes = all_subclasses(LinFixedEF)
Harald Weltee45168e2023-12-21 20:20:44 +010040 maxDiff = None
Harald Welte865eea62023-01-27 19:26:12 +010041
Harald Weltebcd26152023-12-28 09:34:05 +010042 @staticmethod
43 def _parse_t(t):
44 """Parse a test description which can either be a 2-tuple of (enc, dec) or
45 a 3-tuple of (enc, rec_nr, dec)."""
46 if len(t) == 2:
47 encoded = t[0]
48 rec_num = 1
49 decoded = t[1]
50 else:
51 encoded = t[0]
52 rec_num = t[1]
53 decoded = t[2]
54 return encoded, rec_num, decoded
55
Harald Welte865eea62023-01-27 19:26:12 +010056 def test_decode_record(self):
57 """Test the decoder for a linear-fixed EF. Requires the given LinFixedEF subclass
58 to have an '_test_decode' attribute, containing a list of tuples. Each tuple can
59 either be a
60 * 2-tuple (hexstring, decoded_dict) or a
61 * 3-tuple (hexstring, record_nr, decoded_dict)
62 """
63 for c in self.classes:
64 name = get_qualified_name(c)
65 if hasattr(c, '_test_decode'):
66 for t in c._test_decode:
67 with self.subTest(name, test_decode=t):
68 inst = c()
Harald Weltebcd26152023-12-28 09:34:05 +010069 encoded, rec_num, decoded = self._parse_t(t)
Harald Welte865eea62023-01-27 19:26:12 +010070 logging.debug("Testing decode of %s", name)
71 re_dec = inst.decode_record_hex(encoded, rec_num)
72 self.assertEqual(decoded, re_dec)
73
74 def test_encode_record(self):
75 """Test the encoder for a linear-fixed EF. Requires the given LinFixedEF subclass
76 to have an '_test_encode' attribute, containing a list of tuples. Each tuple can
77 either be a
78 * 2-tuple (hexstring, decoded_dict) or a
79 * 3-tuple (hexstring, record_nr, decoded_dict)
80 """
81 for c in self.classes:
82 name = get_qualified_name(c)
83 if hasattr(c, '_test_encode'):
84 for t in c._test_encode:
85 with self.subTest(name, test_encode=t):
86 inst = c()
Harald Weltebcd26152023-12-28 09:34:05 +010087 encoded, rec_num, decoded = self._parse_t(t)
Harald Welte865eea62023-01-27 19:26:12 +010088 logging.debug("Testing encode of %s", name)
89 re_enc = inst.encode_record_hex(decoded, rec_num)
Harald Welte2822dca2023-12-21 22:14:08 +010090 self.assertEqual(encoded.upper(), re_enc.upper())
Harald Welte865eea62023-01-27 19:26:12 +010091
92 def test_de_encode_record(self):
93 """Test the decoder and encoder for a linear-fixed EF. Performs first a decoder
94 test, and then re-encodes the decoded data, comparing the re-encoded data with the
95 initial input data.
96
97 Requires the given LinFixedEF subclass to have a '_test_de_encode' attribute,
98 containing a list of tuples. Each tuple can
99 either be a
100 * 2-tuple (hexstring, decoded_dict) or a
101 * 3-tuple (hexstring, record_nr, decoded_dict)
102 """
103 for c in self.classes:
104 name = get_qualified_name(c)
105 if hasattr(c, '_test_de_encode'):
106 for t in c._test_de_encode:
107 with self.subTest(name, test_de_encode=t):
108 inst = c()
Harald Weltebcd26152023-12-28 09:34:05 +0100109 encoded, rec_num, decoded = self._parse_t(t)
Harald Welte865eea62023-01-27 19:26:12 +0100110 logging.debug("Testing decode of %s", name)
111 re_dec = inst.decode_record_hex(encoded, rec_num)
112 self.assertEqual(decoded, re_dec)
113 # re-encode the decoded data
114 logging.debug("Testing re-encode of %s", name)
115 re_enc = inst.encode_record_hex(re_dec, rec_num)
Harald Welte2822dca2023-12-21 22:14:08 +0100116 self.assertEqual(encoded.upper(), re_enc.upper())
Harald Welte865eea62023-01-27 19:26:12 +0100117
118
119class TransRecEF_Test(unittest.TestCase):
120 classes = all_subclasses(TransRecEF)
Harald Weltee45168e2023-12-21 20:20:44 +0100121 maxDiff = None
Harald Welte865eea62023-01-27 19:26:12 +0100122
123 def test_decode_record(self):
124 """Test the decoder for a transparent record-oriented EF. Requires the given TransRecEF subclass
125 to have an '_test_decode' attribute, containing a list of tuples. Each tuple has to be a
126 2-tuple (hexstring, decoded_dict).
127 """
128 for c in self.classes:
129 name = get_qualified_name(c)
130 if hasattr(c, '_test_decode'):
131 for t in c._test_decode:
132 with self.subTest(name, test_decode=t):
133 inst = c()
134 encoded = t[0]
135 decoded = t[1]
136 logging.debug("Testing decode of %s", name)
137 re_dec = inst.decode_record_hex(encoded)
138 self.assertEqual(decoded, re_dec)
139
140 def test_encode_record(self):
141 """Test the encoder for a transparent record-oriented EF. Requires the given TransRecEF subclass
142 to have an '_test_encode' attribute, containing a list of tuples. Each tuple has to be a
143 2-tuple (hexstring, decoded_dict).
144 """
145 for c in self.classes:
146 name = get_qualified_name(c)
147 if hasattr(c, '_test_decode'):
148 for t in c._test_decode:
149 with self.subTest(name, test_decode=t):
150 inst = c()
151 encoded = t[0]
152 decoded = t[1]
153 logging.debug("Testing decode of %s", name)
154 re_dec = inst.decode_record_hex(encoded)
155 self.assertEqual(decoded, re_dec)
156
157
158 def test_de_encode_record(self):
159 """Test the decoder and encoder for a transparent record-oriented EF. Performs first a decoder
160 test, and then re-encodes the decoded data, comparing the re-encoded data with the
161 initial input data.
162
163 Requires the given TransRecEF subclass to have a '_test_de_encode' attribute,
164 containing a list of tuples. Each tuple has to be a 2-tuple (hexstring, decoded_dict).
165 """
166 for c in self.classes:
167 name = get_qualified_name(c)
168 if hasattr(c, '_test_de_encode'):
169 for t in c._test_de_encode:
170 with self.subTest(name, test_de_encode=t):
171 inst = c()
172 encoded = t[0]
173 decoded = t[1]
174 logging.debug("Testing decode of %s", name)
175 re_dec = inst.decode_record_hex(encoded)
176 self.assertEqual(decoded, re_dec)
177 # re-encode the decoded data
178 logging.debug("Testing re-encode of %s", name)
179 re_enc = inst.encode_record_hex(re_dec)
Harald Welte2822dca2023-12-21 22:14:08 +0100180 self.assertEqual(encoded.upper(), re_enc.upper())
Harald Welte865eea62023-01-27 19:26:12 +0100181
182
183class TransparentEF_Test(unittest.TestCase):
Harald Weltee45168e2023-12-21 20:20:44 +0100184 maxDiff = None
185
Harald Welte865eea62023-01-27 19:26:12 +0100186 @classmethod
187 def get_classes(cls):
188 """get list of TransparentEF sub-classes which are not a TransRecEF subclass."""
189 classes = all_subclasses(TransparentEF)
190 trans_rec_classes = all_subclasses(TransRecEF)
191 return filter(lambda c: c not in trans_rec_classes, classes)
192
193 @classmethod
194 def setUpClass(cls):
195 """set-up method called once for this class by unittest framework"""
196 cls.classes = cls.get_classes()
197
198 def test_decode_file(self):
199 """Test the decoder for a transparent EF. Requires the given TransparentEF subclass
200 to have a '_test_decode' attribute, containing a list of tuples. Each tuple
201 is a 2-tuple (hexstring, decoded_dict).
202 """
203 for c in self.classes:
204 name = get_qualified_name(c)
205 if hasattr(c, '_test_decode'):
206 for t in c._test_decode:
207 with self.subTest(name, test_decode=t):
208 inst = c()
209 encoded = t[0]
210 decoded = t[1]
211 logging.debug("Testing decode of %s", name)
212 re_dec = inst.decode_hex(encoded)
213 self.assertEqual(decoded, re_dec)
214
215 def test_encode_file(self):
216 """Test the encoder for a transparent EF. Requires the given TransparentEF subclass
217 to have a '_test_encode' attribute, containing a list of tuples. Each tuple
218 is a 2-tuple (hexstring, decoded_dict).
219 """
220 for c in self.classes:
221 name = get_qualified_name(c)
222 if hasattr(c, '_test_encode'):
223 for t in c._test_encode:
224 with self.subTest(name, test_encode=t):
225 inst = c()
226 encoded = t[0]
227 decoded = t[1]
228 logging.debug("Testing encode of %s", name)
229 re_dec = inst.decode_hex(encoded)
230 self.assertEqual(decoded, re_dec)
231
232 def test_de_encode_file(self):
233 """Test the decoder and encoder for a transparent EF. Performs first a decoder
234 test, and then re-encodes the decoded data, comparing the re-encoded data with the
235 initial input data.
236
237 Requires the given TransparentEF subclass to have a '_test_de_encode' attribute,
238 containing a list of tuples. Each tuple is a 2-tuple (hexstring, decoded_dict).
239 """
240 for c in self.classes:
241 name = get_qualified_name(c)
242 if hasattr(c, '_test_de_encode'):
243 for t in c._test_de_encode:
244 with self.subTest(name, test_de_encode=t):
245 inst = c()
246 encoded = t[0]
247 decoded = t[1]
248 logging.debug("Testing decode of %s", name)
249 re_dec = inst.decode_hex(encoded)
250 self.assertEqual(decoded, re_dec)
251 logging.debug("Testing re-encode of %s", name)
252 re_dec = inst.decode_hex(encoded)
253 re_enc = inst.encode_hex(re_dec)
Harald Welte2822dca2023-12-21 22:14:08 +0100254 self.assertEqual(encoded.upper(), re_enc.upper())
Harald Welte865eea62023-01-27 19:26:12 +0100255
256
257if __name__ == '__main__':
258 logger = logging.getLogger()
259 logger.setLevel(logging.DEBUG)
260 unittest.main()