2 # PyDERASN -- Python ASN.1 DER codec with abstract structures
3 # Copyright (C) 2017-2018 Sergey Matveev <stargrave@stargrave.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this program. If not, see
17 # <http://www.gnu.org/licenses/>.
19 from datetime import datetime
20 from string import ascii_letters
21 from string import printable
22 from string import whitespace
23 from unittest import TestCase
25 from hypothesis import assume
26 from hypothesis import given
27 from hypothesis import settings
28 from hypothesis.strategies import binary
29 from hypothesis.strategies import booleans
30 from hypothesis.strategies import composite
31 from hypothesis.strategies import data as data_strategy
32 from hypothesis.strategies import datetimes
33 from hypothesis.strategies import dictionaries
34 from hypothesis.strategies import integers
35 from hypothesis.strategies import just
36 from hypothesis.strategies import lists
37 from hypothesis.strategies import none
38 from hypothesis.strategies import one_of
39 from hypothesis.strategies import permutations
40 from hypothesis.strategies import sampled_from
41 from hypothesis.strategies import sets
42 from hypothesis.strategies import text
43 from hypothesis.strategies import tuples
44 from six import assertRaisesRegex
45 from six import byte2int
46 from six import indexbytes
47 from six import int2byte
48 from six import iterbytes
50 from six import text_type
52 from pyderasn import _pp
53 from pyderasn import abs_decode_path
54 from pyderasn import Any
55 from pyderasn import BitString
56 from pyderasn import BMPString
57 from pyderasn import Boolean
58 from pyderasn import BoundsError
59 from pyderasn import Choice
60 from pyderasn import DecodeError
61 from pyderasn import DecodePathDefBy
62 from pyderasn import Enumerated
63 from pyderasn import GeneralizedTime
64 from pyderasn import GeneralString
65 from pyderasn import GraphicString
66 from pyderasn import hexdec
67 from pyderasn import hexenc
68 from pyderasn import IA5String
69 from pyderasn import Integer
70 from pyderasn import InvalidLength
71 from pyderasn import InvalidOID
72 from pyderasn import InvalidValueType
73 from pyderasn import len_decode
74 from pyderasn import len_encode
75 from pyderasn import NotEnoughData
76 from pyderasn import Null
77 from pyderasn import NumericString
78 from pyderasn import ObjectIdentifier
79 from pyderasn import ObjNotReady
80 from pyderasn import ObjUnknown
81 from pyderasn import OctetString
82 from pyderasn import pp_console_row
83 from pyderasn import pprint
84 from pyderasn import PrintableString
85 from pyderasn import Sequence
86 from pyderasn import SequenceOf
87 from pyderasn import Set
88 from pyderasn import SetOf
89 from pyderasn import tag_ctxc
90 from pyderasn import tag_ctxp
91 from pyderasn import tag_decode
92 from pyderasn import tag_encode
93 from pyderasn import tag_strip
94 from pyderasn import TagClassApplication
95 from pyderasn import TagClassContext
96 from pyderasn import TagClassPrivate
97 from pyderasn import TagClassUniversal
98 from pyderasn import TagFormConstructed
99 from pyderasn import TagFormPrimitive
100 from pyderasn import TagMismatch
101 from pyderasn import TeletexString
102 from pyderasn import UniversalString
103 from pyderasn import UTCTime
104 from pyderasn import UTF8String
105 from pyderasn import VideotexString
106 from pyderasn import VisibleString
109 settings.register_profile('local', settings(
111 perform_health_check=False,
113 settings.load_profile('local')
114 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
116 tag_classes = sampled_from((
122 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
125 class TestHex(TestCase):
127 def test_symmetric(self, data):
128 self.assertEqual(hexdec(hexenc(data)), data)
131 class TestTagCoder(TestCase):
132 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
136 integers(min_value=0, max_value=30),
139 def test_short(self, klass, form, num, junk):
140 raw = tag_encode(klass=klass, form=form, num=num)
141 self.assertEqual(tag_decode(raw), (klass, form, num))
142 self.assertEqual(len(raw), 1)
144 byte2int(tag_encode(klass=klass, form=form, num=0)),
145 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
147 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
148 self.assertSequenceEqual(stripped.tobytes(), raw)
149 self.assertEqual(tlen, len(raw))
150 self.assertSequenceEqual(tail, junk)
152 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
156 integers(min_value=31),
159 def test_long(self, klass, form, num, junk):
160 raw = tag_encode(klass=klass, form=form, num=num)
161 self.assertEqual(tag_decode(raw), (klass, form, num))
162 self.assertGreater(len(raw), 1)
164 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
167 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
168 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
169 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
170 self.assertSequenceEqual(stripped.tobytes(), raw)
171 self.assertEqual(tlen, len(raw))
172 self.assertSequenceEqual(tail, junk)
174 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
175 @given(integers(min_value=31))
176 def test_unfinished_tag(self, num):
177 raw = bytearray(tag_encode(num=num))
178 for i in range(1, len(raw)):
180 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
181 tag_strip(bytes(raw))
183 def test_go_vectors_valid(self):
184 for data, (eklass, etag, elen, eform) in (
185 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
186 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
187 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
188 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
189 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
190 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
191 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
192 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
193 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
194 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
196 tag, _, len_encoded = tag_strip(memoryview(data))
197 klass, form, num = tag_decode(tag)
198 _len, _, tail = len_decode(len_encoded)
199 self.assertSequenceEqual(tail, b"")
200 self.assertEqual(klass, eklass)
201 self.assertEqual(num, etag)
202 self.assertEqual(_len, elen)
203 self.assertEqual(form, eform)
205 def test_go_vectors_invalid(self):
213 with self.assertRaises(DecodeError):
214 _, _, len_encoded = tag_strip(memoryview(data))
215 len_decode(len_encoded)
218 integers(min_value=0, max_value=127),
219 integers(min_value=0, max_value=2),
221 def test_long_instead_of_short(self, l, dummy_num):
222 octets = (b"\x00" * dummy_num) + int2byte(l)
223 octets = int2byte((dummy_num + 1) | 0x80) + octets
224 with self.assertRaises(DecodeError):
228 class TestLenCoder(TestCase):
229 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
231 integers(min_value=0, max_value=127),
234 def test_short(self, l, junk):
235 raw = len_encode(l) + junk
236 decoded, llen, tail = len_decode(memoryview(raw))
237 self.assertEqual(decoded, l)
238 self.assertEqual(llen, 1)
239 self.assertEqual(len(raw), 1 + len(junk))
240 self.assertEqual(tail.tobytes(), junk)
242 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
244 integers(min_value=128),
247 def test_long(self, l, junk):
248 raw = len_encode(l) + junk
249 decoded, llen, tail = len_decode(memoryview(raw))
250 self.assertEqual(decoded, l)
251 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
252 self.assertEqual(llen, len(raw) - len(junk))
253 self.assertNotEqual(indexbytes(raw, 1), 0)
254 self.assertSequenceEqual(tail.tobytes(), junk)
256 def test_empty(self):
257 with self.assertRaises(NotEnoughData):
260 @given(integers(min_value=128))
261 def test_stripped(self, _len):
262 with self.assertRaises(NotEnoughData):
263 len_decode(len_encode(_len)[:-1])
266 text_printable = text(alphabet=printable, min_size=1)
270 def text_letters(draw):
271 result = draw(text(alphabet=ascii_letters, min_size=1))
273 result = result.encode("ascii")
277 class CommonMixin(object):
278 def test_tag_default(self):
279 obj = self.base_klass()
280 self.assertEqual(obj.tag, obj.tag_default)
282 def test_simultaneous_impl_expl(self):
283 with self.assertRaises(ValueError):
284 self.base_klass(impl=b"whatever", expl=b"whenever")
286 @given(binary(), integers(), integers(), integers())
287 def test_decoded(self, impl, offset, llen, vlen):
288 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
289 self.assertEqual(obj.offset, offset)
290 self.assertEqual(obj.llen, llen)
291 self.assertEqual(obj.vlen, vlen)
292 self.assertEqual(obj.tlen, len(impl))
293 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
296 def test_impl_inherited(self, impl_tag):
297 class Inherited(self.base_klass):
300 self.assertSequenceEqual(obj.impl, impl_tag)
301 self.assertFalse(obj.expled)
304 def test_expl_inherited(self, expl_tag):
305 class Inherited(self.base_klass):
308 self.assertSequenceEqual(obj.expl, expl_tag)
309 self.assertTrue(obj.expled)
311 def assert_copied_basic_fields(self, obj, obj_copied):
312 self.assertEqual(obj, obj_copied)
313 self.assertSequenceEqual(obj.tag, obj_copied.tag)
314 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
315 self.assertEqual(obj.default, obj_copied.default)
316 self.assertEqual(obj.optional, obj_copied.optional)
317 self.assertEqual(obj.offset, obj_copied.offset)
318 self.assertEqual(obj.llen, obj_copied.llen)
319 self.assertEqual(obj.vlen, obj_copied.vlen)
323 def boolean_values_strategy(draw, do_expl=False):
324 value = draw(one_of(none(), booleans()))
328 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
330 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
331 default = draw(one_of(none(), booleans()))
332 optional = draw(one_of(none(), booleans()))
334 draw(integers(min_value=0)),
335 draw(integers(min_value=0)),
336 draw(integers(min_value=0)),
338 return (value, impl, expl, default, optional, _decoded)
341 class BooleanInherited(Boolean):
345 class TestBoolean(CommonMixin, TestCase):
348 def test_invalid_value_type(self):
349 with self.assertRaises(InvalidValueType) as err:
354 def test_optional(self, optional):
355 obj = Boolean(default=Boolean(False), optional=optional)
356 self.assertTrue(obj.optional)
359 def test_ready(self, value):
361 self.assertFalse(obj.ready)
364 with self.assertRaises(ObjNotReady) as err:
368 self.assertTrue(obj.ready)
372 @given(booleans(), booleans(), binary(), binary())
373 def test_comparison(self, value1, value2, tag1, tag2):
374 for klass in (Boolean, BooleanInherited):
377 self.assertEqual(obj1 == obj2, value1 == value2)
378 self.assertEqual(obj1 != obj2, value1 != value2)
379 self.assertEqual(obj1 == bool(obj2), value1 == value2)
380 obj1 = klass(value1, impl=tag1)
381 obj2 = klass(value1, impl=tag2)
382 self.assertEqual(obj1 == obj2, tag1 == tag2)
383 self.assertEqual(obj1 != obj2, tag1 != tag2)
385 @given(data_strategy())
386 def test_call(self, d):
387 for klass in (Boolean, BooleanInherited):
395 ) = d.draw(boolean_values_strategy())
401 optional_initial or False,
411 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
412 obj = obj_initial(value, impl, expl, default, optional)
414 value_expected = default if value is None else value
416 default_initial if value_expected is None
419 self.assertEqual(obj, value_expected)
420 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
421 self.assertEqual(obj.expl_tag, expl or expl_initial)
424 default_initial if default is None else default,
426 if obj.default is None:
427 optional = optional_initial if optional is None else optional
428 optional = False if optional is None else optional
431 self.assertEqual(obj.optional, optional)
433 @given(boolean_values_strategy())
434 def test_copy(self, values):
435 for klass in (Boolean, BooleanInherited):
437 obj_copied = obj.copy()
438 self.assert_copied_basic_fields(obj, obj_copied)
442 integers(min_value=1).map(tag_encode),
444 def test_stripped(self, value, tag_impl):
445 obj = Boolean(value, impl=tag_impl)
446 with self.assertRaises(NotEnoughData):
447 obj.decode(obj.encode()[:-1])
451 integers(min_value=1).map(tag_ctxc),
453 def test_stripped_expl(self, value, tag_expl):
454 obj = Boolean(value, expl=tag_expl)
455 with self.assertRaises(NotEnoughData):
456 obj.decode(obj.encode()[:-1])
459 integers(min_value=31),
460 integers(min_value=0),
463 def test_bad_tag(self, tag, offset, decode_path):
464 decode_path = tuple(str(i) for i in decode_path)
465 with self.assertRaises(DecodeError) as err:
467 tag_encode(tag)[:-1],
469 decode_path=decode_path,
472 self.assertEqual(err.exception.offset, offset)
473 self.assertEqual(err.exception.decode_path, decode_path)
476 integers(min_value=31),
477 integers(min_value=0),
480 def test_bad_expl_tag(self, tag, offset, decode_path):
481 decode_path = tuple(str(i) for i in decode_path)
482 with self.assertRaises(DecodeError) as err:
483 Boolean(expl=Boolean.tag_default).decode(
484 tag_encode(tag)[:-1],
486 decode_path=decode_path,
489 self.assertEqual(err.exception.offset, offset)
490 self.assertEqual(err.exception.decode_path, decode_path)
493 integers(min_value=128),
494 integers(min_value=0),
497 def test_bad_len(self, l, offset, decode_path):
498 decode_path = tuple(str(i) for i in decode_path)
499 with self.assertRaises(DecodeError) as err:
501 Boolean.tag_default + len_encode(l)[:-1],
503 decode_path=decode_path,
506 self.assertEqual(err.exception.offset, offset)
507 self.assertEqual(err.exception.decode_path, decode_path)
510 integers(min_value=128),
511 integers(min_value=0),
514 def test_bad_expl_len(self, l, offset, decode_path):
515 decode_path = tuple(str(i) for i in decode_path)
516 with self.assertRaises(DecodeError) as err:
517 Boolean(expl=Boolean.tag_default).decode(
518 Boolean.tag_default + len_encode(l)[:-1],
520 decode_path=decode_path,
523 self.assertEqual(err.exception.offset, offset)
524 self.assertEqual(err.exception.decode_path, decode_path)
526 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
528 boolean_values_strategy(),
530 integers(min_value=1).map(tag_ctxc),
531 integers(min_value=0),
533 def test_symmetric(self, values, value, tag_expl, offset):
534 for klass in (Boolean, BooleanInherited):
535 _, _, _, default, optional, _decoded = values
544 self.assertFalse(obj.expled)
545 obj_encoded = obj.encode()
546 obj_expled = obj(value, expl=tag_expl)
547 self.assertTrue(obj_expled.expled)
550 obj_expled_encoded = obj_expled.encode()
551 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
554 self.assertEqual(tail, b"")
555 self.assertEqual(obj_decoded, obj_expled)
556 self.assertNotEqual(obj_decoded, obj)
557 self.assertEqual(bool(obj_decoded), bool(obj_expled))
558 self.assertEqual(bool(obj_decoded), bool(obj))
559 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
560 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
561 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
563 obj_decoded.expl_llen,
564 len(len_encode(len(obj_encoded))),
566 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
567 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
570 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
572 self.assertEqual(obj_decoded.expl_offset, offset)
574 @given(integers(min_value=2))
575 def test_invalid_len(self, l):
576 with self.assertRaises(InvalidLength):
577 Boolean().decode(b"".join((
583 @given(integers(min_value=0 + 1, max_value=255 - 1))
584 def test_invalid_value(self, value):
585 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
586 Boolean().decode(b"".join((
594 def integer_values_strategy(draw, do_expl=False):
595 bound_min, value, default, bound_max = sorted(draw(sets(
604 _specs = draw(sets(text_letters()))
607 min_size=len(_specs),
608 max_size=len(_specs),
610 _specs = list(zip(_specs, values))
613 bounds = (bound_min, bound_max)
617 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
619 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
622 optional = draw(one_of(none(), booleans()))
624 draw(integers(min_value=0)),
625 draw(integers(min_value=0)),
626 draw(integers(min_value=0)),
628 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
631 class IntegerInherited(Integer):
635 class TestInteger(CommonMixin, TestCase):
638 def test_invalid_value_type(self):
639 with self.assertRaises(InvalidValueType) as err:
643 @given(sets(text_letters(), min_size=2))
644 def test_unknown_name(self, names_input):
645 missing = names_input.pop()
648 schema = [(n, 123) for n in names_input]
649 with self.assertRaises(ObjUnknown) as err:
653 @given(sets(text_letters(), min_size=2))
654 def test_known_name(self, names_input):
656 schema = [(n, 123) for n in names_input]
657 Int(names_input.pop())
660 def test_optional(self, optional):
661 obj = Integer(default=Integer(0), optional=optional)
662 self.assertTrue(obj.optional)
665 def test_ready(self, value):
667 self.assertFalse(obj.ready)
670 with self.assertRaises(ObjNotReady) as err:
674 self.assertTrue(obj.ready)
679 @given(integers(), integers(), binary(), binary())
680 def test_comparison(self, value1, value2, tag1, tag2):
681 for klass in (Integer, IntegerInherited):
684 self.assertEqual(obj1 == obj2, value1 == value2)
685 self.assertEqual(obj1 != obj2, value1 != value2)
686 self.assertEqual(obj1 == int(obj2), value1 == value2)
687 obj1 = klass(value1, impl=tag1)
688 obj2 = klass(value1, impl=tag2)
689 self.assertEqual(obj1 == obj2, tag1 == tag2)
690 self.assertEqual(obj1 != obj2, tag1 != tag2)
692 @given(lists(integers()))
693 def test_sorted_works(self, values):
694 self.assertSequenceEqual(
695 [int(v) for v in sorted(Integer(v) for v in values)],
699 @given(data_strategy())
700 def test_named(self, d):
701 names_input = list(d.draw(sets(text_letters(), min_size=1)))
702 values_input = list(d.draw(sets(
704 min_size=len(names_input),
705 max_size=len(names_input),
707 chosen_name = d.draw(sampled_from(names_input))
708 names_input = dict(zip(names_input, values_input))
712 _int = Int(chosen_name)
713 self.assertEqual(_int.named, chosen_name)
714 self.assertEqual(int(_int), names_input[chosen_name])
716 @given(integers(), integers(min_value=0), integers(min_value=0))
717 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
718 value = bound_min + value_delta
719 bound_max = value + bound_delta
720 Integer(value=value, bounds=(bound_min, bound_max))
722 @given(sets(integers(), min_size=3, max_size=3))
723 def test_bounds_unsatisfied(self, values):
724 values = sorted(values)
725 with self.assertRaises(BoundsError) as err:
726 Integer(value=values[0], bounds=(values[1], values[2]))
728 with self.assertRaises(BoundsError) as err:
729 Integer(value=values[2], bounds=(values[0], values[1]))
732 @given(data_strategy())
733 def test_call(self, d):
734 for klass in (Integer, IntegerInherited):
744 ) = d.draw(integer_values_strategy())
751 optional_initial or False,
764 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
765 if (default is None) and (obj_initial.default is not None):
769 (value is not None) and
770 (bounds_initial is not None) and
771 not (bounds_initial[0] <= value <= bounds_initial[1])
776 (default is not None) and
777 (bounds_initial is not None) and
778 not (bounds_initial[0] <= default <= bounds_initial[1])
781 obj = obj_initial(value, bounds, impl, expl, default, optional)
783 value_expected = default if value is None else value
785 default_initial if value_expected is None
788 self.assertEqual(obj, value_expected)
789 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
790 self.assertEqual(obj.expl_tag, expl or expl_initial)
793 default_initial if default is None else default,
795 if obj.default is None:
796 optional = optional_initial if optional is None else optional
797 optional = False if optional is None else optional
800 self.assertEqual(obj.optional, optional)
802 (obj._bound_min, obj._bound_max),
803 bounds or bounds_initial or (float("-inf"), float("+inf")),
807 {} if _specs_initial is None else dict(_specs_initial),
810 @given(integer_values_strategy())
811 def test_copy(self, values):
812 for klass in (Integer, IntegerInherited):
814 obj_copied = obj.copy()
815 self.assert_copied_basic_fields(obj, obj_copied)
816 self.assertEqual(obj.specs, obj_copied.specs)
817 self.assertEqual(obj._bound_min, obj_copied._bound_min)
818 self.assertEqual(obj._bound_max, obj_copied._bound_max)
819 self.assertEqual(obj._value, obj_copied._value)
823 integers(min_value=1).map(tag_encode),
825 def test_stripped(self, value, tag_impl):
826 obj = Integer(value, impl=tag_impl)
827 with self.assertRaises(NotEnoughData):
828 obj.decode(obj.encode()[:-1])
832 integers(min_value=1).map(tag_ctxc),
834 def test_stripped_expl(self, value, tag_expl):
835 obj = Integer(value, expl=tag_expl)
836 with self.assertRaises(NotEnoughData):
837 obj.decode(obj.encode()[:-1])
839 def test_zero_len(self):
840 with self.assertRaises(NotEnoughData):
841 Integer().decode(b"".join((
847 integers(min_value=31),
848 integers(min_value=0),
851 def test_bad_tag(self, tag, offset, decode_path):
852 decode_path = tuple(str(i) for i in decode_path)
853 with self.assertRaises(DecodeError) as err:
855 tag_encode(tag)[:-1],
857 decode_path=decode_path,
860 self.assertEqual(err.exception.offset, offset)
861 self.assertEqual(err.exception.decode_path, decode_path)
864 integers(min_value=128),
865 integers(min_value=0),
868 def test_bad_len(self, l, offset, decode_path):
869 decode_path = tuple(str(i) for i in decode_path)
870 with self.assertRaises(DecodeError) as err:
872 Integer.tag_default + len_encode(l)[:-1],
874 decode_path=decode_path,
877 self.assertEqual(err.exception.offset, offset)
878 self.assertEqual(err.exception.decode_path, decode_path)
881 sets(integers(), min_size=2, max_size=2),
882 integers(min_value=0),
885 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
886 decode_path = tuple(str(i) for i in decode_path)
887 value, bound_min = list(sorted(ints))
890 bounds = (bound_min, bound_min)
891 with self.assertRaises(DecodeError) as err:
893 Integer(value).encode(),
895 decode_path=decode_path,
898 self.assertEqual(err.exception.offset, offset)
899 self.assertEqual(err.exception.decode_path, decode_path)
901 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
903 integer_values_strategy(),
905 integers(min_value=1).map(tag_ctxc),
906 integers(min_value=0),
908 def test_symmetric(self, values, value, tag_expl, offset):
909 for klass in (Integer, IntegerInherited):
910 _, _, _, _, default, optional, _, _decoded = values
919 self.assertFalse(obj.expled)
920 obj_encoded = obj.encode()
921 obj_expled = obj(value, expl=tag_expl)
922 self.assertTrue(obj_expled.expled)
925 obj_expled_encoded = obj_expled.encode()
926 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
929 self.assertEqual(tail, b"")
930 self.assertEqual(obj_decoded, obj_expled)
931 self.assertNotEqual(obj_decoded, obj)
932 self.assertEqual(int(obj_decoded), int(obj_expled))
933 self.assertEqual(int(obj_decoded), int(obj))
934 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
935 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
936 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
938 obj_decoded.expl_llen,
939 len(len_encode(len(obj_encoded))),
941 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
942 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
945 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
947 self.assertEqual(obj_decoded.expl_offset, offset)
949 def test_go_vectors_valid(self):
950 for data, expect in ((
962 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
963 (b"\x80\x00\x00\x00", -2147483648),
966 Integer().decode(b"".join((
968 len_encode(len(data)),
974 def test_go_vectors_invalid(self):
979 with self.assertRaises(DecodeError):
980 Integer().decode(b"".join((
982 len_encode(len(data)),
988 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
992 schema = draw(sets(text_letters(), min_size=1, max_size=256))
994 integers(min_value=0, max_value=255),
995 min_size=len(schema),
996 max_size=len(schema),
998 schema = list(zip(schema, bits))
1000 def _value(value_required):
1001 if not value_required and draw(booleans()):
1003 generation_choice = 0
1005 generation_choice = draw(sampled_from((1, 2, 3)))
1006 if generation_choice == 1 or draw(booleans()):
1007 return "'%s'B" % "".join(draw(lists(
1008 sampled_from(("0", "1")),
1009 max_size=len(schema),
1011 elif generation_choice == 2 or draw(booleans()):
1012 return draw(binary(max_size=len(schema) // 8))
1013 elif generation_choice == 3 or draw(booleans()):
1014 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1016 value = _value(value_required)
1017 default = _value(value_required=False)
1021 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1023 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1024 optional = draw(one_of(none(), booleans()))
1026 draw(integers(min_value=0)),
1027 draw(integers(min_value=0)),
1028 draw(integers(min_value=0)),
1030 return (schema, value, impl, expl, default, optional, _decoded)
1033 class BitStringInherited(BitString):
1037 class TestBitString(CommonMixin, TestCase):
1038 base_klass = BitString
1040 @given(lists(booleans()))
1041 def test_b_encoding(self, bits):
1042 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1043 self.assertEqual(obj.bit_len, len(bits))
1044 self.assertSequenceEqual(list(obj), bits)
1045 for i, bit in enumerate(bits):
1046 self.assertEqual(obj[i], bit)
1048 @given(lists(booleans()))
1049 def test_out_of_bounds_bits(self, bits):
1050 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1051 for i in range(len(bits), len(bits) * 2):
1052 self.assertFalse(obj[i])
1054 def test_bad_b_encoding(self):
1055 with self.assertRaises(ValueError):
1056 BitString("'010120101'B")
1059 integers(min_value=1, max_value=255),
1060 integers(min_value=1, max_value=255),
1062 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1063 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1064 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1065 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1067 class BS(BitString):
1068 schema = (("whatever", 0),)
1069 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1070 self.assertEqual(obj.bit_len, leading_zeros + 1)
1071 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1073 def test_zero_len(self):
1074 with self.assertRaises(NotEnoughData):
1075 BitString().decode(b"".join((
1076 BitString.tag_default,
1080 def test_invalid_value_type(self):
1081 with self.assertRaises(InvalidValueType) as err:
1084 with self.assertRaises(InvalidValueType) as err:
1088 def test_obj_unknown(self):
1089 with self.assertRaises(ObjUnknown) as err:
1090 BitString(b"whatever")["whenever"]
1093 def test_get_invalid_type(self):
1094 with self.assertRaises(InvalidValueType) as err:
1095 BitString(b"whatever")[(1, 2, 3)]
1098 @given(data_strategy())
1099 def test_unknown_name(self, d):
1100 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1101 missing = _schema.pop()
1103 class BS(BitString):
1104 schema = [(n, i) for i, n in enumerate(_schema)]
1105 with self.assertRaises(ObjUnknown) as err:
1110 def test_optional(self, optional):
1111 obj = BitString(default=BitString(b""), optional=optional)
1112 self.assertTrue(obj.optional)
1115 def test_ready(self, value):
1117 self.assertFalse(obj.ready)
1120 with self.assertRaises(ObjNotReady) as err:
1123 obj = BitString(value)
1124 self.assertTrue(obj.ready)
1129 tuples(integers(min_value=0), binary()),
1130 tuples(integers(min_value=0), binary()),
1134 def test_comparison(self, value1, value2, tag1, tag2):
1135 for klass in (BitString, BitStringInherited):
1136 obj1 = klass(value1)
1137 obj2 = klass(value2)
1138 self.assertEqual(obj1 == obj2, value1 == value2)
1139 self.assertEqual(obj1 != obj2, value1 != value2)
1140 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1141 obj1 = klass(value1, impl=tag1)
1142 obj2 = klass(value1, impl=tag2)
1143 self.assertEqual(obj1 == obj2, tag1 == tag2)
1144 self.assertEqual(obj1 != obj2, tag1 != tag2)
1146 @given(data_strategy())
1147 def test_call(self, d):
1148 for klass in (BitString, BitStringInherited):
1157 ) = d.draw(bit_string_values_strategy())
1160 schema = schema_initial
1162 value=value_initial,
1165 default=default_initial,
1166 optional=optional_initial or False,
1167 _decoded=_decoded_initial,
1177 ) = d.draw(bit_string_values_strategy(
1178 schema=schema_initial,
1179 do_expl=impl_initial is None,
1188 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1189 self.assertEqual(obj.expl_tag, expl or expl_initial)
1190 if obj.default is None:
1191 optional = optional_initial if optional is None else optional
1192 optional = False if optional is None else optional
1195 self.assertEqual(obj.optional, optional)
1196 self.assertEqual(obj.specs, obj_initial.specs)
1198 @given(bit_string_values_strategy())
1199 def test_copy(self, values):
1200 for klass in (BitString, BitStringInherited):
1201 _schema, value, impl, expl, default, optional, _decoded = values
1210 optional=optional or False,
1213 obj_copied = obj.copy()
1214 self.assert_copied_basic_fields(obj, obj_copied)
1215 self.assertEqual(obj.specs, obj_copied.specs)
1216 self.assertEqual(obj._value, obj_copied._value)
1220 integers(min_value=1).map(tag_encode),
1222 def test_stripped(self, value, tag_impl):
1223 obj = BitString(value, impl=tag_impl)
1224 with self.assertRaises(NotEnoughData):
1225 obj.decode(obj.encode()[:-1])
1229 integers(min_value=1).map(tag_ctxc),
1231 def test_stripped_expl(self, value, tag_expl):
1232 obj = BitString(value, expl=tag_expl)
1233 with self.assertRaises(NotEnoughData):
1234 obj.decode(obj.encode()[:-1])
1237 integers(min_value=31),
1238 integers(min_value=0),
1241 def test_bad_tag(self, tag, offset, decode_path):
1242 decode_path = tuple(str(i) for i in decode_path)
1243 with self.assertRaises(DecodeError) as err:
1245 tag_encode(tag)[:-1],
1247 decode_path=decode_path,
1250 self.assertEqual(err.exception.offset, offset)
1251 self.assertEqual(err.exception.decode_path, decode_path)
1254 integers(min_value=128),
1255 integers(min_value=0),
1258 def test_bad_len(self, l, offset, decode_path):
1259 decode_path = tuple(str(i) for i in decode_path)
1260 with self.assertRaises(DecodeError) as err:
1262 BitString.tag_default + len_encode(l)[:-1],
1264 decode_path=decode_path,
1267 self.assertEqual(err.exception.offset, offset)
1268 self.assertEqual(err.exception.decode_path, decode_path)
1270 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1271 @given(data_strategy())
1272 def test_symmetric(self, d):
1281 ) = d.draw(bit_string_values_strategy(value_required=True))
1282 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1283 offset = d.draw(integers(min_value=0))
1284 for klass in (BitString, BitStringInherited):
1295 self.assertFalse(obj.expled)
1296 obj_encoded = obj.encode()
1297 obj_expled = obj(value, expl=tag_expl)
1298 self.assertTrue(obj_expled.expled)
1301 obj_expled_encoded = obj_expled.encode()
1302 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
1305 self.assertEqual(tail, b"")
1306 self.assertEqual(obj_decoded, obj_expled)
1307 self.assertNotEqual(obj_decoded, obj)
1308 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1309 self.assertEqual(bytes(obj_decoded), bytes(obj))
1310 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1311 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1312 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1314 obj_decoded.expl_llen,
1315 len(len_encode(len(obj_encoded))),
1317 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1318 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1321 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1323 self.assertEqual(obj_decoded.expl_offset, offset)
1324 if isinstance(value, tuple):
1325 self.assertSetEqual(set(value), set(obj_decoded.named))
1329 @given(integers(min_value=1, max_value=255))
1330 def test_bad_zero_value(self, pad_size):
1331 with self.assertRaises(DecodeError):
1332 BitString().decode(b"".join((
1333 BitString.tag_default,
1338 def test_go_vectors_invalid(self):
1344 with self.assertRaises(DecodeError):
1345 BitString().decode(b"".join((
1346 BitString.tag_default,
1351 def test_go_vectors_valid(self):
1352 obj, _ = BitString().decode(b"".join((
1353 BitString.tag_default,
1357 self.assertEqual(bytes(obj), b"")
1358 self.assertEqual(obj.bit_len, 0)
1360 obj, _ = BitString().decode(b"".join((
1361 BitString.tag_default,
1365 self.assertEqual(bytes(obj), b"\x00")
1366 self.assertEqual(obj.bit_len, 1)
1368 obj = BitString((16, b"\x82\x40"))
1369 self.assertTrue(obj[0])
1370 self.assertFalse(obj[1])
1371 self.assertTrue(obj[6])
1372 self.assertTrue(obj[9])
1373 self.assertFalse(obj[17])
1377 def octet_string_values_strategy(draw, do_expl=False):
1378 bound_min, bound_max = sorted(draw(sets(
1379 integers(min_value=0, max_value=1 << 7),
1383 value = draw(one_of(
1385 binary(min_size=bound_min, max_size=bound_max),
1387 default = draw(one_of(
1389 binary(min_size=bound_min, max_size=bound_max),
1392 if draw(booleans()):
1393 bounds = (bound_min, bound_max)
1397 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1399 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1400 optional = draw(one_of(none(), booleans()))
1402 draw(integers(min_value=0)),
1403 draw(integers(min_value=0)),
1404 draw(integers(min_value=0)),
1406 return (value, bounds, impl, expl, default, optional, _decoded)
1409 class OctetStringInherited(OctetString):
1413 class TestOctetString(CommonMixin, TestCase):
1414 base_klass = OctetString
1416 def test_invalid_value_type(self):
1417 with self.assertRaises(InvalidValueType) as err:
1418 OctetString(text_type(123))
1422 def test_optional(self, optional):
1423 obj = OctetString(default=OctetString(b""), optional=optional)
1424 self.assertTrue(obj.optional)
1427 def test_ready(self, value):
1429 self.assertFalse(obj.ready)
1432 with self.assertRaises(ObjNotReady) as err:
1435 obj = OctetString(value)
1436 self.assertTrue(obj.ready)
1440 @given(binary(), binary(), binary(), binary())
1441 def test_comparison(self, value1, value2, tag1, tag2):
1442 for klass in (OctetString, OctetStringInherited):
1443 obj1 = klass(value1)
1444 obj2 = klass(value2)
1445 self.assertEqual(obj1 == obj2, value1 == value2)
1446 self.assertEqual(obj1 != obj2, value1 != value2)
1447 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
1448 obj1 = klass(value1, impl=tag1)
1449 obj2 = klass(value1, impl=tag2)
1450 self.assertEqual(obj1 == obj2, tag1 == tag2)
1451 self.assertEqual(obj1 != obj2, tag1 != tag2)
1453 @given(lists(binary()))
1454 def test_sorted_works(self, values):
1455 self.assertSequenceEqual(
1456 [bytes(v) for v in sorted(OctetString(v) for v in values)],
1460 @given(data_strategy())
1461 def test_bounds_satisfied(self, d):
1462 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
1463 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
1464 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
1465 OctetString(value=value, bounds=(bound_min, bound_max))
1467 @given(data_strategy())
1468 def test_bounds_unsatisfied(self, d):
1469 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
1470 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
1471 value = d.draw(binary(max_size=bound_min - 1))
1472 with self.assertRaises(BoundsError) as err:
1473 OctetString(value=value, bounds=(bound_min, bound_max))
1475 value = d.draw(binary(min_size=bound_max + 1))
1476 with self.assertRaises(BoundsError) as err:
1477 OctetString(value=value, bounds=(bound_min, bound_max))
1480 @given(data_strategy())
1481 def test_call(self, d):
1482 for klass in (OctetString, OctetStringInherited):
1491 ) = d.draw(octet_string_values_strategy())
1492 obj_initial = klass(
1498 optional_initial or False,
1509 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
1510 if (default is None) and (obj_initial.default is not None):
1513 (bounds is None) and
1514 (value is not None) and
1515 (bounds_initial is not None) and
1516 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
1520 (bounds is None) and
1521 (default is not None) and
1522 (bounds_initial is not None) and
1523 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
1526 obj = obj_initial(value, bounds, impl, expl, default, optional)
1528 value_expected = default if value is None else value
1530 default_initial if value_expected is None
1533 self.assertEqual(obj, value_expected)
1534 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1535 self.assertEqual(obj.expl_tag, expl or expl_initial)
1538 default_initial if default is None else default,
1540 if obj.default is None:
1541 optional = optional_initial if optional is None else optional
1542 optional = False if optional is None else optional
1545 self.assertEqual(obj.optional, optional)
1547 (obj._bound_min, obj._bound_max),
1548 bounds or bounds_initial or (0, float("+inf")),
1551 @given(octet_string_values_strategy())
1552 def test_copy(self, values):
1553 for klass in (OctetString, OctetStringInherited):
1554 obj = klass(*values)
1555 obj_copied = obj.copy()
1556 self.assert_copied_basic_fields(obj, obj_copied)
1557 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1558 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1559 self.assertEqual(obj._value, obj_copied._value)
1563 integers(min_value=1).map(tag_encode),
1565 def test_stripped(self, value, tag_impl):
1566 obj = OctetString(value, impl=tag_impl)
1567 with self.assertRaises(NotEnoughData):
1568 obj.decode(obj.encode()[:-1])
1572 integers(min_value=1).map(tag_ctxc),
1574 def test_stripped_expl(self, value, tag_expl):
1575 obj = OctetString(value, expl=tag_expl)
1576 with self.assertRaises(NotEnoughData):
1577 obj.decode(obj.encode()[:-1])
1580 integers(min_value=31),
1581 integers(min_value=0),
1584 def test_bad_tag(self, tag, offset, decode_path):
1585 decode_path = tuple(str(i) for i in decode_path)
1586 with self.assertRaises(DecodeError) as err:
1587 OctetString().decode(
1588 tag_encode(tag)[:-1],
1590 decode_path=decode_path,
1593 self.assertEqual(err.exception.offset, offset)
1594 self.assertEqual(err.exception.decode_path, decode_path)
1597 integers(min_value=128),
1598 integers(min_value=0),
1601 def test_bad_len(self, l, offset, decode_path):
1602 decode_path = tuple(str(i) for i in decode_path)
1603 with self.assertRaises(DecodeError) as err:
1604 OctetString().decode(
1605 OctetString.tag_default + len_encode(l)[:-1],
1607 decode_path=decode_path,
1610 self.assertEqual(err.exception.offset, offset)
1611 self.assertEqual(err.exception.decode_path, decode_path)
1614 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
1615 integers(min_value=0),
1618 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1619 decode_path = tuple(str(i) for i in decode_path)
1620 value, bound_min = list(sorted(ints))
1622 class String(OctetString):
1623 bounds = (bound_min, bound_min)
1624 with self.assertRaises(DecodeError) as err:
1626 OctetString(b"\x00" * value).encode(),
1628 decode_path=decode_path,
1631 self.assertEqual(err.exception.offset, offset)
1632 self.assertEqual(err.exception.decode_path, decode_path)
1634 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1636 octet_string_values_strategy(),
1638 integers(min_value=1).map(tag_ctxc),
1639 integers(min_value=0),
1641 def test_symmetric(self, values, value, tag_expl, offset):
1642 for klass in (OctetString, OctetStringInherited):
1643 _, _, _, _, default, optional, _decoded = values
1652 self.assertFalse(obj.expled)
1653 obj_encoded = obj.encode()
1654 obj_expled = obj(value, expl=tag_expl)
1655 self.assertTrue(obj_expled.expled)
1658 obj_expled_encoded = obj_expled.encode()
1659 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
1662 self.assertEqual(tail, b"")
1663 self.assertEqual(obj_decoded, obj_expled)
1664 self.assertNotEqual(obj_decoded, obj)
1665 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1666 self.assertEqual(bytes(obj_decoded), bytes(obj))
1667 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1668 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1669 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1671 obj_decoded.expl_llen,
1672 len(len_encode(len(obj_encoded))),
1674 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1675 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1678 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1680 self.assertEqual(obj_decoded.expl_offset, offset)
1684 def null_values_strategy(draw, do_expl=False):
1688 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1690 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1691 optional = draw(one_of(none(), booleans()))
1693 draw(integers(min_value=0)),
1694 draw(integers(min_value=0)),
1695 draw(integers(min_value=0)),
1697 return (impl, expl, optional, _decoded)
1700 class NullInherited(Null):
1704 class TestNull(CommonMixin, TestCase):
1707 def test_ready(self):
1709 self.assertTrue(obj.ready)
1713 @given(binary(), binary())
1714 def test_comparison(self, tag1, tag2):
1715 for klass in (Null, NullInherited):
1716 obj1 = klass(impl=tag1)
1717 obj2 = klass(impl=tag2)
1718 self.assertEqual(obj1 == obj2, tag1 == tag2)
1719 self.assertEqual(obj1 != obj2, tag1 != tag2)
1720 self.assertNotEqual(obj1, tag2)
1722 @given(data_strategy())
1723 def test_call(self, d):
1724 for klass in (Null, NullInherited):
1730 ) = d.draw(null_values_strategy())
1731 obj_initial = klass(
1734 optional=optional_initial or False,
1735 _decoded=_decoded_initial,
1742 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
1743 obj = obj_initial(impl=impl, expl=expl, optional=optional)
1744 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1745 self.assertEqual(obj.expl_tag, expl or expl_initial)
1746 optional = optional_initial if optional is None else optional
1747 optional = False if optional is None else optional
1748 self.assertEqual(obj.optional, optional)
1750 @given(null_values_strategy())
1751 def test_copy(self, values):
1752 for klass in (Null, NullInherited):
1753 impl, expl, optional, _decoded = values
1757 optional=optional or False,
1760 obj_copied = obj.copy()
1761 self.assert_copied_basic_fields(obj, obj_copied)
1763 @given(integers(min_value=1).map(tag_encode))
1764 def test_stripped(self, tag_impl):
1765 obj = Null(impl=tag_impl)
1766 with self.assertRaises(NotEnoughData):
1767 obj.decode(obj.encode()[:-1])
1769 @given(integers(min_value=1).map(tag_ctxc))
1770 def test_stripped_expl(self, tag_expl):
1771 obj = Null(expl=tag_expl)
1772 with self.assertRaises(NotEnoughData):
1773 obj.decode(obj.encode()[:-1])
1776 integers(min_value=31),
1777 integers(min_value=0),
1780 def test_bad_tag(self, tag, offset, decode_path):
1781 decode_path = tuple(str(i) for i in decode_path)
1782 with self.assertRaises(DecodeError) as err:
1784 tag_encode(tag)[:-1],
1786 decode_path=decode_path,
1789 self.assertEqual(err.exception.offset, offset)
1790 self.assertEqual(err.exception.decode_path, decode_path)
1793 integers(min_value=128),
1794 integers(min_value=0),
1797 def test_bad_len(self, l, offset, decode_path):
1798 decode_path = tuple(str(i) for i in decode_path)
1799 with self.assertRaises(DecodeError) as err:
1801 Null.tag_default + len_encode(l)[:-1],
1803 decode_path=decode_path,
1806 self.assertEqual(err.exception.offset, offset)
1807 self.assertEqual(err.exception.decode_path, decode_path)
1809 @given(binary(min_size=1))
1810 def test_tag_mismatch(self, impl):
1811 assume(impl != Null.tag_default)
1812 with self.assertRaises(TagMismatch):
1813 Null(impl=impl).decode(Null().encode())
1816 null_values_strategy(),
1817 integers(min_value=1).map(tag_ctxc),
1818 integers(min_value=0),
1820 def test_symmetric(self, values, tag_expl, offset):
1821 for klass in (Null, NullInherited):
1822 _, _, optional, _decoded = values
1823 obj = klass(optional=optional, _decoded=_decoded)
1826 self.assertFalse(obj.expled)
1827 obj_encoded = obj.encode()
1828 obj_expled = obj(expl=tag_expl)
1829 self.assertTrue(obj_expled.expled)
1832 obj_expled_encoded = obj_expled.encode()
1833 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
1836 self.assertEqual(tail, b"")
1837 self.assertEqual(obj_decoded, obj_expled)
1838 self.assertNotEqual(obj_decoded, obj)
1839 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1840 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1841 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1843 obj_decoded.expl_llen,
1844 len(len_encode(len(obj_encoded))),
1846 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1847 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1850 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1852 self.assertEqual(obj_decoded.expl_offset, offset)
1854 @given(integers(min_value=1))
1855 def test_invalid_len(self, l):
1856 with self.assertRaises(InvalidLength):
1857 Null().decode(b"".join((
1864 def oid_strategy(draw):
1865 first_arc = draw(integers(min_value=0, max_value=2))
1867 if first_arc in (0, 1):
1868 second_arc = draw(integers(min_value=0, max_value=39))
1870 second_arc = draw(integers(min_value=0))
1871 other_arcs = draw(lists(integers(min_value=0)))
1872 return tuple([first_arc, second_arc] + other_arcs)
1876 def oid_values_strategy(draw, do_expl=False):
1877 value = draw(one_of(none(), oid_strategy()))
1881 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1883 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1884 default = draw(one_of(none(), oid_strategy()))
1885 optional = draw(one_of(none(), booleans()))
1887 draw(integers(min_value=0)),
1888 draw(integers(min_value=0)),
1889 draw(integers(min_value=0)),
1891 return (value, impl, expl, default, optional, _decoded)
1894 class ObjectIdentifierInherited(ObjectIdentifier):
1898 class TestObjectIdentifier(CommonMixin, TestCase):
1899 base_klass = ObjectIdentifier
1901 def test_invalid_value_type(self):
1902 with self.assertRaises(InvalidValueType) as err:
1903 ObjectIdentifier(123)
1907 def test_optional(self, optional):
1908 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
1909 self.assertTrue(obj.optional)
1911 @given(oid_strategy())
1912 def test_ready(self, value):
1913 obj = ObjectIdentifier()
1914 self.assertFalse(obj.ready)
1917 with self.assertRaises(ObjNotReady) as err:
1920 obj = ObjectIdentifier(value)
1921 self.assertTrue(obj.ready)
1926 @given(oid_strategy(), oid_strategy(), binary(), binary())
1927 def test_comparison(self, value1, value2, tag1, tag2):
1928 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
1929 obj1 = klass(value1)
1930 obj2 = klass(value2)
1931 self.assertEqual(obj1 == obj2, value1 == value2)
1932 self.assertEqual(obj1 != obj2, value1 != value2)
1933 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
1934 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
1935 obj1 = klass(value1, impl=tag1)
1936 obj2 = klass(value1, impl=tag2)
1937 self.assertEqual(obj1 == obj2, tag1 == tag2)
1938 self.assertEqual(obj1 != obj2, tag1 != tag2)
1940 @given(lists(oid_strategy()))
1941 def test_sorted_works(self, values):
1942 self.assertSequenceEqual(
1943 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
1947 @given(data_strategy())
1948 def test_call(self, d):
1949 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
1957 ) = d.draw(oid_values_strategy())
1958 obj_initial = klass(
1959 value=value_initial,
1962 default=default_initial,
1963 optional=optional_initial or False,
1964 _decoded=_decoded_initial,
1973 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
1982 value_expected = default if value is None else value
1984 default_initial if value_expected is None
1987 self.assertEqual(obj, value_expected)
1988 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1989 self.assertEqual(obj.expl_tag, expl or expl_initial)
1992 default_initial if default is None else default,
1994 if obj.default is None:
1995 optional = optional_initial if optional is None else optional
1996 optional = False if optional is None else optional
1999 self.assertEqual(obj.optional, optional)
2001 @given(oid_values_strategy())
2002 def test_copy(self, values):
2003 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2020 obj_copied = obj.copy()
2021 self.assert_copied_basic_fields(obj, obj_copied)
2022 self.assertEqual(obj._value, obj_copied._value)
2024 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2027 integers(min_value=1).map(tag_encode),
2029 def test_stripped(self, value, tag_impl):
2030 obj = ObjectIdentifier(value, impl=tag_impl)
2031 with self.assertRaises(NotEnoughData):
2032 obj.decode(obj.encode()[:-1])
2036 integers(min_value=1).map(tag_ctxc),
2038 def test_stripped_expl(self, value, tag_expl):
2039 obj = ObjectIdentifier(value, expl=tag_expl)
2040 with self.assertRaises(NotEnoughData):
2041 obj.decode(obj.encode()[:-1])
2044 integers(min_value=31),
2045 integers(min_value=0),
2048 def test_bad_tag(self, tag, offset, decode_path):
2049 decode_path = tuple(str(i) for i in decode_path)
2050 with self.assertRaises(DecodeError) as err:
2051 ObjectIdentifier().decode(
2052 tag_encode(tag)[:-1],
2054 decode_path=decode_path,
2057 self.assertEqual(err.exception.offset, offset)
2058 self.assertEqual(err.exception.decode_path, decode_path)
2061 integers(min_value=128),
2062 integers(min_value=0),
2065 def test_bad_len(self, l, offset, decode_path):
2066 decode_path = tuple(str(i) for i in decode_path)
2067 with self.assertRaises(DecodeError) as err:
2068 ObjectIdentifier().decode(
2069 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2071 decode_path=decode_path,
2074 self.assertEqual(err.exception.offset, offset)
2075 self.assertEqual(err.exception.decode_path, decode_path)
2077 def test_zero_oid(self):
2078 with self.assertRaises(NotEnoughData):
2079 ObjectIdentifier().decode(
2080 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2083 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2084 @given(oid_strategy())
2085 def test_unfinished_oid(self, value):
2086 assume(list(value)[-1] > 255)
2087 obj_encoded = ObjectIdentifier(value).encode()
2088 obj, _ = ObjectIdentifier().decode(obj_encoded)
2089 data = obj_encoded[obj.tlen + obj.llen:-1]
2091 ObjectIdentifier.tag_default,
2092 len_encode(len(data)),
2095 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2098 @given(integers(min_value=0))
2099 def test_invalid_short(self, value):
2100 with self.assertRaises(InvalidOID):
2101 ObjectIdentifier((value,))
2102 with self.assertRaises(InvalidOID):
2103 ObjectIdentifier("%d" % value)
2105 @given(integers(min_value=3), integers(min_value=0))
2106 def test_invalid_first_arc(self, first_arc, second_arc):
2107 with self.assertRaises(InvalidOID):
2108 ObjectIdentifier((first_arc, second_arc))
2109 with self.assertRaises(InvalidOID):
2110 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2112 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2113 def test_invalid_second_arc(self, first_arc, second_arc):
2114 with self.assertRaises(InvalidOID):
2115 ObjectIdentifier((first_arc, second_arc))
2116 with self.assertRaises(InvalidOID):
2117 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2119 @given(text(alphabet=ascii_letters + ".", min_size=1))
2120 def test_junk(self, oid):
2121 with self.assertRaises(InvalidOID):
2122 ObjectIdentifier(oid)
2124 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2125 @given(oid_strategy())
2126 def test_validness(self, oid):
2127 obj = ObjectIdentifier(oid)
2128 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2133 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2135 oid_values_strategy(),
2137 integers(min_value=1).map(tag_ctxc),
2138 integers(min_value=0),
2140 def test_symmetric(self, values, value, tag_expl, offset):
2141 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2142 _, _, _, default, optional, _decoded = values
2151 self.assertFalse(obj.expled)
2152 obj_encoded = obj.encode()
2153 obj_expled = obj(value, expl=tag_expl)
2154 self.assertTrue(obj_expled.expled)
2157 obj_expled_encoded = obj_expled.encode()
2158 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
2161 self.assertEqual(tail, b"")
2162 self.assertEqual(obj_decoded, obj_expled)
2163 self.assertNotEqual(obj_decoded, obj)
2164 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
2165 self.assertEqual(tuple(obj_decoded), tuple(obj))
2166 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2167 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2168 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2170 obj_decoded.expl_llen,
2171 len(len_encode(len(obj_encoded))),
2173 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2174 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2177 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2179 self.assertEqual(obj_decoded.expl_offset, offset)
2182 oid_strategy().map(ObjectIdentifier),
2183 oid_strategy().map(ObjectIdentifier),
2185 def test_add(self, oid1, oid2):
2186 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
2187 for oid_to_add in (oid2, tuple(oid2)):
2188 self.assertEqual(oid1 + oid_to_add, oid_expect)
2189 with self.assertRaises(InvalidValueType):
2192 def test_go_vectors_valid(self):
2193 for data, expect in (
2195 (b"\x55\x02", (2, 5, 2)),
2196 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
2197 (b"\x81\x34\x03", (2, 100, 3)),
2200 ObjectIdentifier().decode(b"".join((
2201 ObjectIdentifier.tag_default,
2202 len_encode(len(data)),
2208 def test_go_vectors_invalid(self):
2209 data = b"\x55\x02\xc0\x80\x80\x80\x80"
2210 with self.assertRaises(DecodeError):
2211 ObjectIdentifier().decode(b"".join((
2212 Integer.tag_default,
2213 len_encode(len(data)),
2219 def enumerated_values_strategy(draw, schema=None, do_expl=False):
2221 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
2222 values = list(draw(sets(
2224 min_size=len(schema),
2225 max_size=len(schema),
2227 schema = list(zip(schema, values))
2228 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
2232 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2234 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2235 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
2236 optional = draw(one_of(none(), booleans()))
2238 draw(integers(min_value=0)),
2239 draw(integers(min_value=0)),
2240 draw(integers(min_value=0)),
2242 return (schema, value, impl, expl, default, optional, _decoded)
2245 class TestEnumerated(CommonMixin, TestCase):
2246 class EWhatever(Enumerated):
2247 schema = (("whatever", 0),)
2249 base_klass = EWhatever
2251 def test_schema_required(self):
2252 with assertRaisesRegex(self, ValueError, "schema must be specified"):
2255 def test_invalid_value_type(self):
2256 with self.assertRaises(InvalidValueType) as err:
2257 self.base_klass((1, 2))
2260 @given(sets(text_letters(), min_size=2))
2261 def test_unknown_name(self, schema_input):
2262 missing = schema_input.pop()
2264 class E(Enumerated):
2265 schema = [(n, 123) for n in schema_input]
2266 with self.assertRaises(ObjUnknown) as err:
2271 sets(text_letters(), min_size=2),
2272 sets(integers(), min_size=2),
2274 def test_unknown_value(self, schema_input, values_input):
2276 missing_value = values_input.pop()
2277 _input = list(zip(schema_input, values_input))
2279 class E(Enumerated):
2281 with self.assertRaises(DecodeError) as err:
2286 def test_optional(self, optional):
2287 obj = self.base_klass(default="whatever", optional=optional)
2288 self.assertTrue(obj.optional)
2290 def test_ready(self):
2291 obj = self.base_klass()
2292 self.assertFalse(obj.ready)
2295 with self.assertRaises(ObjNotReady) as err:
2298 obj = self.base_klass("whatever")
2299 self.assertTrue(obj.ready)
2303 @given(integers(), integers(), binary(), binary())
2304 def test_comparison(self, value1, value2, tag1, tag2):
2305 class E(Enumerated):
2307 ("whatever0", value1),
2308 ("whatever1", value2),
2311 class EInherited(E):
2313 for klass in (E, EInherited):
2314 obj1 = klass(value1)
2315 obj2 = klass(value2)
2316 self.assertEqual(obj1 == obj2, value1 == value2)
2317 self.assertEqual(obj1 != obj2, value1 != value2)
2318 self.assertEqual(obj1 == int(obj2), value1 == value2)
2319 obj1 = klass(value1, impl=tag1)
2320 obj2 = klass(value1, impl=tag2)
2321 self.assertEqual(obj1 == obj2, tag1 == tag2)
2322 self.assertEqual(obj1 != obj2, tag1 != tag2)
2324 @given(data_strategy())
2325 def test_call(self, d):
2334 ) = d.draw(enumerated_values_strategy())
2336 class E(Enumerated):
2337 schema = schema_initial
2339 value=value_initial,
2342 default=default_initial,
2343 optional=optional_initial or False,
2344 _decoded=_decoded_initial,
2354 ) = d.draw(enumerated_values_strategy(
2355 schema=schema_initial,
2356 do_expl=impl_initial is None,
2366 value_expected = default if value is None else value
2368 default_initial if value_expected is None
2373 dict(schema_initial).get(value_expected, value_expected),
2375 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2376 self.assertEqual(obj.expl_tag, expl or expl_initial)
2379 default_initial if default is None else default,
2381 if obj.default is None:
2382 optional = optional_initial if optional is None else optional
2383 optional = False if optional is None else optional
2386 self.assertEqual(obj.optional, optional)
2387 self.assertEqual(obj.specs, dict(schema_initial))
2389 @given(enumerated_values_strategy())
2390 def test_copy(self, values):
2391 schema_input, value, impl, expl, default, optional, _decoded = values
2393 class E(Enumerated):
2394 schema = schema_input
2403 obj_copied = obj.copy()
2404 self.assert_copied_basic_fields(obj, obj_copied)
2405 self.assertEqual(obj.specs, obj_copied.specs)
2407 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2408 @given(data_strategy())
2409 def test_symmetric(self, d):
2410 schema_input, _, _, _, default, optional, _decoded = d.draw(
2411 enumerated_values_strategy(),
2413 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
2414 offset = d.draw(integers(min_value=0))
2415 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
2417 class E(Enumerated):
2418 schema = schema_input
2427 self.assertFalse(obj.expled)
2428 obj_encoded = obj.encode()
2429 obj_expled = obj(value, expl=tag_expl)
2430 self.assertTrue(obj_expled.expled)
2433 obj_expled_encoded = obj_expled.encode()
2434 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
2437 self.assertEqual(tail, b"")
2438 self.assertEqual(obj_decoded, obj_expled)
2439 self.assertNotEqual(obj_decoded, obj)
2440 self.assertEqual(int(obj_decoded), int(obj_expled))
2441 self.assertEqual(int(obj_decoded), int(obj))
2442 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2443 self.assertEqual(obj_decoded.expl_tag, tag_expl)
2444 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2446 obj_decoded.expl_llen,
2447 len(len_encode(len(obj_encoded))),
2449 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2450 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2453 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2455 self.assertEqual(obj_decoded.expl_offset, offset)
2459 def string_values_strategy(draw, alphabet, do_expl=False):
2460 bound_min, bound_max = sorted(draw(sets(
2461 integers(min_value=0, max_value=1 << 7),
2465 value = draw(one_of(
2467 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
2469 default = draw(one_of(
2471 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
2474 if draw(booleans()):
2475 bounds = (bound_min, bound_max)
2479 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2481 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2482 optional = draw(one_of(none(), booleans()))
2484 draw(integers(min_value=0)),
2485 draw(integers(min_value=0)),
2486 draw(integers(min_value=0)),
2488 return (value, bounds, impl, expl, default, optional, _decoded)
2491 class StringMixin(object):
2492 def test_invalid_value_type(self):
2493 with self.assertRaises(InvalidValueType) as err:
2494 self.base_klass((1, 2))
2497 def text_alphabet(self):
2498 if self.base_klass.encoding in ("ascii", "iso-8859-1"):
2499 return printable + whitespace
2503 def test_optional(self, optional):
2504 obj = self.base_klass(default=self.base_klass(""), optional=optional)
2505 self.assertTrue(obj.optional)
2507 @given(data_strategy())
2508 def test_ready(self, d):
2509 obj = self.base_klass()
2510 self.assertFalse(obj.ready)
2514 with self.assertRaises(ObjNotReady) as err:
2517 value = d.draw(text(alphabet=self.text_alphabet()))
2518 obj = self.base_klass(value)
2519 self.assertTrue(obj.ready)
2524 @given(data_strategy())
2525 def test_comparison(self, d):
2526 value1 = d.draw(text(alphabet=self.text_alphabet()))
2527 value2 = d.draw(text(alphabet=self.text_alphabet()))
2528 tag1 = d.draw(binary())
2529 tag2 = d.draw(binary())
2530 obj1 = self.base_klass(value1)
2531 obj2 = self.base_klass(value2)
2532 self.assertEqual(obj1 == obj2, value1 == value2)
2533 self.assertEqual(obj1 != obj2, value1 != value2)
2534 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2535 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
2536 obj1 = self.base_klass(value1, impl=tag1)
2537 obj2 = self.base_klass(value1, impl=tag2)
2538 self.assertEqual(obj1 == obj2, tag1 == tag2)
2539 self.assertEqual(obj1 != obj2, tag1 != tag2)
2541 @given(data_strategy())
2542 def test_bounds_satisfied(self, d):
2543 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2544 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2545 value = d.draw(text(
2546 alphabet=self.text_alphabet(),
2550 self.base_klass(value=value, bounds=(bound_min, bound_max))
2552 @given(data_strategy())
2553 def test_bounds_unsatisfied(self, d):
2554 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2555 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2556 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
2557 with self.assertRaises(BoundsError) as err:
2558 self.base_klass(value=value, bounds=(bound_min, bound_max))
2560 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
2561 with self.assertRaises(BoundsError) as err:
2562 self.base_klass(value=value, bounds=(bound_min, bound_max))
2565 @given(data_strategy())
2566 def test_call(self, d):
2575 ) = d.draw(string_values_strategy(self.text_alphabet()))
2576 obj_initial = self.base_klass(
2582 optional_initial or False,
2593 ) = d.draw(string_values_strategy(
2594 self.text_alphabet(),
2595 do_expl=impl_initial is None,
2597 if (default is None) and (obj_initial.default is not None):
2600 (bounds is None) and
2601 (value is not None) and
2602 (bounds_initial is not None) and
2603 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2607 (bounds is None) and
2608 (default is not None) and
2609 (bounds_initial is not None) and
2610 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2613 obj = obj_initial(value, bounds, impl, expl, default, optional)
2615 value_expected = default if value is None else value
2617 default_initial if value_expected is None
2620 self.assertEqual(obj, value_expected)
2621 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2622 self.assertEqual(obj.expl_tag, expl or expl_initial)
2625 default_initial if default is None else default,
2627 if obj.default is None:
2628 optional = optional_initial if optional is None else optional
2629 optional = False if optional is None else optional
2632 self.assertEqual(obj.optional, optional)
2634 (obj._bound_min, obj._bound_max),
2635 bounds or bounds_initial or (0, float("+inf")),
2638 @given(data_strategy())
2639 def test_copy(self, d):
2640 values = d.draw(string_values_strategy(self.text_alphabet()))
2641 obj = self.base_klass(*values)
2642 obj_copied = obj.copy()
2643 self.assert_copied_basic_fields(obj, obj_copied)
2644 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2645 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2646 self.assertEqual(obj._value, obj_copied._value)
2648 @given(data_strategy())
2649 def test_stripped(self, d):
2650 value = d.draw(text(alphabet=self.text_alphabet()))
2651 tag_impl = tag_encode(d.draw(integers(min_value=1)))
2652 obj = self.base_klass(value, impl=tag_impl)
2653 with self.assertRaises(NotEnoughData):
2654 obj.decode(obj.encode()[:-1])
2656 @given(data_strategy())
2657 def test_stripped_expl(self, d):
2658 value = d.draw(text(alphabet=self.text_alphabet()))
2659 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
2660 obj = self.base_klass(value, expl=tag_expl)
2661 with self.assertRaises(NotEnoughData):
2662 obj.decode(obj.encode()[:-1])
2665 integers(min_value=31),
2666 integers(min_value=0),
2669 def test_bad_tag(self, tag, offset, decode_path):
2670 decode_path = tuple(str(i) for i in decode_path)
2671 with self.assertRaises(DecodeError) as err:
2672 self.base_klass().decode(
2673 tag_encode(tag)[:-1],
2675 decode_path=decode_path,
2678 self.assertEqual(err.exception.offset, offset)
2679 self.assertEqual(err.exception.decode_path, decode_path)
2682 integers(min_value=128),
2683 integers(min_value=0),
2686 def test_bad_len(self, l, offset, decode_path):
2687 decode_path = tuple(str(i) for i in decode_path)
2688 with self.assertRaises(DecodeError) as err:
2689 self.base_klass().decode(
2690 self.base_klass.tag_default + len_encode(l)[:-1],
2692 decode_path=decode_path,
2695 self.assertEqual(err.exception.offset, offset)
2696 self.assertEqual(err.exception.decode_path, decode_path)
2699 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2700 integers(min_value=0),
2703 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2704 decode_path = tuple(str(i) for i in decode_path)
2705 value, bound_min = list(sorted(ints))
2707 class String(self.base_klass):
2708 # Multiply this value by four, to satisfy UTF-32 bounds
2709 # (4 bytes per character) validation
2710 bounds = (bound_min * 4, bound_min * 4)
2711 with self.assertRaises(DecodeError) as err:
2713 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
2715 decode_path=decode_path,
2718 self.assertEqual(err.exception.offset, offset)
2719 self.assertEqual(err.exception.decode_path, decode_path)
2721 @given(data_strategy())
2722 def test_symmetric(self, d):
2723 values = d.draw(string_values_strategy(self.text_alphabet()))
2724 value = d.draw(text(alphabet=self.text_alphabet()))
2725 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
2726 offset = d.draw(integers(min_value=0))
2727 _, _, _, _, default, optional, _decoded = values
2728 obj = self.base_klass(
2736 self.assertFalse(obj.expled)
2737 obj_encoded = obj.encode()
2738 obj_expled = obj(value, expl=tag_expl)
2739 self.assertTrue(obj_expled.expled)
2742 obj_expled_encoded = obj_expled.encode()
2743 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
2746 self.assertEqual(tail, b"")
2747 self.assertEqual(obj_decoded, obj_expled)
2748 self.assertNotEqual(obj_decoded, obj)
2749 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2750 self.assertEqual(bytes(obj_decoded), bytes(obj))
2751 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
2752 self.assertEqual(text_type(obj_decoded), text_type(obj))
2753 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2754 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2755 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2757 obj_decoded.expl_llen,
2758 len(len_encode(len(obj_encoded))),
2760 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2761 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2764 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2766 self.assertEqual(obj_decoded.expl_offset, offset)
2769 class TestUTF8String(StringMixin, CommonMixin, TestCase):
2770 base_klass = UTF8String
2773 class TestNumericString(StringMixin, CommonMixin, TestCase):
2774 base_klass = NumericString
2777 class TestPrintableString(StringMixin, CommonMixin, TestCase):
2778 base_klass = PrintableString
2781 class TestTeletexString(StringMixin, CommonMixin, TestCase):
2782 base_klass = TeletexString
2785 class TestVideotexString(StringMixin, CommonMixin, TestCase):
2786 base_klass = VideotexString
2789 class TestIA5String(StringMixin, CommonMixin, TestCase):
2790 base_klass = IA5String
2793 class TestGraphicString(StringMixin, CommonMixin, TestCase):
2794 base_klass = GraphicString
2797 class TestVisibleString(StringMixin, CommonMixin, TestCase):
2798 base_klass = VisibleString
2801 class TestGeneralString(StringMixin, CommonMixin, TestCase):
2802 base_klass = GeneralString
2805 class TestUniversalString(StringMixin, CommonMixin, TestCase):
2806 base_klass = UniversalString
2809 class TestBMPString(StringMixin, CommonMixin, TestCase):
2810 base_klass = BMPString
2814 def generalized_time_values_strategy(
2822 if draw(booleans()):
2823 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
2825 value = value.replace(microsecond=0)
2827 if draw(booleans()):
2828 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
2830 default = default.replace(microsecond=0)
2834 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2836 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2837 optional = draw(one_of(none(), booleans()))
2839 draw(integers(min_value=0)),
2840 draw(integers(min_value=0)),
2841 draw(integers(min_value=0)),
2843 return (value, impl, expl, default, optional, _decoded)
2846 class TimeMixin(object):
2847 def test_invalid_value_type(self):
2848 with self.assertRaises(InvalidValueType) as err:
2849 self.base_klass(datetime.now().timetuple())
2852 @given(data_strategy())
2853 def test_optional(self, d):
2854 default = d.draw(datetimes(
2855 min_value=self.min_datetime,
2856 max_value=self.max_datetime,
2858 optional = d.draw(booleans())
2859 obj = self.base_klass(default=default, optional=optional)
2860 self.assertTrue(obj.optional)
2862 @given(data_strategy())
2863 def test_ready(self, d):
2864 obj = self.base_klass()
2865 self.assertFalse(obj.ready)
2868 with self.assertRaises(ObjNotReady) as err:
2871 value = d.draw(datetimes(min_value=self.min_datetime))
2872 obj = self.base_klass(value)
2873 self.assertTrue(obj.ready)
2877 @given(data_strategy())
2878 def test_comparison(self, d):
2879 value1 = d.draw(datetimes(
2880 min_value=self.min_datetime,
2881 max_value=self.max_datetime,
2883 value2 = d.draw(datetimes(
2884 min_value=self.min_datetime,
2885 max_value=self.max_datetime,
2887 tag1 = d.draw(binary())
2888 tag2 = d.draw(binary())
2890 value1 = value1.replace(microsecond=0)
2891 value2 = value2.replace(microsecond=0)
2892 obj1 = self.base_klass(value1)
2893 obj2 = self.base_klass(value2)
2894 self.assertEqual(obj1 == obj2, value1 == value2)
2895 self.assertEqual(obj1 != obj2, value1 != value2)
2896 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
2897 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2898 obj1 = self.base_klass(value1, impl=tag1)
2899 obj2 = self.base_klass(value1, impl=tag2)
2900 self.assertEqual(obj1 == obj2, tag1 == tag2)
2901 self.assertEqual(obj1 != obj2, tag1 != tag2)
2903 @given(data_strategy())
2904 def test_call(self, d):
2912 ) = d.draw(generalized_time_values_strategy(
2913 min_datetime=self.min_datetime,
2914 max_datetime=self.max_datetime,
2915 omit_ms=self.omit_ms,
2917 obj_initial = self.base_klass(
2918 value=value_initial,
2921 default=default_initial,
2922 optional=optional_initial or False,
2923 _decoded=_decoded_initial,
2932 ) = d.draw(generalized_time_values_strategy(
2933 min_datetime=self.min_datetime,
2934 max_datetime=self.max_datetime,
2935 omit_ms=self.omit_ms,
2936 do_expl=impl_initial is None,
2946 value_expected = default if value is None else value
2948 default_initial if value_expected is None
2951 self.assertEqual(obj, value_expected)
2952 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2953 self.assertEqual(obj.expl_tag, expl or expl_initial)
2956 default_initial if default is None else default,
2958 if obj.default is None:
2959 optional = optional_initial if optional is None else optional
2960 optional = False if optional is None else optional
2963 self.assertEqual(obj.optional, optional)
2965 @given(data_strategy())
2966 def test_copy(self, d):
2967 values = d.draw(generalized_time_values_strategy(
2968 min_datetime=self.min_datetime,
2969 max_datetime=self.max_datetime,
2971 obj = self.base_klass(*values)
2972 obj_copied = obj.copy()
2973 self.assert_copied_basic_fields(obj, obj_copied)
2974 self.assertEqual(obj._value, obj_copied._value)
2976 @given(data_strategy())
2977 def test_stripped(self, d):
2978 value = d.draw(datetimes(
2979 min_value=self.min_datetime,
2980 max_value=self.max_datetime,
2982 tag_impl = tag_encode(d.draw(integers(min_value=1)))
2983 obj = self.base_klass(value, impl=tag_impl)
2984 with self.assertRaises(NotEnoughData):
2985 obj.decode(obj.encode()[:-1])
2987 @given(data_strategy())
2988 def test_stripped_expl(self, d):
2989 value = d.draw(datetimes(
2990 min_value=self.min_datetime,
2991 max_value=self.max_datetime,
2993 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
2994 obj = self.base_klass(value, expl=tag_expl)
2995 with self.assertRaises(NotEnoughData):
2996 obj.decode(obj.encode()[:-1])
2998 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2999 @given(data_strategy())
3000 def test_symmetric(self, d):
3001 values = d.draw(generalized_time_values_strategy(
3002 min_datetime=self.min_datetime,
3003 max_datetime=self.max_datetime,
3005 value = d.draw(datetimes(
3006 min_value=self.min_datetime,
3007 max_value=self.max_datetime,
3009 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3010 offset = d.draw(integers(min_value=0))
3011 _, _, _, default, optional, _decoded = values
3012 obj = self.base_klass(
3020 self.assertFalse(obj.expled)
3021 obj_encoded = obj.encode()
3022 obj_expled = obj(value, expl=tag_expl)
3023 self.assertTrue(obj_expled.expled)
3026 obj_expled_encoded = obj_expled.encode()
3027 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
3030 self.assertEqual(tail, b"")
3031 self.assertEqual(obj_decoded, obj_expled)
3032 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
3033 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
3034 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3035 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3036 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3038 obj_decoded.expl_llen,
3039 len(len_encode(len(obj_encoded))),
3041 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3042 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3045 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3047 self.assertEqual(obj_decoded.expl_offset, offset)
3050 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
3051 base_klass = GeneralizedTime
3053 min_datetime = datetime(1900, 1, 1)
3054 max_datetime = datetime(9999, 12, 31)
3056 def test_go_vectors_invalid(self):
3068 b"-20100102030410Z",
3069 b"2010-0102030410Z",
3070 b"2010-0002030410Z",
3071 b"201001-02030410Z",
3072 b"20100102-030410Z",
3073 b"2010010203-0410Z",
3074 b"201001020304-10Z",
3075 # These ones are INVALID in *DER*, but accepted
3076 # by Go's encoding/asn1
3077 b"20100102030405+0607",
3078 b"20100102030405-0607",
3080 with self.assertRaises(DecodeError) as err:
3081 GeneralizedTime(data)
3084 def test_go_vectors_valid(self):
3086 GeneralizedTime(b"20100102030405Z").todatetime(),
3087 datetime(2010, 1, 2, 3, 4, 5, 0),
3091 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
3092 base_klass = UTCTime
3094 min_datetime = datetime(2000, 1, 1)
3095 max_datetime = datetime(2049, 12, 31)
3097 def test_go_vectors_invalid(self):
3123 # These ones are INVALID in *DER*, but accepted
3124 # by Go's encoding/asn1
3125 b"910506164540-0700",
3126 b"910506164540+0730",
3130 with self.assertRaises(DecodeError) as err:
3134 def test_go_vectors_valid(self):
3136 UTCTime(b"910506234540Z").todatetime(),
3137 datetime(1991, 5, 6, 23, 45, 40, 0),
3140 @given(integers(min_value=0, max_value=49))
3141 def test_pre50(self, year):
3143 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
3147 @given(integers(min_value=50, max_value=99))
3148 def test_post50(self, year):
3150 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
3156 def any_values_strategy(draw, do_expl=False):
3157 value = draw(one_of(none(), binary()))
3160 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3161 optional = draw(one_of(none(), booleans()))
3163 draw(integers(min_value=0)),
3164 draw(integers(min_value=0)),
3165 draw(integers(min_value=0)),
3167 return (value, expl, optional, _decoded)
3170 class AnyInherited(Any):
3174 class TestAny(CommonMixin, TestCase):
3177 def test_invalid_value_type(self):
3178 with self.assertRaises(InvalidValueType) as err:
3183 def test_optional(self, optional):
3184 obj = Any(optional=optional)
3185 self.assertEqual(obj.optional, optional)
3188 def test_ready(self, value):
3190 self.assertFalse(obj.ready)
3193 with self.assertRaises(ObjNotReady) as err:
3197 self.assertTrue(obj.ready)
3202 def test_basic(self, value):
3203 integer_encoded = Integer(value).encode()
3205 Any(integer_encoded),
3206 Any(Integer(value)),
3207 Any(Any(Integer(value))),
3209 self.assertSequenceEqual(bytes(obj), integer_encoded)
3211 obj.decode(obj.encode())[0].vlen,
3212 len(integer_encoded),
3216 self.assertSequenceEqual(obj.encode(), integer_encoded)
3218 @given(binary(), binary())
3219 def test_comparison(self, value1, value2):
3220 for klass in (Any, AnyInherited):
3221 obj1 = klass(value1)
3222 obj2 = klass(value2)
3223 self.assertEqual(obj1 == obj2, value1 == value2)
3224 self.assertEqual(obj1 != obj2, value1 != value2)
3225 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3227 @given(data_strategy())
3228 def test_call(self, d):
3229 for klass in (Any, AnyInherited):
3235 ) = d.draw(any_values_strategy())
3236 obj_initial = klass(
3239 optional_initial or False,
3247 ) = d.draw(any_values_strategy(do_expl=True))
3248 obj = obj_initial(value, expl, optional)
3250 value_expected = None if value is None else value
3251 self.assertEqual(obj, value_expected)
3252 self.assertEqual(obj.expl_tag, expl or expl_initial)
3253 if obj.default is None:
3254 optional = optional_initial if optional is None else optional
3255 optional = False if optional is None else optional
3256 self.assertEqual(obj.optional, optional)
3258 def test_simultaneous_impl_expl(self):
3259 # override it, as Any does not have implicit tag
3262 def test_decoded(self):
3263 # override it, as Any does not have implicit tag
3266 @given(any_values_strategy())
3267 def test_copy(self, values):
3268 for klass in (Any, AnyInherited):
3269 obj = klass(*values)
3270 obj_copied = obj.copy()
3271 self.assert_copied_basic_fields(obj, obj_copied)
3272 self.assertEqual(obj._value, obj_copied._value)
3274 @given(binary().map(OctetString))
3275 def test_stripped(self, value):
3277 with self.assertRaises(NotEnoughData):
3278 obj.decode(obj.encode()[:-1])
3282 integers(min_value=1).map(tag_ctxc),
3284 def test_stripped_expl(self, value, tag_expl):
3285 obj = Any(value, expl=tag_expl)
3286 with self.assertRaises(NotEnoughData):
3287 obj.decode(obj.encode()[:-1])
3290 integers(min_value=31),
3291 integers(min_value=0),
3294 def test_bad_tag(self, tag, offset, decode_path):
3295 decode_path = tuple(str(i) for i in decode_path)
3296 with self.assertRaises(DecodeError) as err:
3298 tag_encode(tag)[:-1],
3300 decode_path=decode_path,
3303 self.assertEqual(err.exception.offset, offset)
3304 self.assertEqual(err.exception.decode_path, decode_path)
3307 integers(min_value=128),
3308 integers(min_value=0),
3311 def test_bad_len(self, l, offset, decode_path):
3312 decode_path = tuple(str(i) for i in decode_path)
3313 with self.assertRaises(DecodeError) as err:
3315 Any.tag_default + len_encode(l)[:-1],
3317 decode_path=decode_path,
3320 self.assertEqual(err.exception.offset, offset)
3321 self.assertEqual(err.exception.decode_path, decode_path)
3323 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3325 any_values_strategy(),
3326 integers().map(lambda x: Integer(x).encode()),
3327 integers(min_value=1).map(tag_ctxc),
3328 integers(min_value=0),
3330 def test_symmetric(self, values, value, tag_expl, offset):
3331 for klass in (Any, AnyInherited):
3332 _, _, optional, _decoded = values
3333 obj = klass(value=value, optional=optional, _decoded=_decoded)
3336 self.assertFalse(obj.expled)
3337 obj_encoded = obj.encode()
3338 obj_expled = obj(value, expl=tag_expl)
3339 self.assertTrue(obj_expled.expled)
3342 obj_expled_encoded = obj_expled.encode()
3343 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
3346 self.assertEqual(tail, b"")
3347 self.assertEqual(obj_decoded, obj_expled)
3348 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3349 self.assertEqual(bytes(obj_decoded), bytes(obj))
3350 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3351 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3352 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3354 obj_decoded.expl_llen,
3355 len(len_encode(len(obj_encoded))),
3357 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3358 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3361 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3363 self.assertEqual(obj_decoded.expl_offset, offset)
3364 self.assertEqual(obj_decoded.tlen, 0)
3365 self.assertEqual(obj_decoded.llen, 0)
3366 self.assertEqual(obj_decoded.vlen, len(value))
3370 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
3372 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
3373 tags = [tag_encode(tag) for tag in draw(sets(
3374 integers(min_value=0),
3375 min_size=len(names),
3376 max_size=len(names),
3378 schema = [(name, Integer(impl=tag)) for name, tag in zip(names, tags)]
3380 if value_required or draw(booleans()):
3381 value = draw(tuples(
3382 sampled_from([name for name, _ in schema]),
3383 integers().map(Integer),
3387 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3388 default = draw(one_of(
3390 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
3392 optional = draw(one_of(none(), booleans()))
3394 draw(integers(min_value=0)),
3395 draw(integers(min_value=0)),
3396 draw(integers(min_value=0)),
3398 return (schema, value, expl, default, optional, _decoded)
3401 class ChoiceInherited(Choice):
3405 class TestChoice(CommonMixin, TestCase):
3407 schema = (("whatever", Boolean()),)
3410 def test_schema_required(self):
3411 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3414 def test_impl_forbidden(self):
3415 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
3416 Choice(impl=b"whatever")
3418 def test_invalid_value_type(self):
3419 with self.assertRaises(InvalidValueType) as err:
3420 self.base_klass(123)
3422 with self.assertRaises(ObjUnknown) as err:
3423 self.base_klass(("whenever", Boolean(False)))
3425 with self.assertRaises(InvalidValueType) as err:
3426 self.base_klass(("whatever", Integer(123)))
3430 def test_optional(self, optional):
3431 obj = self.base_klass(
3432 default=self.base_klass(("whatever", Boolean(False))),
3435 self.assertTrue(obj.optional)
3438 def test_ready(self, value):
3439 obj = self.base_klass()
3440 self.assertFalse(obj.ready)
3443 self.assertIsNone(obj["whatever"])
3444 with self.assertRaises(ObjNotReady) as err:
3447 obj["whatever"] = Boolean()
3448 self.assertFalse(obj.ready)
3451 obj["whatever"] = Boolean(value)
3452 self.assertTrue(obj.ready)
3456 @given(booleans(), booleans())
3457 def test_comparison(self, value1, value2):
3458 class WahlInherited(self.base_klass):
3460 for klass in (self.base_klass, WahlInherited):
3461 obj1 = klass(("whatever", Boolean(value1)))
3462 obj2 = klass(("whatever", Boolean(value2)))
3463 self.assertEqual(obj1 == obj2, value1 == value2)
3464 self.assertEqual(obj1 != obj2, value1 != value2)
3465 self.assertEqual(obj1 == obj2._value, value1 == value2)
3466 self.assertFalse(obj1 == obj2._value[1])
3468 @given(data_strategy())
3469 def test_call(self, d):
3470 for klass in (Choice, ChoiceInherited):
3478 ) = d.draw(choice_values_strategy())
3481 schema = schema_initial
3483 value=value_initial,
3485 default=default_initial,
3486 optional=optional_initial or False,
3487 _decoded=_decoded_initial,
3496 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
3497 obj = obj_initial(value, expl, default, optional)
3499 value_expected = default if value is None else value
3501 default_initial if value_expected is None
3504 self.assertEqual(obj.choice, value_expected[0])
3505 self.assertEqual(obj.value, int(value_expected[1]))
3506 self.assertEqual(obj.expl_tag, expl or expl_initial)
3507 default_expect = default_initial if default is None else default
3508 if default_expect is not None:
3509 self.assertEqual(obj.default.choice, default_expect[0])
3510 self.assertEqual(obj.default.value, int(default_expect[1]))
3511 if obj.default is None:
3512 optional = optional_initial if optional is None else optional
3513 optional = False if optional is None else optional
3516 self.assertEqual(obj.optional, optional)
3517 self.assertEqual(obj.specs, obj_initial.specs)
3519 def test_simultaneous_impl_expl(self):
3520 # override it, as Any does not have implicit tag
3523 def test_decoded(self):
3524 # override it, as Any does not have implicit tag
3527 @given(choice_values_strategy())
3528 def test_copy(self, values):
3529 _schema, value, expl, default, optional, _decoded = values
3531 class Wahl(self.base_klass):
3537 optional=optional or False,
3540 obj_copied = obj.copy()
3541 self.assertIsNone(obj.tag)
3542 self.assertIsNone(obj_copied.tag)
3543 # hack for assert_copied_basic_fields
3544 obj.tag = "whatever"
3545 obj_copied.tag = "whatever"
3546 self.assert_copied_basic_fields(obj, obj_copied)
3547 self.assertEqual(obj._value, obj_copied._value)
3548 self.assertEqual(obj.specs, obj_copied.specs)
3551 def test_stripped(self, value):
3552 obj = self.base_klass(("whatever", Boolean(value)))
3553 with self.assertRaises(NotEnoughData):
3554 obj.decode(obj.encode()[:-1])
3558 integers(min_value=1).map(tag_ctxc),
3560 def test_stripped_expl(self, value, tag_expl):
3561 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
3562 with self.assertRaises(NotEnoughData):
3563 obj.decode(obj.encode()[:-1])
3565 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3566 @given(data_strategy())
3567 def test_symmetric(self, d):
3568 _schema, value, _, default, optional, _decoded = d.draw(
3569 choice_values_strategy(value_required=True)
3571 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3572 offset = d.draw(integers(min_value=0))
3574 class Wahl(self.base_klass):
3584 self.assertFalse(obj.expled)
3585 obj_encoded = obj.encode()
3586 obj_expled = obj(value, expl=tag_expl)
3587 self.assertTrue(obj_expled.expled)
3590 obj_expled_encoded = obj_expled.encode()
3591 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
3594 self.assertEqual(tail, b"")
3595 self.assertEqual(obj_decoded, obj_expled)
3596 self.assertEqual(obj_decoded.choice, obj_expled.choice)
3597 self.assertEqual(obj_decoded.value, obj_expled.value)
3598 self.assertEqual(obj_decoded.choice, obj.choice)
3599 self.assertEqual(obj_decoded.value, obj.value)
3600 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3601 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3602 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3604 obj_decoded.expl_llen,
3605 len(len_encode(len(obj_encoded))),
3607 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3608 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3611 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3613 self.assertEqual(obj_decoded.expl_offset, offset)
3614 self.assertSequenceEqual(
3616 obj_decoded.value.offset - offset:
3617 obj_decoded.value.offset + obj_decoded.value.tlvlen - offset
3623 def test_set_get(self, value):
3626 ("erste", Boolean()),
3627 ("zweite", Integer()),
3630 with self.assertRaises(ObjUnknown) as err:
3631 obj["whatever"] = "whenever"
3632 with self.assertRaises(InvalidValueType) as err:
3633 obj["zweite"] = Boolean(False)
3634 obj["zweite"] = Integer(value)
3636 with self.assertRaises(ObjUnknown) as err:
3639 self.assertIsNone(obj["erste"])
3640 self.assertEqual(obj["zweite"], Integer(value))
3642 def test_tag_mismatch(self):
3645 ("erste", Boolean()),
3647 int_encoded = Integer(123).encode()
3648 bool_encoded = Boolean(False).encode()
3650 obj.decode(bool_encoded)
3651 with self.assertRaises(TagMismatch):
3652 obj.decode(int_encoded)
3656 def seq_values_strategy(draw, seq_klass, do_expl=False):
3658 if draw(booleans()):
3661 k: v for k, v in draw(dictionaries(
3664 booleans().map(Boolean),
3665 integers().map(Integer),
3670 if draw(booleans()):
3671 schema = list(draw(dictionaries(
3674 booleans().map(Boolean),
3675 integers().map(Integer),
3681 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3683 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3685 if draw(booleans()):
3686 default = seq_klass()
3688 k: v for k, v in draw(dictionaries(
3691 booleans().map(Boolean),
3692 integers().map(Integer),
3696 optional = draw(one_of(none(), booleans()))
3698 draw(integers(min_value=0)),
3699 draw(integers(min_value=0)),
3700 draw(integers(min_value=0)),
3702 return (value, schema, impl, expl, default, optional, _decoded)
3706 def sequence_strategy(draw, seq_klass):
3707 inputs = draw(lists(
3709 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
3710 tuples(just(Integer), integers(), one_of(none(), integers())),
3715 integers(min_value=1),
3716 min_size=len(inputs),
3717 max_size=len(inputs),
3720 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
3721 for tag, expled in zip(tags, draw(lists(
3723 min_size=len(inputs),
3724 max_size=len(inputs),
3728 for i, optional in enumerate(draw(lists(
3729 sampled_from(("required", "optional", "empty")),
3730 min_size=len(inputs),
3731 max_size=len(inputs),
3733 if optional in ("optional", "empty"):
3734 inits[i]["optional"] = True
3735 if optional == "empty":
3737 empties = set(empties)
3738 names = list(draw(sets(
3740 min_size=len(inputs),
3741 max_size=len(inputs),
3744 for i, (klass, value, default) in enumerate(inputs):
3745 schema.append((names[i], klass(default=default, **inits[i])))
3746 seq_name = draw(text_letters())
3747 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
3750 for i, (klass, value, default) in enumerate(inputs):
3757 "default_value": None if spec.default is None else default,
3761 expect["optional"] = True
3763 expect["presented"] = True
3764 expect["value"] = value
3766 expect["optional"] = True
3767 if default is not None and default == value:
3768 expect["presented"] = False
3769 seq[name] = klass(value)
3770 expects.append(expect)
3775 def sequences_strategy(draw, seq_klass):
3776 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
3778 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
3779 for tag, expled in zip(tags, draw(lists(
3786 i for i, is_default in enumerate(draw(lists(
3792 names = list(draw(sets(
3797 seq_expectses = draw(lists(
3798 sequence_strategy(seq_klass=seq_klass),
3802 seqs = [seq for seq, _ in seq_expectses]
3804 for i, (name, seq) in enumerate(zip(names, seqs)):
3807 seq(default=(seq if i in defaulted else None), **inits[i]),
3809 seq_name = draw(text_letters())
3810 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
3813 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
3816 "expects": expects_inner,
3819 seq_outer[name] = seq_inner
3820 if seq_outer.specs[name].default is None:
3821 expect["presented"] = True
3822 expect_outers.append(expect)
3823 return seq_outer, expect_outers
3826 class SeqMixing(object):
3827 def test_invalid_value_type(self):
3828 with self.assertRaises(InvalidValueType) as err:
3829 self.base_klass((1, 2, 3))
3832 def test_invalid_value_type_set(self):
3833 class Seq(self.base_klass):
3834 schema = (("whatever", Boolean()),)
3836 with self.assertRaises(InvalidValueType) as err:
3837 seq["whatever"] = Integer(123)
3841 def test_optional(self, optional):
3842 obj = self.base_klass(default=self.base_klass(), optional=optional)
3843 self.assertTrue(obj.optional)
3845 @given(data_strategy())
3846 def test_ready(self, d):
3848 str(i): v for i, v in enumerate(d.draw(lists(
3855 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
3862 for name in d.draw(permutations(
3863 list(ready.keys()) + list(non_ready.keys()),
3865 schema_input.append((name, Boolean()))
3867 class Seq(self.base_klass):
3868 schema = tuple(schema_input)
3870 for name in ready.keys():
3872 seq[name] = Boolean()
3873 self.assertFalse(seq.ready)
3876 for name, value in ready.items():
3877 seq[name] = Boolean(value)
3878 self.assertFalse(seq.ready)
3881 with self.assertRaises(ObjNotReady) as err:
3884 for name, value in non_ready.items():
3885 seq[name] = Boolean(value)
3886 self.assertTrue(seq.ready)
3890 @given(data_strategy())
3891 def test_call(self, d):
3892 class SeqInherited(self.base_klass):
3894 for klass in (self.base_klass, SeqInherited):
3903 ) = d.draw(seq_values_strategy(seq_klass=klass))
3904 obj_initial = klass(
3910 optional_initial or False,
3921 ) = d.draw(seq_values_strategy(
3923 do_expl=impl_initial is None,
3925 obj = obj_initial(value, impl, expl, default, optional)
3926 value_expected = default if value is None else value
3928 default_initial if value_expected is None
3931 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
3932 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3933 self.assertEqual(obj.expl_tag, expl or expl_initial)
3935 {} if obj.default is None else obj.default._value,
3936 getattr(default_initial if default is None else default, "_value", {}),
3938 if obj.default is None:
3939 optional = optional_initial if optional is None else optional
3940 optional = False if optional is None else optional
3943 self.assertEqual(list(obj.specs.items()), schema_initial or [])
3944 self.assertEqual(obj.optional, optional)
3946 @given(data_strategy())
3947 def test_copy(self, d):
3948 class SeqInherited(self.base_klass):
3950 for klass in (self.base_klass, SeqInherited):
3951 values = d.draw(seq_values_strategy(seq_klass=klass))
3952 obj = klass(*values)
3953 obj_copied = obj.copy()
3954 self.assert_copied_basic_fields(obj, obj_copied)
3955 self.assertEqual(obj.specs, obj_copied.specs)
3956 self.assertEqual(obj._value, obj_copied._value)
3958 @given(data_strategy())
3959 def test_stripped(self, d):
3960 value = d.draw(integers())
3961 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3963 class Seq(self.base_klass):
3965 schema = (("whatever", Integer()),)
3967 seq["whatever"] = Integer(value)
3968 with self.assertRaises(NotEnoughData):
3969 seq.decode(seq.encode()[:-1])
3971 @given(data_strategy())
3972 def test_stripped_expl(self, d):
3973 value = d.draw(integers())
3974 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3976 class Seq(self.base_klass):
3978 schema = (("whatever", Integer()),)
3980 seq["whatever"] = Integer(value)
3981 with self.assertRaises(NotEnoughData):
3982 seq.decode(seq.encode()[:-1])
3984 @given(binary(min_size=2))
3985 def test_non_tag_mismatch_raised(self, junk):
3987 _, _, len_encoded = tag_strip(memoryview(junk))
3988 len_decode(len_encoded)
3994 class Seq(self.base_klass):
3996 ("whatever", Integer()),
3998 ("whenever", Integer()),
4001 seq["whatever"] = Integer(123)
4002 seq["junk"] = Any(junk)
4003 seq["whenever"] = Integer(123)
4004 with self.assertRaises(DecodeError):
4005 seq.decode(seq.encode())
4008 integers(min_value=31),
4009 integers(min_value=0),
4012 def test_bad_tag(self, tag, offset, decode_path):
4013 decode_path = tuple(str(i) for i in decode_path)
4014 with self.assertRaises(DecodeError) as err:
4015 self.base_klass().decode(
4016 tag_encode(tag)[:-1],
4018 decode_path=decode_path,
4021 self.assertEqual(err.exception.offset, offset)
4022 self.assertEqual(err.exception.decode_path, decode_path)
4025 integers(min_value=128),
4026 integers(min_value=0),
4029 def test_bad_len(self, l, offset, decode_path):
4030 decode_path = tuple(str(i) for i in decode_path)
4031 with self.assertRaises(DecodeError) as err:
4032 self.base_klass().decode(
4033 self.base_klass.tag_default + len_encode(l)[:-1],
4035 decode_path=decode_path,
4038 self.assertEqual(err.exception.offset, offset)
4039 self.assertEqual(err.exception.decode_path, decode_path)
4041 def _assert_expects(self, seq, expects):
4042 for expect in expects:
4044 seq.specs[expect["name"]].optional,
4047 if expect["default_value"] is not None:
4049 seq.specs[expect["name"]].default,
4050 expect["default_value"],
4052 if expect["presented"]:
4053 self.assertIn(expect["name"], seq)
4054 self.assertEqual(seq[expect["name"]], expect["value"])
4056 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4057 @given(data_strategy())
4058 def test_symmetric(self, d):
4059 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
4060 self.assertTrue(seq.ready)
4061 self.assertFalse(seq.decoded)
4062 self._assert_expects(seq, expects)
4065 seq_encoded = seq.encode()
4066 seq_decoded, tail = seq.decode(seq_encoded)
4067 self.assertEqual(tail, b"")
4068 self.assertTrue(seq.ready)
4069 self._assert_expects(seq_decoded, expects)
4070 self.assertEqual(seq, seq_decoded)
4071 self.assertEqual(seq_decoded.encode(), seq_encoded)
4072 for expect in expects:
4073 if not expect["presented"]:
4074 self.assertNotIn(expect["name"], seq_decoded)
4076 self.assertIn(expect["name"], seq_decoded)
4077 obj = seq_decoded[expect["name"]]
4078 self.assertTrue(obj.decoded)
4079 offset = obj.expl_offset if obj.expled else obj.offset
4080 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
4081 self.assertSequenceEqual(
4082 seq_encoded[offset:offset + tlvlen],
4086 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4087 @given(data_strategy())
4088 def test_symmetric_with_seq(self, d):
4089 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
4090 self.assertTrue(seq.ready)
4091 seq_encoded = seq.encode()
4092 seq_decoded, tail = seq.decode(seq_encoded)
4093 self.assertEqual(tail, b"")
4094 self.assertTrue(seq.ready)
4095 self.assertEqual(seq, seq_decoded)
4096 self.assertEqual(seq_decoded.encode(), seq_encoded)
4097 for expect_outer in expect_outers:
4098 if not expect_outer["presented"]:
4099 self.assertNotIn(expect_outer["name"], seq_decoded)
4101 self.assertIn(expect_outer["name"], seq_decoded)
4102 obj = seq_decoded[expect_outer["name"]]
4103 self.assertTrue(obj.decoded)
4104 offset = obj.expl_offset if obj.expled else obj.offset
4105 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
4106 self.assertSequenceEqual(
4107 seq_encoded[offset:offset + tlvlen],
4110 self._assert_expects(obj, expect_outer["expects"])
4112 @given(data_strategy())
4113 def test_default_disappears(self, d):
4114 _schema = list(d.draw(dictionaries(
4116 sets(integers(), min_size=2, max_size=2),
4120 class Seq(self.base_klass):
4122 (n, Integer(default=d))
4123 for n, (_, d) in _schema
4126 for name, (value, _) in _schema:
4127 seq[name] = Integer(value)
4128 self.assertEqual(len(seq._value), len(_schema))
4129 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
4130 self.assertGreater(len(seq.encode()), len(empty_seq))
4131 for name, (_, default) in _schema:
4132 seq[name] = Integer(default)
4133 self.assertEqual(len(seq._value), 0)
4134 self.assertSequenceEqual(seq.encode(), empty_seq)
4136 @given(data_strategy())
4137 def test_encoded_default_accepted(self, d):
4138 _schema = list(d.draw(dictionaries(
4143 tags = [tag_encode(tag) for tag in d.draw(sets(
4144 integers(min_value=0),
4145 min_size=len(_schema),
4146 max_size=len(_schema),
4149 class SeqWithoutDefault(self.base_klass):
4151 (n, Integer(impl=t))
4152 for (n, _), t in zip(_schema, tags)
4154 seq_without_default = SeqWithoutDefault()
4155 for name, value in _schema:
4156 seq_without_default[name] = Integer(value)
4157 seq_encoded = seq_without_default.encode()
4159 class SeqWithDefault(self.base_klass):
4161 (n, Integer(default=v, impl=t))
4162 for (n, v), t in zip(_schema, tags)
4164 seq_with_default = SeqWithDefault()
4165 seq_decoded, _ = seq_with_default.decode(seq_encoded)
4166 for name, value in _schema:
4167 self.assertEqual(seq_decoded[name], seq_with_default[name])
4168 self.assertEqual(seq_decoded[name], value)
4170 @given(data_strategy())
4171 def test_missing_from_spec(self, d):
4172 names = list(d.draw(sets(text_letters(), min_size=2)))
4173 tags = [tag_encode(tag) for tag in d.draw(sets(
4174 integers(min_value=0),
4175 min_size=len(names),
4176 max_size=len(names),
4178 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
4180 class SeqFull(self.base_klass):
4181 schema = [(n, Integer(impl=t)) for n, t in names_tags]
4182 seq_full = SeqFull()
4183 for i, name in enumerate(names):
4184 seq_full[name] = Integer(i)
4185 seq_encoded = seq_full.encode()
4186 altered = names_tags[:-2] + names_tags[-1:]
4188 class SeqMissing(self.base_klass):
4189 schema = [(n, Integer(impl=t)) for n, t in altered]
4190 seq_missing = SeqMissing()
4191 with self.assertRaises(TagMismatch):
4192 seq_missing.decode(seq_encoded)
4195 class TestSequence(SeqMixing, CommonMixin, TestCase):
4196 base_klass = Sequence
4202 def test_remaining(self, value, junk):
4203 class Seq(Sequence):
4205 ("whatever", Integer()),
4207 int_encoded = Integer(value).encode()
4209 Sequence.tag_default,
4210 len_encode(len(int_encoded + junk)),
4213 with assertRaisesRegex(self, DecodeError, "remaining"):
4214 Seq().decode(junked)
4216 @given(sets(text_letters(), min_size=2))
4217 def test_obj_unknown(self, names):
4218 missing = names.pop()
4220 class Seq(Sequence):
4221 schema = [(n, Boolean()) for n in names]
4223 with self.assertRaises(ObjUnknown) as err:
4226 with self.assertRaises(ObjUnknown) as err:
4227 seq[missing] = Boolean()
4231 class TestSet(SeqMixing, CommonMixin, TestCase):
4234 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4235 @given(data_strategy())
4236 def test_sorted(self, d):
4238 tag_encode(tag) for tag in
4239 d.draw(sets(integers(min_value=1), min_size=1, max_size=10))
4243 schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
4245 for name, _ in Seq.schema:
4246 seq[name] = OctetString(b"")
4247 seq_encoded = seq.encode()
4248 seq_decoded, _ = seq.decode(seq_encoded)
4249 self.assertSequenceEqual(
4250 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
4251 b"".join(sorted([seq[name].encode() for name, _ in Seq.schema])),
4256 def seqof_values_strategy(draw, schema=None, do_expl=False):
4258 schema = draw(sampled_from((Boolean(), Integer())))
4259 bound_min, bound_max = sorted(draw(sets(
4260 integers(min_value=0, max_value=10),
4264 if isinstance(schema, Boolean):
4265 values_generator = booleans().map(Boolean)
4266 elif isinstance(schema, Integer):
4267 values_generator = integers().map(Integer)
4268 values_generator = lists(
4273 values = draw(one_of(none(), values_generator))
4277 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4279 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4280 default = draw(one_of(none(), values_generator))
4281 optional = draw(one_of(none(), booleans()))
4283 draw(integers(min_value=0)),
4284 draw(integers(min_value=0)),
4285 draw(integers(min_value=0)),
4290 (bound_min, bound_max),
4299 class SeqOfMixing(object):
4300 def test_invalid_value_type(self):
4301 with self.assertRaises(InvalidValueType) as err:
4302 self.base_klass(123)
4305 def test_invalid_values_type(self):
4306 class SeqOf(self.base_klass):
4308 with self.assertRaises(InvalidValueType) as err:
4309 SeqOf([Integer(123), Boolean(False), Integer(234)])
4312 def test_schema_required(self):
4313 with assertRaisesRegex(self, ValueError, "schema must be specified"):
4314 self.base_klass.__mro__[1]()
4316 @given(booleans(), booleans(), binary(), binary())
4317 def test_comparison(self, value1, value2, tag1, tag2):
4318 class SeqOf(self.base_klass):
4320 obj1 = SeqOf([Boolean(value1)])
4321 obj2 = SeqOf([Boolean(value2)])
4322 self.assertEqual(obj1 == obj2, value1 == value2)
4323 self.assertEqual(obj1 != obj2, value1 != value2)
4324 self.assertEqual(obj1 == list(obj2), value1 == value2)
4325 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
4326 obj1 = SeqOf([Boolean(value1)], impl=tag1)
4327 obj2 = SeqOf([Boolean(value1)], impl=tag2)
4328 self.assertEqual(obj1 == obj2, tag1 == tag2)
4329 self.assertEqual(obj1 != obj2, tag1 != tag2)
4331 @given(lists(booleans()))
4332 def test_iter(self, values):
4333 class SeqOf(self.base_klass):
4335 obj = SeqOf([Boolean(value) for value in values])
4336 self.assertEqual(len(obj), len(values))
4337 for i, value in enumerate(obj):
4338 self.assertEqual(value, values[i])
4340 @given(data_strategy())
4341 def test_ready(self, d):
4342 ready = [Integer(v) for v in d.draw(lists(
4349 range(d.draw(integers(min_value=1, max_value=5)))
4352 class SeqOf(self.base_klass):
4354 values = d.draw(permutations(ready + non_ready))
4356 for value in values:
4358 self.assertFalse(seqof.ready)
4361 with self.assertRaises(ObjNotReady) as err:
4364 for i, value in enumerate(values):
4365 self.assertEqual(seqof[i], value)
4366 if not seqof[i].ready:
4367 seqof[i] = Integer(i)
4368 self.assertTrue(seqof.ready)
4372 def test_spec_mismatch(self):
4373 class SeqOf(self.base_klass):
4376 seqof.append(Integer(123))
4377 with self.assertRaises(ValueError):
4378 seqof.append(Boolean(False))
4379 with self.assertRaises(ValueError):
4380 seqof[0] = Boolean(False)
4382 @given(data_strategy())
4383 def test_bounds_satisfied(self, d):
4384 class SeqOf(self.base_klass):
4386 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
4387 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
4388 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
4389 SeqOf(value=value, bounds=(bound_min, bound_max))
4391 @given(data_strategy())
4392 def test_bounds_unsatisfied(self, d):
4393 class SeqOf(self.base_klass):
4395 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
4396 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
4397 value = [Boolean()] * d.draw(integers(max_value=bound_min - 1))
4398 with self.assertRaises(BoundsError) as err:
4399 SeqOf(value=value, bounds=(bound_min, bound_max))
4401 value = [Boolean()] * d.draw(integers(
4402 min_value=bound_max + 1,
4403 max_value=bound_max + 10,
4405 with self.assertRaises(BoundsError) as err:
4406 SeqOf(value=value, bounds=(bound_min, bound_max))
4409 @given(integers(min_value=1, max_value=10))
4410 def test_out_of_bounds(self, bound_max):
4411 class SeqOf(self.base_klass):
4413 bounds = (0, bound_max)
4415 for _ in range(bound_max):
4416 seqof.append(Integer(123))
4417 with self.assertRaises(BoundsError):
4418 seqof.append(Integer(123))
4420 @given(data_strategy())
4421 def test_call(self, d):
4431 ) = d.draw(seqof_values_strategy())
4433 class SeqOf(self.base_klass):
4434 schema = schema_initial
4435 obj_initial = SeqOf(
4436 value=value_initial,
4437 bounds=bounds_initial,
4440 default=default_initial,
4441 optional=optional_initial or False,
4442 _decoded=_decoded_initial,
4453 ) = d.draw(seqof_values_strategy(
4454 schema=schema_initial,
4455 do_expl=impl_initial is None,
4457 if (default is None) and (obj_initial.default is not None):
4460 (bounds is None) and
4461 (value is not None) and
4462 (bounds_initial is not None) and
4463 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
4467 (bounds is None) and
4468 (default is not None) and
4469 (bounds_initial is not None) and
4470 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
4482 value_expected = default if value is None else value
4484 default_initial if value_expected is None
4487 value_expected = () if value_expected is None else value_expected
4488 self.assertEqual(obj, value_expected)
4489 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4490 self.assertEqual(obj.expl_tag, expl or expl_initial)
4493 default_initial if default is None else default,
4495 if obj.default is None:
4496 optional = optional_initial if optional is None else optional
4497 optional = False if optional is None else optional
4500 self.assertEqual(obj.optional, optional)
4502 (obj._bound_min, obj._bound_max),
4503 bounds or bounds_initial or (0, float("+inf")),
4506 @given(seqof_values_strategy())
4507 def test_copy(self, values):
4508 _schema, value, bounds, impl, expl, default, optional, _decoded = values
4510 class SeqOf(self.base_klass):
4518 optional=optional or False,
4521 obj_copied = obj.copy()
4522 self.assert_copied_basic_fields(obj, obj_copied)
4523 self.assertEqual(obj._bound_min, obj_copied._bound_min)
4524 self.assertEqual(obj._bound_max, obj_copied._bound_max)
4525 self.assertEqual(obj._value, obj_copied._value)
4529 integers(min_value=1).map(tag_encode),
4531 def test_stripped(self, values, tag_impl):
4532 class SeqOf(self.base_klass):
4533 schema = OctetString()
4534 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
4535 with self.assertRaises(NotEnoughData):
4536 obj.decode(obj.encode()[:-1])
4540 integers(min_value=1).map(tag_ctxc),
4542 def test_stripped_expl(self, values, tag_expl):
4543 class SeqOf(self.base_klass):
4544 schema = OctetString()
4545 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
4546 with self.assertRaises(NotEnoughData):
4547 obj.decode(obj.encode()[:-1])
4550 integers(min_value=31),
4551 integers(min_value=0),
4554 def test_bad_tag(self, tag, offset, decode_path):
4555 decode_path = tuple(str(i) for i in decode_path)
4556 with self.assertRaises(DecodeError) as err:
4557 self.base_klass().decode(
4558 tag_encode(tag)[:-1],
4560 decode_path=decode_path,
4563 self.assertEqual(err.exception.offset, offset)
4564 self.assertEqual(err.exception.decode_path, decode_path)
4567 integers(min_value=128),
4568 integers(min_value=0),
4571 def test_bad_len(self, l, offset, decode_path):
4572 decode_path = tuple(str(i) for i in decode_path)
4573 with self.assertRaises(DecodeError) as err:
4574 self.base_klass().decode(
4575 self.base_klass.tag_default + len_encode(l)[:-1],
4577 decode_path=decode_path,
4580 self.assertEqual(err.exception.offset, offset)
4581 self.assertEqual(err.exception.decode_path, decode_path)
4583 @given(binary(min_size=1))
4584 def test_tag_mismatch(self, impl):
4585 assume(impl != self.base_klass.tag_default)
4586 with self.assertRaises(TagMismatch):
4587 self.base_klass(impl=impl).decode(self.base_klass().encode())
4589 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4591 seqof_values_strategy(schema=Integer()),
4592 lists(integers().map(Integer)),
4593 integers(min_value=1).map(tag_ctxc),
4594 integers(min_value=0),
4596 def test_symmetric(self, values, value, tag_expl, offset):
4597 _, _, _, _, _, default, optional, _decoded = values
4599 class SeqOf(self.base_klass):
4609 self.assertFalse(obj.expled)
4610 obj_encoded = obj.encode()
4611 obj_expled = obj(value, expl=tag_expl)
4612 self.assertTrue(obj_expled.expled)
4615 obj_expled_encoded = obj_expled.encode()
4616 obj_decoded, tail = obj_expled.decode(obj_expled_encoded, offset=offset)
4619 self.assertEqual(tail, b"")
4620 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
4621 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4622 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4623 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4625 obj_decoded.expl_llen,
4626 len(len_encode(len(obj_encoded))),
4628 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4629 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4632 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4634 self.assertEqual(obj_decoded.expl_offset, offset)
4635 for obj_inner in obj_decoded:
4636 self.assertIn(obj_inner, obj_decoded)
4637 self.assertSequenceEqual(
4640 obj_inner.offset - offset:
4641 obj_inner.offset + obj_inner.tlvlen - offset
4646 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
4647 class SeqOf(SequenceOf):
4651 def _test_symmetric_compare_objs(self, obj1, obj2):
4652 self.assertEqual(obj1, obj2)
4653 self.assertSequenceEqual(list(obj1), list(obj2))
4656 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
4661 def _test_symmetric_compare_objs(self, obj1, obj2):
4662 self.assertSetEqual(
4663 set(int(v) for v in obj1),
4664 set(int(v) for v in obj2),
4667 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4668 @given(data_strategy())
4669 def test_sorted(self, d):
4670 values = [OctetString(v) for v in d.draw(lists(binary()))]
4673 schema = OctetString()
4675 seq_encoded = seq.encode()
4676 seq_decoded, _ = seq.decode(seq_encoded)
4677 self.assertSequenceEqual(
4678 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
4679 b"".join(sorted([v.encode() for v in values])),
4683 class TestGoMarshalVectors(TestCase):
4685 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
4686 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
4687 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
4688 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
4689 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
4691 class Seq(Sequence):
4693 ("erste", Integer()),
4694 ("zweite", Integer(optional=True))
4697 seq["erste"] = Integer(64)
4698 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
4699 seq["erste"] = Integer(0x123456)
4700 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
4701 seq["erste"] = Integer(64)
4702 seq["zweite"] = Integer(65)
4703 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
4705 class NestedSeq(Sequence):
4709 seq["erste"] = Integer(127)
4710 seq["zweite"] = None
4711 nested = NestedSeq()
4712 nested["nest"] = seq
4713 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
4715 self.assertSequenceEqual(
4716 OctetString(b"\x01\x02\x03").encode(),
4717 hexdec("0403010203"),
4720 class Seq(Sequence):
4722 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
4725 seq["erste"] = Integer(64)
4726 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
4728 class Seq(Sequence):
4730 ("erste", Integer(expl=tag_ctxc(5))),
4733 seq["erste"] = Integer(64)
4734 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
4736 class Seq(Sequence):
4739 impl=tag_encode(0, klass=TagClassContext),
4744 seq["erste"] = Null()
4745 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
4747 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
4749 self.assertSequenceEqual(
4750 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
4751 hexdec("170d3730303130313030303030305a"),
4753 self.assertSequenceEqual(
4754 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
4755 hexdec("170d3039313131353232353631365a"),
4757 self.assertSequenceEqual(
4758 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
4759 hexdec("180f32313030303430353132303130315a"),
4762 class Seq(Sequence):
4764 ("erste", GeneralizedTime()),
4767 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
4768 self.assertSequenceEqual(
4770 hexdec("3011180f32303039313131353232353631365a"),
4773 self.assertSequenceEqual(
4774 BitString((1, b"\x80")).encode(),
4777 self.assertSequenceEqual(
4778 BitString((12, b"\x81\xF0")).encode(),
4779 hexdec("03030481f0"),
4782 self.assertSequenceEqual(
4783 ObjectIdentifier("1.2.3.4").encode(),
4784 hexdec("06032a0304"),
4786 self.assertSequenceEqual(
4787 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
4788 hexdec("06092a864888932d010105"),
4790 self.assertSequenceEqual(
4791 ObjectIdentifier("2.100.3").encode(),
4792 hexdec("0603813403"),
4795 self.assertSequenceEqual(
4796 PrintableString("test").encode(),
4797 hexdec("130474657374"),
4799 self.assertSequenceEqual(
4800 PrintableString("x" * 127).encode(),
4801 hexdec("137F" + "78" * 127),
4803 self.assertSequenceEqual(
4804 PrintableString("x" * 128).encode(),
4805 hexdec("138180" + "78" * 128),
4807 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
4809 class Seq(Sequence):
4811 ("erste", IA5String()),
4814 seq["erste"] = IA5String("test")
4815 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
4817 class Seq(Sequence):
4819 ("erste", PrintableString()),
4822 seq["erste"] = PrintableString("test")
4823 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
4824 seq["erste"] = PrintableString("test*")
4825 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
4827 class Seq(Sequence):
4829 ("erste", Any(optional=True)),
4830 ("zweite", Integer()),
4833 seq["zweite"] = Integer(64)
4834 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
4839 seq.append(Integer(10))
4840 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
4842 class _SeqOf(SequenceOf):
4843 schema = PrintableString()
4845 class SeqOf(SequenceOf):
4848 _seqof.append(PrintableString("1"))
4850 seqof.append(_seqof)
4851 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
4853 class Seq(Sequence):
4855 ("erste", Integer(default=1)),
4858 seq["erste"] = Integer(0)
4859 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
4860 seq["erste"] = Integer(1)
4861 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
4862 seq["erste"] = Integer(2)
4863 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
4866 class TestPP(TestCase):
4867 @given(data_strategy())
4868 def test_oid_printing(self, d):
4870 str(ObjectIdentifier(k)): v * 2
4871 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
4873 chosen = d.draw(sampled_from(sorted(oids)))
4874 chosen_id = oids[chosen]
4875 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
4876 self.assertNotIn(chosen_id, pp_console_row(pp))
4877 self.assertIn(chosen_id, pp_console_row(pp, oids=oids))
4880 class TestAutoAddSlots(TestCase):
4882 class Inher(Integer):
4885 with self.assertRaises(AttributeError):
4887 inher.unexistent = "whatever"
4890 class TestOIDDefines(TestCase):
4891 @given(data_strategy())
4892 def runTest(self, d):
4893 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
4894 value_name_chosen = d.draw(sampled_from(value_names))
4896 ObjectIdentifier(oid)
4897 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
4899 oid_chosen = d.draw(sampled_from(oids))
4900 values = d.draw(lists(
4902 min_size=len(value_names),
4903 max_size=len(value_names),
4906 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
4907 oid: Integer() for oid in oids[:-1]
4910 for i, value_name in enumerate(value_names):
4911 _schema.append((value_name, Any(expl=tag_ctxp(i))))
4913 class Seq(Sequence):
4916 for value_name, value in zip(value_names, values):
4917 seq[value_name] = Any(Integer(value).encode())
4918 seq["type"] = oid_chosen
4919 seq, _ = Seq().decode(seq.encode())
4920 for value_name in value_names:
4921 if value_name == value_name_chosen:
4923 self.assertIsNone(seq[value_name].defined)
4924 if value_name_chosen in oids[:-1]:
4925 self.assertIsNotNone(seq[value_name_chosen].defined)
4926 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
4927 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
4930 class TestDefinesByPath(TestCase):
4931 def test_generated(self):
4932 class Seq(Sequence):
4934 ("type", ObjectIdentifier()),
4935 ("value", OctetString(expl=tag_ctxc(123))),
4938 class SeqInner(Sequence):
4940 ("typeInner", ObjectIdentifier()),
4941 ("valueInner", Any()),
4944 class PairValue(SetOf):
4947 class Pair(Sequence):
4949 ("type", ObjectIdentifier()),
4950 ("value", PairValue()),
4953 class Pairs(SequenceOf):
4960 type_octet_stringed,
4962 ObjectIdentifier(oid)
4963 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
4965 seq_integered = Seq()
4966 seq_integered["type"] = type_integered
4967 seq_integered["value"] = OctetString(Integer(123).encode())
4968 seq_integered_raw = seq_integered.encode()
4972 (type_octet_stringed, OctetString(b"whatever")),
4973 (type_integered, Integer(123)),
4974 (type_octet_stringed, OctetString(b"whenever")),
4975 (type_integered, Integer(234)),
4977 for t, v in pairs_input:
4980 pair["value"] = PairValue((Any(v),))
4982 seq_inner = SeqInner()
4983 seq_inner["typeInner"] = type_innered
4984 seq_inner["valueInner"] = Any(pairs)
4985 seq_sequenced = Seq()
4986 seq_sequenced["type"] = type_sequenced
4987 seq_sequenced["value"] = OctetString(seq_inner.encode())
4988 seq_sequenced_raw = seq_sequenced.encode()
4990 defines_by_path = []
4991 seq_integered, _ = Seq().decode(seq_integered_raw)
4992 self.assertIsNone(seq_integered["value"].defined)
4993 defines_by_path.append(
4994 (("type",), ((("value",), {
4995 type_integered: Integer(),
4996 type_sequenced: SeqInner(),
4999 seq_integered, _ = Seq().decode(
5001 ctx={"defines_by_path": defines_by_path},
5003 self.assertIsNotNone(seq_integered["value"].defined)
5004 self.assertEqual(seq_integered["value"].defined[0], type_integered)
5005 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
5006 self.assertTrue(seq_integered_raw[
5007 seq_integered["value"].defined[1].offset:
5008 ].startswith(Integer(123).encode()))
5010 seq_sequenced, _ = Seq().decode(
5012 ctx={"defines_by_path": defines_by_path},
5014 self.assertIsNotNone(seq_sequenced["value"].defined)
5015 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
5016 seq_inner = seq_sequenced["value"].defined[1]
5017 self.assertIsNone(seq_inner["valueInner"].defined)
5019 defines_by_path.append((
5020 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
5021 ((("valueInner",), {type_innered: Pairs()}),),
5023 seq_sequenced, _ = Seq().decode(
5025 ctx={"defines_by_path": defines_by_path},
5027 self.assertIsNotNone(seq_sequenced["value"].defined)
5028 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
5029 seq_inner = seq_sequenced["value"].defined[1]
5030 self.assertIsNotNone(seq_inner["valueInner"].defined)
5031 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
5032 pairs = seq_inner["valueInner"].defined[1]
5034 self.assertIsNone(pair["value"][0].defined)
5036 defines_by_path.append((
5039 DecodePathDefBy(type_sequenced),
5041 DecodePathDefBy(type_innered),
5046 type_integered: Integer(),
5047 type_octet_stringed: OctetString(),
5050 seq_sequenced, _ = Seq().decode(
5052 ctx={"defines_by_path": defines_by_path},
5054 self.assertIsNotNone(seq_sequenced["value"].defined)
5055 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
5056 seq_inner = seq_sequenced["value"].defined[1]
5057 self.assertIsNotNone(seq_inner["valueInner"].defined)
5058 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
5059 pairs_got = seq_inner["valueInner"].defined[1]
5060 for pair_input, pair_got in zip(pairs_input, pairs_got):
5061 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
5062 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
5064 @given(oid_strategy(), integers())
5065 def test_simple(self, oid, tgt):
5066 class Inner(Sequence):
5068 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
5069 ObjectIdentifier(oid): Integer(),
5073 class Outer(Sequence):
5076 ("tgt", OctetString()),
5080 inner["oid"] = ObjectIdentifier(oid)
5082 outer["inner"] = inner
5083 outer["tgt"] = OctetString(Integer(tgt).encode())
5084 decoded, _ = Outer().decode(outer.encode())
5085 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
5088 class TestAbsDecodePath(TestCase):
5090 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
5091 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
5093 def test_concat(self, decode_path, rel_path):
5094 self.assertSequenceEqual(
5095 abs_decode_path(decode_path, rel_path),
5096 decode_path + rel_path,
5100 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
5101 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
5103 def test_abs(self, decode_path, rel_path):
5104 self.assertSequenceEqual(
5105 abs_decode_path(decode_path, ("/",) + rel_path),
5110 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
5111 integers(min_value=1, max_value=3),
5112 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
5114 def test_dots(self, decode_path, number_of_dots, rel_path):
5115 self.assertSequenceEqual(
5116 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
5117 decode_path[:-number_of_dots] + rel_path,
5121 class TestStrictDefaultExistence(TestCase):
5122 @given(data_strategy())
5123 def runTest(self, d):
5124 count = d.draw(integers(min_value=1, max_value=10))
5125 chosen = d.draw(integers(min_value=0, max_value=count - 1))
5127 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
5128 for i in range(count)
5131 class Seq(Sequence):
5134 for i in range(count):
5135 seq["int%d" % i] = Integer(123)
5137 chosen = "int%d" % chosen
5138 seq.specs[chosen] = seq.specs[chosen](default=123)
5140 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
5141 seq.decode(raw, ctx={"strict_default_existence": True})