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 digits
22 from string import printable
23 from string import whitespace
24 from unittest import TestCase
26 from hypothesis import assume
27 from hypothesis import given
28 from hypothesis import settings
29 from hypothesis.strategies import binary
30 from hypothesis.strategies import booleans
31 from hypothesis.strategies import composite
32 from hypothesis.strategies import data as data_strategy
33 from hypothesis.strategies import datetimes
34 from hypothesis.strategies import dictionaries
35 from hypothesis.strategies import integers
36 from hypothesis.strategies import just
37 from hypothesis.strategies import lists
38 from hypothesis.strategies import none
39 from hypothesis.strategies import one_of
40 from hypothesis.strategies import permutations
41 from hypothesis.strategies import sampled_from
42 from hypothesis.strategies import sets
43 from hypothesis.strategies import text
44 from hypothesis.strategies import tuples
45 from six import assertRaisesRegex
46 from six import byte2int
47 from six import indexbytes
48 from six import int2byte
49 from six import iterbytes
51 from six import text_type
52 from six import unichr as six_unichr
54 from pyderasn import _pp
55 from pyderasn import abs_decode_path
56 from pyderasn import Any
57 from pyderasn import BitString
58 from pyderasn import BMPString
59 from pyderasn import Boolean
60 from pyderasn import BoundsError
61 from pyderasn import Choice
62 from pyderasn import DecodeError
63 from pyderasn import DecodePathDefBy
64 from pyderasn import Enumerated
65 from pyderasn import GeneralizedTime
66 from pyderasn import GeneralString
67 from pyderasn import GraphicString
68 from pyderasn import hexdec
69 from pyderasn import hexenc
70 from pyderasn import IA5String
71 from pyderasn import Integer
72 from pyderasn import InvalidLength
73 from pyderasn import InvalidOID
74 from pyderasn import InvalidValueType
75 from pyderasn import len_decode
76 from pyderasn import len_encode
77 from pyderasn import NotEnoughData
78 from pyderasn import Null
79 from pyderasn import NumericString
80 from pyderasn import ObjectIdentifier
81 from pyderasn import ObjNotReady
82 from pyderasn import ObjUnknown
83 from pyderasn import OctetString
84 from pyderasn import pp_console_row
85 from pyderasn import pprint
86 from pyderasn import PrintableString
87 from pyderasn import Sequence
88 from pyderasn import SequenceOf
89 from pyderasn import Set
90 from pyderasn import SetOf
91 from pyderasn import tag_ctxc
92 from pyderasn import tag_ctxp
93 from pyderasn import tag_decode
94 from pyderasn import tag_encode
95 from pyderasn import tag_strip
96 from pyderasn import TagClassApplication
97 from pyderasn import TagClassContext
98 from pyderasn import TagClassPrivate
99 from pyderasn import TagClassUniversal
100 from pyderasn import TagFormConstructed
101 from pyderasn import TagFormPrimitive
102 from pyderasn import TagMismatch
103 from pyderasn import TeletexString
104 from pyderasn import UniversalString
105 from pyderasn import UTCTime
106 from pyderasn import UTF8String
107 from pyderasn import VideotexString
108 from pyderasn import VisibleString
111 settings.register_profile("local", settings(
113 perform_health_check=False,
115 settings.load_profile("local")
116 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
118 tag_classes = sampled_from((
124 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
127 class TestHex(TestCase):
129 def test_symmetric(self, data):
130 self.assertEqual(hexdec(hexenc(data)), data)
133 class TestTagCoder(TestCase):
134 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
138 integers(min_value=0, max_value=30),
141 def test_short(self, klass, form, num, junk):
142 raw = tag_encode(klass=klass, form=form, num=num)
143 self.assertEqual(tag_decode(raw), (klass, form, num))
144 self.assertEqual(len(raw), 1)
146 byte2int(tag_encode(klass=klass, form=form, num=0)),
147 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
149 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
150 self.assertSequenceEqual(stripped.tobytes(), raw)
151 self.assertEqual(tlen, len(raw))
152 self.assertSequenceEqual(tail, junk)
154 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
158 integers(min_value=31),
161 def test_long(self, klass, form, num, junk):
162 raw = tag_encode(klass=klass, form=form, num=num)
163 self.assertEqual(tag_decode(raw), (klass, form, num))
164 self.assertGreater(len(raw), 1)
166 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
169 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
170 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
171 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
172 self.assertSequenceEqual(stripped.tobytes(), raw)
173 self.assertEqual(tlen, len(raw))
174 self.assertSequenceEqual(tail, junk)
176 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
177 @given(integers(min_value=31))
178 def test_unfinished_tag(self, num):
179 raw = bytearray(tag_encode(num=num))
180 for i in range(1, len(raw)):
182 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
183 tag_strip(bytes(raw))
185 def test_go_vectors_valid(self):
186 for data, (eklass, etag, elen, eform) in (
187 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
188 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
189 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
190 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
191 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
192 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
193 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
194 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
195 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
196 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
198 tag, _, len_encoded = tag_strip(memoryview(data))
199 klass, form, num = tag_decode(tag)
200 _len, _, tail = len_decode(len_encoded)
201 self.assertSequenceEqual(tail, b"")
202 self.assertEqual(klass, eklass)
203 self.assertEqual(num, etag)
204 self.assertEqual(_len, elen)
205 self.assertEqual(form, eform)
207 def test_go_vectors_invalid(self):
215 with self.assertRaises(DecodeError):
216 _, _, len_encoded = tag_strip(memoryview(data))
217 len_decode(len_encoded)
220 integers(min_value=0, max_value=127),
221 integers(min_value=0, max_value=2),
223 def test_long_instead_of_short(self, l, dummy_num):
224 octets = (b"\x00" * dummy_num) + int2byte(l)
225 octets = int2byte((dummy_num + 1) | 0x80) + octets
226 with self.assertRaises(DecodeError):
230 class TestLenCoder(TestCase):
231 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
233 integers(min_value=0, max_value=127),
236 def test_short(self, l, junk):
237 raw = len_encode(l) + junk
238 decoded, llen, tail = len_decode(memoryview(raw))
239 self.assertEqual(decoded, l)
240 self.assertEqual(llen, 1)
241 self.assertEqual(len(raw), 1 + len(junk))
242 self.assertEqual(tail.tobytes(), junk)
244 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
246 integers(min_value=128),
249 def test_long(self, l, junk):
250 raw = len_encode(l) + junk
251 decoded, llen, tail = len_decode(memoryview(raw))
252 self.assertEqual(decoded, l)
253 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
254 self.assertEqual(llen, len(raw) - len(junk))
255 self.assertNotEqual(indexbytes(raw, 1), 0)
256 self.assertSequenceEqual(tail.tobytes(), junk)
258 def test_empty(self):
259 with self.assertRaises(NotEnoughData):
262 @given(integers(min_value=128))
263 def test_stripped(self, _len):
264 with self.assertRaises(NotEnoughData):
265 len_decode(len_encode(_len)[:-1])
268 text_printable = text(alphabet=printable, min_size=1)
272 def text_letters(draw):
273 result = draw(text(alphabet=ascii_letters, min_size=1))
275 result = result.encode("ascii")
279 class CommonMixin(object):
280 def test_tag_default(self):
281 obj = self.base_klass()
282 self.assertEqual(obj.tag, obj.tag_default)
284 def test_simultaneous_impl_expl(self):
285 with self.assertRaises(ValueError):
286 self.base_klass(impl=b"whatever", expl=b"whenever")
288 @given(binary(min_size=1), integers(), integers(), integers())
289 def test_decoded(self, impl, offset, llen, vlen):
290 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
291 self.assertEqual(obj.offset, offset)
292 self.assertEqual(obj.llen, llen)
293 self.assertEqual(obj.vlen, vlen)
294 self.assertEqual(obj.tlen, len(impl))
295 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
297 @given(binary(min_size=1))
298 def test_impl_inherited(self, impl_tag):
299 class Inherited(self.base_klass):
302 self.assertSequenceEqual(obj.impl, impl_tag)
303 self.assertFalse(obj.expled)
306 def test_expl_inherited(self, expl_tag):
307 class Inherited(self.base_klass):
310 self.assertSequenceEqual(obj.expl, expl_tag)
311 self.assertTrue(obj.expled)
313 def assert_copied_basic_fields(self, obj, obj_copied):
314 self.assertEqual(obj, obj_copied)
315 self.assertSequenceEqual(obj.tag, obj_copied.tag)
316 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
317 self.assertEqual(obj.default, obj_copied.default)
318 self.assertEqual(obj.optional, obj_copied.optional)
319 self.assertEqual(obj.offset, obj_copied.offset)
320 self.assertEqual(obj.llen, obj_copied.llen)
321 self.assertEqual(obj.vlen, obj_copied.vlen)
325 def boolean_values_strategy(draw, do_expl=False):
326 value = draw(one_of(none(), booleans()))
330 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
332 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
333 default = draw(one_of(none(), booleans()))
334 optional = draw(one_of(none(), booleans()))
336 draw(integers(min_value=0)),
337 draw(integers(min_value=0)),
338 draw(integers(min_value=0)),
340 return (value, impl, expl, default, optional, _decoded)
343 class BooleanInherited(Boolean):
347 class TestBoolean(CommonMixin, TestCase):
350 def test_invalid_value_type(self):
351 with self.assertRaises(InvalidValueType) as err:
356 def test_optional(self, optional):
357 obj = Boolean(default=Boolean(False), optional=optional)
358 self.assertTrue(obj.optional)
361 def test_ready(self, value):
363 self.assertFalse(obj.ready)
366 with self.assertRaises(ObjNotReady) as err:
370 self.assertTrue(obj.ready)
374 @given(booleans(), booleans(), binary(), binary())
375 def test_comparison(self, value1, value2, tag1, tag2):
376 for klass in (Boolean, BooleanInherited):
379 self.assertEqual(obj1 == obj2, value1 == value2)
380 self.assertEqual(obj1 != obj2, value1 != value2)
381 self.assertEqual(obj1 == bool(obj2), value1 == value2)
382 obj1 = klass(value1, impl=tag1)
383 obj2 = klass(value1, impl=tag2)
384 self.assertEqual(obj1 == obj2, tag1 == tag2)
385 self.assertEqual(obj1 != obj2, tag1 != tag2)
387 @given(data_strategy())
388 def test_call(self, d):
389 for klass in (Boolean, BooleanInherited):
397 ) = d.draw(boolean_values_strategy())
403 optional_initial or False,
413 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
414 obj = obj_initial(value, impl, expl, default, optional)
416 value_expected = default if value is None else value
418 default_initial if value_expected is None
421 self.assertEqual(obj, value_expected)
422 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
423 self.assertEqual(obj.expl_tag, expl or expl_initial)
426 default_initial if default is None else default,
428 if obj.default is None:
429 optional = optional_initial if optional is None else optional
430 optional = False if optional is None else optional
433 self.assertEqual(obj.optional, optional)
435 @given(boolean_values_strategy())
436 def test_copy(self, values):
437 for klass in (Boolean, BooleanInherited):
439 obj_copied = obj.copy()
440 self.assert_copied_basic_fields(obj, obj_copied)
444 integers(min_value=1).map(tag_encode),
446 def test_stripped(self, value, tag_impl):
447 obj = Boolean(value, impl=tag_impl)
448 with self.assertRaises(NotEnoughData):
449 obj.decode(obj.encode()[:-1])
453 integers(min_value=1).map(tag_ctxc),
455 def test_stripped_expl(self, value, tag_expl):
456 obj = Boolean(value, expl=tag_expl)
457 with self.assertRaises(NotEnoughData):
458 obj.decode(obj.encode()[:-1])
461 integers(min_value=31),
462 integers(min_value=0),
465 def test_bad_tag(self, tag, offset, decode_path):
466 decode_path = tuple(str(i) for i in decode_path)
467 with self.assertRaises(DecodeError) as err:
469 tag_encode(tag)[:-1],
471 decode_path=decode_path,
474 self.assertEqual(err.exception.offset, offset)
475 self.assertEqual(err.exception.decode_path, decode_path)
478 integers(min_value=31),
479 integers(min_value=0),
482 def test_bad_expl_tag(self, tag, offset, decode_path):
483 decode_path = tuple(str(i) for i in decode_path)
484 with self.assertRaises(DecodeError) as err:
485 Boolean(expl=Boolean.tag_default).decode(
486 tag_encode(tag)[:-1],
488 decode_path=decode_path,
491 self.assertEqual(err.exception.offset, offset)
492 self.assertEqual(err.exception.decode_path, decode_path)
495 integers(min_value=128),
496 integers(min_value=0),
499 def test_bad_len(self, l, offset, decode_path):
500 decode_path = tuple(str(i) for i in decode_path)
501 with self.assertRaises(DecodeError) as err:
503 Boolean.tag_default + len_encode(l)[:-1],
505 decode_path=decode_path,
508 self.assertEqual(err.exception.offset, offset)
509 self.assertEqual(err.exception.decode_path, decode_path)
512 integers(min_value=128),
513 integers(min_value=0),
516 def test_bad_expl_len(self, l, offset, decode_path):
517 decode_path = tuple(str(i) for i in decode_path)
518 with self.assertRaises(DecodeError) as err:
519 Boolean(expl=Boolean.tag_default).decode(
520 Boolean.tag_default + len_encode(l)[:-1],
522 decode_path=decode_path,
525 self.assertEqual(err.exception.offset, offset)
526 self.assertEqual(err.exception.decode_path, decode_path)
528 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
530 boolean_values_strategy(),
532 integers(min_value=1).map(tag_ctxc),
533 integers(min_value=0),
536 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
537 for klass in (Boolean, BooleanInherited):
538 _, _, _, default, optional, _decoded = values
547 self.assertFalse(obj.expled)
548 obj_encoded = obj.encode()
549 obj_expled = obj(value, expl=tag_expl)
550 self.assertTrue(obj_expled.expled)
553 obj_expled_encoded = obj_expled.encode()
554 obj_decoded, tail = obj_expled.decode(
555 obj_expled_encoded + tail_junk,
560 self.assertEqual(tail, tail_junk)
561 self.assertEqual(obj_decoded, obj_expled)
562 self.assertNotEqual(obj_decoded, obj)
563 self.assertEqual(bool(obj_decoded), bool(obj_expled))
564 self.assertEqual(bool(obj_decoded), bool(obj))
565 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
566 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
567 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
569 obj_decoded.expl_llen,
570 len(len_encode(len(obj_encoded))),
572 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
573 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
576 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
578 self.assertEqual(obj_decoded.expl_offset, offset)
580 @given(integers(min_value=2))
581 def test_invalid_len(self, l):
582 with self.assertRaises(InvalidLength):
583 Boolean().decode(b"".join((
589 @given(integers(min_value=0 + 1, max_value=255 - 1))
590 def test_invalid_value(self, value):
591 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
592 Boolean().decode(b"".join((
600 def integer_values_strategy(draw, do_expl=False):
601 bound_min, value, default, bound_max = sorted(draw(sets(
610 _specs = draw(sets(text_letters()))
613 min_size=len(_specs),
614 max_size=len(_specs),
616 _specs = list(zip(_specs, values))
619 bounds = (bound_min, bound_max)
623 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
625 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
628 optional = draw(one_of(none(), booleans()))
630 draw(integers(min_value=0)),
631 draw(integers(min_value=0)),
632 draw(integers(min_value=0)),
634 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
637 class IntegerInherited(Integer):
641 class TestInteger(CommonMixin, TestCase):
644 def test_invalid_value_type(self):
645 with self.assertRaises(InvalidValueType) as err:
649 @given(sets(text_letters(), min_size=2))
650 def test_unknown_name(self, names_input):
651 missing = names_input.pop()
654 schema = [(n, 123) for n in names_input]
655 with self.assertRaises(ObjUnknown) as err:
659 @given(sets(text_letters(), min_size=2))
660 def test_known_name(self, names_input):
662 schema = [(n, 123) for n in names_input]
663 Int(names_input.pop())
666 def test_optional(self, optional):
667 obj = Integer(default=Integer(0), optional=optional)
668 self.assertTrue(obj.optional)
671 def test_ready(self, value):
673 self.assertFalse(obj.ready)
676 with self.assertRaises(ObjNotReady) as err:
680 self.assertTrue(obj.ready)
685 @given(integers(), integers(), binary(), binary())
686 def test_comparison(self, value1, value2, tag1, tag2):
687 for klass in (Integer, IntegerInherited):
690 self.assertEqual(obj1 == obj2, value1 == value2)
691 self.assertEqual(obj1 != obj2, value1 != value2)
692 self.assertEqual(obj1 == int(obj2), value1 == value2)
693 obj1 = klass(value1, impl=tag1)
694 obj2 = klass(value1, impl=tag2)
695 self.assertEqual(obj1 == obj2, tag1 == tag2)
696 self.assertEqual(obj1 != obj2, tag1 != tag2)
698 @given(lists(integers()))
699 def test_sorted_works(self, values):
700 self.assertSequenceEqual(
701 [int(v) for v in sorted(Integer(v) for v in values)],
705 @given(data_strategy())
706 def test_named(self, d):
707 names_input = list(d.draw(sets(text_letters(), min_size=1)))
708 values_input = list(d.draw(sets(
710 min_size=len(names_input),
711 max_size=len(names_input),
713 chosen_name = d.draw(sampled_from(names_input))
714 names_input = dict(zip(names_input, values_input))
718 _int = Int(chosen_name)
719 self.assertEqual(_int.named, chosen_name)
720 self.assertEqual(int(_int), names_input[chosen_name])
722 @given(integers(), integers(min_value=0), integers(min_value=0))
723 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
724 value = bound_min + value_delta
725 bound_max = value + bound_delta
726 Integer(value=value, bounds=(bound_min, bound_max))
728 @given(sets(integers(), min_size=3, max_size=3))
729 def test_bounds_unsatisfied(self, values):
730 values = sorted(values)
731 with self.assertRaises(BoundsError) as err:
732 Integer(value=values[0], bounds=(values[1], values[2]))
734 with self.assertRaises(BoundsError) as err:
735 Integer(value=values[2], bounds=(values[0], values[1]))
738 @given(data_strategy())
739 def test_call(self, d):
740 for klass in (Integer, IntegerInherited):
750 ) = d.draw(integer_values_strategy())
757 optional_initial or False,
770 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
771 if (default is None) and (obj_initial.default is not None):
775 (value is not None) and
776 (bounds_initial is not None) and
777 not (bounds_initial[0] <= value <= bounds_initial[1])
782 (default is not None) and
783 (bounds_initial is not None) and
784 not (bounds_initial[0] <= default <= bounds_initial[1])
787 obj = obj_initial(value, bounds, impl, expl, default, optional)
789 value_expected = default if value is None else value
791 default_initial if value_expected is None
794 self.assertEqual(obj, value_expected)
795 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
796 self.assertEqual(obj.expl_tag, expl or expl_initial)
799 default_initial if default is None else default,
801 if obj.default is None:
802 optional = optional_initial if optional is None else optional
803 optional = False if optional is None else optional
806 self.assertEqual(obj.optional, optional)
808 (obj._bound_min, obj._bound_max),
809 bounds or bounds_initial or (float("-inf"), float("+inf")),
813 {} if _specs_initial is None else dict(_specs_initial),
816 @given(integer_values_strategy())
817 def test_copy(self, values):
818 for klass in (Integer, IntegerInherited):
820 obj_copied = obj.copy()
821 self.assert_copied_basic_fields(obj, obj_copied)
822 self.assertEqual(obj.specs, obj_copied.specs)
823 self.assertEqual(obj._bound_min, obj_copied._bound_min)
824 self.assertEqual(obj._bound_max, obj_copied._bound_max)
825 self.assertEqual(obj._value, obj_copied._value)
829 integers(min_value=1).map(tag_encode),
831 def test_stripped(self, value, tag_impl):
832 obj = Integer(value, impl=tag_impl)
833 with self.assertRaises(NotEnoughData):
834 obj.decode(obj.encode()[:-1])
838 integers(min_value=1).map(tag_ctxc),
840 def test_stripped_expl(self, value, tag_expl):
841 obj = Integer(value, expl=tag_expl)
842 with self.assertRaises(NotEnoughData):
843 obj.decode(obj.encode()[:-1])
845 def test_zero_len(self):
846 with self.assertRaises(NotEnoughData):
847 Integer().decode(b"".join((
853 integers(min_value=31),
854 integers(min_value=0),
857 def test_bad_tag(self, tag, offset, decode_path):
858 decode_path = tuple(str(i) for i in decode_path)
859 with self.assertRaises(DecodeError) as err:
861 tag_encode(tag)[:-1],
863 decode_path=decode_path,
866 self.assertEqual(err.exception.offset, offset)
867 self.assertEqual(err.exception.decode_path, decode_path)
870 integers(min_value=128),
871 integers(min_value=0),
874 def test_bad_len(self, l, offset, decode_path):
875 decode_path = tuple(str(i) for i in decode_path)
876 with self.assertRaises(DecodeError) as err:
878 Integer.tag_default + len_encode(l)[:-1],
880 decode_path=decode_path,
883 self.assertEqual(err.exception.offset, offset)
884 self.assertEqual(err.exception.decode_path, decode_path)
887 sets(integers(), min_size=2, max_size=2),
888 integers(min_value=0),
891 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
892 decode_path = tuple(str(i) for i in decode_path)
893 value, bound_min = list(sorted(ints))
896 bounds = (bound_min, bound_min)
897 with self.assertRaises(DecodeError) as err:
899 Integer(value).encode(),
901 decode_path=decode_path,
904 self.assertEqual(err.exception.offset, offset)
905 self.assertEqual(err.exception.decode_path, decode_path)
907 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
909 integer_values_strategy(),
911 integers(min_value=1).map(tag_ctxc),
912 integers(min_value=0),
915 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
916 for klass in (Integer, IntegerInherited):
917 _, _, _, _, default, optional, _, _decoded = values
926 self.assertFalse(obj.expled)
927 obj_encoded = obj.encode()
928 obj_expled = obj(value, expl=tag_expl)
929 self.assertTrue(obj_expled.expled)
932 obj_expled_encoded = obj_expled.encode()
933 obj_decoded, tail = obj_expled.decode(
934 obj_expled_encoded + tail_junk,
939 self.assertEqual(tail, tail_junk)
940 self.assertEqual(obj_decoded, obj_expled)
941 self.assertNotEqual(obj_decoded, obj)
942 self.assertEqual(int(obj_decoded), int(obj_expled))
943 self.assertEqual(int(obj_decoded), int(obj))
944 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
945 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
946 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
948 obj_decoded.expl_llen,
949 len(len_encode(len(obj_encoded))),
951 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
952 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
955 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
957 self.assertEqual(obj_decoded.expl_offset, offset)
959 def test_go_vectors_valid(self):
960 for data, expect in ((
972 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
973 (b"\x80\x00\x00\x00", -2147483648),
976 Integer().decode(b"".join((
978 len_encode(len(data)),
984 def test_go_vectors_invalid(self):
989 with self.assertRaises(DecodeError):
990 Integer().decode(b"".join((
992 len_encode(len(data)),
998 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1001 if draw(booleans()):
1002 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1004 integers(min_value=0, max_value=255),
1005 min_size=len(schema),
1006 max_size=len(schema),
1008 schema = list(zip(schema, bits))
1010 def _value(value_required):
1011 if not value_required and draw(booleans()):
1013 generation_choice = 0
1015 generation_choice = draw(sampled_from((1, 2, 3)))
1016 if generation_choice == 1 or draw(booleans()):
1017 return "'%s'B" % "".join(draw(lists(
1018 sampled_from(("0", "1")),
1019 max_size=len(schema),
1021 elif generation_choice == 2 or draw(booleans()):
1022 return draw(binary(max_size=len(schema) // 8))
1023 elif generation_choice == 3 or draw(booleans()):
1024 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1026 value = _value(value_required)
1027 default = _value(value_required=False)
1031 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1033 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1034 optional = draw(one_of(none(), booleans()))
1036 draw(integers(min_value=0)),
1037 draw(integers(min_value=0)),
1038 draw(integers(min_value=0)),
1040 return (schema, value, impl, expl, default, optional, _decoded)
1043 class BitStringInherited(BitString):
1047 class TestBitString(CommonMixin, TestCase):
1048 base_klass = BitString
1050 @given(lists(booleans()))
1051 def test_b_encoding(self, bits):
1052 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1053 self.assertEqual(obj.bit_len, len(bits))
1054 self.assertSequenceEqual(list(obj), bits)
1055 for i, bit in enumerate(bits):
1056 self.assertEqual(obj[i], bit)
1058 @given(lists(booleans()))
1059 def test_out_of_bounds_bits(self, bits):
1060 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1061 for i in range(len(bits), len(bits) * 2):
1062 self.assertFalse(obj[i])
1064 def test_bad_b_encoding(self):
1065 with self.assertRaises(ValueError):
1066 BitString("'010120101'B")
1069 integers(min_value=1, max_value=255),
1070 integers(min_value=1, max_value=255),
1072 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1073 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1074 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1075 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1077 class BS(BitString):
1078 schema = (("whatever", 0),)
1079 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1080 self.assertEqual(obj.bit_len, leading_zeros + 1)
1081 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1083 def test_zero_len(self):
1084 with self.assertRaises(NotEnoughData):
1085 BitString().decode(b"".join((
1086 BitString.tag_default,
1090 def test_invalid_value_type(self):
1091 with self.assertRaises(InvalidValueType) as err:
1094 with self.assertRaises(InvalidValueType) as err:
1098 def test_obj_unknown(self):
1099 with self.assertRaises(ObjUnknown) as err:
1100 BitString(b"whatever")["whenever"]
1103 def test_get_invalid_type(self):
1104 with self.assertRaises(InvalidValueType) as err:
1105 BitString(b"whatever")[(1, 2, 3)]
1108 @given(data_strategy())
1109 def test_unknown_name(self, d):
1110 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1111 missing = _schema.pop()
1113 class BS(BitString):
1114 schema = [(n, i) for i, n in enumerate(_schema)]
1115 with self.assertRaises(ObjUnknown) as err:
1120 def test_optional(self, optional):
1121 obj = BitString(default=BitString(b""), optional=optional)
1122 self.assertTrue(obj.optional)
1125 def test_ready(self, value):
1127 self.assertFalse(obj.ready)
1130 with self.assertRaises(ObjNotReady) as err:
1133 obj = BitString(value)
1134 self.assertTrue(obj.ready)
1139 tuples(integers(min_value=0), binary()),
1140 tuples(integers(min_value=0), binary()),
1144 def test_comparison(self, value1, value2, tag1, tag2):
1145 for klass in (BitString, BitStringInherited):
1146 obj1 = klass(value1)
1147 obj2 = klass(value2)
1148 self.assertEqual(obj1 == obj2, value1 == value2)
1149 self.assertEqual(obj1 != obj2, value1 != value2)
1150 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1151 obj1 = klass(value1, impl=tag1)
1152 obj2 = klass(value1, impl=tag2)
1153 self.assertEqual(obj1 == obj2, tag1 == tag2)
1154 self.assertEqual(obj1 != obj2, tag1 != tag2)
1156 @given(data_strategy())
1157 def test_call(self, d):
1158 for klass in (BitString, BitStringInherited):
1167 ) = d.draw(bit_string_values_strategy())
1170 schema = schema_initial
1172 value=value_initial,
1175 default=default_initial,
1176 optional=optional_initial or False,
1177 _decoded=_decoded_initial,
1187 ) = d.draw(bit_string_values_strategy(
1188 schema=schema_initial,
1189 do_expl=impl_initial is None,
1198 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1199 self.assertEqual(obj.expl_tag, expl or expl_initial)
1200 if obj.default is None:
1201 optional = optional_initial if optional is None else optional
1202 optional = False if optional is None else optional
1205 self.assertEqual(obj.optional, optional)
1206 self.assertEqual(obj.specs, obj_initial.specs)
1208 @given(bit_string_values_strategy())
1209 def test_copy(self, values):
1210 for klass in (BitString, BitStringInherited):
1211 _schema, value, impl, expl, default, optional, _decoded = values
1220 optional=optional or False,
1223 obj_copied = obj.copy()
1224 self.assert_copied_basic_fields(obj, obj_copied)
1225 self.assertEqual(obj.specs, obj_copied.specs)
1226 self.assertEqual(obj._value, obj_copied._value)
1230 integers(min_value=1).map(tag_encode),
1232 def test_stripped(self, value, tag_impl):
1233 obj = BitString(value, impl=tag_impl)
1234 with self.assertRaises(NotEnoughData):
1235 obj.decode(obj.encode()[:-1])
1239 integers(min_value=1).map(tag_ctxc),
1241 def test_stripped_expl(self, value, tag_expl):
1242 obj = BitString(value, expl=tag_expl)
1243 with self.assertRaises(NotEnoughData):
1244 obj.decode(obj.encode()[:-1])
1247 integers(min_value=31),
1248 integers(min_value=0),
1251 def test_bad_tag(self, tag, offset, decode_path):
1252 decode_path = tuple(str(i) for i in decode_path)
1253 with self.assertRaises(DecodeError) as err:
1255 tag_encode(tag)[:-1],
1257 decode_path=decode_path,
1260 self.assertEqual(err.exception.offset, offset)
1261 self.assertEqual(err.exception.decode_path, decode_path)
1264 integers(min_value=128),
1265 integers(min_value=0),
1268 def test_bad_len(self, l, offset, decode_path):
1269 decode_path = tuple(str(i) for i in decode_path)
1270 with self.assertRaises(DecodeError) as err:
1272 BitString.tag_default + len_encode(l)[:-1],
1274 decode_path=decode_path,
1277 self.assertEqual(err.exception.offset, offset)
1278 self.assertEqual(err.exception.decode_path, decode_path)
1280 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1281 @given(data_strategy())
1282 def test_symmetric(self, d):
1291 ) = d.draw(bit_string_values_strategy(value_required=True))
1292 tail_junk = d.draw(binary(max_size=5))
1293 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1294 offset = d.draw(integers(min_value=0))
1295 for klass in (BitString, BitStringInherited):
1306 self.assertFalse(obj.expled)
1307 obj_encoded = obj.encode()
1308 obj_expled = obj(value, expl=tag_expl)
1309 self.assertTrue(obj_expled.expled)
1312 obj_expled_encoded = obj_expled.encode()
1313 obj_decoded, tail = obj_expled.decode(
1314 obj_expled_encoded + tail_junk,
1319 self.assertEqual(tail, tail_junk)
1320 self.assertEqual(obj_decoded, obj_expled)
1321 self.assertNotEqual(obj_decoded, obj)
1322 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1323 self.assertEqual(bytes(obj_decoded), bytes(obj))
1324 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1325 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1326 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1328 obj_decoded.expl_llen,
1329 len(len_encode(len(obj_encoded))),
1331 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1332 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1335 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1337 self.assertEqual(obj_decoded.expl_offset, offset)
1338 if isinstance(value, tuple):
1339 self.assertSetEqual(set(value), set(obj_decoded.named))
1343 @given(integers(min_value=1, max_value=255))
1344 def test_bad_zero_value(self, pad_size):
1345 with self.assertRaises(DecodeError):
1346 BitString().decode(b"".join((
1347 BitString.tag_default,
1352 def test_go_vectors_invalid(self):
1358 with self.assertRaises(DecodeError):
1359 BitString().decode(b"".join((
1360 BitString.tag_default,
1365 def test_go_vectors_valid(self):
1366 obj, _ = BitString().decode(b"".join((
1367 BitString.tag_default,
1371 self.assertEqual(bytes(obj), b"")
1372 self.assertEqual(obj.bit_len, 0)
1374 obj, _ = BitString().decode(b"".join((
1375 BitString.tag_default,
1379 self.assertEqual(bytes(obj), b"\x00")
1380 self.assertEqual(obj.bit_len, 1)
1382 obj = BitString((16, b"\x82\x40"))
1383 self.assertTrue(obj[0])
1384 self.assertFalse(obj[1])
1385 self.assertTrue(obj[6])
1386 self.assertTrue(obj[9])
1387 self.assertFalse(obj[17])
1391 def octet_string_values_strategy(draw, do_expl=False):
1392 bound_min, bound_max = sorted(draw(sets(
1393 integers(min_value=0, max_value=1 << 7),
1397 value = draw(one_of(
1399 binary(min_size=bound_min, max_size=bound_max),
1401 default = draw(one_of(
1403 binary(min_size=bound_min, max_size=bound_max),
1406 if draw(booleans()):
1407 bounds = (bound_min, bound_max)
1411 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1413 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1414 optional = draw(one_of(none(), booleans()))
1416 draw(integers(min_value=0)),
1417 draw(integers(min_value=0)),
1418 draw(integers(min_value=0)),
1420 return (value, bounds, impl, expl, default, optional, _decoded)
1423 class OctetStringInherited(OctetString):
1427 class TestOctetString(CommonMixin, TestCase):
1428 base_klass = OctetString
1430 def test_invalid_value_type(self):
1431 with self.assertRaises(InvalidValueType) as err:
1432 OctetString(text_type(123))
1436 def test_optional(self, optional):
1437 obj = OctetString(default=OctetString(b""), optional=optional)
1438 self.assertTrue(obj.optional)
1441 def test_ready(self, value):
1443 self.assertFalse(obj.ready)
1446 with self.assertRaises(ObjNotReady) as err:
1449 obj = OctetString(value)
1450 self.assertTrue(obj.ready)
1454 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
1455 def test_comparison(self, value1, value2, tag1, tag2):
1456 for klass in (OctetString, OctetStringInherited):
1457 obj1 = klass(value1)
1458 obj2 = klass(value2)
1459 self.assertEqual(obj1 == obj2, value1 == value2)
1460 self.assertEqual(obj1 != obj2, value1 != value2)
1461 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
1462 obj1 = klass(value1, impl=tag1)
1463 obj2 = klass(value1, impl=tag2)
1464 self.assertEqual(obj1 == obj2, tag1 == tag2)
1465 self.assertEqual(obj1 != obj2, tag1 != tag2)
1467 @given(lists(binary()))
1468 def test_sorted_works(self, values):
1469 self.assertSequenceEqual(
1470 [bytes(v) for v in sorted(OctetString(v) for v in values)],
1474 @given(data_strategy())
1475 def test_bounds_satisfied(self, d):
1476 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
1477 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
1478 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
1479 OctetString(value=value, bounds=(bound_min, bound_max))
1481 @given(data_strategy())
1482 def test_bounds_unsatisfied(self, d):
1483 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
1484 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
1485 value = d.draw(binary(max_size=bound_min - 1))
1486 with self.assertRaises(BoundsError) as err:
1487 OctetString(value=value, bounds=(bound_min, bound_max))
1489 value = d.draw(binary(min_size=bound_max + 1))
1490 with self.assertRaises(BoundsError) as err:
1491 OctetString(value=value, bounds=(bound_min, bound_max))
1494 @given(data_strategy())
1495 def test_call(self, d):
1496 for klass in (OctetString, OctetStringInherited):
1505 ) = d.draw(octet_string_values_strategy())
1506 obj_initial = klass(
1512 optional_initial or False,
1523 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
1524 if (default is None) and (obj_initial.default is not None):
1527 (bounds is None) and
1528 (value is not None) and
1529 (bounds_initial is not None) and
1530 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
1534 (bounds is None) and
1535 (default is not None) and
1536 (bounds_initial is not None) and
1537 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
1540 obj = obj_initial(value, bounds, impl, expl, default, optional)
1542 value_expected = default if value is None else value
1544 default_initial if value_expected is None
1547 self.assertEqual(obj, value_expected)
1548 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1549 self.assertEqual(obj.expl_tag, expl or expl_initial)
1552 default_initial if default is None else default,
1554 if obj.default is None:
1555 optional = optional_initial if optional is None else optional
1556 optional = False if optional is None else optional
1559 self.assertEqual(obj.optional, optional)
1561 (obj._bound_min, obj._bound_max),
1562 bounds or bounds_initial or (0, float("+inf")),
1565 @given(octet_string_values_strategy())
1566 def test_copy(self, values):
1567 for klass in (OctetString, OctetStringInherited):
1568 obj = klass(*values)
1569 obj_copied = obj.copy()
1570 self.assert_copied_basic_fields(obj, obj_copied)
1571 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1572 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1573 self.assertEqual(obj._value, obj_copied._value)
1577 integers(min_value=1).map(tag_encode),
1579 def test_stripped(self, value, tag_impl):
1580 obj = OctetString(value, impl=tag_impl)
1581 with self.assertRaises(NotEnoughData):
1582 obj.decode(obj.encode()[:-1])
1586 integers(min_value=1).map(tag_ctxc),
1588 def test_stripped_expl(self, value, tag_expl):
1589 obj = OctetString(value, expl=tag_expl)
1590 with self.assertRaises(NotEnoughData):
1591 obj.decode(obj.encode()[:-1])
1594 integers(min_value=31),
1595 integers(min_value=0),
1598 def test_bad_tag(self, tag, offset, decode_path):
1599 decode_path = tuple(str(i) for i in decode_path)
1600 with self.assertRaises(DecodeError) as err:
1601 OctetString().decode(
1602 tag_encode(tag)[:-1],
1604 decode_path=decode_path,
1607 self.assertEqual(err.exception.offset, offset)
1608 self.assertEqual(err.exception.decode_path, decode_path)
1611 integers(min_value=128),
1612 integers(min_value=0),
1615 def test_bad_len(self, l, offset, decode_path):
1616 decode_path = tuple(str(i) for i in decode_path)
1617 with self.assertRaises(DecodeError) as err:
1618 OctetString().decode(
1619 OctetString.tag_default + len_encode(l)[:-1],
1621 decode_path=decode_path,
1624 self.assertEqual(err.exception.offset, offset)
1625 self.assertEqual(err.exception.decode_path, decode_path)
1628 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
1629 integers(min_value=0),
1632 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1633 decode_path = tuple(str(i) for i in decode_path)
1634 value, bound_min = list(sorted(ints))
1636 class String(OctetString):
1637 bounds = (bound_min, bound_min)
1638 with self.assertRaises(DecodeError) as err:
1640 OctetString(b"\x00" * value).encode(),
1642 decode_path=decode_path,
1645 self.assertEqual(err.exception.offset, offset)
1646 self.assertEqual(err.exception.decode_path, decode_path)
1648 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1650 octet_string_values_strategy(),
1652 integers(min_value=1).map(tag_ctxc),
1653 integers(min_value=0),
1656 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
1657 for klass in (OctetString, OctetStringInherited):
1658 _, _, _, _, default, optional, _decoded = values
1667 self.assertFalse(obj.expled)
1668 obj_encoded = obj.encode()
1669 obj_expled = obj(value, expl=tag_expl)
1670 self.assertTrue(obj_expled.expled)
1673 obj_expled_encoded = obj_expled.encode()
1674 obj_decoded, tail = obj_expled.decode(
1675 obj_expled_encoded + tail_junk,
1680 self.assertEqual(tail, tail_junk)
1681 self.assertEqual(obj_decoded, obj_expled)
1682 self.assertNotEqual(obj_decoded, obj)
1683 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1684 self.assertEqual(bytes(obj_decoded), bytes(obj))
1685 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1686 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1687 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1689 obj_decoded.expl_llen,
1690 len(len_encode(len(obj_encoded))),
1692 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1693 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1696 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1698 self.assertEqual(obj_decoded.expl_offset, offset)
1702 def null_values_strategy(draw, do_expl=False):
1706 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1708 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1709 optional = draw(one_of(none(), booleans()))
1711 draw(integers(min_value=0)),
1712 draw(integers(min_value=0)),
1713 draw(integers(min_value=0)),
1715 return (impl, expl, optional, _decoded)
1718 class NullInherited(Null):
1722 class TestNull(CommonMixin, TestCase):
1725 def test_ready(self):
1727 self.assertTrue(obj.ready)
1731 @given(binary(), binary())
1732 def test_comparison(self, tag1, tag2):
1733 for klass in (Null, NullInherited):
1734 obj1 = klass(impl=tag1)
1735 obj2 = klass(impl=tag2)
1736 self.assertEqual(obj1 == obj2, tag1 == tag2)
1737 self.assertEqual(obj1 != obj2, tag1 != tag2)
1738 self.assertNotEqual(obj1, tag2)
1740 @given(data_strategy())
1741 def test_call(self, d):
1742 for klass in (Null, NullInherited):
1748 ) = d.draw(null_values_strategy())
1749 obj_initial = klass(
1752 optional=optional_initial or False,
1753 _decoded=_decoded_initial,
1760 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
1761 obj = obj_initial(impl=impl, expl=expl, optional=optional)
1762 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1763 self.assertEqual(obj.expl_tag, expl or expl_initial)
1764 optional = optional_initial if optional is None else optional
1765 optional = False if optional is None else optional
1766 self.assertEqual(obj.optional, optional)
1768 @given(null_values_strategy())
1769 def test_copy(self, values):
1770 for klass in (Null, NullInherited):
1771 impl, expl, optional, _decoded = values
1775 optional=optional or False,
1778 obj_copied = obj.copy()
1779 self.assert_copied_basic_fields(obj, obj_copied)
1781 @given(integers(min_value=1).map(tag_encode))
1782 def test_stripped(self, tag_impl):
1783 obj = Null(impl=tag_impl)
1784 with self.assertRaises(NotEnoughData):
1785 obj.decode(obj.encode()[:-1])
1787 @given(integers(min_value=1).map(tag_ctxc))
1788 def test_stripped_expl(self, tag_expl):
1789 obj = Null(expl=tag_expl)
1790 with self.assertRaises(NotEnoughData):
1791 obj.decode(obj.encode()[:-1])
1794 integers(min_value=31),
1795 integers(min_value=0),
1798 def test_bad_tag(self, tag, offset, decode_path):
1799 decode_path = tuple(str(i) for i in decode_path)
1800 with self.assertRaises(DecodeError) as err:
1802 tag_encode(tag)[:-1],
1804 decode_path=decode_path,
1807 self.assertEqual(err.exception.offset, offset)
1808 self.assertEqual(err.exception.decode_path, decode_path)
1811 integers(min_value=128),
1812 integers(min_value=0),
1815 def test_bad_len(self, l, offset, decode_path):
1816 decode_path = tuple(str(i) for i in decode_path)
1817 with self.assertRaises(DecodeError) as err:
1819 Null.tag_default + len_encode(l)[:-1],
1821 decode_path=decode_path,
1824 self.assertEqual(err.exception.offset, offset)
1825 self.assertEqual(err.exception.decode_path, decode_path)
1827 @given(binary(min_size=1))
1828 def test_tag_mismatch(self, impl):
1829 assume(impl != Null.tag_default)
1830 with self.assertRaises(TagMismatch):
1831 Null(impl=impl).decode(Null().encode())
1834 null_values_strategy(),
1835 integers(min_value=1).map(tag_ctxc),
1836 integers(min_value=0),
1839 def test_symmetric(self, values, tag_expl, offset, tail_junk):
1840 for klass in (Null, NullInherited):
1841 _, _, optional, _decoded = values
1842 obj = klass(optional=optional, _decoded=_decoded)
1845 self.assertFalse(obj.expled)
1846 obj_encoded = obj.encode()
1847 obj_expled = obj(expl=tag_expl)
1848 self.assertTrue(obj_expled.expled)
1851 obj_expled_encoded = obj_expled.encode()
1852 obj_decoded, tail = obj_expled.decode(
1853 obj_expled_encoded + tail_junk,
1858 self.assertEqual(tail, tail_junk)
1859 self.assertEqual(obj_decoded, obj_expled)
1860 self.assertNotEqual(obj_decoded, obj)
1861 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1862 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1863 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1865 obj_decoded.expl_llen,
1866 len(len_encode(len(obj_encoded))),
1868 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1869 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1872 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1874 self.assertEqual(obj_decoded.expl_offset, offset)
1876 @given(integers(min_value=1))
1877 def test_invalid_len(self, l):
1878 with self.assertRaises(InvalidLength):
1879 Null().decode(b"".join((
1886 def oid_strategy(draw):
1887 first_arc = draw(integers(min_value=0, max_value=2))
1889 if first_arc in (0, 1):
1890 second_arc = draw(integers(min_value=0, max_value=39))
1892 second_arc = draw(integers(min_value=0))
1893 other_arcs = draw(lists(integers(min_value=0)))
1894 return tuple([first_arc, second_arc] + other_arcs)
1898 def oid_values_strategy(draw, do_expl=False):
1899 value = draw(one_of(none(), oid_strategy()))
1903 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1905 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1906 default = draw(one_of(none(), oid_strategy()))
1907 optional = draw(one_of(none(), booleans()))
1909 draw(integers(min_value=0)),
1910 draw(integers(min_value=0)),
1911 draw(integers(min_value=0)),
1913 return (value, impl, expl, default, optional, _decoded)
1916 class ObjectIdentifierInherited(ObjectIdentifier):
1920 class TestObjectIdentifier(CommonMixin, TestCase):
1921 base_klass = ObjectIdentifier
1923 def test_invalid_value_type(self):
1924 with self.assertRaises(InvalidValueType) as err:
1925 ObjectIdentifier(123)
1929 def test_optional(self, optional):
1930 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
1931 self.assertTrue(obj.optional)
1933 @given(oid_strategy())
1934 def test_ready(self, value):
1935 obj = ObjectIdentifier()
1936 self.assertFalse(obj.ready)
1939 with self.assertRaises(ObjNotReady) as err:
1942 obj = ObjectIdentifier(value)
1943 self.assertTrue(obj.ready)
1948 @given(oid_strategy(), oid_strategy(), binary(), binary())
1949 def test_comparison(self, value1, value2, tag1, tag2):
1950 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
1951 obj1 = klass(value1)
1952 obj2 = klass(value2)
1953 self.assertEqual(obj1 == obj2, value1 == value2)
1954 self.assertEqual(obj1 != obj2, value1 != value2)
1955 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
1956 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
1957 obj1 = klass(value1, impl=tag1)
1958 obj2 = klass(value1, impl=tag2)
1959 self.assertEqual(obj1 == obj2, tag1 == tag2)
1960 self.assertEqual(obj1 != obj2, tag1 != tag2)
1962 @given(lists(oid_strategy()))
1963 def test_sorted_works(self, values):
1964 self.assertSequenceEqual(
1965 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
1969 @given(data_strategy())
1970 def test_call(self, d):
1971 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
1979 ) = d.draw(oid_values_strategy())
1980 obj_initial = klass(
1981 value=value_initial,
1984 default=default_initial,
1985 optional=optional_initial or False,
1986 _decoded=_decoded_initial,
1995 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2004 value_expected = default if value is None else value
2006 default_initial if value_expected is None
2009 self.assertEqual(obj, value_expected)
2010 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2011 self.assertEqual(obj.expl_tag, expl or expl_initial)
2014 default_initial if default is None else default,
2016 if obj.default is None:
2017 optional = optional_initial if optional is None else optional
2018 optional = False if optional is None else optional
2021 self.assertEqual(obj.optional, optional)
2023 @given(oid_values_strategy())
2024 def test_copy(self, values):
2025 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2042 obj_copied = obj.copy()
2043 self.assert_copied_basic_fields(obj, obj_copied)
2044 self.assertEqual(obj._value, obj_copied._value)
2046 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2049 integers(min_value=1).map(tag_encode),
2051 def test_stripped(self, value, tag_impl):
2052 obj = ObjectIdentifier(value, impl=tag_impl)
2053 with self.assertRaises(NotEnoughData):
2054 obj.decode(obj.encode()[:-1])
2058 integers(min_value=1).map(tag_ctxc),
2060 def test_stripped_expl(self, value, tag_expl):
2061 obj = ObjectIdentifier(value, expl=tag_expl)
2062 with self.assertRaises(NotEnoughData):
2063 obj.decode(obj.encode()[:-1])
2066 integers(min_value=31),
2067 integers(min_value=0),
2070 def test_bad_tag(self, tag, offset, decode_path):
2071 decode_path = tuple(str(i) for i in decode_path)
2072 with self.assertRaises(DecodeError) as err:
2073 ObjectIdentifier().decode(
2074 tag_encode(tag)[:-1],
2076 decode_path=decode_path,
2079 self.assertEqual(err.exception.offset, offset)
2080 self.assertEqual(err.exception.decode_path, decode_path)
2083 integers(min_value=128),
2084 integers(min_value=0),
2087 def test_bad_len(self, l, offset, decode_path):
2088 decode_path = tuple(str(i) for i in decode_path)
2089 with self.assertRaises(DecodeError) as err:
2090 ObjectIdentifier().decode(
2091 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2093 decode_path=decode_path,
2096 self.assertEqual(err.exception.offset, offset)
2097 self.assertEqual(err.exception.decode_path, decode_path)
2099 def test_zero_oid(self):
2100 with self.assertRaises(NotEnoughData):
2101 ObjectIdentifier().decode(
2102 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2105 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2106 @given(oid_strategy())
2107 def test_unfinished_oid(self, value):
2108 assume(list(value)[-1] > 255)
2109 obj_encoded = ObjectIdentifier(value).encode()
2110 obj, _ = ObjectIdentifier().decode(obj_encoded)
2111 data = obj_encoded[obj.tlen + obj.llen:-1]
2113 ObjectIdentifier.tag_default,
2114 len_encode(len(data)),
2117 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2120 @given(integers(min_value=0))
2121 def test_invalid_short(self, value):
2122 with self.assertRaises(InvalidOID):
2123 ObjectIdentifier((value,))
2124 with self.assertRaises(InvalidOID):
2125 ObjectIdentifier("%d" % value)
2127 @given(integers(min_value=3), integers(min_value=0))
2128 def test_invalid_first_arc(self, first_arc, second_arc):
2129 with self.assertRaises(InvalidOID):
2130 ObjectIdentifier((first_arc, second_arc))
2131 with self.assertRaises(InvalidOID):
2132 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2134 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2135 def test_invalid_second_arc(self, first_arc, second_arc):
2136 with self.assertRaises(InvalidOID):
2137 ObjectIdentifier((first_arc, second_arc))
2138 with self.assertRaises(InvalidOID):
2139 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2141 @given(text(alphabet=ascii_letters + ".", min_size=1))
2142 def test_junk(self, oid):
2143 with self.assertRaises(InvalidOID):
2144 ObjectIdentifier(oid)
2146 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2147 @given(oid_strategy())
2148 def test_validness(self, oid):
2149 obj = ObjectIdentifier(oid)
2150 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2155 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2157 oid_values_strategy(),
2159 integers(min_value=1).map(tag_ctxc),
2160 integers(min_value=0),
2163 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
2164 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2165 _, _, _, default, optional, _decoded = values
2174 self.assertFalse(obj.expled)
2175 obj_encoded = obj.encode()
2176 obj_expled = obj(value, expl=tag_expl)
2177 self.assertTrue(obj_expled.expled)
2180 obj_expled_encoded = obj_expled.encode()
2181 obj_decoded, tail = obj_expled.decode(
2182 obj_expled_encoded + tail_junk,
2187 self.assertEqual(tail, tail_junk)
2188 self.assertEqual(obj_decoded, obj_expled)
2189 self.assertNotEqual(obj_decoded, obj)
2190 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
2191 self.assertEqual(tuple(obj_decoded), tuple(obj))
2192 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2193 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2194 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2196 obj_decoded.expl_llen,
2197 len(len_encode(len(obj_encoded))),
2199 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2200 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2203 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2205 self.assertEqual(obj_decoded.expl_offset, offset)
2208 oid_strategy().map(ObjectIdentifier),
2209 oid_strategy().map(ObjectIdentifier),
2211 def test_add(self, oid1, oid2):
2212 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
2213 for oid_to_add in (oid2, tuple(oid2)):
2214 self.assertEqual(oid1 + oid_to_add, oid_expect)
2215 with self.assertRaises(InvalidValueType):
2218 def test_go_vectors_valid(self):
2219 for data, expect in (
2221 (b"\x55\x02", (2, 5, 2)),
2222 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
2223 (b"\x81\x34\x03", (2, 100, 3)),
2226 ObjectIdentifier().decode(b"".join((
2227 ObjectIdentifier.tag_default,
2228 len_encode(len(data)),
2234 def test_go_vectors_invalid(self):
2235 data = b"\x55\x02\xc0\x80\x80\x80\x80"
2236 with self.assertRaises(DecodeError):
2237 ObjectIdentifier().decode(b"".join((
2238 Integer.tag_default,
2239 len_encode(len(data)),
2245 def enumerated_values_strategy(draw, schema=None, do_expl=False):
2247 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
2248 values = list(draw(sets(
2250 min_size=len(schema),
2251 max_size=len(schema),
2253 schema = list(zip(schema, values))
2254 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
2258 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2260 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2261 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
2262 optional = draw(one_of(none(), booleans()))
2264 draw(integers(min_value=0)),
2265 draw(integers(min_value=0)),
2266 draw(integers(min_value=0)),
2268 return (schema, value, impl, expl, default, optional, _decoded)
2271 class TestEnumerated(CommonMixin, TestCase):
2272 class EWhatever(Enumerated):
2273 schema = (("whatever", 0),)
2275 base_klass = EWhatever
2277 def test_schema_required(self):
2278 with assertRaisesRegex(self, ValueError, "schema must be specified"):
2281 def test_invalid_value_type(self):
2282 with self.assertRaises(InvalidValueType) as err:
2283 self.base_klass((1, 2))
2286 @given(sets(text_letters(), min_size=2))
2287 def test_unknown_name(self, schema_input):
2288 missing = schema_input.pop()
2290 class E(Enumerated):
2291 schema = [(n, 123) for n in schema_input]
2292 with self.assertRaises(ObjUnknown) as err:
2297 sets(text_letters(), min_size=2),
2298 sets(integers(), min_size=2),
2300 def test_unknown_value(self, schema_input, values_input):
2302 missing_value = values_input.pop()
2303 _input = list(zip(schema_input, values_input))
2305 class E(Enumerated):
2307 with self.assertRaises(DecodeError) as err:
2312 def test_optional(self, optional):
2313 obj = self.base_klass(default="whatever", optional=optional)
2314 self.assertTrue(obj.optional)
2316 def test_ready(self):
2317 obj = self.base_klass()
2318 self.assertFalse(obj.ready)
2321 with self.assertRaises(ObjNotReady) as err:
2324 obj = self.base_klass("whatever")
2325 self.assertTrue(obj.ready)
2329 @given(integers(), integers(), binary(), binary())
2330 def test_comparison(self, value1, value2, tag1, tag2):
2331 class E(Enumerated):
2333 ("whatever0", value1),
2334 ("whatever1", value2),
2337 class EInherited(E):
2339 for klass in (E, EInherited):
2340 obj1 = klass(value1)
2341 obj2 = klass(value2)
2342 self.assertEqual(obj1 == obj2, value1 == value2)
2343 self.assertEqual(obj1 != obj2, value1 != value2)
2344 self.assertEqual(obj1 == int(obj2), value1 == value2)
2345 obj1 = klass(value1, impl=tag1)
2346 obj2 = klass(value1, impl=tag2)
2347 self.assertEqual(obj1 == obj2, tag1 == tag2)
2348 self.assertEqual(obj1 != obj2, tag1 != tag2)
2350 @given(data_strategy())
2351 def test_call(self, d):
2360 ) = d.draw(enumerated_values_strategy())
2362 class E(Enumerated):
2363 schema = schema_initial
2365 value=value_initial,
2368 default=default_initial,
2369 optional=optional_initial or False,
2370 _decoded=_decoded_initial,
2380 ) = d.draw(enumerated_values_strategy(
2381 schema=schema_initial,
2382 do_expl=impl_initial is None,
2392 value_expected = default if value is None else value
2394 default_initial if value_expected is None
2399 dict(schema_initial).get(value_expected, value_expected),
2401 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2402 self.assertEqual(obj.expl_tag, expl or expl_initial)
2405 default_initial if default is None else default,
2407 if obj.default is None:
2408 optional = optional_initial if optional is None else optional
2409 optional = False if optional is None else optional
2412 self.assertEqual(obj.optional, optional)
2413 self.assertEqual(obj.specs, dict(schema_initial))
2415 @given(enumerated_values_strategy())
2416 def test_copy(self, values):
2417 schema_input, value, impl, expl, default, optional, _decoded = values
2419 class E(Enumerated):
2420 schema = schema_input
2429 obj_copied = obj.copy()
2430 self.assert_copied_basic_fields(obj, obj_copied)
2431 self.assertEqual(obj.specs, obj_copied.specs)
2433 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2434 @given(data_strategy())
2435 def test_symmetric(self, d):
2436 schema_input, _, _, _, default, optional, _decoded = d.draw(
2437 enumerated_values_strategy(),
2439 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
2440 offset = d.draw(integers(min_value=0))
2441 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
2442 tail_junk = d.draw(binary(max_size=5))
2444 class E(Enumerated):
2445 schema = schema_input
2454 self.assertFalse(obj.expled)
2455 obj_encoded = obj.encode()
2456 obj_expled = obj(value, expl=tag_expl)
2457 self.assertTrue(obj_expled.expled)
2460 obj_expled_encoded = obj_expled.encode()
2461 obj_decoded, tail = obj_expled.decode(
2462 obj_expled_encoded + tail_junk,
2467 self.assertEqual(tail, tail_junk)
2468 self.assertEqual(obj_decoded, obj_expled)
2469 self.assertNotEqual(obj_decoded, obj)
2470 self.assertEqual(int(obj_decoded), int(obj_expled))
2471 self.assertEqual(int(obj_decoded), int(obj))
2472 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2473 self.assertEqual(obj_decoded.expl_tag, tag_expl)
2474 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2476 obj_decoded.expl_llen,
2477 len(len_encode(len(obj_encoded))),
2479 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2480 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2483 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2485 self.assertEqual(obj_decoded.expl_offset, offset)
2489 def string_values_strategy(draw, alphabet, do_expl=False):
2490 bound_min, bound_max = sorted(draw(sets(
2491 integers(min_value=0, max_value=1 << 7),
2495 value = draw(one_of(
2497 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
2499 default = draw(one_of(
2501 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
2504 if draw(booleans()):
2505 bounds = (bound_min, bound_max)
2509 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2511 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2512 optional = draw(one_of(none(), booleans()))
2514 draw(integers(min_value=0)),
2515 draw(integers(min_value=0)),
2516 draw(integers(min_value=0)),
2518 return (value, bounds, impl, expl, default, optional, _decoded)
2521 class StringMixin(object):
2522 def test_invalid_value_type(self):
2523 with self.assertRaises(InvalidValueType) as err:
2524 self.base_klass((1, 2))
2527 def text_alphabet(self):
2528 if self.base_klass.encoding in ("ascii", "iso-8859-1"):
2529 return printable + whitespace
2533 def test_optional(self, optional):
2534 obj = self.base_klass(default=self.base_klass(""), optional=optional)
2535 self.assertTrue(obj.optional)
2537 @given(data_strategy())
2538 def test_ready(self, d):
2539 obj = self.base_klass()
2540 self.assertFalse(obj.ready)
2544 with self.assertRaises(ObjNotReady) as err:
2547 value = d.draw(text(alphabet=self.text_alphabet()))
2548 obj = self.base_klass(value)
2549 self.assertTrue(obj.ready)
2554 @given(data_strategy())
2555 def test_comparison(self, d):
2556 value1 = d.draw(text(alphabet=self.text_alphabet()))
2557 value2 = d.draw(text(alphabet=self.text_alphabet()))
2558 tag1 = d.draw(binary(min_size=1))
2559 tag2 = d.draw(binary(min_size=1))
2560 obj1 = self.base_klass(value1)
2561 obj2 = self.base_klass(value2)
2562 self.assertEqual(obj1 == obj2, value1 == value2)
2563 self.assertEqual(obj1 != obj2, value1 != value2)
2564 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2565 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
2566 obj1 = self.base_klass(value1, impl=tag1)
2567 obj2 = self.base_klass(value1, impl=tag2)
2568 self.assertEqual(obj1 == obj2, tag1 == tag2)
2569 self.assertEqual(obj1 != obj2, tag1 != tag2)
2571 @given(data_strategy())
2572 def test_bounds_satisfied(self, d):
2573 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2574 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2575 value = d.draw(text(
2576 alphabet=self.text_alphabet(),
2580 self.base_klass(value=value, bounds=(bound_min, bound_max))
2582 @given(data_strategy())
2583 def test_bounds_unsatisfied(self, d):
2584 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2585 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2586 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
2587 with self.assertRaises(BoundsError) as err:
2588 self.base_klass(value=value, bounds=(bound_min, bound_max))
2590 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
2591 with self.assertRaises(BoundsError) as err:
2592 self.base_klass(value=value, bounds=(bound_min, bound_max))
2595 @given(data_strategy())
2596 def test_call(self, d):
2605 ) = d.draw(string_values_strategy(self.text_alphabet()))
2606 obj_initial = self.base_klass(
2612 optional_initial or False,
2623 ) = d.draw(string_values_strategy(
2624 self.text_alphabet(),
2625 do_expl=impl_initial is None,
2627 if (default is None) and (obj_initial.default is not None):
2630 (bounds is None) and
2631 (value is not None) and
2632 (bounds_initial is not None) and
2633 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2637 (bounds is None) and
2638 (default is not None) and
2639 (bounds_initial is not None) and
2640 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2643 obj = obj_initial(value, bounds, impl, expl, default, optional)
2645 value_expected = default if value is None else value
2647 default_initial if value_expected is None
2650 self.assertEqual(obj, value_expected)
2651 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2652 self.assertEqual(obj.expl_tag, expl or expl_initial)
2655 default_initial if default is None else default,
2657 if obj.default is None:
2658 optional = optional_initial if optional is None else optional
2659 optional = False if optional is None else optional
2662 self.assertEqual(obj.optional, optional)
2664 (obj._bound_min, obj._bound_max),
2665 bounds or bounds_initial or (0, float("+inf")),
2668 @given(data_strategy())
2669 def test_copy(self, d):
2670 values = d.draw(string_values_strategy(self.text_alphabet()))
2671 obj = self.base_klass(*values)
2672 obj_copied = obj.copy()
2673 self.assert_copied_basic_fields(obj, obj_copied)
2674 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2675 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2676 self.assertEqual(obj._value, obj_copied._value)
2678 @given(data_strategy())
2679 def test_stripped(self, d):
2680 value = d.draw(text(alphabet=self.text_alphabet()))
2681 tag_impl = tag_encode(d.draw(integers(min_value=1)))
2682 obj = self.base_klass(value, impl=tag_impl)
2683 with self.assertRaises(NotEnoughData):
2684 obj.decode(obj.encode()[:-1])
2686 @given(data_strategy())
2687 def test_stripped_expl(self, d):
2688 value = d.draw(text(alphabet=self.text_alphabet()))
2689 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
2690 obj = self.base_klass(value, expl=tag_expl)
2691 with self.assertRaises(NotEnoughData):
2692 obj.decode(obj.encode()[:-1])
2695 integers(min_value=31),
2696 integers(min_value=0),
2699 def test_bad_tag(self, tag, offset, decode_path):
2700 decode_path = tuple(str(i) for i in decode_path)
2701 with self.assertRaises(DecodeError) as err:
2702 self.base_klass().decode(
2703 tag_encode(tag)[:-1],
2705 decode_path=decode_path,
2708 self.assertEqual(err.exception.offset, offset)
2709 self.assertEqual(err.exception.decode_path, decode_path)
2712 integers(min_value=128),
2713 integers(min_value=0),
2716 def test_bad_len(self, l, offset, decode_path):
2717 decode_path = tuple(str(i) for i in decode_path)
2718 with self.assertRaises(DecodeError) as err:
2719 self.base_klass().decode(
2720 self.base_klass.tag_default + len_encode(l)[:-1],
2722 decode_path=decode_path,
2725 self.assertEqual(err.exception.offset, offset)
2726 self.assertEqual(err.exception.decode_path, decode_path)
2729 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2730 integers(min_value=0),
2733 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2734 decode_path = tuple(str(i) for i in decode_path)
2735 value, bound_min = list(sorted(ints))
2737 class String(self.base_klass):
2738 # Multiply this value by four, to satisfy UTF-32 bounds
2739 # (4 bytes per character) validation
2740 bounds = (bound_min * 4, bound_min * 4)
2741 with self.assertRaises(DecodeError) as err:
2743 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
2745 decode_path=decode_path,
2748 self.assertEqual(err.exception.offset, offset)
2749 self.assertEqual(err.exception.decode_path, decode_path)
2751 @given(data_strategy())
2752 def test_symmetric(self, d):
2753 values = d.draw(string_values_strategy(self.text_alphabet()))
2754 value = d.draw(text(alphabet=self.text_alphabet()))
2755 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
2756 offset = d.draw(integers(min_value=0))
2757 tail_junk = d.draw(binary(max_size=5))
2758 _, _, _, _, default, optional, _decoded = values
2759 obj = self.base_klass(
2767 self.assertFalse(obj.expled)
2768 obj_encoded = obj.encode()
2769 obj_expled = obj(value, expl=tag_expl)
2770 self.assertTrue(obj_expled.expled)
2773 obj_expled_encoded = obj_expled.encode()
2774 obj_decoded, tail = obj_expled.decode(
2775 obj_expled_encoded + tail_junk,
2780 self.assertEqual(tail, tail_junk)
2781 self.assertEqual(obj_decoded, obj_expled)
2782 self.assertNotEqual(obj_decoded, obj)
2783 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2784 self.assertEqual(bytes(obj_decoded), bytes(obj))
2785 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
2786 self.assertEqual(text_type(obj_decoded), text_type(obj))
2787 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2788 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2789 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2791 obj_decoded.expl_llen,
2792 len(len_encode(len(obj_encoded))),
2794 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2795 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2798 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2800 self.assertEqual(obj_decoded.expl_offset, offset)
2803 class TestUTF8String(StringMixin, CommonMixin, TestCase):
2804 base_klass = UTF8String
2807 class UnicodeDecodeErrorMixin(object):
2809 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
2813 def test_unicode_decode_error(self, cyrillic_text):
2814 with self.assertRaises(DecodeError):
2815 self.base_klass(cyrillic_text)
2818 class TestNumericString(StringMixin, CommonMixin, TestCase):
2819 base_klass = NumericString
2821 def text_alphabet(self):
2824 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
2825 def test_non_numeric(self, cyrillic_text):
2826 with assertRaisesRegex(self, DecodeError, "non-numeric"):
2827 self.base_klass(cyrillic_text)
2830 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2831 integers(min_value=0),
2834 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2835 decode_path = tuple(str(i) for i in decode_path)
2836 value, bound_min = list(sorted(ints))
2838 class String(self.base_klass):
2839 bounds = (bound_min, bound_min)
2840 with self.assertRaises(DecodeError) as err:
2842 self.base_klass(b"1" * value).encode(),
2844 decode_path=decode_path,
2847 self.assertEqual(err.exception.offset, offset)
2848 self.assertEqual(err.exception.decode_path, decode_path)
2851 class TestPrintableString(
2852 UnicodeDecodeErrorMixin,
2857 base_klass = PrintableString
2860 class TestTeletexString(
2861 UnicodeDecodeErrorMixin,
2866 base_klass = TeletexString
2869 class TestVideotexString(
2870 UnicodeDecodeErrorMixin,
2875 base_klass = VideotexString
2878 class TestIA5String(
2879 UnicodeDecodeErrorMixin,
2884 base_klass = IA5String
2887 class TestGraphicString(
2888 UnicodeDecodeErrorMixin,
2893 base_klass = GraphicString
2896 class TestVisibleString(
2897 UnicodeDecodeErrorMixin,
2902 base_klass = VisibleString
2905 class TestGeneralString(
2906 UnicodeDecodeErrorMixin,
2911 base_klass = GeneralString
2914 class TestUniversalString(StringMixin, CommonMixin, TestCase):
2915 base_klass = UniversalString
2918 class TestBMPString(StringMixin, CommonMixin, TestCase):
2919 base_klass = BMPString
2923 def generalized_time_values_strategy(
2931 if draw(booleans()):
2932 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
2934 value = value.replace(microsecond=0)
2936 if draw(booleans()):
2937 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
2939 default = default.replace(microsecond=0)
2943 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2945 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2946 optional = draw(one_of(none(), booleans()))
2948 draw(integers(min_value=0)),
2949 draw(integers(min_value=0)),
2950 draw(integers(min_value=0)),
2952 return (value, impl, expl, default, optional, _decoded)
2955 class TimeMixin(object):
2956 def test_invalid_value_type(self):
2957 with self.assertRaises(InvalidValueType) as err:
2958 self.base_klass(datetime.now().timetuple())
2961 @given(data_strategy())
2962 def test_optional(self, d):
2963 default = d.draw(datetimes(
2964 min_value=self.min_datetime,
2965 max_value=self.max_datetime,
2967 optional = d.draw(booleans())
2968 obj = self.base_klass(default=default, optional=optional)
2969 self.assertTrue(obj.optional)
2971 @given(data_strategy())
2972 def test_ready(self, d):
2973 obj = self.base_klass()
2974 self.assertFalse(obj.ready)
2977 with self.assertRaises(ObjNotReady) as err:
2980 value = d.draw(datetimes(min_value=self.min_datetime))
2981 obj = self.base_klass(value)
2982 self.assertTrue(obj.ready)
2986 @given(data_strategy())
2987 def test_comparison(self, d):
2988 value1 = d.draw(datetimes(
2989 min_value=self.min_datetime,
2990 max_value=self.max_datetime,
2992 value2 = d.draw(datetimes(
2993 min_value=self.min_datetime,
2994 max_value=self.max_datetime,
2996 tag1 = d.draw(binary(min_size=1))
2997 tag2 = d.draw(binary(min_size=1))
2999 value1 = value1.replace(microsecond=0)
3000 value2 = value2.replace(microsecond=0)
3001 obj1 = self.base_klass(value1)
3002 obj2 = self.base_klass(value2)
3003 self.assertEqual(obj1 == obj2, value1 == value2)
3004 self.assertEqual(obj1 != obj2, value1 != value2)
3005 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
3006 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3007 obj1 = self.base_klass(value1, impl=tag1)
3008 obj2 = self.base_klass(value1, impl=tag2)
3009 self.assertEqual(obj1 == obj2, tag1 == tag2)
3010 self.assertEqual(obj1 != obj2, tag1 != tag2)
3012 @given(data_strategy())
3013 def test_call(self, d):
3021 ) = d.draw(generalized_time_values_strategy(
3022 min_datetime=self.min_datetime,
3023 max_datetime=self.max_datetime,
3024 omit_ms=self.omit_ms,
3026 obj_initial = self.base_klass(
3027 value=value_initial,
3030 default=default_initial,
3031 optional=optional_initial or False,
3032 _decoded=_decoded_initial,
3041 ) = d.draw(generalized_time_values_strategy(
3042 min_datetime=self.min_datetime,
3043 max_datetime=self.max_datetime,
3044 omit_ms=self.omit_ms,
3045 do_expl=impl_initial is None,
3055 value_expected = default if value is None else value
3057 default_initial if value_expected is None
3060 self.assertEqual(obj, value_expected)
3061 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3062 self.assertEqual(obj.expl_tag, expl or expl_initial)
3065 default_initial if default is None else default,
3067 if obj.default is None:
3068 optional = optional_initial if optional is None else optional
3069 optional = False if optional is None else optional
3072 self.assertEqual(obj.optional, optional)
3074 @given(data_strategy())
3075 def test_copy(self, d):
3076 values = d.draw(generalized_time_values_strategy(
3077 min_datetime=self.min_datetime,
3078 max_datetime=self.max_datetime,
3080 obj = self.base_klass(*values)
3081 obj_copied = obj.copy()
3082 self.assert_copied_basic_fields(obj, obj_copied)
3083 self.assertEqual(obj._value, obj_copied._value)
3085 @given(data_strategy())
3086 def test_stripped(self, d):
3087 value = d.draw(datetimes(
3088 min_value=self.min_datetime,
3089 max_value=self.max_datetime,
3091 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3092 obj = self.base_klass(value, impl=tag_impl)
3093 with self.assertRaises(NotEnoughData):
3094 obj.decode(obj.encode()[:-1])
3096 @given(data_strategy())
3097 def test_stripped_expl(self, d):
3098 value = d.draw(datetimes(
3099 min_value=self.min_datetime,
3100 max_value=self.max_datetime,
3102 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3103 obj = self.base_klass(value, expl=tag_expl)
3104 with self.assertRaises(NotEnoughData):
3105 obj.decode(obj.encode()[:-1])
3107 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3108 @given(data_strategy())
3109 def test_symmetric(self, d):
3110 values = d.draw(generalized_time_values_strategy(
3111 min_datetime=self.min_datetime,
3112 max_datetime=self.max_datetime,
3114 value = d.draw(datetimes(
3115 min_value=self.min_datetime,
3116 max_value=self.max_datetime,
3118 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3119 offset = d.draw(integers(min_value=0))
3120 tail_junk = d.draw(binary(max_size=5))
3121 _, _, _, default, optional, _decoded = values
3122 obj = self.base_klass(
3130 self.assertFalse(obj.expled)
3131 obj_encoded = obj.encode()
3132 obj_expled = obj(value, expl=tag_expl)
3133 self.assertTrue(obj_expled.expled)
3136 obj_expled_encoded = obj_expled.encode()
3137 obj_decoded, tail = obj_expled.decode(
3138 obj_expled_encoded + tail_junk,
3143 self.assertEqual(tail, tail_junk)
3144 self.assertEqual(obj_decoded, obj_expled)
3145 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
3146 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
3147 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3148 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3149 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3151 obj_decoded.expl_llen,
3152 len(len_encode(len(obj_encoded))),
3154 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3155 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3158 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3160 self.assertEqual(obj_decoded.expl_offset, offset)
3163 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
3164 base_klass = GeneralizedTime
3166 min_datetime = datetime(1900, 1, 1)
3167 max_datetime = datetime(9999, 12, 31)
3169 def test_go_vectors_invalid(self):
3181 b"-20100102030410Z",
3182 b"2010-0102030410Z",
3183 b"2010-0002030410Z",
3184 b"201001-02030410Z",
3185 b"20100102-030410Z",
3186 b"2010010203-0410Z",
3187 b"201001020304-10Z",
3188 # These ones are INVALID in *DER*, but accepted
3189 # by Go's encoding/asn1
3190 b"20100102030405+0607",
3191 b"20100102030405-0607",
3193 with self.assertRaises(DecodeError) as err:
3194 GeneralizedTime(data)
3197 def test_go_vectors_valid(self):
3199 GeneralizedTime(b"20100102030405Z").todatetime(),
3200 datetime(2010, 1, 2, 3, 4, 5, 0),
3204 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
3205 base_klass = UTCTime
3207 min_datetime = datetime(2000, 1, 1)
3208 max_datetime = datetime(2049, 12, 31)
3210 def test_go_vectors_invalid(self):
3236 # These ones are INVALID in *DER*, but accepted
3237 # by Go's encoding/asn1
3238 b"910506164540-0700",
3239 b"910506164540+0730",
3243 with self.assertRaises(DecodeError) as err:
3247 def test_go_vectors_valid(self):
3249 UTCTime(b"910506234540Z").todatetime(),
3250 datetime(1991, 5, 6, 23, 45, 40, 0),
3253 @given(integers(min_value=0, max_value=49))
3254 def test_pre50(self, year):
3256 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
3260 @given(integers(min_value=50, max_value=99))
3261 def test_post50(self, year):
3263 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
3269 def any_values_strategy(draw, do_expl=False):
3270 value = draw(one_of(none(), binary()))
3273 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3274 optional = draw(one_of(none(), booleans()))
3276 draw(integers(min_value=0)),
3277 draw(integers(min_value=0)),
3278 draw(integers(min_value=0)),
3280 return (value, expl, optional, _decoded)
3283 class AnyInherited(Any):
3287 class TestAny(CommonMixin, TestCase):
3290 def test_invalid_value_type(self):
3291 with self.assertRaises(InvalidValueType) as err:
3296 def test_optional(self, optional):
3297 obj = Any(optional=optional)
3298 self.assertEqual(obj.optional, optional)
3301 def test_ready(self, value):
3303 self.assertFalse(obj.ready)
3306 with self.assertRaises(ObjNotReady) as err:
3310 self.assertTrue(obj.ready)
3315 def test_basic(self, value):
3316 integer_encoded = Integer(value).encode()
3318 Any(integer_encoded),
3319 Any(Integer(value)),
3320 Any(Any(Integer(value))),
3322 self.assertSequenceEqual(bytes(obj), integer_encoded)
3324 obj.decode(obj.encode())[0].vlen,
3325 len(integer_encoded),
3329 self.assertSequenceEqual(obj.encode(), integer_encoded)
3331 @given(binary(), binary())
3332 def test_comparison(self, value1, value2):
3333 for klass in (Any, AnyInherited):
3334 obj1 = klass(value1)
3335 obj2 = klass(value2)
3336 self.assertEqual(obj1 == obj2, value1 == value2)
3337 self.assertEqual(obj1 != obj2, value1 != value2)
3338 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3340 @given(data_strategy())
3341 def test_call(self, d):
3342 for klass in (Any, AnyInherited):
3348 ) = d.draw(any_values_strategy())
3349 obj_initial = klass(
3352 optional_initial or False,
3360 ) = d.draw(any_values_strategy(do_expl=True))
3361 obj = obj_initial(value, expl, optional)
3363 value_expected = None if value is None else value
3364 self.assertEqual(obj, value_expected)
3365 self.assertEqual(obj.expl_tag, expl or expl_initial)
3366 if obj.default is None:
3367 optional = optional_initial if optional is None else optional
3368 optional = False if optional is None else optional
3369 self.assertEqual(obj.optional, optional)
3371 def test_simultaneous_impl_expl(self):
3372 # override it, as Any does not have implicit tag
3375 def test_decoded(self):
3376 # override it, as Any does not have implicit tag
3379 @given(any_values_strategy())
3380 def test_copy(self, values):
3381 for klass in (Any, AnyInherited):
3382 obj = klass(*values)
3383 obj_copied = obj.copy()
3384 self.assert_copied_basic_fields(obj, obj_copied)
3385 self.assertEqual(obj._value, obj_copied._value)
3387 @given(binary().map(OctetString))
3388 def test_stripped(self, value):
3390 with self.assertRaises(NotEnoughData):
3391 obj.decode(obj.encode()[:-1])
3395 integers(min_value=1).map(tag_ctxc),
3397 def test_stripped_expl(self, value, tag_expl):
3398 obj = Any(value, expl=tag_expl)
3399 with self.assertRaises(NotEnoughData):
3400 obj.decode(obj.encode()[:-1])
3403 integers(min_value=31),
3404 integers(min_value=0),
3407 def test_bad_tag(self, tag, offset, decode_path):
3408 decode_path = tuple(str(i) for i in decode_path)
3409 with self.assertRaises(DecodeError) as err:
3411 tag_encode(tag)[:-1],
3413 decode_path=decode_path,
3416 self.assertEqual(err.exception.offset, offset)
3417 self.assertEqual(err.exception.decode_path, decode_path)
3420 integers(min_value=128),
3421 integers(min_value=0),
3424 def test_bad_len(self, l, offset, decode_path):
3425 decode_path = tuple(str(i) for i in decode_path)
3426 with self.assertRaises(DecodeError) as err:
3428 Any.tag_default + len_encode(l)[:-1],
3430 decode_path=decode_path,
3433 self.assertEqual(err.exception.offset, offset)
3434 self.assertEqual(err.exception.decode_path, decode_path)
3436 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3438 any_values_strategy(),
3439 integers().map(lambda x: Integer(x).encode()),
3440 integers(min_value=1).map(tag_ctxc),
3441 integers(min_value=0),
3444 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
3445 for klass in (Any, AnyInherited):
3446 _, _, optional, _decoded = values
3447 obj = klass(value=value, optional=optional, _decoded=_decoded)
3450 self.assertFalse(obj.expled)
3451 obj_encoded = obj.encode()
3452 obj_expled = obj(value, expl=tag_expl)
3453 self.assertTrue(obj_expled.expled)
3456 obj_expled_encoded = obj_expled.encode()
3457 obj_decoded, tail = obj_expled.decode(
3458 obj_expled_encoded + tail_junk,
3463 self.assertEqual(tail, tail_junk)
3464 self.assertEqual(obj_decoded, obj_expled)
3465 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3466 self.assertEqual(bytes(obj_decoded), bytes(obj))
3467 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3468 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3469 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3471 obj_decoded.expl_llen,
3472 len(len_encode(len(obj_encoded))),
3474 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3475 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3478 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3480 self.assertEqual(obj_decoded.expl_offset, offset)
3481 self.assertEqual(obj_decoded.tlen, 0)
3482 self.assertEqual(obj_decoded.llen, 0)
3483 self.assertEqual(obj_decoded.vlen, len(value))
3487 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
3489 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
3490 tags = [tag_encode(tag) for tag in draw(sets(
3491 integers(min_value=0),
3492 min_size=len(names),
3493 max_size=len(names),
3495 schema = [(name, Integer(impl=tag)) for name, tag in zip(names, tags)]
3497 if value_required or draw(booleans()):
3498 value = draw(tuples(
3499 sampled_from([name for name, _ in schema]),
3500 integers().map(Integer),
3504 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3505 default = draw(one_of(
3507 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
3509 optional = draw(one_of(none(), booleans()))
3511 draw(integers(min_value=0)),
3512 draw(integers(min_value=0)),
3513 draw(integers(min_value=0)),
3515 return (schema, value, expl, default, optional, _decoded)
3518 class ChoiceInherited(Choice):
3522 class TestChoice(CommonMixin, TestCase):
3524 schema = (("whatever", Boolean()),)
3527 def test_schema_required(self):
3528 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3531 def test_impl_forbidden(self):
3532 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
3533 Choice(impl=b"whatever")
3535 def test_invalid_value_type(self):
3536 with self.assertRaises(InvalidValueType) as err:
3537 self.base_klass(123)
3539 with self.assertRaises(ObjUnknown) as err:
3540 self.base_klass(("whenever", Boolean(False)))
3542 with self.assertRaises(InvalidValueType) as err:
3543 self.base_klass(("whatever", Integer(123)))
3547 def test_optional(self, optional):
3548 obj = self.base_klass(
3549 default=self.base_klass(("whatever", Boolean(False))),
3552 self.assertTrue(obj.optional)
3555 def test_ready(self, value):
3556 obj = self.base_klass()
3557 self.assertFalse(obj.ready)
3560 self.assertIsNone(obj["whatever"])
3561 with self.assertRaises(ObjNotReady) as err:
3564 obj["whatever"] = Boolean()
3565 self.assertFalse(obj.ready)
3568 obj["whatever"] = Boolean(value)
3569 self.assertTrue(obj.ready)
3573 @given(booleans(), booleans())
3574 def test_comparison(self, value1, value2):
3575 class WahlInherited(self.base_klass):
3577 for klass in (self.base_klass, WahlInherited):
3578 obj1 = klass(("whatever", Boolean(value1)))
3579 obj2 = klass(("whatever", Boolean(value2)))
3580 self.assertEqual(obj1 == obj2, value1 == value2)
3581 self.assertEqual(obj1 != obj2, value1 != value2)
3582 self.assertEqual(obj1 == obj2._value, value1 == value2)
3583 self.assertFalse(obj1 == obj2._value[1])
3585 @given(data_strategy())
3586 def test_call(self, d):
3587 for klass in (Choice, ChoiceInherited):
3595 ) = d.draw(choice_values_strategy())
3598 schema = schema_initial
3600 value=value_initial,
3602 default=default_initial,
3603 optional=optional_initial or False,
3604 _decoded=_decoded_initial,
3613 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
3614 obj = obj_initial(value, expl, default, optional)
3616 value_expected = default if value is None else value
3618 default_initial if value_expected is None
3621 self.assertEqual(obj.choice, value_expected[0])
3622 self.assertEqual(obj.value, int(value_expected[1]))
3623 self.assertEqual(obj.expl_tag, expl or expl_initial)
3624 default_expect = default_initial if default is None else default
3625 if default_expect is not None:
3626 self.assertEqual(obj.default.choice, default_expect[0])
3627 self.assertEqual(obj.default.value, int(default_expect[1]))
3628 if obj.default is None:
3629 optional = optional_initial if optional is None else optional
3630 optional = False if optional is None else optional
3633 self.assertEqual(obj.optional, optional)
3634 self.assertEqual(obj.specs, obj_initial.specs)
3636 def test_simultaneous_impl_expl(self):
3637 # override it, as Any does not have implicit tag
3640 def test_decoded(self):
3641 # override it, as Any does not have implicit tag
3644 @given(choice_values_strategy())
3645 def test_copy(self, values):
3646 _schema, value, expl, default, optional, _decoded = values
3648 class Wahl(self.base_klass):
3654 optional=optional or False,
3657 obj_copied = obj.copy()
3658 self.assertIsNone(obj.tag)
3659 self.assertIsNone(obj_copied.tag)
3660 # hack for assert_copied_basic_fields
3661 obj.tag = "whatever"
3662 obj_copied.tag = "whatever"
3663 self.assert_copied_basic_fields(obj, obj_copied)
3664 self.assertEqual(obj._value, obj_copied._value)
3665 self.assertEqual(obj.specs, obj_copied.specs)
3668 def test_stripped(self, value):
3669 obj = self.base_klass(("whatever", Boolean(value)))
3670 with self.assertRaises(NotEnoughData):
3671 obj.decode(obj.encode()[:-1])
3675 integers(min_value=1).map(tag_ctxc),
3677 def test_stripped_expl(self, value, tag_expl):
3678 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
3679 with self.assertRaises(NotEnoughData):
3680 obj.decode(obj.encode()[:-1])
3682 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3683 @given(data_strategy())
3684 def test_symmetric(self, d):
3685 _schema, value, _, default, optional, _decoded = d.draw(
3686 choice_values_strategy(value_required=True)
3688 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3689 offset = d.draw(integers(min_value=0))
3690 tail_junk = d.draw(binary(max_size=5))
3692 class Wahl(self.base_klass):
3702 self.assertFalse(obj.expled)
3703 obj_encoded = obj.encode()
3704 obj_expled = obj(value, expl=tag_expl)
3705 self.assertTrue(obj_expled.expled)
3708 obj_expled_encoded = obj_expled.encode()
3709 obj_decoded, tail = obj_expled.decode(
3710 obj_expled_encoded + tail_junk,
3715 self.assertEqual(tail, tail_junk)
3716 self.assertEqual(obj_decoded, obj_expled)
3717 self.assertEqual(obj_decoded.choice, obj_expled.choice)
3718 self.assertEqual(obj_decoded.value, obj_expled.value)
3719 self.assertEqual(obj_decoded.choice, obj.choice)
3720 self.assertEqual(obj_decoded.value, obj.value)
3721 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3722 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3723 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3725 obj_decoded.expl_llen,
3726 len(len_encode(len(obj_encoded))),
3728 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3729 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3732 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3734 self.assertEqual(obj_decoded.expl_offset, offset)
3735 self.assertSequenceEqual(
3737 obj_decoded.value.offset - offset:
3738 obj_decoded.value.offset + obj_decoded.value.tlvlen - offset
3744 def test_set_get(self, value):
3747 ("erste", Boolean()),
3748 ("zweite", Integer()),
3751 with self.assertRaises(ObjUnknown) as err:
3752 obj["whatever"] = "whenever"
3753 with self.assertRaises(InvalidValueType) as err:
3754 obj["zweite"] = Boolean(False)
3755 obj["zweite"] = Integer(value)
3757 with self.assertRaises(ObjUnknown) as err:
3760 self.assertIsNone(obj["erste"])
3761 self.assertEqual(obj["zweite"], Integer(value))
3763 def test_tag_mismatch(self):
3766 ("erste", Boolean()),
3768 int_encoded = Integer(123).encode()
3769 bool_encoded = Boolean(False).encode()
3771 obj.decode(bool_encoded)
3772 with self.assertRaises(TagMismatch):
3773 obj.decode(int_encoded)
3775 def test_tag_mismatch_underlying(self):
3776 class SeqOfBoolean(SequenceOf):
3779 class SeqOfInteger(SequenceOf):
3784 ("erste", SeqOfBoolean()),
3787 int_encoded = SeqOfInteger((Integer(123),)).encode()
3788 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
3790 obj.decode(bool_encoded)
3791 with self.assertRaises(TagMismatch) as err:
3792 obj.decode(int_encoded)
3793 self.assertEqual(err.exception.decode_path, ("erste", "0"))
3797 def seq_values_strategy(draw, seq_klass, do_expl=False):
3799 if draw(booleans()):
3802 k: v for k, v in draw(dictionaries(
3805 booleans().map(Boolean),
3806 integers().map(Integer),
3811 if draw(booleans()):
3812 schema = list(draw(dictionaries(
3815 booleans().map(Boolean),
3816 integers().map(Integer),
3822 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3824 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3826 if draw(booleans()):
3827 default = seq_klass()
3829 k: v for k, v in draw(dictionaries(
3832 booleans().map(Boolean),
3833 integers().map(Integer),
3837 optional = draw(one_of(none(), booleans()))
3839 draw(integers(min_value=0)),
3840 draw(integers(min_value=0)),
3841 draw(integers(min_value=0)),
3843 return (value, schema, impl, expl, default, optional, _decoded)
3847 def sequence_strategy(draw, seq_klass):
3848 inputs = draw(lists(
3850 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
3851 tuples(just(Integer), integers(), one_of(none(), integers())),
3856 integers(min_value=1),
3857 min_size=len(inputs),
3858 max_size=len(inputs),
3861 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
3862 for tag, expled in zip(tags, draw(lists(
3864 min_size=len(inputs),
3865 max_size=len(inputs),
3869 for i, optional in enumerate(draw(lists(
3870 sampled_from(("required", "optional", "empty")),
3871 min_size=len(inputs),
3872 max_size=len(inputs),
3874 if optional in ("optional", "empty"):
3875 inits[i]["optional"] = True
3876 if optional == "empty":
3878 empties = set(empties)
3879 names = list(draw(sets(
3881 min_size=len(inputs),
3882 max_size=len(inputs),
3885 for i, (klass, value, default) in enumerate(inputs):
3886 schema.append((names[i], klass(default=default, **inits[i])))
3887 seq_name = draw(text_letters())
3888 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
3891 for i, (klass, value, default) in enumerate(inputs):
3898 "default_value": None if spec.default is None else default,
3902 expect["optional"] = True
3904 expect["presented"] = True
3905 expect["value"] = value
3907 expect["optional"] = True
3908 if default is not None and default == value:
3909 expect["presented"] = False
3910 seq[name] = klass(value)
3911 expects.append(expect)
3916 def sequences_strategy(draw, seq_klass):
3917 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
3919 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
3920 for tag, expled in zip(tags, draw(lists(
3927 i for i, is_default in enumerate(draw(lists(
3933 names = list(draw(sets(
3938 seq_expectses = draw(lists(
3939 sequence_strategy(seq_klass=seq_klass),
3943 seqs = [seq for seq, _ in seq_expectses]
3945 for i, (name, seq) in enumerate(zip(names, seqs)):
3948 seq(default=(seq if i in defaulted else None), **inits[i]),
3950 seq_name = draw(text_letters())
3951 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
3954 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
3957 "expects": expects_inner,
3960 seq_outer[name] = seq_inner
3961 if seq_outer.specs[name].default is None:
3962 expect["presented"] = True
3963 expect_outers.append(expect)
3964 return seq_outer, expect_outers
3967 class SeqMixing(object):
3968 def test_invalid_value_type(self):
3969 with self.assertRaises(InvalidValueType) as err:
3970 self.base_klass(123)
3973 def test_invalid_value_type_set(self):
3974 class Seq(self.base_klass):
3975 schema = (("whatever", Boolean()),)
3977 with self.assertRaises(InvalidValueType) as err:
3978 seq["whatever"] = Integer(123)
3982 def test_optional(self, optional):
3983 obj = self.base_klass(default=self.base_klass(), optional=optional)
3984 self.assertTrue(obj.optional)
3986 @given(data_strategy())
3987 def test_ready(self, d):
3989 str(i): v for i, v in enumerate(d.draw(lists(
3996 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
4003 for name in d.draw(permutations(
4004 list(ready.keys()) + list(non_ready.keys()),
4006 schema_input.append((name, Boolean()))
4008 class Seq(self.base_klass):
4009 schema = tuple(schema_input)
4011 for name in ready.keys():
4013 seq[name] = Boolean()
4014 self.assertFalse(seq.ready)
4017 for name, value in ready.items():
4018 seq[name] = Boolean(value)
4019 self.assertFalse(seq.ready)
4022 with self.assertRaises(ObjNotReady) as err:
4025 for name, value in non_ready.items():
4026 seq[name] = Boolean(value)
4027 self.assertTrue(seq.ready)
4031 @given(data_strategy())
4032 def test_call(self, d):
4033 class SeqInherited(self.base_klass):
4035 for klass in (self.base_klass, SeqInherited):
4044 ) = d.draw(seq_values_strategy(seq_klass=klass))
4045 obj_initial = klass(
4051 optional_initial or False,
4062 ) = d.draw(seq_values_strategy(
4064 do_expl=impl_initial is None,
4066 obj = obj_initial(value, impl, expl, default, optional)
4067 value_expected = default if value is None else value
4069 default_initial if value_expected is None
4072 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
4073 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4074 self.assertEqual(obj.expl_tag, expl or expl_initial)
4076 {} if obj.default is None else obj.default._value,
4077 getattr(default_initial if default is None else default, "_value", {}),
4079 if obj.default is None:
4080 optional = optional_initial if optional is None else optional
4081 optional = False if optional is None else optional
4084 self.assertEqual(list(obj.specs.items()), schema_initial or [])
4085 self.assertEqual(obj.optional, optional)
4087 @given(data_strategy())
4088 def test_copy(self, d):
4089 class SeqInherited(self.base_klass):
4091 for klass in (self.base_klass, SeqInherited):
4092 values = d.draw(seq_values_strategy(seq_klass=klass))
4093 obj = klass(*values)
4094 obj_copied = obj.copy()
4095 self.assert_copied_basic_fields(obj, obj_copied)
4096 self.assertEqual(obj.specs, obj_copied.specs)
4097 self.assertEqual(obj._value, obj_copied._value)
4099 @given(data_strategy())
4100 def test_stripped(self, d):
4101 value = d.draw(integers())
4102 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4104 class Seq(self.base_klass):
4106 schema = (("whatever", Integer()),)
4108 seq["whatever"] = Integer(value)
4109 with self.assertRaises(NotEnoughData):
4110 seq.decode(seq.encode()[:-1])
4112 @given(data_strategy())
4113 def test_stripped_expl(self, d):
4114 value = d.draw(integers())
4115 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4117 class Seq(self.base_klass):
4119 schema = (("whatever", Integer()),)
4121 seq["whatever"] = Integer(value)
4122 with self.assertRaises(NotEnoughData):
4123 seq.decode(seq.encode()[:-1])
4125 @given(binary(min_size=2))
4126 def test_non_tag_mismatch_raised(self, junk):
4128 _, _, len_encoded = tag_strip(memoryview(junk))
4129 len_decode(len_encoded)
4135 class Seq(self.base_klass):
4137 ("whatever", Integer()),
4139 ("whenever", Integer()),
4142 seq["whatever"] = Integer(123)
4143 seq["junk"] = Any(junk)
4144 seq["whenever"] = Integer(123)
4145 with self.assertRaises(DecodeError):
4146 seq.decode(seq.encode())
4149 integers(min_value=31),
4150 integers(min_value=0),
4153 def test_bad_tag(self, tag, offset, decode_path):
4154 decode_path = tuple(str(i) for i in decode_path)
4155 with self.assertRaises(DecodeError) as err:
4156 self.base_klass().decode(
4157 tag_encode(tag)[:-1],
4159 decode_path=decode_path,
4162 self.assertEqual(err.exception.offset, offset)
4163 self.assertEqual(err.exception.decode_path, decode_path)
4166 integers(min_value=128),
4167 integers(min_value=0),
4170 def test_bad_len(self, l, offset, decode_path):
4171 decode_path = tuple(str(i) for i in decode_path)
4172 with self.assertRaises(DecodeError) as err:
4173 self.base_klass().decode(
4174 self.base_klass.tag_default + len_encode(l)[:-1],
4176 decode_path=decode_path,
4179 self.assertEqual(err.exception.offset, offset)
4180 self.assertEqual(err.exception.decode_path, decode_path)
4182 def _assert_expects(self, seq, expects):
4183 for expect in expects:
4185 seq.specs[expect["name"]].optional,
4188 if expect["default_value"] is not None:
4190 seq.specs[expect["name"]].default,
4191 expect["default_value"],
4193 if expect["presented"]:
4194 self.assertIn(expect["name"], seq)
4195 self.assertEqual(seq[expect["name"]], expect["value"])
4197 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4198 @given(data_strategy())
4199 def test_symmetric(self, d):
4200 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
4201 tail_junk = d.draw(binary(max_size=5))
4202 self.assertTrue(seq.ready)
4203 self.assertFalse(seq.decoded)
4204 self._assert_expects(seq, expects)
4207 seq_encoded = seq.encode()
4208 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
4209 self.assertEqual(tail, tail_junk)
4210 self.assertTrue(seq.ready)
4211 self._assert_expects(seq_decoded, expects)
4212 self.assertEqual(seq, seq_decoded)
4213 self.assertEqual(seq_decoded.encode(), seq_encoded)
4214 for expect in expects:
4215 if not expect["presented"]:
4216 self.assertNotIn(expect["name"], seq_decoded)
4218 self.assertIn(expect["name"], seq_decoded)
4219 obj = seq_decoded[expect["name"]]
4220 self.assertTrue(obj.decoded)
4221 offset = obj.expl_offset if obj.expled else obj.offset
4222 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
4223 self.assertSequenceEqual(
4224 seq_encoded[offset:offset + tlvlen],
4228 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4229 @given(data_strategy())
4230 def test_symmetric_with_seq(self, d):
4231 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
4232 self.assertTrue(seq.ready)
4233 seq_encoded = seq.encode()
4234 seq_decoded, tail = seq.decode(seq_encoded)
4235 self.assertEqual(tail, b"")
4236 self.assertTrue(seq.ready)
4237 self.assertEqual(seq, seq_decoded)
4238 self.assertEqual(seq_decoded.encode(), seq_encoded)
4239 for expect_outer in expect_outers:
4240 if not expect_outer["presented"]:
4241 self.assertNotIn(expect_outer["name"], seq_decoded)
4243 self.assertIn(expect_outer["name"], seq_decoded)
4244 obj = seq_decoded[expect_outer["name"]]
4245 self.assertTrue(obj.decoded)
4246 offset = obj.expl_offset if obj.expled else obj.offset
4247 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
4248 self.assertSequenceEqual(
4249 seq_encoded[offset:offset + tlvlen],
4252 self._assert_expects(obj, expect_outer["expects"])
4254 @given(data_strategy())
4255 def test_default_disappears(self, d):
4256 _schema = list(d.draw(dictionaries(
4258 sets(integers(), min_size=2, max_size=2),
4262 class Seq(self.base_klass):
4264 (n, Integer(default=d))
4265 for n, (_, d) in _schema
4268 for name, (value, _) in _schema:
4269 seq[name] = Integer(value)
4270 self.assertEqual(len(seq._value), len(_schema))
4271 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
4272 self.assertGreater(len(seq.encode()), len(empty_seq))
4273 for name, (_, default) in _schema:
4274 seq[name] = Integer(default)
4275 self.assertEqual(len(seq._value), 0)
4276 self.assertSequenceEqual(seq.encode(), empty_seq)
4278 @given(data_strategy())
4279 def test_encoded_default_accepted(self, d):
4280 _schema = list(d.draw(dictionaries(
4285 tags = [tag_encode(tag) for tag in d.draw(sets(
4286 integers(min_value=0),
4287 min_size=len(_schema),
4288 max_size=len(_schema),
4291 class SeqWithoutDefault(self.base_klass):
4293 (n, Integer(impl=t))
4294 for (n, _), t in zip(_schema, tags)
4296 seq_without_default = SeqWithoutDefault()
4297 for name, value in _schema:
4298 seq_without_default[name] = Integer(value)
4299 seq_encoded = seq_without_default.encode()
4301 class SeqWithDefault(self.base_klass):
4303 (n, Integer(default=v, impl=t))
4304 for (n, v), t in zip(_schema, tags)
4306 seq_with_default = SeqWithDefault()
4307 seq_decoded, _ = seq_with_default.decode(seq_encoded)
4308 for name, value in _schema:
4309 self.assertEqual(seq_decoded[name], seq_with_default[name])
4310 self.assertEqual(seq_decoded[name], value)
4312 @given(data_strategy())
4313 def test_missing_from_spec(self, d):
4314 names = list(d.draw(sets(text_letters(), min_size=2)))
4315 tags = [tag_encode(tag) for tag in d.draw(sets(
4316 integers(min_value=0),
4317 min_size=len(names),
4318 max_size=len(names),
4320 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
4322 class SeqFull(self.base_klass):
4323 schema = [(n, Integer(impl=t)) for n, t in names_tags]
4324 seq_full = SeqFull()
4325 for i, name in enumerate(names):
4326 seq_full[name] = Integer(i)
4327 seq_encoded = seq_full.encode()
4328 altered = names_tags[:-2] + names_tags[-1:]
4330 class SeqMissing(self.base_klass):
4331 schema = [(n, Integer(impl=t)) for n, t in altered]
4332 seq_missing = SeqMissing()
4333 with self.assertRaises(TagMismatch):
4334 seq_missing.decode(seq_encoded)
4337 class TestSequence(SeqMixing, CommonMixin, TestCase):
4338 base_klass = Sequence
4344 def test_remaining(self, value, junk):
4345 class Seq(Sequence):
4347 ("whatever", Integer()),
4349 int_encoded = Integer(value).encode()
4351 Sequence.tag_default,
4352 len_encode(len(int_encoded + junk)),
4355 with assertRaisesRegex(self, DecodeError, "remaining"):
4356 Seq().decode(junked)
4358 @given(sets(text_letters(), min_size=2))
4359 def test_obj_unknown(self, names):
4360 missing = names.pop()
4362 class Seq(Sequence):
4363 schema = [(n, Boolean()) for n in names]
4365 with self.assertRaises(ObjUnknown) as err:
4368 with self.assertRaises(ObjUnknown) as err:
4369 seq[missing] = Boolean()
4373 class TestSet(SeqMixing, CommonMixin, TestCase):
4376 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4377 @given(data_strategy())
4378 def test_sorted(self, d):
4380 tag_encode(tag) for tag in
4381 d.draw(sets(integers(min_value=1), min_size=1, max_size=10))
4385 schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
4387 for name, _ in Seq.schema:
4388 seq[name] = OctetString(b"")
4389 seq_encoded = seq.encode()
4390 seq_decoded, _ = seq.decode(seq_encoded)
4391 self.assertSequenceEqual(
4392 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
4393 b"".join(sorted([seq[name].encode() for name, _ in Seq.schema])),
4398 def seqof_values_strategy(draw, schema=None, do_expl=False):
4400 schema = draw(sampled_from((Boolean(), Integer())))
4401 bound_min, bound_max = sorted(draw(sets(
4402 integers(min_value=0, max_value=10),
4406 if isinstance(schema, Boolean):
4407 values_generator = booleans().map(Boolean)
4408 elif isinstance(schema, Integer):
4409 values_generator = integers().map(Integer)
4410 values_generator = lists(
4415 values = draw(one_of(none(), values_generator))
4419 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4421 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4422 default = draw(one_of(none(), values_generator))
4423 optional = draw(one_of(none(), booleans()))
4425 draw(integers(min_value=0)),
4426 draw(integers(min_value=0)),
4427 draw(integers(min_value=0)),
4432 (bound_min, bound_max),
4441 class SeqOfMixing(object):
4442 def test_invalid_value_type(self):
4443 with self.assertRaises(InvalidValueType) as err:
4444 self.base_klass(123)
4447 def test_invalid_values_type(self):
4448 class SeqOf(self.base_klass):
4450 with self.assertRaises(InvalidValueType) as err:
4451 SeqOf([Integer(123), Boolean(False), Integer(234)])
4454 def test_schema_required(self):
4455 with assertRaisesRegex(self, ValueError, "schema must be specified"):
4456 self.base_klass.__mro__[1]()
4458 @given(booleans(), booleans(), binary(), binary())
4459 def test_comparison(self, value1, value2, tag1, tag2):
4460 class SeqOf(self.base_klass):
4462 obj1 = SeqOf([Boolean(value1)])
4463 obj2 = SeqOf([Boolean(value2)])
4464 self.assertEqual(obj1 == obj2, value1 == value2)
4465 self.assertEqual(obj1 != obj2, value1 != value2)
4466 self.assertEqual(obj1 == list(obj2), value1 == value2)
4467 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
4468 obj1 = SeqOf([Boolean(value1)], impl=tag1)
4469 obj2 = SeqOf([Boolean(value1)], impl=tag2)
4470 self.assertEqual(obj1 == obj2, tag1 == tag2)
4471 self.assertEqual(obj1 != obj2, tag1 != tag2)
4473 @given(lists(booleans()))
4474 def test_iter(self, values):
4475 class SeqOf(self.base_klass):
4477 obj = SeqOf([Boolean(value) for value in values])
4478 self.assertEqual(len(obj), len(values))
4479 for i, value in enumerate(obj):
4480 self.assertEqual(value, values[i])
4482 @given(data_strategy())
4483 def test_ready(self, d):
4484 ready = [Integer(v) for v in d.draw(lists(
4491 range(d.draw(integers(min_value=1, max_value=5)))
4494 class SeqOf(self.base_klass):
4496 values = d.draw(permutations(ready + non_ready))
4498 for value in values:
4500 self.assertFalse(seqof.ready)
4503 with self.assertRaises(ObjNotReady) as err:
4506 for i, value in enumerate(values):
4507 self.assertEqual(seqof[i], value)
4508 if not seqof[i].ready:
4509 seqof[i] = Integer(i)
4510 self.assertTrue(seqof.ready)
4514 def test_spec_mismatch(self):
4515 class SeqOf(self.base_klass):
4518 seqof.append(Integer(123))
4519 with self.assertRaises(ValueError):
4520 seqof.append(Boolean(False))
4521 with self.assertRaises(ValueError):
4522 seqof[0] = Boolean(False)
4524 @given(data_strategy())
4525 def test_bounds_satisfied(self, d):
4526 class SeqOf(self.base_klass):
4528 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
4529 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
4530 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
4531 SeqOf(value=value, bounds=(bound_min, bound_max))
4533 @given(data_strategy())
4534 def test_bounds_unsatisfied(self, d):
4535 class SeqOf(self.base_klass):
4537 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
4538 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
4539 value = [Boolean()] * d.draw(integers(max_value=bound_min - 1))
4540 with self.assertRaises(BoundsError) as err:
4541 SeqOf(value=value, bounds=(bound_min, bound_max))
4543 value = [Boolean()] * d.draw(integers(
4544 min_value=bound_max + 1,
4545 max_value=bound_max + 10,
4547 with self.assertRaises(BoundsError) as err:
4548 SeqOf(value=value, bounds=(bound_min, bound_max))
4551 @given(integers(min_value=1, max_value=10))
4552 def test_out_of_bounds(self, bound_max):
4553 class SeqOf(self.base_klass):
4555 bounds = (0, bound_max)
4557 for _ in range(bound_max):
4558 seqof.append(Integer(123))
4559 with self.assertRaises(BoundsError):
4560 seqof.append(Integer(123))
4562 @given(data_strategy())
4563 def test_call(self, d):
4573 ) = d.draw(seqof_values_strategy())
4575 class SeqOf(self.base_klass):
4576 schema = schema_initial
4577 obj_initial = SeqOf(
4578 value=value_initial,
4579 bounds=bounds_initial,
4582 default=default_initial,
4583 optional=optional_initial or False,
4584 _decoded=_decoded_initial,
4595 ) = d.draw(seqof_values_strategy(
4596 schema=schema_initial,
4597 do_expl=impl_initial is None,
4599 if (default is None) and (obj_initial.default is not None):
4602 (bounds is None) and
4603 (value is not None) and
4604 (bounds_initial is not None) and
4605 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
4609 (bounds is None) and
4610 (default is not None) and
4611 (bounds_initial is not None) and
4612 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
4624 value_expected = default if value is None else value
4626 default_initial if value_expected is None
4629 value_expected = () if value_expected is None else value_expected
4630 self.assertEqual(obj, value_expected)
4631 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4632 self.assertEqual(obj.expl_tag, expl or expl_initial)
4635 default_initial if default is None else default,
4637 if obj.default is None:
4638 optional = optional_initial if optional is None else optional
4639 optional = False if optional is None else optional
4642 self.assertEqual(obj.optional, optional)
4644 (obj._bound_min, obj._bound_max),
4645 bounds or bounds_initial or (0, float("+inf")),
4648 @given(seqof_values_strategy())
4649 def test_copy(self, values):
4650 _schema, value, bounds, impl, expl, default, optional, _decoded = values
4652 class SeqOf(self.base_klass):
4660 optional=optional or False,
4663 obj_copied = obj.copy()
4664 self.assert_copied_basic_fields(obj, obj_copied)
4665 self.assertEqual(obj._bound_min, obj_copied._bound_min)
4666 self.assertEqual(obj._bound_max, obj_copied._bound_max)
4667 self.assertEqual(obj._value, obj_copied._value)
4671 integers(min_value=1).map(tag_encode),
4673 def test_stripped(self, values, tag_impl):
4674 class SeqOf(self.base_klass):
4675 schema = OctetString()
4676 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
4677 with self.assertRaises(NotEnoughData):
4678 obj.decode(obj.encode()[:-1])
4682 integers(min_value=1).map(tag_ctxc),
4684 def test_stripped_expl(self, values, tag_expl):
4685 class SeqOf(self.base_klass):
4686 schema = OctetString()
4687 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
4688 with self.assertRaises(NotEnoughData):
4689 obj.decode(obj.encode()[:-1])
4692 integers(min_value=31),
4693 integers(min_value=0),
4696 def test_bad_tag(self, tag, offset, decode_path):
4697 decode_path = tuple(str(i) for i in decode_path)
4698 with self.assertRaises(DecodeError) as err:
4699 self.base_klass().decode(
4700 tag_encode(tag)[:-1],
4702 decode_path=decode_path,
4705 self.assertEqual(err.exception.offset, offset)
4706 self.assertEqual(err.exception.decode_path, decode_path)
4709 integers(min_value=128),
4710 integers(min_value=0),
4713 def test_bad_len(self, l, offset, decode_path):
4714 decode_path = tuple(str(i) for i in decode_path)
4715 with self.assertRaises(DecodeError) as err:
4716 self.base_klass().decode(
4717 self.base_klass.tag_default + len_encode(l)[:-1],
4719 decode_path=decode_path,
4722 self.assertEqual(err.exception.offset, offset)
4723 self.assertEqual(err.exception.decode_path, decode_path)
4725 @given(binary(min_size=1))
4726 def test_tag_mismatch(self, impl):
4727 assume(impl != self.base_klass.tag_default)
4728 with self.assertRaises(TagMismatch):
4729 self.base_klass(impl=impl).decode(self.base_klass().encode())
4731 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4733 seqof_values_strategy(schema=Integer()),
4734 lists(integers().map(Integer)),
4735 integers(min_value=1).map(tag_ctxc),
4736 integers(min_value=0),
4739 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
4740 _, _, _, _, _, default, optional, _decoded = values
4742 class SeqOf(self.base_klass):
4752 self.assertFalse(obj.expled)
4753 obj_encoded = obj.encode()
4754 obj_expled = obj(value, expl=tag_expl)
4755 self.assertTrue(obj_expled.expled)
4758 obj_expled_encoded = obj_expled.encode()
4759 obj_decoded, tail = obj_expled.decode(
4760 obj_expled_encoded + tail_junk,
4765 self.assertEqual(tail, tail_junk)
4766 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
4767 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4768 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4769 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4771 obj_decoded.expl_llen,
4772 len(len_encode(len(obj_encoded))),
4774 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4775 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4778 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4780 self.assertEqual(obj_decoded.expl_offset, offset)
4781 for obj_inner in obj_decoded:
4782 self.assertIn(obj_inner, obj_decoded)
4783 self.assertSequenceEqual(
4786 obj_inner.offset - offset:
4787 obj_inner.offset + obj_inner.tlvlen - offset
4792 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
4793 class SeqOf(SequenceOf):
4797 def _test_symmetric_compare_objs(self, obj1, obj2):
4798 self.assertEqual(obj1, obj2)
4799 self.assertSequenceEqual(list(obj1), list(obj2))
4802 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
4807 def _test_symmetric_compare_objs(self, obj1, obj2):
4808 self.assertSetEqual(
4809 set(int(v) for v in obj1),
4810 set(int(v) for v in obj2),
4813 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4814 @given(data_strategy())
4815 def test_sorted(self, d):
4816 values = [OctetString(v) for v in d.draw(lists(binary()))]
4819 schema = OctetString()
4821 seq_encoded = seq.encode()
4822 seq_decoded, _ = seq.decode(seq_encoded)
4823 self.assertSequenceEqual(
4824 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
4825 b"".join(sorted([v.encode() for v in values])),
4829 class TestGoMarshalVectors(TestCase):
4831 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
4832 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
4833 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
4834 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
4835 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
4837 class Seq(Sequence):
4839 ("erste", Integer()),
4840 ("zweite", Integer(optional=True))
4843 seq["erste"] = Integer(64)
4844 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
4845 seq["erste"] = Integer(0x123456)
4846 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
4847 seq["erste"] = Integer(64)
4848 seq["zweite"] = Integer(65)
4849 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
4851 class NestedSeq(Sequence):
4855 seq["erste"] = Integer(127)
4856 seq["zweite"] = None
4857 nested = NestedSeq()
4858 nested["nest"] = seq
4859 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
4861 self.assertSequenceEqual(
4862 OctetString(b"\x01\x02\x03").encode(),
4863 hexdec("0403010203"),
4866 class Seq(Sequence):
4868 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
4871 seq["erste"] = Integer(64)
4872 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
4874 class Seq(Sequence):
4876 ("erste", Integer(expl=tag_ctxc(5))),
4879 seq["erste"] = Integer(64)
4880 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
4882 class Seq(Sequence):
4885 impl=tag_encode(0, klass=TagClassContext),
4890 seq["erste"] = Null()
4891 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
4893 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
4895 self.assertSequenceEqual(
4896 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
4897 hexdec("170d3730303130313030303030305a"),
4899 self.assertSequenceEqual(
4900 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
4901 hexdec("170d3039313131353232353631365a"),
4903 self.assertSequenceEqual(
4904 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
4905 hexdec("180f32313030303430353132303130315a"),
4908 class Seq(Sequence):
4910 ("erste", GeneralizedTime()),
4913 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
4914 self.assertSequenceEqual(
4916 hexdec("3011180f32303039313131353232353631365a"),
4919 self.assertSequenceEqual(
4920 BitString((1, b"\x80")).encode(),
4923 self.assertSequenceEqual(
4924 BitString((12, b"\x81\xF0")).encode(),
4925 hexdec("03030481f0"),
4928 self.assertSequenceEqual(
4929 ObjectIdentifier("1.2.3.4").encode(),
4930 hexdec("06032a0304"),
4932 self.assertSequenceEqual(
4933 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
4934 hexdec("06092a864888932d010105"),
4936 self.assertSequenceEqual(
4937 ObjectIdentifier("2.100.3").encode(),
4938 hexdec("0603813403"),
4941 self.assertSequenceEqual(
4942 PrintableString("test").encode(),
4943 hexdec("130474657374"),
4945 self.assertSequenceEqual(
4946 PrintableString("x" * 127).encode(),
4947 hexdec("137F" + "78" * 127),
4949 self.assertSequenceEqual(
4950 PrintableString("x" * 128).encode(),
4951 hexdec("138180" + "78" * 128),
4953 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
4955 class Seq(Sequence):
4957 ("erste", IA5String()),
4960 seq["erste"] = IA5String("test")
4961 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
4963 class Seq(Sequence):
4965 ("erste", PrintableString()),
4968 seq["erste"] = PrintableString("test")
4969 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
4970 seq["erste"] = PrintableString("test*")
4971 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
4973 class Seq(Sequence):
4975 ("erste", Any(optional=True)),
4976 ("zweite", Integer()),
4979 seq["zweite"] = Integer(64)
4980 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
4985 seq.append(Integer(10))
4986 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
4988 class _SeqOf(SequenceOf):
4989 schema = PrintableString()
4991 class SeqOf(SequenceOf):
4994 _seqof.append(PrintableString("1"))
4996 seqof.append(_seqof)
4997 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
4999 class Seq(Sequence):
5001 ("erste", Integer(default=1)),
5004 seq["erste"] = Integer(0)
5005 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
5006 seq["erste"] = Integer(1)
5007 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
5008 seq["erste"] = Integer(2)
5009 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
5012 class TestPP(TestCase):
5013 @given(data_strategy())
5014 def test_oid_printing(self, d):
5016 str(ObjectIdentifier(k)): v * 2
5017 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
5019 chosen = d.draw(sampled_from(sorted(oids)))
5020 chosen_id = oids[chosen]
5021 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
5022 self.assertNotIn(chosen_id, pp_console_row(pp))
5023 self.assertIn(chosen_id, pp_console_row(pp, oids=oids))
5026 class TestAutoAddSlots(TestCase):
5028 class Inher(Integer):
5031 with self.assertRaises(AttributeError):
5033 inher.unexistent = "whatever"
5036 class TestOIDDefines(TestCase):
5037 @given(data_strategy())
5038 def runTest(self, d):
5039 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
5040 value_name_chosen = d.draw(sampled_from(value_names))
5042 ObjectIdentifier(oid)
5043 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
5045 oid_chosen = d.draw(sampled_from(oids))
5046 values = d.draw(lists(
5048 min_size=len(value_names),
5049 max_size=len(value_names),
5052 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
5053 oid: Integer() for oid in oids[:-1]
5056 for i, value_name in enumerate(value_names):
5057 _schema.append((value_name, Any(expl=tag_ctxp(i))))
5059 class Seq(Sequence):
5062 for value_name, value in zip(value_names, values):
5063 seq[value_name] = Any(Integer(value).encode())
5064 seq["type"] = oid_chosen
5065 seq, _ = Seq().decode(seq.encode())
5066 for value_name in value_names:
5067 if value_name == value_name_chosen:
5069 self.assertIsNone(seq[value_name].defined)
5070 if value_name_chosen in oids[:-1]:
5071 self.assertIsNotNone(seq[value_name_chosen].defined)
5072 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
5073 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
5076 class TestDefinesByPath(TestCase):
5077 def test_generated(self):
5078 class Seq(Sequence):
5080 ("type", ObjectIdentifier()),
5081 ("value", OctetString(expl=tag_ctxc(123))),
5084 class SeqInner(Sequence):
5086 ("typeInner", ObjectIdentifier()),
5087 ("valueInner", Any()),
5090 class PairValue(SetOf):
5093 class Pair(Sequence):
5095 ("type", ObjectIdentifier()),
5096 ("value", PairValue()),
5099 class Pairs(SequenceOf):
5106 type_octet_stringed,
5108 ObjectIdentifier(oid)
5109 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
5111 seq_integered = Seq()
5112 seq_integered["type"] = type_integered
5113 seq_integered["value"] = OctetString(Integer(123).encode())
5114 seq_integered_raw = seq_integered.encode()
5118 (type_octet_stringed, OctetString(b"whatever")),
5119 (type_integered, Integer(123)),
5120 (type_octet_stringed, OctetString(b"whenever")),
5121 (type_integered, Integer(234)),
5123 for t, v in pairs_input:
5126 pair["value"] = PairValue((Any(v),))
5128 seq_inner = SeqInner()
5129 seq_inner["typeInner"] = type_innered
5130 seq_inner["valueInner"] = Any(pairs)
5131 seq_sequenced = Seq()
5132 seq_sequenced["type"] = type_sequenced
5133 seq_sequenced["value"] = OctetString(seq_inner.encode())
5134 seq_sequenced_raw = seq_sequenced.encode()
5136 defines_by_path = []
5137 seq_integered, _ = Seq().decode(seq_integered_raw)
5138 self.assertIsNone(seq_integered["value"].defined)
5139 defines_by_path.append(
5140 (("type",), ((("value",), {
5141 type_integered: Integer(),
5142 type_sequenced: SeqInner(),
5145 seq_integered, _ = Seq().decode(
5147 ctx={"defines_by_path": defines_by_path},
5149 self.assertIsNotNone(seq_integered["value"].defined)
5150 self.assertEqual(seq_integered["value"].defined[0], type_integered)
5151 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
5152 self.assertTrue(seq_integered_raw[
5153 seq_integered["value"].defined[1].offset:
5154 ].startswith(Integer(123).encode()))
5156 seq_sequenced, _ = Seq().decode(
5158 ctx={"defines_by_path": defines_by_path},
5160 self.assertIsNotNone(seq_sequenced["value"].defined)
5161 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
5162 seq_inner = seq_sequenced["value"].defined[1]
5163 self.assertIsNone(seq_inner["valueInner"].defined)
5165 defines_by_path.append((
5166 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
5167 ((("valueInner",), {type_innered: Pairs()}),),
5169 seq_sequenced, _ = Seq().decode(
5171 ctx={"defines_by_path": defines_by_path},
5173 self.assertIsNotNone(seq_sequenced["value"].defined)
5174 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
5175 seq_inner = seq_sequenced["value"].defined[1]
5176 self.assertIsNotNone(seq_inner["valueInner"].defined)
5177 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
5178 pairs = seq_inner["valueInner"].defined[1]
5180 self.assertIsNone(pair["value"][0].defined)
5182 defines_by_path.append((
5185 DecodePathDefBy(type_sequenced),
5187 DecodePathDefBy(type_innered),
5192 type_integered: Integer(),
5193 type_octet_stringed: OctetString(),
5196 seq_sequenced, _ = Seq().decode(
5198 ctx={"defines_by_path": defines_by_path},
5200 self.assertIsNotNone(seq_sequenced["value"].defined)
5201 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
5202 seq_inner = seq_sequenced["value"].defined[1]
5203 self.assertIsNotNone(seq_inner["valueInner"].defined)
5204 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
5205 pairs_got = seq_inner["valueInner"].defined[1]
5206 for pair_input, pair_got in zip(pairs_input, pairs_got):
5207 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
5208 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
5210 @given(oid_strategy(), integers())
5211 def test_simple(self, oid, tgt):
5212 class Inner(Sequence):
5214 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
5215 ObjectIdentifier(oid): Integer(),
5219 class Outer(Sequence):
5222 ("tgt", OctetString()),
5226 inner["oid"] = ObjectIdentifier(oid)
5228 outer["inner"] = inner
5229 outer["tgt"] = OctetString(Integer(tgt).encode())
5230 decoded, _ = Outer().decode(outer.encode())
5231 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
5234 class TestAbsDecodePath(TestCase):
5236 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
5237 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
5239 def test_concat(self, decode_path, rel_path):
5240 self.assertSequenceEqual(
5241 abs_decode_path(decode_path, rel_path),
5242 decode_path + rel_path,
5246 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
5247 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
5249 def test_abs(self, decode_path, rel_path):
5250 self.assertSequenceEqual(
5251 abs_decode_path(decode_path, ("/",) + rel_path),
5256 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
5257 integers(min_value=1, max_value=3),
5258 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
5260 def test_dots(self, decode_path, number_of_dots, rel_path):
5261 self.assertSequenceEqual(
5262 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
5263 decode_path[:-number_of_dots] + rel_path,
5267 class TestStrictDefaultExistence(TestCase):
5268 @given(data_strategy())
5269 def runTest(self, d):
5270 count = d.draw(integers(min_value=1, max_value=10))
5271 chosen = d.draw(integers(min_value=0, max_value=count - 1))
5273 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
5274 for i in range(count)
5277 class Seq(Sequence):
5280 for i in range(count):
5281 seq["int%d" % i] = Integer(123)
5283 chosen = "int%d" % chosen
5284 seq.specs[chosen] = seq.specs[chosen](default=123)
5286 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
5287 seq.decode(raw, ctx={"strict_default_existence": True})