2 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
3 # Copyright (C) 2017-2020 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, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this program. If not, see
16 # <http://www.gnu.org/licenses/>.
19 from copy import deepcopy
20 from datetime import datetime
21 from datetime import timedelta
22 from importlib import import_module
23 from io import BytesIO
24 from operator import attrgetter
25 from os import environ
26 from os import urandom
27 from random import random
28 from string import ascii_letters
29 from string import digits
30 from string import printable
31 from string import whitespace
32 from time import mktime
34 from unittest import TestCase
36 from dateutil.tz import UTC
37 from hypothesis import assume
38 from hypothesis import given
39 from hypothesis import settings
40 from hypothesis.strategies import binary
41 from hypothesis.strategies import booleans
42 from hypothesis.strategies import composite
43 from hypothesis.strategies import data as data_strategy
44 from hypothesis.strategies import datetimes
45 from hypothesis.strategies import dictionaries
46 from hypothesis.strategies import integers
47 from hypothesis.strategies import just
48 from hypothesis.strategies import lists
49 from hypothesis.strategies import none
50 from hypothesis.strategies import one_of
51 from hypothesis.strategies import permutations
52 from hypothesis.strategies import sampled_from
53 from hypothesis.strategies import sets
54 from hypothesis.strategies import text
55 from hypothesis.strategies import tuples
56 from six import assertRaisesRegex
57 from six import binary_type
58 from six import byte2int
59 from six import indexbytes
60 from six import int2byte
61 from six import iterbytes
63 from six import text_type
64 from six import unichr as six_unichr
65 from six.moves import xrange as six_xrange
66 from six.moves.cPickle import dumps as pickle_dumps
67 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
68 from six.moves.cPickle import loads as pickle_loads
70 from pyderasn import _pp
71 from pyderasn import abs_decode_path
72 from pyderasn import Any
73 from pyderasn import BitString
74 from pyderasn import BMPString
75 from pyderasn import Boolean
76 from pyderasn import BoundsError
77 from pyderasn import Choice
78 from pyderasn import DecodeError
79 from pyderasn import DecodePathDefBy
80 from pyderasn import encode2pass
81 from pyderasn import encode_cer
82 from pyderasn import Enumerated
83 from pyderasn import EOC
84 from pyderasn import EOC_LEN
85 from pyderasn import ExceedingData
86 from pyderasn import GeneralizedTime
87 from pyderasn import GeneralString
88 from pyderasn import GraphicString
89 from pyderasn import hexdec
90 from pyderasn import hexenc
91 from pyderasn import IA5String
92 from pyderasn import Integer
93 from pyderasn import InvalidLength
94 from pyderasn import InvalidOID
95 from pyderasn import InvalidValueType
96 from pyderasn import len_decode
97 from pyderasn import len_encode
98 from pyderasn import LEN_YYMMDDHHMMSSZ
99 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
100 from pyderasn import LEN_YYYYMMDDHHMMSSZ
101 from pyderasn import LENINDEF
102 from pyderasn import LenIndefForm
103 from pyderasn import NotEnoughData
104 from pyderasn import Null
105 from pyderasn import NumericString
106 from pyderasn import ObjectIdentifier
107 from pyderasn import ObjNotReady
108 from pyderasn import ObjUnknown
109 from pyderasn import OctetString
110 from pyderasn import pp_console_row
111 from pyderasn import pprint
112 from pyderasn import PrintableString
113 from pyderasn import Sequence
114 from pyderasn import SequenceOf
115 from pyderasn import Set
116 from pyderasn import SetOf
117 from pyderasn import tag_ctxc
118 from pyderasn import tag_ctxp
119 from pyderasn import tag_decode
120 from pyderasn import tag_encode
121 from pyderasn import tag_strip
122 from pyderasn import TagClassApplication
123 from pyderasn import TagClassContext
124 from pyderasn import TagClassPrivate
125 from pyderasn import TagClassUniversal
126 from pyderasn import TagFormConstructed
127 from pyderasn import TagFormPrimitive
128 from pyderasn import TagMismatch
129 from pyderasn import TeletexString
130 from pyderasn import UniversalString
131 from pyderasn import UTCTime
132 from pyderasn import UTF8String
133 from pyderasn import VideotexString
134 from pyderasn import VisibleString
137 max_examples = environ.get("MAX_EXAMPLES")
138 settings.register_profile("local", settings(
140 **({"max_examples": int(max_examples)} if max_examples else {})
142 settings.load_profile("local")
143 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
145 tag_classes = sampled_from((
151 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
152 decode_path_strat = lists(integers(), max_size=3).map(
153 lambda decode_path: tuple(str(dp) for dp in decode_path)
155 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
158 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
160 self_module = import_module(__name__)
163 def register_class(klass):
164 klassname = klass.__name__ + str(time()).replace(".", "")
165 klass.__name__ = klassname
166 klass.__qualname__ = klassname
167 setattr(self_module, klassname, klass)
170 def assert_exceeding_data(self, call, junk):
173 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
178 class TestHex(TestCase):
180 def test_symmetric(self, data):
181 self.assertEqual(hexdec(hexenc(data)), data)
184 class TestTagCoder(TestCase):
185 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
189 integers(min_value=0, max_value=30),
192 def test_short(self, klass, form, num, junk):
193 raw = tag_encode(klass=klass, form=form, num=num)
194 self.assertEqual(tag_decode(raw), (klass, form, num))
195 self.assertEqual(len(raw), 1)
197 byte2int(tag_encode(klass=klass, form=form, num=0)),
198 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
200 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
201 self.assertSequenceEqual(stripped.tobytes(), raw)
202 self.assertEqual(tlen, len(raw))
203 self.assertSequenceEqual(tail, junk)
205 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
209 integers(min_value=31),
212 def test_long(self, klass, form, num, junk):
213 raw = tag_encode(klass=klass, form=form, num=num)
214 self.assertEqual(tag_decode(raw), (klass, form, num))
215 self.assertGreater(len(raw), 1)
217 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
220 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
221 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
222 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
223 self.assertSequenceEqual(stripped.tobytes(), raw)
224 self.assertEqual(tlen, len(raw))
225 self.assertSequenceEqual(tail, junk)
227 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
228 @given(integers(min_value=31))
229 def test_unfinished_tag(self, num):
230 raw = bytearray(tag_encode(num=num))
231 for i in range(1, len(raw)):
233 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
234 tag_strip(bytes(raw))
236 def test_go_vectors_valid(self):
237 for data, (eklass, etag, elen, eform) in (
238 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
239 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
240 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
241 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
242 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
243 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
244 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
245 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
246 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
247 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
249 tag, _, len_encoded = tag_strip(memoryview(data))
250 klass, form, num = tag_decode(tag)
251 _len, _, tail = len_decode(len_encoded)
252 self.assertSequenceEqual(tail, b"")
253 self.assertEqual(klass, eklass)
254 self.assertEqual(num, etag)
255 self.assertEqual(_len, elen)
256 self.assertEqual(form, eform)
258 def test_go_vectors_invalid(self):
266 with self.assertRaises(DecodeError):
267 _, _, len_encoded = tag_strip(memoryview(data))
268 len_decode(len_encoded)
271 integers(min_value=0, max_value=127),
272 integers(min_value=0, max_value=2),
274 def test_long_instead_of_short(self, l, dummy_num):
275 octets = (b"\x00" * dummy_num) + int2byte(l)
276 octets = int2byte((dummy_num + 1) | 0x80) + octets
277 with self.assertRaises(DecodeError):
280 @given(tag_classes, tag_forms, integers(min_value=31))
281 def test_leading_zero_byte(self, klass, form, num):
282 raw = tag_encode(klass=klass, form=form, num=num)
283 raw = b"".join((raw[:1], b"\x80", raw[1:]))
284 with assertRaisesRegex(self, DecodeError, "leading zero byte"):
287 @given(tag_classes, tag_forms, integers(max_value=30, min_value=0))
288 def test_unexpected_long_form(self, klass, form, num):
289 raw = int2byte(klass | form | 31) + int2byte(num)
290 with assertRaisesRegex(self, DecodeError, "unexpected long form"):
294 class TestLenCoder(TestCase):
295 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
297 integers(min_value=0, max_value=127),
300 def test_short(self, l, junk):
301 raw = len_encode(l) + junk
302 decoded, llen, tail = len_decode(memoryview(raw))
303 self.assertEqual(decoded, l)
304 self.assertEqual(llen, 1)
305 self.assertEqual(len(raw), 1 + len(junk))
306 self.assertEqual(tail.tobytes(), junk)
308 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
310 integers(min_value=128),
313 def test_long(self, l, junk):
314 raw = len_encode(l) + junk
315 decoded, llen, tail = len_decode(memoryview(raw))
316 self.assertEqual(decoded, l)
317 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
318 self.assertEqual(llen, len(raw) - len(junk))
319 self.assertNotEqual(indexbytes(raw, 1), 0)
320 self.assertSequenceEqual(tail.tobytes(), junk)
322 def test_empty(self):
323 with self.assertRaises(NotEnoughData):
326 @given(integers(min_value=128))
327 def test_stripped(self, _len):
328 with self.assertRaises(NotEnoughData):
329 len_decode(len_encode(_len)[:-1])
332 text_printable = text(alphabet=printable, min_size=1)
336 def text_letters(draw):
337 result = draw(text(alphabet=ascii_letters, min_size=1))
339 result = result.encode("ascii")
343 class CommonMixin(object):
344 def test_tag_default(self):
345 obj = self.base_klass()
346 self.assertEqual(obj.tag, obj.tag_default)
348 def test_simultaneous_impl_expl(self):
349 with self.assertRaises(ValueError):
350 self.base_klass(impl=b"whatever", expl=b"whenever")
352 @given(binary(min_size=1), integers(), integers(), integers())
353 def test_decoded(self, impl, offset, llen, vlen):
354 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
355 self.assertEqual(obj.offset, offset)
356 self.assertEqual(obj.llen, llen)
357 self.assertEqual(obj.vlen, vlen)
358 self.assertEqual(obj.tlen, len(impl))
359 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
361 @given(binary(min_size=1))
362 def test_impl_inherited(self, impl_tag):
363 class Inherited(self.base_klass):
366 self.assertSequenceEqual(obj.impl, impl_tag)
367 self.assertFalse(obj.expled)
369 tag_class, _, tag_num = tag_decode(impl_tag)
370 self.assertEqual(obj.tag_order, (tag_class, tag_num))
372 @given(binary(min_size=1))
373 def test_expl_inherited(self, expl_tag):
374 class Inherited(self.base_klass):
377 self.assertSequenceEqual(obj.expl, expl_tag)
378 self.assertTrue(obj.expled)
380 tag_class, _, tag_num = tag_decode(expl_tag)
381 self.assertEqual(obj.tag_order, (tag_class, tag_num))
383 def assert_copied_basic_fields(self, obj, obj_copied):
384 self.assertEqual(obj, obj_copied)
385 self.assertSequenceEqual(obj.tag, obj_copied.tag)
386 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
387 self.assertEqual(obj.default, obj_copied.default)
388 self.assertEqual(obj.optional, obj_copied.optional)
389 self.assertEqual(obj.offset, obj_copied.offset)
390 self.assertEqual(obj.llen, obj_copied.llen)
391 self.assertEqual(obj.vlen, obj_copied.vlen)
393 self.assertEqual(obj.tag_order, obj_copied.tag_order)
397 def boolean_values_strategy(draw, do_expl=False):
398 value = draw(one_of(none(), booleans()))
402 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
404 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
405 default = draw(one_of(none(), booleans()))
406 optional = draw(one_of(none(), booleans()))
408 draw(integers(min_value=0)),
409 draw(integers(min_value=0)),
410 draw(integers(min_value=0)),
412 return (value, impl, expl, default, optional, _decoded)
415 class BooleanInherited(Boolean):
419 class TestBoolean(CommonMixin, TestCase):
422 def test_invalid_value_type(self):
423 with self.assertRaises(InvalidValueType) as err:
428 def test_optional(self, optional):
429 obj = Boolean(default=Boolean(False), optional=optional)
430 self.assertTrue(obj.optional)
433 def test_ready(self, value):
435 self.assertFalse(obj.ready)
438 pprint(obj, big_blobs=True, with_decode_path=True)
439 with self.assertRaises(ObjNotReady) as err:
441 with self.assertRaises(ObjNotReady) as err:
445 self.assertTrue(obj.ready)
448 pprint(obj, big_blobs=True, with_decode_path=True)
450 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
451 def test_comparison(self, value1, value2, tag1, tag2):
452 for klass in (Boolean, BooleanInherited):
455 self.assertEqual(obj1 == obj2, value1 == value2)
456 self.assertEqual(obj1 != obj2, value1 != value2)
457 self.assertEqual(obj1 == bool(obj2), value1 == value2)
458 obj1 = klass(value1, impl=tag1)
459 obj2 = klass(value1, impl=tag2)
460 self.assertEqual(obj1 == obj2, tag1 == tag2)
461 self.assertEqual(obj1 != obj2, tag1 != tag2)
463 @given(data_strategy())
464 def test_call(self, d):
465 for klass in (Boolean, BooleanInherited):
473 ) = d.draw(boolean_values_strategy())
479 optional_initial or False,
489 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
490 obj = obj_initial(value, impl, expl, default, optional)
492 value_expected = default if value is None else value
494 default_initial if value_expected is None
497 self.assertEqual(obj, value_expected)
498 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
499 self.assertEqual(obj.expl_tag, expl or expl_initial)
502 default_initial if default is None else default,
504 if obj.default is None:
505 optional = optional_initial if optional is None else optional
506 optional = False if optional is None else optional
509 self.assertEqual(obj.optional, optional)
511 @given(boolean_values_strategy())
512 def test_copy(self, values):
513 for klass in (Boolean, BooleanInherited):
515 for copy_func in copy_funcs:
516 obj_copied = copy_func(obj)
517 self.assert_copied_basic_fields(obj, obj_copied)
521 integers(min_value=1).map(tag_encode),
523 def test_stripped(self, value, tag_impl):
524 obj = Boolean(value, impl=tag_impl)
525 with self.assertRaises(NotEnoughData):
526 obj.decode(obj.encode()[:-1])
527 with self.assertRaises(NotEnoughData):
528 obj.decode(encode2pass(obj)[:-1])
532 integers(min_value=1).map(tag_ctxc),
534 def test_stripped_expl(self, value, tag_expl):
535 obj = Boolean(value, expl=tag_expl)
536 with self.assertRaises(NotEnoughData):
537 obj.decode(obj.encode()[:-1])
538 with self.assertRaises(NotEnoughData):
539 obj.decode(encode2pass(obj)[:-1])
542 integers(min_value=31),
543 integers(min_value=0),
546 def test_bad_tag(self, tag, offset, decode_path):
547 with self.assertRaises(DecodeError) as err:
549 tag_encode(tag)[:-1],
551 decode_path=decode_path,
554 self.assertEqual(err.exception.offset, offset)
555 self.assertEqual(err.exception.decode_path, decode_path)
558 integers(min_value=31),
559 integers(min_value=0),
562 def test_bad_expl_tag(self, tag, offset, decode_path):
563 with self.assertRaises(DecodeError) as err:
564 Boolean(expl=Boolean.tag_default).decode(
565 tag_encode(tag)[:-1],
567 decode_path=decode_path,
570 self.assertEqual(err.exception.offset, offset)
571 self.assertEqual(err.exception.decode_path, decode_path)
574 integers(min_value=128),
575 integers(min_value=0),
578 def test_bad_len(self, l, offset, decode_path):
579 with self.assertRaises(DecodeError) as err:
581 Boolean.tag_default + len_encode(l)[:-1],
583 decode_path=decode_path,
586 self.assertEqual(err.exception.offset, offset)
587 self.assertEqual(err.exception.decode_path, decode_path)
590 integers(min_value=128),
591 integers(min_value=0),
594 def test_bad_expl_len(self, l, offset, decode_path):
595 with self.assertRaises(DecodeError) as err:
596 Boolean(expl=Boolean.tag_default).decode(
597 Boolean.tag_default + len_encode(l)[:-1],
599 decode_path=decode_path,
602 self.assertEqual(err.exception.offset, offset)
603 self.assertEqual(err.exception.decode_path, decode_path)
605 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
607 boolean_values_strategy(),
609 integers(min_value=1).map(tag_ctxc),
610 integers(min_value=0),
614 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
615 for klass in (Boolean, BooleanInherited):
616 _, _, _, default, optional, _decoded = values
625 pprint(obj, big_blobs=True, with_decode_path=True)
626 self.assertFalse(obj.expled)
627 obj_encoded = obj.encode()
628 self.assertEqual(encode2pass(obj), obj_encoded)
629 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
630 obj_expled = obj(value, expl=tag_expl)
631 self.assertTrue(obj_expled.expled)
633 list(obj_expled.pps())
634 pprint(obj_expled, big_blobs=True, with_decode_path=True)
635 obj_expled_cer = encode_cer(obj_expled)
636 self.assertNotEqual(obj_expled_cer, obj_encoded)
637 self.assertSequenceEqual(
638 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
641 obj_expled_hex_encoded = obj_expled.hexencode()
642 ctx_copied = deepcopy(ctx_dummy)
643 obj_decoded, tail = obj_expled.hexdecode(
644 obj_expled_hex_encoded + hexenc(tail_junk),
648 self.assertDictEqual(ctx_copied, ctx_dummy)
650 list(obj_decoded.pps())
651 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
652 self.assertEqual(tail, tail_junk)
653 self.assertEqual(obj_decoded, obj_expled)
654 self.assertNotEqual(obj_decoded, obj)
655 self.assertEqual(bool(obj_decoded), bool(obj_expled))
656 self.assertEqual(bool(obj_decoded), bool(obj))
657 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
658 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
659 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
661 obj_decoded.expl_llen,
662 len(len_encode(len(obj_encoded))),
664 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
665 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
668 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
670 self.assertEqual(obj_decoded.expl_offset, offset)
671 assert_exceeding_data(
673 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
677 evgens = list(obj_expled.decode_evgen(
678 hexdec(obj_expled_hex_encoded) + tail_junk,
680 decode_path=decode_path,
683 self.assertEqual(len(evgens), 1)
684 _decode_path, obj, tail = evgens[0]
685 self.assertSequenceEqual(tail, tail_junk)
686 self.assertEqual(_decode_path, decode_path)
687 self.assertEqual(obj, obj_decoded)
688 self.assertEqual(obj.expl_offset, offset)
692 @given(integers(min_value=2))
693 def test_invalid_len(self, l):
694 with self.assertRaises(InvalidLength):
695 Boolean().decode(b"".join((
701 @given(integers(min_value=0 + 1, max_value=255 - 1))
702 def test_ber_value(self, value):
703 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
704 Boolean().decode(b"".join((
714 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
715 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
716 self.assertTrue(bool(obj))
717 self.assertTrue(obj.ber_encoded)
718 self.assertFalse(obj.lenindef)
719 self.assertTrue(obj.bered)
721 self.assertTrue(obj.ber_encoded)
722 self.assertFalse(obj.lenindef)
723 self.assertTrue(obj.bered)
726 integers(min_value=1).map(tag_ctxc),
727 binary().filter(lambda x: not x.startswith(EOC)),
729 def test_ber_expl_no_eoc(self, expl, junk):
730 encoded = expl + LENINDEF + Boolean(False).encode()
731 with self.assertRaises(LenIndefForm):
732 Boolean(expl=expl).decode(encoded + junk)
733 with assertRaisesRegex(self, DecodeError, "no EOC"):
734 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
735 obj, tail = Boolean(expl=expl).decode(
736 encoded + EOC + junk,
739 self.assertTrue(obj.expl_lenindef)
740 self.assertFalse(obj.lenindef)
741 self.assertFalse(obj.ber_encoded)
742 self.assertTrue(obj.bered)
744 self.assertTrue(obj.expl_lenindef)
745 self.assertFalse(obj.lenindef)
746 self.assertFalse(obj.ber_encoded)
747 self.assertTrue(obj.bered)
748 self.assertSequenceEqual(tail, junk)
751 pprint(obj, big_blobs=True, with_decode_path=True)
754 integers(min_value=1).map(tag_ctxc),
761 def test_ber_expl(self, expl, values):
767 Boolean(value).encode() +
770 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
772 class SeqOf(SequenceOf):
773 schema = Boolean(expl=expl)
774 with self.assertRaises(LenIndefForm):
775 SeqOf().decode(encoded)
776 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
777 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
778 self.assertSequenceEqual(tail, b"")
779 self.assertSequenceEqual([bool(v) for v in seqof], values)
795 len(expl) + 1 + 3 + EOC_LEN,
806 pprint(seqof, big_blobs=True, with_decode_path=True)
810 def integer_values_strategy(draw, do_expl=False):
811 bound_min, value, default, bound_max = sorted(draw(sets(
820 _specs = draw(sets(text_letters()))
823 min_size=len(_specs),
824 max_size=len(_specs),
826 _specs = list(zip(_specs, values))
829 bounds = (bound_min, bound_max)
833 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
835 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
838 optional = draw(one_of(none(), booleans()))
840 draw(integers(min_value=0)),
841 draw(integers(min_value=0)),
842 draw(integers(min_value=0)),
844 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
847 class IntegerInherited(Integer):
851 class TestInteger(CommonMixin, TestCase):
854 def test_invalid_value_type(self):
855 with self.assertRaises(InvalidValueType) as err:
859 @given(sets(text_letters(), min_size=2))
860 def test_unknown_name(self, names_input):
861 missing = names_input.pop()
864 schema = [(n, 123) for n in names_input]
865 with self.assertRaises(ObjUnknown) as err:
869 @given(sets(text_letters(), min_size=2))
870 def test_known_name(self, names_input):
872 schema = [(n, 123) for n in names_input]
873 Int(names_input.pop())
876 def test_optional(self, optional):
877 obj = Integer(default=Integer(0), optional=optional)
878 self.assertTrue(obj.optional)
881 def test_ready(self, value):
883 self.assertFalse(obj.ready)
886 pprint(obj, big_blobs=True, with_decode_path=True)
887 with self.assertRaises(ObjNotReady) as err:
889 with self.assertRaises(ObjNotReady) as err:
893 self.assertTrue(obj.ready)
896 pprint(obj, big_blobs=True, with_decode_path=True)
899 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
900 def test_comparison(self, value1, value2, tag1, tag2):
901 for klass in (Integer, IntegerInherited):
904 self.assertEqual(obj1 == obj2, value1 == value2)
905 self.assertEqual(obj1 != obj2, value1 != value2)
906 self.assertEqual(obj1 == int(obj2), value1 == value2)
907 obj1 = klass(value1, impl=tag1)
908 obj2 = klass(value1, impl=tag2)
909 self.assertEqual(obj1 == obj2, tag1 == tag2)
910 self.assertEqual(obj1 != obj2, tag1 != tag2)
912 @given(lists(integers()))
913 def test_sorted_works(self, values):
914 self.assertSequenceEqual(
915 [int(v) for v in sorted(Integer(v) for v in values)],
919 @given(data_strategy())
920 def test_named(self, d):
921 names_input = list(d.draw(sets(text_letters(), min_size=1)))
922 values_input = list(d.draw(sets(
924 min_size=len(names_input),
925 max_size=len(names_input),
927 chosen_name = d.draw(sampled_from(names_input))
928 names_input = dict(zip(names_input, values_input))
932 _int = Int(chosen_name)
933 self.assertEqual(_int.named, chosen_name)
934 self.assertEqual(int(_int), names_input[chosen_name])
936 @given(integers(), integers(min_value=0), integers(min_value=0))
937 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
938 value = bound_min + value_delta
939 bound_max = value + bound_delta
940 Integer(value=value, bounds=(bound_min, bound_max))
942 @given(sets(integers(), min_size=3, max_size=3))
943 def test_bounds_unsatisfied(self, values):
944 values = sorted(values)
945 with self.assertRaises(BoundsError) as err:
946 Integer(value=values[0], bounds=(values[1], values[2]))
948 with assertRaisesRegex(self, DecodeError, "bounds") as err:
949 Integer(bounds=(values[1], values[2])).decode(
950 Integer(values[0]).encode()
953 with assertRaisesRegex(self, DecodeError, "bounds") as err:
954 Integer(bounds=(values[1], values[2])).decode(
955 encode2pass(Integer(values[0]))
957 with self.assertRaises(BoundsError) as err:
958 Integer(value=values[2], bounds=(values[0], values[1]))
960 with assertRaisesRegex(self, DecodeError, "bounds") as err:
961 Integer(bounds=(values[0], values[1])).decode(
962 Integer(values[2]).encode()
965 with assertRaisesRegex(self, DecodeError, "bounds") as err:
966 Integer(bounds=(values[0], values[1])).decode(
967 encode2pass(Integer(values[2]))
970 @given(data_strategy())
971 def test_call(self, d):
972 for klass in (Integer, IntegerInherited):
982 ) = d.draw(integer_values_strategy())
989 optional_initial or False,
1002 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
1003 if (default is None) and (obj_initial.default is not None):
1006 (bounds is None) and
1007 (value is not None) and
1008 (bounds_initial is not None) and
1009 not (bounds_initial[0] <= value <= bounds_initial[1])
1013 (bounds is None) and
1014 (default is not None) and
1015 (bounds_initial is not None) and
1016 not (bounds_initial[0] <= default <= bounds_initial[1])
1019 obj = obj_initial(value, bounds, impl, expl, default, optional)
1021 value_expected = default if value is None else value
1023 default_initial if value_expected is None
1026 self.assertEqual(obj, value_expected)
1027 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1028 self.assertEqual(obj.expl_tag, expl or expl_initial)
1031 default_initial if default is None else default,
1033 if obj.default is None:
1034 optional = optional_initial if optional is None else optional
1035 optional = False if optional is None else optional
1038 self.assertEqual(obj.optional, optional)
1040 (obj._bound_min, obj._bound_max),
1041 bounds or bounds_initial or (float("-inf"), float("+inf")),
1045 {} if _specs_initial is None else dict(_specs_initial),
1048 @given(integer_values_strategy())
1049 def test_copy(self, values):
1050 for klass in (Integer, IntegerInherited):
1051 obj = klass(*values)
1052 for copy_func in copy_funcs:
1053 obj_copied = copy_func(obj)
1054 self.assert_copied_basic_fields(obj, obj_copied)
1055 self.assertEqual(obj.specs, obj_copied.specs)
1056 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1057 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1058 self.assertEqual(obj._value, obj_copied._value)
1062 integers(min_value=1).map(tag_encode),
1064 def test_stripped(self, value, tag_impl):
1065 obj = Integer(value, impl=tag_impl)
1066 with self.assertRaises(NotEnoughData):
1067 obj.decode(obj.encode()[:-1])
1071 integers(min_value=1).map(tag_ctxc),
1073 def test_stripped_expl(self, value, tag_expl):
1074 obj = Integer(value, expl=tag_expl)
1075 with self.assertRaises(NotEnoughData):
1076 obj.decode(obj.encode()[:-1])
1078 def test_zero_len(self):
1079 with self.assertRaises(NotEnoughData):
1080 Integer().decode(b"".join((
1081 Integer.tag_default,
1086 integers(min_value=31),
1087 integers(min_value=0),
1090 def test_bad_tag(self, tag, offset, decode_path):
1091 with self.assertRaises(DecodeError) as err:
1093 tag_encode(tag)[:-1],
1095 decode_path=decode_path,
1098 self.assertEqual(err.exception.offset, offset)
1099 self.assertEqual(err.exception.decode_path, decode_path)
1102 integers(min_value=128),
1103 integers(min_value=0),
1106 def test_bad_len(self, l, offset, decode_path):
1107 with self.assertRaises(DecodeError) as err:
1109 Integer.tag_default + len_encode(l)[:-1],
1111 decode_path=decode_path,
1114 self.assertEqual(err.exception.offset, offset)
1115 self.assertEqual(err.exception.decode_path, decode_path)
1118 sets(integers(), min_size=2, max_size=2),
1119 integers(min_value=0),
1122 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1123 value, bound_min = list(sorted(ints))
1126 bounds = (bound_min, bound_min)
1127 with self.assertRaises(DecodeError) as err:
1129 Integer(value).encode(),
1131 decode_path=decode_path,
1134 self.assertEqual(err.exception.offset, offset)
1135 self.assertEqual(err.exception.decode_path, decode_path)
1137 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1139 integer_values_strategy(),
1141 integers(min_value=1).map(tag_ctxc),
1142 integers(min_value=0),
1146 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1147 for klass in (Integer, IntegerInherited):
1148 _, _, _, _, default, optional, _, _decoded = values
1157 pprint(obj, big_blobs=True, with_decode_path=True)
1158 self.assertFalse(obj.expled)
1159 obj_encoded = obj.encode()
1160 self.assertEqual(encode2pass(obj), obj_encoded)
1161 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1162 obj_expled = obj(value, expl=tag_expl)
1163 self.assertTrue(obj_expled.expled)
1165 list(obj_expled.pps())
1166 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1167 obj_expled_encoded = obj_expled.encode()
1168 obj_expled_cer = encode_cer(obj_expled)
1169 self.assertNotEqual(obj_expled_cer, obj_encoded)
1170 self.assertSequenceEqual(
1171 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1174 ctx_copied = deepcopy(ctx_dummy)
1175 obj_decoded, tail = obj_expled.decode(
1176 obj_expled_encoded + tail_junk,
1180 self.assertDictEqual(ctx_copied, ctx_dummy)
1182 list(obj_decoded.pps())
1183 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1184 self.assertEqual(tail, tail_junk)
1185 self.assertEqual(obj_decoded, obj_expled)
1186 self.assertNotEqual(obj_decoded, obj)
1187 self.assertEqual(int(obj_decoded), int(obj_expled))
1188 self.assertEqual(int(obj_decoded), int(obj))
1189 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1190 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1191 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1193 obj_decoded.expl_llen,
1194 len(len_encode(len(obj_encoded))),
1196 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1197 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1200 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1202 self.assertEqual(obj_decoded.expl_offset, offset)
1203 assert_exceeding_data(
1205 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1209 evgens = list(obj_expled.decode_evgen(
1210 obj_expled_encoded + tail_junk,
1212 decode_path=decode_path,
1215 self.assertEqual(len(evgens), 1)
1216 _decode_path, obj, tail = evgens[0]
1217 self.assertSequenceEqual(tail, tail_junk)
1218 self.assertEqual(_decode_path, decode_path)
1219 self.assertEqual(obj, obj_decoded)
1220 self.assertEqual(obj.expl_offset, offset)
1224 def test_go_vectors_valid(self):
1225 for data, expect in ((
1229 (b"\xff\x7f", -129),
1233 (b"\xff\x00", -256),
1237 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1238 (b"\x80\x00\x00\x00", -2147483648),
1241 Integer().decode(b"".join((
1242 Integer.tag_default,
1243 len_encode(len(data)),
1249 def test_go_vectors_invalid(self):
1254 with self.assertRaises(DecodeError):
1255 Integer().decode(b"".join((
1256 Integer.tag_default,
1257 len_encode(len(data)),
1263 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1266 if draw(booleans()):
1267 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1269 integers(min_value=0, max_value=255),
1270 min_size=len(schema),
1271 max_size=len(schema),
1273 schema = list(zip(schema, bits))
1275 def _value(value_required):
1276 if not value_required and draw(booleans()):
1278 generation_choice = 0
1280 generation_choice = draw(sampled_from((1, 2, 3)))
1281 if generation_choice == 1 or draw(booleans()):
1282 return "'%s'B" % "".join(draw(lists(
1283 sampled_from(("0", "1")),
1284 max_size=len(schema),
1286 if generation_choice == 2 or draw(booleans()):
1287 return draw(binary(max_size=len(schema) // 8))
1288 if generation_choice == 3 or draw(booleans()):
1289 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1291 value = _value(value_required)
1292 default = _value(value_required=False)
1296 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1298 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1299 optional = draw(one_of(none(), booleans()))
1301 draw(integers(min_value=0)),
1302 draw(integers(min_value=0)),
1303 draw(integers(min_value=0)),
1305 return (schema, value, impl, expl, default, optional, _decoded)
1308 class BitStringInherited(BitString):
1312 class TestBitString(CommonMixin, TestCase):
1313 base_klass = BitString
1315 @given(lists(booleans()))
1316 def test_b_encoding(self, bits):
1317 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1318 self.assertEqual(obj.bit_len, len(bits))
1319 self.assertSequenceEqual(list(obj), bits)
1320 for i, bit in enumerate(bits):
1321 self.assertEqual(obj[i], bit)
1323 @given(lists(booleans()))
1324 def test_out_of_bounds_bits(self, bits):
1325 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1326 for i in range(len(bits), len(bits) * 2):
1327 self.assertFalse(obj[i])
1329 def test_bad_b_encoding(self):
1330 with self.assertRaises(ValueError):
1331 BitString("'010120101'B")
1334 integers(min_value=1, max_value=255),
1335 integers(min_value=1, max_value=255),
1337 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1338 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1339 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1340 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1342 class BS(BitString):
1343 schema = (("whatever", 0),)
1344 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1345 self.assertEqual(obj.bit_len, leading_zeros + 1)
1346 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1348 def test_zero_len(self):
1349 with self.assertRaises(NotEnoughData):
1350 BitString().decode(b"".join((
1351 BitString.tag_default,
1355 def test_invalid_value_type(self):
1356 with self.assertRaises(InvalidValueType) as err:
1359 with self.assertRaises(InvalidValueType) as err:
1363 def test_obj_unknown(self):
1364 with self.assertRaises(ObjUnknown) as err:
1365 BitString(b"whatever")["whenever"]
1368 def test_get_invalid_type(self):
1369 with self.assertRaises(InvalidValueType) as err:
1370 BitString(b"whatever")[(1, 2, 3)]
1373 @given(data_strategy())
1374 def test_unknown_name(self, d):
1375 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1376 missing = _schema.pop()
1378 class BS(BitString):
1379 schema = [(n, i) for i, n in enumerate(_schema)]
1380 with self.assertRaises(ObjUnknown) as err:
1385 def test_optional(self, optional):
1386 obj = BitString(default=BitString(b""), optional=optional)
1387 self.assertTrue(obj.optional)
1390 def test_ready(self, value):
1392 self.assertFalse(obj.ready)
1395 pprint(obj, big_blobs=True, with_decode_path=True)
1396 with self.assertRaises(ObjNotReady) as err:
1399 with self.assertRaises(ObjNotReady) as err:
1401 obj = BitString(value)
1402 self.assertTrue(obj.ready)
1405 pprint(obj, big_blobs=True, with_decode_path=True)
1408 tuples(integers(min_value=0), binary()),
1409 tuples(integers(min_value=0), binary()),
1413 def test_comparison(self, value1, value2, tag1, tag2):
1414 for klass in (BitString, BitStringInherited):
1415 obj1 = klass(value1)
1416 obj2 = klass(value2)
1417 self.assertEqual(obj1 == obj2, value1 == value2)
1418 self.assertEqual(obj1 != obj2, value1 != value2)
1419 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1420 obj1 = klass(value1, impl=tag1)
1421 obj2 = klass(value1, impl=tag2)
1422 self.assertEqual(obj1 == obj2, tag1 == tag2)
1423 self.assertEqual(obj1 != obj2, tag1 != tag2)
1425 @given(data_strategy())
1426 def test_call(self, d):
1427 for klass in (BitString, BitStringInherited):
1436 ) = d.draw(bit_string_values_strategy())
1439 schema = schema_initial
1441 value=value_initial,
1444 default=default_initial,
1445 optional=optional_initial or False,
1446 _decoded=_decoded_initial,
1456 ) = d.draw(bit_string_values_strategy(
1457 schema=schema_initial,
1458 do_expl=impl_initial is None,
1467 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1468 self.assertEqual(obj.expl_tag, expl or expl_initial)
1469 if obj.default is None:
1470 optional = optional_initial if optional is None else optional
1471 optional = False if optional is None else optional
1474 self.assertEqual(obj.optional, optional)
1475 self.assertEqual(obj.specs, obj_initial.specs)
1477 @given(bit_string_values_strategy())
1478 def test_copy(self, values):
1479 for klass in (BitString, BitStringInherited):
1480 _schema, value, impl, expl, default, optional, _decoded = values
1490 optional=optional or False,
1493 for copy_func in copy_funcs:
1494 obj_copied = copy_func(obj)
1495 self.assert_copied_basic_fields(obj, obj_copied)
1496 self.assertEqual(obj.specs, obj_copied.specs)
1497 self.assertEqual(obj._value, obj_copied._value)
1501 integers(min_value=1).map(tag_encode),
1503 def test_stripped(self, value, tag_impl):
1504 obj = BitString(value, impl=tag_impl)
1505 with self.assertRaises(NotEnoughData):
1506 obj.decode(obj.encode()[:-1])
1510 integers(min_value=1).map(tag_ctxc),
1512 def test_stripped_expl(self, value, tag_expl):
1513 obj = BitString(value, expl=tag_expl)
1514 with self.assertRaises(NotEnoughData):
1515 obj.decode(obj.encode()[:-1])
1518 integers(min_value=31),
1519 integers(min_value=0),
1522 def test_bad_tag(self, tag, offset, decode_path):
1523 with self.assertRaises(DecodeError) as err:
1525 tag_encode(tag)[:-1],
1527 decode_path=decode_path,
1530 self.assertEqual(err.exception.offset, offset)
1531 self.assertEqual(err.exception.decode_path, decode_path)
1534 integers(min_value=128),
1535 integers(min_value=0),
1538 def test_bad_len(self, l, offset, decode_path):
1539 with self.assertRaises(DecodeError) as err:
1541 BitString.tag_default + len_encode(l)[:-1],
1543 decode_path=decode_path,
1546 self.assertEqual(err.exception.offset, offset)
1547 self.assertEqual(err.exception.decode_path, decode_path)
1549 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1550 @given(data_strategy())
1551 def test_symmetric(self, d):
1560 ) = d.draw(bit_string_values_strategy(value_required=True))
1561 tail_junk = d.draw(binary(max_size=5))
1562 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1563 offset = d.draw(integers(min_value=0))
1564 decode_path = d.draw(decode_path_strat)
1565 for klass in (BitString, BitStringInherited):
1576 pprint(obj, big_blobs=True, with_decode_path=True)
1577 self.assertFalse(obj.expled)
1578 obj_encoded = obj.encode()
1579 self.assertEqual(encode2pass(obj), obj_encoded)
1580 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1581 obj_expled = obj(value, expl=tag_expl)
1582 self.assertTrue(obj_expled.expled)
1584 list(obj_expled.pps())
1585 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1586 obj_expled_encoded = obj_expled.encode()
1587 obj_expled_cer = encode_cer(obj_expled)
1588 self.assertNotEqual(obj_expled_cer, obj_encoded)
1589 self.assertSequenceEqual(
1590 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1593 ctx_copied = deepcopy(ctx_dummy)
1594 obj_decoded, tail = obj_expled.decode(
1595 obj_expled_encoded + tail_junk,
1599 self.assertDictEqual(ctx_copied, ctx_dummy)
1601 list(obj_decoded.pps())
1602 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1603 self.assertEqual(tail, tail_junk)
1604 self.assertEqual(obj_decoded, obj_expled)
1605 self.assertNotEqual(obj_decoded, obj)
1606 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1607 self.assertEqual(bytes(obj_decoded), bytes(obj))
1608 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1609 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1610 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1612 obj_decoded.expl_llen,
1613 len(len_encode(len(obj_encoded))),
1615 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1616 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1619 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1621 self.assertEqual(obj_decoded.expl_offset, offset)
1622 if isinstance(value, tuple):
1623 self.assertSetEqual(set(value), set(obj_decoded.named))
1626 assert_exceeding_data(
1628 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1632 evgens = list(obj_expled.decode_evgen(
1633 obj_expled_encoded + tail_junk,
1635 decode_path=decode_path,
1638 self.assertEqual(len(evgens), 1)
1639 _decode_path, obj, tail = evgens[0]
1640 self.assertSequenceEqual(tail, tail_junk)
1641 self.assertEqual(_decode_path, decode_path)
1642 self.assertEqual(obj.expl_offset, offset)
1646 @given(integers(min_value=1, max_value=255))
1647 def test_bad_zero_value(self, pad_size):
1648 with self.assertRaises(DecodeError):
1649 BitString().decode(b"".join((
1650 BitString.tag_default,
1655 def test_go_vectors_invalid(self):
1661 with self.assertRaises(DecodeError):
1662 BitString().decode(b"".join((
1663 BitString.tag_default,
1668 def test_go_vectors_valid(self):
1669 obj, _ = BitString().decode(b"".join((
1670 BitString.tag_default,
1674 self.assertEqual(bytes(obj), b"")
1675 self.assertEqual(obj.bit_len, 0)
1677 obj, _ = BitString().decode(b"".join((
1678 BitString.tag_default,
1682 self.assertEqual(bytes(obj), b"\x00")
1683 self.assertEqual(obj.bit_len, 1)
1685 obj = BitString((16, b"\x82\x40"))
1686 self.assertTrue(obj[0])
1687 self.assertFalse(obj[1])
1688 self.assertTrue(obj[6])
1689 self.assertTrue(obj[9])
1690 self.assertFalse(obj[17])
1692 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1694 integers(min_value=1, max_value=30),
1697 binary(min_size=1, max_size=5),
1699 binary(min_size=1, max_size=5),
1707 lists(booleans(), min_size=1),
1711 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1712 def chunk_constructed(contents):
1714 tag_encode(form=TagFormConstructed, num=3) +
1716 b"".join(BitString(content).encode() for content in contents) +
1720 chunks_len_expected = []
1721 payload_expected = b""
1722 bit_len_expected = 0
1723 for chunk_input in chunk_inputs:
1724 if isinstance(chunk_input, binary_type):
1725 chunks.append(BitString(chunk_input).encode())
1726 payload_expected += chunk_input
1727 bit_len_expected += len(chunk_input) * 8
1728 chunks_len_expected.append(len(chunk_input) + 1)
1730 chunks.append(chunk_constructed(chunk_input))
1731 payload = b"".join(chunk_input)
1732 payload_expected += payload
1733 bit_len_expected += len(payload) * 8
1734 for c in chunk_input:
1735 chunks_len_expected.append(len(c) + 1)
1736 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1737 chunk_last = BitString("'%s'B" % "".join(
1738 "1" if bit else "0" for bit in chunk_last_bits
1740 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1741 payload_expected += bytes(chunk_last)
1742 bit_len_expected += chunk_last.bit_len
1743 encoded_indefinite = (
1744 tag_encode(form=TagFormConstructed, num=impl) +
1747 chunk_last.encode() +
1750 encoded_definite = (
1751 tag_encode(form=TagFormConstructed, num=impl) +
1752 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1756 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1757 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1758 for lenindef_expected, encoded in (
1759 (True, encoded_indefinite),
1760 (False, encoded_definite),
1762 obj, tail = BitString(impl=tag_encode(impl)).decode(
1764 ctx={"bered": True},
1766 self.assertSequenceEqual(tail, junk)
1767 self.assertEqual(obj.bit_len, bit_len_expected)
1768 self.assertSequenceEqual(bytes(obj), payload_expected)
1769 self.assertTrue(obj.ber_encoded)
1770 self.assertEqual(obj.lenindef, lenindef_expected)
1771 self.assertTrue(obj.bered)
1773 self.assertTrue(obj.ber_encoded)
1774 self.assertEqual(obj.lenindef, lenindef_expected)
1775 self.assertTrue(obj.bered)
1776 self.assertEqual(len(encoded), obj.tlvlen)
1779 pprint(obj, big_blobs=True, with_decode_path=True)
1781 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1783 decode_path=decode_path,
1784 ctx={"bered": True},
1786 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1787 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1788 self.assertGreater(len(dp), len(decode_path))
1789 self.assertEqual(obj.vlen, chunk_len_expected)
1792 integers(min_value=0),
1795 def test_ber_definite_too_short(self, offset, decode_path):
1796 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1798 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1800 decode_path=decode_path,
1801 ctx={"bered": True},
1803 self.assertEqual(err.exception.decode_path, decode_path)
1804 self.assertEqual(err.exception.offset, offset)
1807 integers(min_value=0),
1810 def test_ber_definite_no_data(self, offset, decode_path):
1811 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1813 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1815 decode_path=decode_path,
1816 ctx={"bered": True},
1818 self.assertEqual(err.exception.decode_path, decode_path)
1819 self.assertEqual(err.exception.offset, offset)
1822 integers(min_value=0),
1824 integers(min_value=1, max_value=3),
1826 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1827 bs = BitString(b"data").encode()
1828 with self.assertRaises(NotEnoughData) as err:
1830 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1832 decode_path=decode_path,
1833 ctx={"bered": True},
1835 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1836 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1839 integers(min_value=0),
1841 integers(min_value=1, max_value=3),
1843 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1844 bs = BitString(b"data").encode()
1845 bs_longer = BitString(b"data-longer").encode()
1846 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1849 tag_encode(3, form=TagFormConstructed) +
1850 len_encode((chunks + 1) * len(bs)) +
1855 decode_path=decode_path,
1856 ctx={"bered": True},
1858 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1859 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1862 integers(min_value=0),
1865 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1866 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1868 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1870 decode_path=decode_path,
1871 ctx={"bered": True},
1873 self.assertEqual(err.exception.decode_path, decode_path)
1874 self.assertEqual(err.exception.offset, offset)
1876 @given(data_strategy())
1877 def test_ber_indefinite_not_multiple(self, d):
1878 bs_short = BitString("'A'H").encode()
1879 bs_full = BitString("'AA'H").encode()
1880 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1881 chunks.append(bs_short)
1882 d.draw(permutations(chunks))
1883 chunks.append(bs_short)
1884 offset = d.draw(integers(min_value=0))
1885 decode_path = d.draw(decode_path_strat)
1886 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1889 tag_encode(3, form=TagFormConstructed) +
1895 decode_path=decode_path,
1896 ctx={"bered": True},
1899 err.exception.decode_path,
1900 decode_path + (str(chunks.index(bs_short)),),
1903 err.exception.offset,
1904 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1907 def test_x690_vector(self):
1908 vector = BitString("'0A3B5F291CD'H")
1909 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1910 self.assertSequenceEqual(tail, b"")
1911 self.assertEqual(obj, vector)
1912 obj, tail = BitString().decode(
1913 hexdec("23800303000A3B0305045F291CD00000"),
1914 ctx={"bered": True},
1916 self.assertSequenceEqual(tail, b"")
1917 self.assertEqual(obj, vector)
1918 self.assertTrue(obj.ber_encoded)
1919 self.assertTrue(obj.lenindef)
1920 self.assertTrue(obj.bered)
1922 self.assertTrue(obj.ber_encoded)
1923 self.assertTrue(obj.lenindef)
1924 self.assertTrue(obj.bered)
1926 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1927 @given(integers(min_value=1000, max_value=3000))
1928 def test_cer(self, data_len):
1929 data = urandom(data_len)
1930 encoded = encode_cer(BitString(data))
1931 ctx = {"bered": True}
1932 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1933 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1934 evgens_expected = data_len // 999
1935 if evgens_expected * 999 != data_len:
1936 evgens_expected += 1
1937 evgens_expected += 1
1938 self.assertEqual(len(evgens), evgens_expected)
1939 for (_, obj, _) in evgens[:-2]:
1940 self.assertEqual(obj.vlen, 1000)
1941 _, obj, _ = evgens[-2]
1942 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1946 def octet_string_values_strategy(draw, do_expl=False):
1947 bound_min, bound_max = sorted(draw(sets(
1948 integers(min_value=0, max_value=1 << 7),
1952 value = draw(one_of(
1954 binary(min_size=bound_min, max_size=bound_max),
1956 default = draw(one_of(
1958 binary(min_size=bound_min, max_size=bound_max),
1961 if draw(booleans()):
1962 bounds = (bound_min, bound_max)
1966 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1968 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1969 optional = draw(one_of(none(), booleans()))
1971 draw(integers(min_value=0)),
1972 draw(integers(min_value=0)),
1973 draw(integers(min_value=0)),
1975 return (value, bounds, impl, expl, default, optional, _decoded)
1978 class OctetStringInherited(OctetString):
1982 class TestOctetString(CommonMixin, TestCase):
1983 base_klass = OctetString
1985 def test_invalid_value_type(self):
1986 with self.assertRaises(InvalidValueType) as err:
1987 OctetString(text_type(123))
1991 def test_optional(self, optional):
1992 obj = OctetString(default=OctetString(b""), optional=optional)
1993 self.assertTrue(obj.optional)
1996 def test_ready(self, value):
1998 self.assertFalse(obj.ready)
2001 pprint(obj, big_blobs=True, with_decode_path=True)
2002 with self.assertRaises(ObjNotReady) as err:
2005 with self.assertRaises(ObjNotReady) as err:
2007 obj = OctetString(value)
2008 self.assertTrue(obj.ready)
2011 pprint(obj, big_blobs=True, with_decode_path=True)
2013 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
2014 def test_comparison(self, value1, value2, tag1, tag2):
2015 for klass in (OctetString, OctetStringInherited):
2016 obj1 = klass(value1)
2017 obj2 = klass(value2)
2018 self.assertEqual(obj1 == obj2, value1 == value2)
2019 self.assertEqual(obj1 != obj2, value1 != value2)
2020 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2021 obj1 = klass(value1, impl=tag1)
2022 obj2 = klass(value1, impl=tag2)
2023 self.assertEqual(obj1 == obj2, tag1 == tag2)
2024 self.assertEqual(obj1 != obj2, tag1 != tag2)
2026 @given(lists(binary()))
2027 def test_sorted_works(self, values):
2028 self.assertSequenceEqual(
2029 [bytes(v) for v in sorted(OctetString(v) for v in values)],
2033 @given(data_strategy())
2034 def test_bounds_satisfied(self, d):
2035 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2036 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2037 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
2038 OctetString(value=value, bounds=(bound_min, bound_max))
2040 @given(data_strategy())
2041 def test_bounds_unsatisfied(self, d):
2042 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2043 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2044 value = d.draw(binary(max_size=bound_min - 1))
2045 with self.assertRaises(BoundsError) as err:
2046 OctetString(value=value, bounds=(bound_min, bound_max))
2048 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2049 OctetString(bounds=(bound_min, bound_max)).decode(
2050 OctetString(value).encode()
2053 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2054 OctetString(bounds=(bound_min, bound_max)).decode(
2055 encode2pass(OctetString(value))
2057 value = d.draw(binary(min_size=bound_max + 1))
2058 with self.assertRaises(BoundsError) as err:
2059 OctetString(value=value, bounds=(bound_min, bound_max))
2061 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2062 OctetString(bounds=(bound_min, bound_max)).decode(
2063 OctetString(value).encode()
2066 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2067 OctetString(bounds=(bound_min, bound_max)).decode(
2068 encode2pass(OctetString(value))
2071 @given(data_strategy())
2072 def test_call(self, d):
2073 for klass in (OctetString, OctetStringInherited):
2082 ) = d.draw(octet_string_values_strategy())
2083 obj_initial = klass(
2089 optional_initial or False,
2100 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2101 if (default is None) and (obj_initial.default is not None):
2104 (bounds is None) and
2105 (value is not None) and
2106 (bounds_initial is not None) and
2107 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2111 (bounds is None) and
2112 (default is not None) and
2113 (bounds_initial is not None) and
2114 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2117 obj = obj_initial(value, bounds, impl, expl, default, optional)
2119 value_expected = default if value is None else value
2121 default_initial if value_expected is None
2124 self.assertEqual(obj, value_expected)
2125 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2126 self.assertEqual(obj.expl_tag, expl or expl_initial)
2129 default_initial if default is None else default,
2131 if obj.default is None:
2132 optional = optional_initial if optional is None else optional
2133 optional = False if optional is None else optional
2136 self.assertEqual(obj.optional, optional)
2138 (obj._bound_min, obj._bound_max),
2139 bounds or bounds_initial or (0, float("+inf")),
2142 @given(octet_string_values_strategy())
2143 def test_copy(self, values):
2144 for klass in (OctetString, OctetStringInherited):
2145 obj = klass(*values)
2146 for copy_func in copy_funcs:
2147 obj_copied = copy_func(obj)
2148 self.assert_copied_basic_fields(obj, obj_copied)
2149 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2150 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2151 self.assertEqual(obj._value, obj_copied._value)
2155 integers(min_value=1).map(tag_encode),
2157 def test_stripped(self, value, tag_impl):
2158 obj = OctetString(value, impl=tag_impl)
2159 with self.assertRaises(NotEnoughData):
2160 obj.decode(obj.encode()[:-1])
2164 integers(min_value=1).map(tag_ctxc),
2166 def test_stripped_expl(self, value, tag_expl):
2167 obj = OctetString(value, expl=tag_expl)
2168 with self.assertRaises(NotEnoughData):
2169 obj.decode(obj.encode()[:-1])
2172 integers(min_value=31),
2173 integers(min_value=0),
2176 def test_bad_tag(self, tag, offset, decode_path):
2177 with self.assertRaises(DecodeError) as err:
2178 OctetString().decode(
2179 tag_encode(tag)[:-1],
2181 decode_path=decode_path,
2184 self.assertEqual(err.exception.offset, offset)
2185 self.assertEqual(err.exception.decode_path, decode_path)
2188 integers(min_value=128),
2189 integers(min_value=0),
2192 def test_bad_len(self, l, offset, decode_path):
2193 with self.assertRaises(DecodeError) as err:
2194 OctetString().decode(
2195 OctetString.tag_default + len_encode(l)[:-1],
2197 decode_path=decode_path,
2200 self.assertEqual(err.exception.offset, offset)
2201 self.assertEqual(err.exception.decode_path, decode_path)
2204 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2205 integers(min_value=0),
2208 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2209 value, bound_min = list(sorted(ints))
2211 class String(OctetString):
2212 bounds = (bound_min, bound_min)
2213 with self.assertRaises(DecodeError) as err:
2215 OctetString(b"\x00" * value).encode(),
2217 decode_path=decode_path,
2220 self.assertEqual(err.exception.offset, offset)
2221 self.assertEqual(err.exception.decode_path, decode_path)
2223 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2225 octet_string_values_strategy(),
2227 integers(min_value=1).map(tag_ctxc),
2228 integers(min_value=0),
2232 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2233 for klass in (OctetString, OctetStringInherited):
2234 _, _, _, _, default, optional, _decoded = values
2243 pprint(obj, big_blobs=True, with_decode_path=True)
2244 self.assertFalse(obj.expled)
2245 obj_encoded = obj.encode()
2246 self.assertEqual(encode2pass(obj), obj_encoded)
2247 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2248 obj_expled = obj(value, expl=tag_expl)
2249 self.assertTrue(obj_expled.expled)
2251 list(obj_expled.pps())
2252 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2253 obj_expled_encoded = obj_expled.encode()
2254 obj_expled_cer = encode_cer(obj_expled)
2255 self.assertNotEqual(obj_expled_cer, obj_encoded)
2256 self.assertSequenceEqual(
2257 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2260 ctx_copied = deepcopy(ctx_dummy)
2261 obj_decoded, tail = obj_expled.decode(
2262 obj_expled_encoded + tail_junk,
2266 self.assertDictEqual(ctx_copied, ctx_dummy)
2268 list(obj_decoded.pps())
2269 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2270 self.assertEqual(tail, tail_junk)
2271 self.assertEqual(obj_decoded, obj_expled)
2272 self.assertNotEqual(obj_decoded, obj)
2273 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2274 self.assertEqual(bytes(obj_decoded), bytes(obj))
2275 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2276 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2277 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2279 obj_decoded.expl_llen,
2280 len(len_encode(len(obj_encoded))),
2282 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2283 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2286 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2288 self.assertEqual(obj_decoded.expl_offset, offset)
2289 assert_exceeding_data(
2291 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2295 evgens = list(obj_expled.decode_evgen(
2296 obj_expled_encoded + tail_junk,
2298 decode_path=decode_path,
2301 self.assertEqual(len(evgens), 1)
2302 _decode_path, obj, tail = evgens[0]
2303 self.assertSequenceEqual(tail, tail_junk)
2304 self.assertEqual(_decode_path, decode_path)
2305 self.assertEqual(obj.expl_offset, offset)
2309 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2311 integers(min_value=1, max_value=30),
2314 binary(min_size=1, max_size=5),
2316 binary(min_size=1, max_size=5),
2327 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2328 def chunk_constructed(contents):
2330 tag_encode(form=TagFormConstructed, num=4) +
2332 b"".join(OctetString(content).encode() for content in contents) +
2336 chunks_len_expected = []
2337 payload_expected = b""
2338 for chunk_input in chunk_inputs:
2339 if isinstance(chunk_input, binary_type):
2340 chunks.append(OctetString(chunk_input).encode())
2341 payload_expected += chunk_input
2342 chunks_len_expected.append(len(chunk_input))
2344 chunks.append(chunk_constructed(chunk_input))
2345 payload = b"".join(chunk_input)
2346 payload_expected += payload
2347 for c in chunk_input:
2348 chunks_len_expected.append(len(c))
2349 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2350 encoded_indefinite = (
2351 tag_encode(form=TagFormConstructed, num=impl) +
2356 encoded_definite = (
2357 tag_encode(form=TagFormConstructed, num=impl) +
2358 len_encode(len(b"".join(chunks))) +
2361 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2362 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2363 for lenindef_expected, encoded in (
2364 (True, encoded_indefinite),
2365 (False, encoded_definite),
2367 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2369 ctx={"bered": True},
2371 self.assertSequenceEqual(tail, junk)
2372 self.assertSequenceEqual(bytes(obj), payload_expected)
2373 self.assertTrue(obj.ber_encoded)
2374 self.assertEqual(obj.lenindef, lenindef_expected)
2375 self.assertTrue(obj.bered)
2377 self.assertTrue(obj.ber_encoded)
2378 self.assertEqual(obj.lenindef, lenindef_expected)
2379 self.assertTrue(obj.bered)
2380 self.assertEqual(len(encoded), obj.tlvlen)
2383 pprint(obj, big_blobs=True, with_decode_path=True)
2385 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2387 decode_path=decode_path,
2388 ctx={"bered": True},
2390 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2391 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2392 self.assertGreater(len(dp), len(decode_path))
2393 self.assertEqual(obj.vlen, chunk_len_expected)
2396 integers(min_value=0),
2399 def test_ber_definite_too_short(self, offset, decode_path):
2400 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2401 OctetString().decode(
2402 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2404 decode_path=decode_path,
2405 ctx={"bered": True},
2407 self.assertEqual(err.exception.decode_path, decode_path)
2408 self.assertEqual(err.exception.offset, offset)
2411 integers(min_value=0),
2413 integers(min_value=1, max_value=3),
2415 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2416 bs = OctetString(b"data").encode()
2417 with self.assertRaises(NotEnoughData) as err:
2418 OctetString().decode(
2419 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2421 decode_path=decode_path,
2422 ctx={"bered": True},
2424 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2425 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2428 integers(min_value=0),
2430 integers(min_value=1, max_value=3),
2432 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2433 bs = OctetString(b"data").encode()
2434 bs_longer = OctetString(b"data-longer").encode()
2435 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2436 OctetString().decode(
2438 tag_encode(4, form=TagFormConstructed) +
2439 len_encode((chunks + 1) * len(bs)) +
2444 decode_path=decode_path,
2445 ctx={"bered": True},
2447 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2448 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2450 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2451 @given(integers(min_value=1001, max_value=3000))
2452 def test_cer(self, data_len):
2453 data = urandom(data_len)
2454 encoded = encode_cer(OctetString(data))
2455 ctx = {"bered": True}
2456 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2457 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2458 evgens_expected = data_len // 1000
2459 if evgens_expected * 1000 != data_len:
2460 evgens_expected += 1
2461 evgens_expected += 1
2462 self.assertEqual(len(evgens), evgens_expected)
2463 for (_, obj, _) in evgens[:-2]:
2464 self.assertEqual(obj.vlen, 1000)
2465 _, obj, _ = evgens[-2]
2466 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2470 def null_values_strategy(draw, do_expl=False):
2474 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2476 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2477 optional = draw(one_of(none(), booleans()))
2479 draw(integers(min_value=0)),
2480 draw(integers(min_value=0)),
2481 draw(integers(min_value=0)),
2483 return (impl, expl, optional, _decoded)
2486 class NullInherited(Null):
2490 class TestNull(CommonMixin, TestCase):
2493 def test_ready(self):
2495 self.assertTrue(obj.ready)
2498 pprint(obj, big_blobs=True, with_decode_path=True)
2500 @given(binary(min_size=1), binary(min_size=1))
2501 def test_comparison(self, tag1, tag2):
2502 for klass in (Null, NullInherited):
2503 obj1 = klass(impl=tag1)
2504 obj2 = klass(impl=tag2)
2505 self.assertEqual(obj1 == obj2, tag1 == tag2)
2506 self.assertEqual(obj1 != obj2, tag1 != tag2)
2507 self.assertNotEqual(obj1, tag2)
2509 @given(data_strategy())
2510 def test_call(self, d):
2511 for klass in (Null, NullInherited):
2517 ) = d.draw(null_values_strategy())
2518 obj_initial = klass(
2521 optional=optional_initial or False,
2522 _decoded=_decoded_initial,
2529 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2530 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2531 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2532 self.assertEqual(obj.expl_tag, expl or expl_initial)
2533 optional = optional_initial if optional is None else optional
2534 optional = False if optional is None else optional
2535 self.assertEqual(obj.optional, optional)
2537 @given(null_values_strategy())
2538 def test_copy(self, values):
2539 for klass in (Null, NullInherited):
2540 impl, expl, optional, _decoded = values
2544 optional=optional or False,
2547 for copy_func in copy_funcs:
2548 obj_copied = copy_func(obj)
2549 self.assert_copied_basic_fields(obj, obj_copied)
2551 @given(integers(min_value=1).map(tag_encode))
2552 def test_stripped(self, tag_impl):
2553 obj = Null(impl=tag_impl)
2554 with self.assertRaises(NotEnoughData):
2555 obj.decode(obj.encode()[:-1])
2557 @given(integers(min_value=1).map(tag_ctxc))
2558 def test_stripped_expl(self, tag_expl):
2559 obj = Null(expl=tag_expl)
2560 with self.assertRaises(NotEnoughData):
2561 obj.decode(obj.encode()[:-1])
2564 integers(min_value=31),
2565 integers(min_value=0),
2568 def test_bad_tag(self, tag, offset, decode_path):
2569 with self.assertRaises(DecodeError) as err:
2571 tag_encode(tag)[:-1],
2573 decode_path=decode_path,
2576 self.assertEqual(err.exception.offset, offset)
2577 self.assertEqual(err.exception.decode_path, decode_path)
2580 integers(min_value=128),
2581 integers(min_value=0),
2584 def test_bad_len(self, l, offset, decode_path):
2585 with self.assertRaises(DecodeError) as err:
2587 Null.tag_default + len_encode(l)[:-1],
2589 decode_path=decode_path,
2592 self.assertEqual(err.exception.offset, offset)
2593 self.assertEqual(err.exception.decode_path, decode_path)
2595 @given(binary(min_size=1))
2596 def test_tag_mismatch(self, impl):
2597 assume(impl != Null.tag_default)
2598 with self.assertRaises(TagMismatch):
2599 Null(impl=impl).decode(Null().encode())
2602 null_values_strategy(),
2603 integers(min_value=1).map(tag_ctxc),
2604 integers(min_value=0),
2608 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2609 for klass in (Null, NullInherited):
2610 _, _, optional, _decoded = values
2611 obj = klass(optional=optional, _decoded=_decoded)
2614 pprint(obj, big_blobs=True, with_decode_path=True)
2615 self.assertFalse(obj.expled)
2616 obj_encoded = obj.encode()
2617 self.assertEqual(encode2pass(obj), obj_encoded)
2618 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2619 obj_expled = obj(expl=tag_expl)
2620 self.assertTrue(obj_expled.expled)
2622 list(obj_expled.pps())
2623 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2624 obj_expled_encoded = obj_expled.encode()
2625 obj_expled_cer = encode_cer(obj_expled)
2626 self.assertNotEqual(obj_expled_cer, obj_encoded)
2627 self.assertSequenceEqual(
2628 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2631 ctx_copied = deepcopy(ctx_dummy)
2632 obj_decoded, tail = obj_expled.decode(
2633 obj_expled_encoded + tail_junk,
2637 self.assertDictEqual(ctx_copied, ctx_dummy)
2639 list(obj_decoded.pps())
2640 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2641 self.assertEqual(tail, tail_junk)
2642 self.assertEqual(obj_decoded, obj_expled)
2643 self.assertNotEqual(obj_decoded, obj)
2644 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2645 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2646 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2648 obj_decoded.expl_llen,
2649 len(len_encode(len(obj_encoded))),
2651 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2652 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2655 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2657 self.assertEqual(obj_decoded.expl_offset, offset)
2658 assert_exceeding_data(
2660 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2664 evgens = list(obj_expled.decode_evgen(
2665 obj_expled_encoded + tail_junk,
2667 decode_path=decode_path,
2670 self.assertEqual(len(evgens), 1)
2671 _decode_path, obj, tail = evgens[0]
2672 self.assertSequenceEqual(tail, tail_junk)
2673 self.assertEqual(_decode_path, decode_path)
2674 self.assertEqual(obj, obj_decoded)
2675 self.assertEqual(obj.expl_offset, offset)
2679 @given(integers(min_value=1))
2680 def test_invalid_len(self, l):
2681 with self.assertRaises(InvalidLength):
2682 Null().decode(b"".join((
2689 def oid_strategy(draw):
2690 first_arc = draw(integers(min_value=0, max_value=2))
2692 if first_arc in (0, 1):
2693 second_arc = draw(integers(min_value=0, max_value=39))
2695 second_arc = draw(integers(min_value=0))
2696 other_arcs = draw(lists(integers(min_value=0)))
2697 return tuple([first_arc, second_arc] + other_arcs)
2701 def oid_values_strategy(draw, do_expl=False):
2702 value = draw(one_of(none(), oid_strategy()))
2706 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2708 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2709 default = draw(one_of(none(), oid_strategy()))
2710 optional = draw(one_of(none(), booleans()))
2712 draw(integers(min_value=0)),
2713 draw(integers(min_value=0)),
2714 draw(integers(min_value=0)),
2716 return (value, impl, expl, default, optional, _decoded)
2719 class ObjectIdentifierInherited(ObjectIdentifier):
2723 class TestObjectIdentifier(CommonMixin, TestCase):
2724 base_klass = ObjectIdentifier
2726 def test_invalid_value_type(self):
2727 with self.assertRaises(InvalidValueType) as err:
2728 ObjectIdentifier(123)
2732 def test_optional(self, optional):
2733 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2734 self.assertTrue(obj.optional)
2736 @given(oid_strategy())
2737 def test_ready(self, value):
2738 obj = ObjectIdentifier()
2739 self.assertFalse(obj.ready)
2742 pprint(obj, big_blobs=True, with_decode_path=True)
2743 with self.assertRaises(ObjNotReady) as err:
2746 with self.assertRaises(ObjNotReady) as err:
2748 obj = ObjectIdentifier(value)
2749 self.assertTrue(obj.ready)
2750 self.assertFalse(obj.ber_encoded)
2753 pprint(obj, big_blobs=True, with_decode_path=True)
2756 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2757 def test_comparison(self, value1, value2, tag1, tag2):
2758 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2759 obj1 = klass(value1)
2760 obj2 = klass(value2)
2761 self.assertEqual(obj1 == obj2, value1 == value2)
2762 self.assertEqual(obj1 != obj2, value1 != value2)
2763 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2764 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2765 obj1 = klass(value1, impl=tag1)
2766 obj2 = klass(value1, impl=tag2)
2767 self.assertEqual(obj1 == obj2, tag1 == tag2)
2768 self.assertEqual(obj1 != obj2, tag1 != tag2)
2770 @given(lists(oid_strategy()))
2771 def test_sorted_works(self, values):
2772 self.assertSequenceEqual(
2773 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2777 @given(data_strategy())
2778 def test_call(self, d):
2779 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2787 ) = d.draw(oid_values_strategy())
2788 obj_initial = klass(
2789 value=value_initial,
2792 default=default_initial,
2793 optional=optional_initial or False,
2794 _decoded=_decoded_initial,
2803 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2812 value_expected = default if value is None else value
2814 default_initial if value_expected is None
2817 self.assertEqual(obj, value_expected)
2818 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2819 self.assertEqual(obj.expl_tag, expl or expl_initial)
2822 default_initial if default is None else default,
2824 if obj.default is None:
2825 optional = optional_initial if optional is None else optional
2826 optional = False if optional is None else optional
2829 self.assertEqual(obj.optional, optional)
2831 @given(oid_values_strategy())
2832 def test_copy(self, values):
2833 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2850 for copy_func in copy_funcs:
2851 obj_copied = copy_func(obj)
2852 self.assert_copied_basic_fields(obj, obj_copied)
2853 self.assertEqual(obj._value, obj_copied._value)
2855 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2858 integers(min_value=1).map(tag_encode),
2860 def test_stripped(self, value, tag_impl):
2861 obj = ObjectIdentifier(value, impl=tag_impl)
2862 with self.assertRaises(NotEnoughData):
2863 obj.decode(obj.encode()[:-1])
2867 integers(min_value=1).map(tag_ctxc),
2869 def test_stripped_expl(self, value, tag_expl):
2870 obj = ObjectIdentifier(value, expl=tag_expl)
2871 with self.assertRaises(NotEnoughData):
2872 obj.decode(obj.encode()[:-1])
2875 integers(min_value=31),
2876 integers(min_value=0),
2879 def test_bad_tag(self, tag, offset, decode_path):
2880 with self.assertRaises(DecodeError) as err:
2881 ObjectIdentifier().decode(
2882 tag_encode(tag)[:-1],
2884 decode_path=decode_path,
2887 self.assertEqual(err.exception.offset, offset)
2888 self.assertEqual(err.exception.decode_path, decode_path)
2891 integers(min_value=128),
2892 integers(min_value=0),
2895 def test_bad_len(self, l, offset, decode_path):
2896 with self.assertRaises(DecodeError) as err:
2897 ObjectIdentifier().decode(
2898 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2900 decode_path=decode_path,
2903 self.assertEqual(err.exception.offset, offset)
2904 self.assertEqual(err.exception.decode_path, decode_path)
2906 def test_zero_oid(self):
2907 with self.assertRaises(NotEnoughData):
2908 ObjectIdentifier().decode(
2909 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2912 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2913 @given(oid_strategy())
2914 def test_unfinished_oid(self, value):
2915 assume(list(value)[-1] > 255)
2916 obj_encoded = ObjectIdentifier(value).encode()
2917 obj, _ = ObjectIdentifier().decode(obj_encoded)
2918 data = obj_encoded[obj.tlen + obj.llen:-1]
2920 ObjectIdentifier.tag_default,
2921 len_encode(len(data)),
2924 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2927 @given(integers(min_value=0))
2928 def test_invalid_short(self, value):
2929 with self.assertRaises(InvalidOID):
2930 ObjectIdentifier((value,))
2931 with self.assertRaises(InvalidOID):
2932 ObjectIdentifier("%d" % value)
2934 @given(integers(min_value=3), integers(min_value=0))
2935 def test_invalid_first_arc(self, first_arc, second_arc):
2936 with self.assertRaises(InvalidOID):
2937 ObjectIdentifier((first_arc, second_arc))
2938 with self.assertRaises(InvalidOID):
2939 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2941 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2942 def test_invalid_second_arc(self, first_arc, second_arc):
2943 with self.assertRaises(InvalidOID):
2944 ObjectIdentifier((first_arc, second_arc))
2945 with self.assertRaises(InvalidOID):
2946 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2948 @given(text(alphabet=ascii_letters + ".", min_size=1))
2949 def test_junk(self, oid):
2950 with self.assertRaises(InvalidOID):
2951 ObjectIdentifier(oid)
2953 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2954 @given(oid_strategy())
2955 def test_validness(self, oid):
2956 obj = ObjectIdentifier(oid)
2957 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2960 pprint(obj, big_blobs=True, with_decode_path=True)
2962 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2964 oid_values_strategy(),
2966 integers(min_value=1).map(tag_ctxc),
2967 integers(min_value=0),
2971 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2972 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2973 _, _, _, default, optional, _decoded = values
2982 pprint(obj, big_blobs=True, with_decode_path=True)
2983 self.assertFalse(obj.expled)
2984 obj_encoded = obj.encode()
2985 self.assertEqual(encode2pass(obj), obj_encoded)
2986 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2987 obj_expled = obj(value, expl=tag_expl)
2988 self.assertTrue(obj_expled.expled)
2990 list(obj_expled.pps())
2991 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2992 obj_expled_encoded = obj_expled.encode()
2993 obj_expled_cer = encode_cer(obj_expled)
2994 self.assertNotEqual(obj_expled_cer, obj_encoded)
2995 self.assertSequenceEqual(
2996 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2999 ctx_copied = deepcopy(ctx_dummy)
3000 obj_decoded, tail = obj_expled.decode(
3001 obj_expled_encoded + tail_junk,
3005 self.assertDictEqual(ctx_copied, ctx_dummy)
3007 list(obj_decoded.pps())
3008 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3009 self.assertEqual(tail, tail_junk)
3010 self.assertEqual(obj_decoded, obj_expled)
3011 self.assertNotEqual(obj_decoded, obj)
3012 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
3013 self.assertEqual(tuple(obj_decoded), tuple(obj))
3014 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3015 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3016 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3018 obj_decoded.expl_llen,
3019 len(len_encode(len(obj_encoded))),
3021 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3022 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3025 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3027 self.assertEqual(obj_decoded.expl_offset, offset)
3028 assert_exceeding_data(
3030 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3034 evgens = list(obj_expled.decode_evgen(
3035 obj_expled_encoded + tail_junk,
3037 decode_path=decode_path,
3040 self.assertEqual(len(evgens), 1)
3041 _decode_path, obj, tail = evgens[0]
3042 self.assertSequenceEqual(tail, tail_junk)
3043 self.assertEqual(_decode_path, decode_path)
3044 self.assertEqual(obj, obj_decoded)
3045 self.assertEqual(obj.expl_offset, offset)
3050 oid_strategy().map(ObjectIdentifier),
3051 oid_strategy().map(ObjectIdentifier),
3053 def test_add(self, oid1, oid2):
3054 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3055 for oid_to_add in (oid2, tuple(oid2)):
3056 self.assertEqual(oid1 + oid_to_add, oid_expect)
3057 with self.assertRaises(InvalidValueType):
3060 def test_go_vectors_valid(self):
3061 for data, expect in (
3063 (b"\x55\x02", (2, 5, 2)),
3064 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3065 (b"\x81\x34\x03", (2, 100, 3)),
3068 ObjectIdentifier().decode(b"".join((
3069 ObjectIdentifier.tag_default,
3070 len_encode(len(data)),
3076 def test_go_vectors_invalid(self):
3077 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3078 with self.assertRaises(DecodeError):
3079 ObjectIdentifier().decode(b"".join((
3080 Integer.tag_default,
3081 len_encode(len(data)),
3085 def test_x690_vector(self):
3087 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3088 ObjectIdentifier((2, 999, 3)),
3091 def test_nonnormalized_first_arc(self):
3093 ObjectIdentifier.tag_default +
3096 ObjectIdentifier((1, 0)).encode()[-1:]
3098 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3099 self.assertTrue(obj.ber_encoded)
3100 self.assertTrue(obj.bered)
3102 self.assertTrue(obj.ber_encoded)
3103 self.assertTrue(obj.bered)
3104 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3105 ObjectIdentifier().decode(tampered)
3107 @given(data_strategy())
3108 def test_negative_arcs(self, d):
3109 oid = list(d.draw(oid_strategy()))
3112 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3114 if oid[idx - 1] == 0:
3116 with self.assertRaises(InvalidOID):
3117 ObjectIdentifier(tuple(oid))
3118 with self.assertRaises(InvalidOID):
3119 ObjectIdentifier(".".join(str(i) for i in oid))
3121 @given(data_strategy())
3122 def test_plused_arcs(self, d):
3123 oid = [str(arc) for arc in d.draw(oid_strategy())]
3124 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3125 oid[idx - 1] = "+" + oid[idx - 1]
3126 with self.assertRaises(InvalidOID):
3127 ObjectIdentifier(".".join(str(i) for i in oid))
3129 @given(data_strategy())
3130 def test_nonnormalized_arcs(self, d):
3131 arcs = d.draw(lists(
3132 integers(min_value=0, max_value=100),
3136 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3137 _, _, lv = tag_strip(dered)
3138 _, _, v = len_decode(lv)
3139 v_no_first_arc = v[1:]
3140 idx_for_tamper = d.draw(integers(
3142 max_value=len(v_no_first_arc) - 1,
3144 tampered = list(bytearray(v_no_first_arc))
3145 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3146 tampered.insert(idx_for_tamper, 0x80)
3147 tampered = bytes(bytearray(tampered))
3149 ObjectIdentifier.tag_default +
3150 len_encode(len(tampered)) +
3153 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3154 self.assertTrue(obj.ber_encoded)
3155 self.assertTrue(obj.bered)
3157 self.assertTrue(obj.ber_encoded)
3158 self.assertTrue(obj.bered)
3159 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3160 ObjectIdentifier().decode(tampered)
3164 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3166 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3167 values = list(draw(sets(
3169 min_size=len(schema),
3170 max_size=len(schema),
3172 schema = list(zip(schema, values))
3173 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3177 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3179 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3180 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3181 optional = draw(one_of(none(), booleans()))
3183 draw(integers(min_value=0)),
3184 draw(integers(min_value=0)),
3185 draw(integers(min_value=0)),
3187 return (schema, value, impl, expl, default, optional, _decoded)
3190 class TestEnumerated(CommonMixin, TestCase):
3191 class EWhatever(Enumerated):
3192 schema = (("whatever", 0),)
3194 base_klass = EWhatever
3196 def test_schema_required(self):
3197 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3200 def test_invalid_value_type(self):
3201 with self.assertRaises(InvalidValueType) as err:
3202 self.base_klass((1, 2))
3205 @given(sets(text_letters(), min_size=2))
3206 def test_unknown_name(self, schema_input):
3207 missing = schema_input.pop()
3209 class E(Enumerated):
3210 schema = [(n, 123) for n in schema_input]
3211 with self.assertRaises(ObjUnknown) as err:
3216 sets(text_letters(), min_size=2),
3217 sets(integers(), min_size=2),
3219 def test_unknown_value(self, schema_input, values_input):
3221 missing_value = values_input.pop()
3222 _input = list(zip(schema_input, values_input))
3224 class E(Enumerated):
3226 with self.assertRaises(DecodeError) as err:
3231 def test_optional(self, optional):
3232 obj = self.base_klass(default="whatever", optional=optional)
3233 self.assertTrue(obj.optional)
3235 def test_ready(self):
3236 obj = self.base_klass()
3237 self.assertFalse(obj.ready)
3240 pprint(obj, big_blobs=True, with_decode_path=True)
3241 with self.assertRaises(ObjNotReady) as err:
3244 obj = self.base_klass("whatever")
3245 self.assertTrue(obj.ready)
3248 pprint(obj, big_blobs=True, with_decode_path=True)
3250 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3251 def test_comparison(self, value1, value2, tag1, tag2):
3252 class E(Enumerated):
3254 ("whatever0", value1),
3255 ("whatever1", value2),
3258 class EInherited(E):
3260 for klass in (E, EInherited):
3261 obj1 = klass(value1)
3262 obj2 = klass(value2)
3263 self.assertEqual(obj1 == obj2, value1 == value2)
3264 self.assertEqual(obj1 != obj2, value1 != value2)
3265 self.assertEqual(obj1 == int(obj2), value1 == value2)
3266 obj1 = klass(value1, impl=tag1)
3267 obj2 = klass(value1, impl=tag2)
3268 self.assertEqual(obj1 == obj2, tag1 == tag2)
3269 self.assertEqual(obj1 != obj2, tag1 != tag2)
3271 @given(data_strategy())
3272 def test_call(self, d):
3281 ) = d.draw(enumerated_values_strategy())
3283 class E(Enumerated):
3284 schema = schema_initial
3286 value=value_initial,
3289 default=default_initial,
3290 optional=optional_initial or False,
3291 _decoded=_decoded_initial,
3301 ) = d.draw(enumerated_values_strategy(
3302 schema=schema_initial,
3303 do_expl=impl_initial is None,
3313 value_expected = default if value is None else value
3315 default_initial if value_expected is None
3320 dict(schema_initial).get(value_expected, value_expected),
3322 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3323 self.assertEqual(obj.expl_tag, expl or expl_initial)
3326 default_initial if default is None else default,
3328 if obj.default is None:
3329 optional = optional_initial if optional is None else optional
3330 optional = False if optional is None else optional
3333 self.assertEqual(obj.optional, optional)
3334 self.assertEqual(obj.specs, dict(schema_initial))
3336 @given(enumerated_values_strategy())
3337 def test_copy(self, values):
3338 schema_input, value, impl, expl, default, optional, _decoded = values
3340 class E(Enumerated):
3341 schema = schema_input
3351 for copy_func in copy_funcs:
3352 obj_copied = copy_func(obj)
3353 self.assert_copied_basic_fields(obj, obj_copied)
3354 self.assertEqual(obj.specs, obj_copied.specs)
3356 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3357 @given(data_strategy())
3358 def test_symmetric(self, d):
3359 schema_input, _, _, _, default, optional, _decoded = d.draw(
3360 enumerated_values_strategy(),
3362 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3363 offset = d.draw(integers(min_value=0))
3364 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3365 tail_junk = d.draw(binary(max_size=5))
3366 decode_path = d.draw(decode_path_strat)
3368 class E(Enumerated):
3369 schema = schema_input
3378 pprint(obj, big_blobs=True, with_decode_path=True)
3379 self.assertFalse(obj.expled)
3380 obj_encoded = obj.encode()
3381 self.assertEqual(encode2pass(obj), obj_encoded)
3382 obj_expled = obj(value, expl=tag_expl)
3383 self.assertTrue(obj_expled.expled)
3385 list(obj_expled.pps())
3386 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3387 obj_expled_encoded = obj_expled.encode()
3388 ctx_copied = deepcopy(ctx_dummy)
3389 obj_decoded, tail = obj_expled.decode(
3390 obj_expled_encoded + tail_junk,
3394 self.assertDictEqual(ctx_copied, ctx_dummy)
3396 list(obj_decoded.pps())
3397 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3398 self.assertEqual(tail, tail_junk)
3399 self.assertEqual(obj_decoded, obj_expled)
3400 self.assertNotEqual(obj_decoded, obj)
3401 self.assertEqual(int(obj_decoded), int(obj_expled))
3402 self.assertEqual(int(obj_decoded), int(obj))
3403 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3404 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3405 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3407 obj_decoded.expl_llen,
3408 len(len_encode(len(obj_encoded))),
3410 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3411 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3414 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3416 self.assertEqual(obj_decoded.expl_offset, offset)
3417 assert_exceeding_data(
3419 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3423 evgens = list(obj_expled.decode_evgen(
3424 obj_expled_encoded + tail_junk,
3426 decode_path=decode_path,
3429 self.assertEqual(len(evgens), 1)
3430 _decode_path, obj, tail = evgens[0]
3431 self.assertSequenceEqual(tail, tail_junk)
3432 self.assertEqual(_decode_path, decode_path)
3433 self.assertEqual(obj, obj_decoded)
3434 self.assertEqual(obj.expl_offset, offset)
3440 def string_values_strategy(draw, alphabet, do_expl=False):
3441 bound_min, bound_max = sorted(draw(sets(
3442 integers(min_value=0, max_value=1 << 7),
3446 value = draw(one_of(
3448 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3450 default = draw(one_of(
3452 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3455 if draw(booleans()):
3456 bounds = (bound_min, bound_max)
3460 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3462 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3463 optional = draw(one_of(none(), booleans()))
3465 draw(integers(min_value=0)),
3466 draw(integers(min_value=0)),
3467 draw(integers(min_value=0)),
3469 return (value, bounds, impl, expl, default, optional, _decoded)
3472 class StringMixin(object):
3473 def test_invalid_value_type(self):
3474 with self.assertRaises(InvalidValueType) as err:
3475 self.base_klass((1, 2))
3478 def text_alphabet(self):
3479 return "".join(six_unichr(c) for c in six_xrange(256))
3482 def test_optional(self, optional):
3483 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3484 self.assertTrue(obj.optional)
3486 @given(data_strategy())
3487 def test_ready(self, d):
3488 obj = self.base_klass()
3489 self.assertFalse(obj.ready)
3492 pprint(obj, big_blobs=True, with_decode_path=True)
3494 with self.assertRaises(ObjNotReady) as err:
3497 with self.assertRaises(ObjNotReady) as err:
3499 value = d.draw(text(alphabet=self.text_alphabet()))
3500 obj = self.base_klass(value)
3501 self.assertTrue(obj.ready)
3504 pprint(obj, big_blobs=True, with_decode_path=True)
3507 @given(data_strategy())
3508 def test_comparison(self, d):
3509 value1 = d.draw(text(alphabet=self.text_alphabet()))
3510 value2 = d.draw(text(alphabet=self.text_alphabet()))
3511 tag1 = d.draw(binary(min_size=1))
3512 tag2 = d.draw(binary(min_size=1))
3513 obj1 = self.base_klass(value1)
3514 obj2 = self.base_klass(value2)
3515 self.assertEqual(obj1 == obj2, value1 == value2)
3516 self.assertEqual(obj1 != obj2, value1 != value2)
3517 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3518 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3519 obj1 = self.base_klass(value1, impl=tag1)
3520 obj2 = self.base_klass(value1, impl=tag2)
3521 self.assertEqual(obj1 == obj2, tag1 == tag2)
3522 self.assertEqual(obj1 != obj2, tag1 != tag2)
3524 @given(data_strategy())
3525 def test_bounds_satisfied(self, d):
3526 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3527 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3528 value = d.draw(text(
3529 alphabet=self.text_alphabet(),
3533 self.base_klass(value=value, bounds=(bound_min, bound_max))
3535 @given(data_strategy())
3536 def test_bounds_unsatisfied(self, d):
3537 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3538 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3539 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3540 with self.assertRaises(BoundsError) as err:
3541 self.base_klass(value=value, bounds=(bound_min, bound_max))
3543 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3544 self.base_klass(bounds=(bound_min, bound_max)).decode(
3545 self.base_klass(value).encode()
3548 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3549 self.base_klass(bounds=(bound_min, bound_max)).decode(
3550 encode2pass(self.base_klass(value))
3552 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3553 with self.assertRaises(BoundsError) as err:
3554 self.base_klass(value=value, bounds=(bound_min, bound_max))
3556 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3557 self.base_klass(bounds=(bound_min, bound_max)).decode(
3558 self.base_klass(value).encode()
3561 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3562 self.base_klass(bounds=(bound_min, bound_max)).decode(
3563 encode2pass(self.base_klass(value))
3566 @given(data_strategy())
3567 def test_call(self, d):
3576 ) = d.draw(string_values_strategy(self.text_alphabet()))
3577 obj_initial = self.base_klass(
3583 optional_initial or False,
3594 ) = d.draw(string_values_strategy(
3595 self.text_alphabet(),
3596 do_expl=impl_initial is None,
3598 if (default is None) and (obj_initial.default is not None):
3601 (bounds is None) and
3602 (value is not None) and
3603 (bounds_initial is not None) and
3604 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3608 (bounds is None) and
3609 (default is not None) and
3610 (bounds_initial is not None) and
3611 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3614 obj = obj_initial(value, bounds, impl, 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, value_expected)
3622 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3623 self.assertEqual(obj.expl_tag, expl or expl_initial)
3626 default_initial if default is None else default,
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)
3635 (obj._bound_min, obj._bound_max),
3636 bounds or bounds_initial or (0, float("+inf")),
3639 @given(data_strategy())
3640 def test_copy(self, d):
3641 values = d.draw(string_values_strategy(self.text_alphabet()))
3642 obj = self.base_klass(*values)
3643 for copy_func in copy_funcs:
3644 obj_copied = copy_func(obj)
3645 self.assert_copied_basic_fields(obj, obj_copied)
3646 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3647 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3648 self.assertEqual(obj._value, obj_copied._value)
3650 @given(data_strategy())
3651 def test_stripped(self, d):
3652 value = d.draw(text(alphabet=self.text_alphabet()))
3653 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3654 obj = self.base_klass(value, impl=tag_impl)
3655 with self.assertRaises(NotEnoughData):
3656 obj.decode(obj.encode()[:-1])
3658 @given(data_strategy())
3659 def test_stripped_expl(self, d):
3660 value = d.draw(text(alphabet=self.text_alphabet()))
3661 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3662 obj = self.base_klass(value, expl=tag_expl)
3663 with self.assertRaises(NotEnoughData):
3664 obj.decode(obj.encode()[:-1])
3667 integers(min_value=31),
3668 integers(min_value=0),
3671 def test_bad_tag(self, tag, offset, decode_path):
3672 with self.assertRaises(DecodeError) as err:
3673 self.base_klass().decode(
3674 tag_encode(tag)[:-1],
3676 decode_path=decode_path,
3679 self.assertEqual(err.exception.offset, offset)
3680 self.assertEqual(err.exception.decode_path, decode_path)
3683 integers(min_value=128),
3684 integers(min_value=0),
3687 def test_bad_len(self, l, offset, decode_path):
3688 with self.assertRaises(DecodeError) as err:
3689 self.base_klass().decode(
3690 self.base_klass.tag_default + len_encode(l)[:-1],
3692 decode_path=decode_path,
3695 self.assertEqual(err.exception.offset, offset)
3696 self.assertEqual(err.exception.decode_path, decode_path)
3699 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3700 integers(min_value=0),
3703 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3704 value, bound_min = list(sorted(ints))
3706 class String(self.base_klass):
3707 # Multiply this value by four, to satisfy UTF-32 bounds
3708 # (4 bytes per character) validation
3709 bounds = (bound_min * 4, bound_min * 4)
3710 with self.assertRaises(DecodeError) as err:
3712 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3714 decode_path=decode_path,
3717 self.assertEqual(err.exception.offset, offset)
3718 self.assertEqual(err.exception.decode_path, decode_path)
3720 @given(data_strategy())
3721 def test_symmetric(self, d):
3722 values = d.draw(string_values_strategy(self.text_alphabet()))
3723 value = d.draw(text(alphabet=self.text_alphabet()))
3724 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3725 offset = d.draw(integers(min_value=0))
3726 tail_junk = d.draw(binary(max_size=5))
3727 decode_path = d.draw(decode_path_strat)
3728 _, _, _, _, default, optional, _decoded = values
3729 obj = self.base_klass(
3737 pprint(obj, big_blobs=True, with_decode_path=True)
3738 self.assertFalse(obj.expled)
3739 obj_encoded = obj.encode()
3740 self.assertEqual(encode2pass(obj), obj_encoded)
3741 obj_expled = obj(value, expl=tag_expl)
3742 self.assertTrue(obj_expled.expled)
3744 list(obj_expled.pps())
3745 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3746 obj_expled_encoded = obj_expled.encode()
3747 ctx_copied = deepcopy(ctx_dummy)
3748 obj_decoded, tail = obj_expled.decode(
3749 obj_expled_encoded + tail_junk,
3753 self.assertDictEqual(ctx_copied, ctx_dummy)
3755 list(obj_decoded.pps())
3756 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3757 self.assertEqual(tail, tail_junk)
3758 self.assertEqual(obj_decoded, obj_expled)
3759 self.assertNotEqual(obj_decoded, obj)
3760 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3761 self.assertEqual(bytes(obj_decoded), bytes(obj))
3762 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3763 self.assertEqual(text_type(obj_decoded), text_type(obj))
3764 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3765 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3766 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3768 obj_decoded.expl_llen,
3769 len(len_encode(len(obj_encoded))),
3771 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3772 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3775 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3777 self.assertEqual(obj_decoded.expl_offset, offset)
3778 assert_exceeding_data(
3780 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3784 evgens = list(obj_expled.decode_evgen(
3785 obj_expled_encoded + tail_junk,
3787 decode_path=decode_path,
3790 self.assertEqual(len(evgens), 1)
3791 _decode_path, obj, tail = evgens[0]
3792 self.assertSequenceEqual(tail, tail_junk)
3793 self.assertEqual(_decode_path, decode_path)
3794 if not getattr(self, "evgen_mode_skip_value", True):
3795 self.assertEqual(obj, obj_decoded)
3796 self.assertEqual(obj.expl_offset, offset)
3801 cyrillic_letters = text(
3802 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3808 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3809 base_klass = UTF8String
3811 @given(cyrillic_letters)
3812 def test_byte_per_primitive(self, chars):
3814 char_raw = char.encode("utf-8")
3815 encoded = b"".join((
3816 self.base_klass().tag_constructed,
3818 OctetString(char_raw[:1]).encode(),
3819 OctetString(char_raw[1:2]).encode(),
3823 self.base_klass().decod(encoded, ctx={"bered": True}),
3828 class UnicodeDecodeErrorMixin(object):
3829 @given(cyrillic_letters)
3830 def test_unicode_decode_error(self, cyrillic_text):
3831 with self.assertRaises(DecodeError):
3832 self.base_klass(cyrillic_text)
3835 class TestNumericString(StringMixin, CommonMixin, TestCase):
3836 base_klass = NumericString
3838 def text_alphabet(self):
3841 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3842 def test_non_numeric(self, non_numeric_text):
3843 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3844 self.base_klass(non_numeric_text)
3847 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3848 integers(min_value=0),
3851 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3852 value, bound_min = list(sorted(ints))
3854 class String(self.base_klass):
3855 bounds = (bound_min, bound_min)
3856 with self.assertRaises(DecodeError) as err:
3858 self.base_klass(b"1" * value).encode(),
3860 decode_path=decode_path,
3863 self.assertEqual(err.exception.offset, offset)
3864 self.assertEqual(err.exception.decode_path, decode_path)
3866 def test_byte_per_primitive(self):
3867 encoded = b"".join((
3868 self.base_klass().tag_constructed,
3870 OctetString(b"1").encode(),
3871 OctetString(b"2").encode(),
3875 self.base_klass().decod(encoded, ctx={"bered": True}),
3880 class TestPrintableString(
3881 UnicodeDecodeErrorMixin,
3886 base_klass = PrintableString
3888 def text_alphabet(self):
3889 return ascii_letters + digits + " '()+,-./:=?"
3891 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3892 def test_non_printable(self, non_printable_text):
3893 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3894 self.base_klass(non_printable_text)
3897 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3898 integers(min_value=0),
3901 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3902 value, bound_min = list(sorted(ints))
3904 class String(self.base_klass):
3905 bounds = (bound_min, bound_min)
3906 with self.assertRaises(DecodeError) as err:
3908 self.base_klass(b"1" * value).encode(),
3910 decode_path=decode_path,
3913 self.assertEqual(err.exception.offset, offset)
3914 self.assertEqual(err.exception.decode_path, decode_path)
3916 def test_allowable_invalid_chars(self):
3918 ("*", {"allow_asterisk": True}),
3919 ("&", {"allow_ampersand": True}),
3920 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3923 obj = self.base_klass(s)
3924 for prop in kwargs.keys():
3925 self.assertFalse(getattr(obj, prop))
3927 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3929 self.base_klass(s, **kwargs)
3930 klass = self.base_klass(**kwargs)
3932 for prop in kwargs.keys():
3933 self.assertTrue(getattr(obj, prop))
3936 for prop in kwargs.keys():
3937 self.assertTrue(getattr(obj, prop))
3940 class TestTeletexString(
3941 UnicodeDecodeErrorMixin,
3946 base_klass = TeletexString
3949 class TestVideotexString(
3950 UnicodeDecodeErrorMixin,
3955 base_klass = VideotexString
3958 class TestIA5String(
3959 UnicodeDecodeErrorMixin,
3964 base_klass = IA5String
3966 def text_alphabet(self):
3967 return "".join(six_unichr(c) for c in six_xrange(128))
3969 @given(integers(min_value=128, max_value=255))
3970 def test_alphabet_bad(self, code):
3971 with self.assertRaises(DecodeError):
3972 self.base_klass().decod(
3973 self.base_klass.tag_default +
3975 bytes(bytearray([code])),
3979 class TestGraphicString(
3980 UnicodeDecodeErrorMixin,
3985 base_klass = GraphicString
3988 class TestVisibleString(
3989 UnicodeDecodeErrorMixin,
3994 base_klass = VisibleString
3996 def text_alphabet(self):
3997 return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
3999 def test_x690_vector(self):
4000 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
4001 self.assertSequenceEqual(tail, b"")
4002 self.assertEqual(str(obj), "Jones")
4003 self.assertFalse(obj.ber_encoded)
4004 self.assertFalse(obj.lenindef)
4005 self.assertFalse(obj.bered)
4007 obj, tail = VisibleString().decode(
4008 hexdec("3A0904034A6F6E04026573"),
4009 ctx={"bered": True},
4011 self.assertSequenceEqual(tail, b"")
4012 self.assertEqual(str(obj), "Jones")
4013 self.assertTrue(obj.ber_encoded)
4014 self.assertFalse(obj.lenindef)
4015 self.assertTrue(obj.bered)
4017 self.assertTrue(obj.ber_encoded)
4018 self.assertFalse(obj.lenindef)
4019 self.assertTrue(obj.bered)
4021 obj, tail = VisibleString().decode(
4022 hexdec("3A8004034A6F6E040265730000"),
4023 ctx={"bered": True},
4025 self.assertSequenceEqual(tail, b"")
4026 self.assertEqual(str(obj), "Jones")
4027 self.assertTrue(obj.ber_encoded)
4028 self.assertTrue(obj.lenindef)
4029 self.assertTrue(obj.bered)
4031 self.assertTrue(obj.ber_encoded)
4032 self.assertTrue(obj.lenindef)
4033 self.assertTrue(obj.bered)
4036 integers(min_value=0, max_value=ord(" ") - 1),
4037 integers(min_value=ord("~") + 1, max_value=255),
4039 def test_alphabet_bad(self, code):
4040 with self.assertRaises(DecodeError):
4041 self.base_klass().decod(
4042 self.base_klass.tag_default +
4044 bytes(bytearray([code])),
4048 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
4049 integers(min_value=0),
4052 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
4053 value, bound_min = list(sorted(ints))
4055 class String(self.base_klass):
4056 bounds = (bound_min, bound_min)
4057 with self.assertRaises(DecodeError) as err:
4059 self.base_klass(b"1" * value).encode(),
4061 decode_path=decode_path,
4064 self.assertEqual(err.exception.offset, offset)
4065 self.assertEqual(err.exception.decode_path, decode_path)
4068 class TestGeneralString(
4069 UnicodeDecodeErrorMixin,
4074 base_klass = GeneralString
4077 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4078 base_klass = UniversalString
4081 class TestBMPString(StringMixin, CommonMixin, TestCase):
4082 base_klass = BMPString
4086 def generalized_time_values_strategy(
4094 if draw(booleans()):
4095 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4097 value = value.replace(microsecond=0)
4099 if draw(booleans()):
4100 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4102 default = default.replace(microsecond=0)
4106 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4108 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4109 optional = draw(one_of(none(), booleans()))
4111 draw(integers(min_value=0)),
4112 draw(integers(min_value=0)),
4113 draw(integers(min_value=0)),
4115 return (value, impl, expl, default, optional, _decoded)
4118 class TimeMixin(object):
4119 def test_invalid_value_type(self):
4120 with self.assertRaises(InvalidValueType) as err:
4121 self.base_klass(datetime.now().timetuple())
4124 @given(data_strategy())
4125 def test_optional(self, d):
4126 default = d.draw(datetimes(
4127 min_value=self.min_datetime,
4128 max_value=self.max_datetime,
4130 optional = d.draw(booleans())
4131 obj = self.base_klass(default=default, optional=optional)
4132 self.assertTrue(obj.optional)
4134 @given(data_strategy())
4135 def test_ready(self, d):
4136 obj = self.base_klass()
4137 self.assertFalse(obj.ready)
4140 pprint(obj, big_blobs=True, with_decode_path=True)
4141 with self.assertRaises(ObjNotReady) as err:
4144 with self.assertRaises(ObjNotReady) as err:
4146 value = d.draw(datetimes(
4147 min_value=self.min_datetime,
4148 max_value=self.max_datetime,
4150 obj = self.base_klass(value)
4151 self.assertTrue(obj.ready)
4154 pprint(obj, big_blobs=True, with_decode_path=True)
4156 @given(data_strategy())
4157 def test_comparison(self, d):
4158 value1 = d.draw(datetimes(
4159 min_value=self.min_datetime,
4160 max_value=self.max_datetime,
4162 value2 = d.draw(datetimes(
4163 min_value=self.min_datetime,
4164 max_value=self.max_datetime,
4166 tag1 = d.draw(binary(min_size=1))
4167 tag2 = d.draw(binary(min_size=1))
4169 value1 = value1.replace(microsecond=0)
4170 value2 = value2.replace(microsecond=0)
4171 obj1 = self.base_klass(value1)
4172 obj2 = self.base_klass(value2)
4173 self.assertEqual(obj1 == obj2, value1 == value2)
4174 self.assertEqual(obj1 != obj2, value1 != value2)
4175 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4176 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4177 obj1 = self.base_klass(value1, impl=tag1)
4178 obj2 = self.base_klass(value1, impl=tag2)
4179 self.assertEqual(obj1 == obj2, tag1 == tag2)
4180 self.assertEqual(obj1 != obj2, tag1 != tag2)
4182 @given(data_strategy())
4183 def test_call(self, d):
4191 ) = d.draw(generalized_time_values_strategy(
4192 min_datetime=self.min_datetime,
4193 max_datetime=self.max_datetime,
4194 omit_ms=self.omit_ms,
4196 obj_initial = self.base_klass(
4197 value=value_initial,
4200 default=default_initial,
4201 optional=optional_initial or False,
4202 _decoded=_decoded_initial,
4211 ) = d.draw(generalized_time_values_strategy(
4212 min_datetime=self.min_datetime,
4213 max_datetime=self.max_datetime,
4214 omit_ms=self.omit_ms,
4215 do_expl=impl_initial is None,
4225 value_expected = default if value is None else value
4227 default_initial if value_expected is None
4230 self.assertEqual(obj, value_expected)
4231 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4232 self.assertEqual(obj.expl_tag, expl or expl_initial)
4235 default_initial if default is None else default,
4237 if obj.default is None:
4238 optional = optional_initial if optional is None else optional
4239 optional = False if optional is None else optional
4242 self.assertEqual(obj.optional, optional)
4244 @given(data_strategy())
4245 def test_copy(self, d):
4246 values = d.draw(generalized_time_values_strategy(
4247 min_datetime=self.min_datetime,
4248 max_datetime=self.max_datetime,
4250 obj = self.base_klass(*values)
4251 for copy_func in copy_funcs:
4252 obj_copied = copy_func(obj)
4253 self.assert_copied_basic_fields(obj, obj_copied)
4254 self.assertEqual(obj._value, obj_copied._value)
4256 @given(data_strategy())
4257 def test_stripped(self, d):
4258 value = d.draw(datetimes(
4259 min_value=self.min_datetime,
4260 max_value=self.max_datetime,
4262 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4263 obj = self.base_klass(value, impl=tag_impl)
4264 with self.assertRaises(NotEnoughData):
4265 obj.decode(obj.encode()[:-1])
4267 @given(data_strategy())
4268 def test_stripped_expl(self, d):
4269 value = d.draw(datetimes(
4270 min_value=self.min_datetime,
4271 max_value=self.max_datetime,
4273 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4274 obj = self.base_klass(value, expl=tag_expl)
4275 with self.assertRaises(NotEnoughData):
4276 obj.decode(obj.encode()[:-1])
4278 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4279 @given(data_strategy())
4280 def test_symmetric(self, d):
4281 values = d.draw(generalized_time_values_strategy(
4282 min_datetime=self.min_datetime,
4283 max_datetime=self.max_datetime,
4285 value = d.draw(datetimes(
4286 min_value=self.min_datetime,
4287 max_value=self.max_datetime,
4289 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4290 offset = d.draw(integers(min_value=0))
4291 tail_junk = d.draw(binary(max_size=5))
4292 _, _, _, default, optional, _decoded = values
4293 obj = self.base_klass(
4301 pprint(obj, big_blobs=True, with_decode_path=True)
4302 self.assertFalse(obj.expled)
4303 obj_encoded = obj.encode()
4304 self.assertEqual(encode2pass(obj), obj_encoded)
4305 self.additional_symmetric_check(value, obj_encoded)
4306 obj_expled = obj(value, expl=tag_expl)
4307 self.assertTrue(obj_expled.expled)
4309 list(obj_expled.pps())
4310 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4311 obj_expled_encoded = obj_expled.encode()
4312 ctx_copied = deepcopy(ctx_dummy)
4313 obj_decoded, tail = obj_expled.decode(
4314 obj_expled_encoded + tail_junk,
4318 self.assertDictEqual(ctx_copied, ctx_dummy)
4320 list(obj_decoded.pps())
4321 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4322 self.assertEqual(tail, tail_junk)
4323 self.assertEqual(obj_decoded, obj_expled)
4324 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4325 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4326 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4327 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4328 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4330 obj_decoded.expl_llen,
4331 len(len_encode(len(obj_encoded))),
4333 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4334 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4337 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4339 self.assertEqual(obj_decoded.expl_offset, offset)
4340 assert_exceeding_data(
4342 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4347 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4348 base_klass = GeneralizedTime
4350 min_datetime = datetime(1900, 1, 1)
4351 max_datetime = datetime(9999, 12, 31)
4352 evgen_mode_skip_value = False
4354 def additional_symmetric_check(self, value, obj_encoded):
4355 if value.microsecond > 0:
4356 self.assertFalse(obj_encoded.endswith(b"0Z"))
4358 def test_repr_not_ready(self):
4359 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4360 repr(GeneralizedTime())
4362 def test_x690_vector_valid(self):
4366 b"19920722132100.3Z",
4368 GeneralizedTime(data)
4370 def test_x690_vector_invalid(self):
4373 b"19920622123421.0Z",
4374 b"19920722132100.30Z",
4376 with self.assertRaises(DecodeError) as err:
4377 GeneralizedTime(data)
4380 def test_go_vectors_invalid(self):
4392 b"-20100102030410Z",
4393 b"2010-0102030410Z",
4394 b"2010-0002030410Z",
4395 b"201001-02030410Z",
4396 b"20100102-030410Z",
4397 b"2010010203-0410Z",
4398 b"201001020304-10Z",
4399 # These ones are INVALID in *DER*, but accepted
4400 # by Go's encoding/asn1
4401 b"20100102030405+0607",
4402 b"20100102030405-0607",
4404 with self.assertRaises(DecodeError) as err:
4405 GeneralizedTime(data)
4408 def test_go_vectors_valid(self):
4410 GeneralizedTime(b"20100102030405Z").todatetime(),
4411 datetime(2010, 1, 2, 3, 4, 5, 0),
4414 def test_go_vectors_valid_ber(self):
4416 b"20100102030405+0607",
4417 b"20100102030405-0607",
4419 GeneralizedTime(data, ctx={"bered": True})
4421 def test_utc_offsets(self):
4422 """Some know equal UTC offsets
4425 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4429 "200101011130-0700",
4430 "200101011500-03:30",
4433 self.assertEqual(dts[0], dts[1])
4434 self.assertEqual(dts[0], dts[2])
4435 self.assertEqual(dts[0], dts[3])
4437 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4438 @given(data_strategy())
4439 def test_valid_ber(self, d):
4440 min_year = 1901 if PY2 else 2
4441 year = d.draw(integers(min_value=min_year, max_value=9999))
4442 month = d.draw(integers(min_value=1, max_value=12))
4443 day = d.draw(integers(min_value=1, max_value=28))
4444 hours = d.draw(integers(min_value=0, max_value=23))
4445 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4446 dt = datetime(year, month, day, hours)
4447 fractions_sign = d.draw(sampled_from(" ,."))
4449 if fractions_sign != " ":
4450 fractions = random()
4451 if d.draw(booleans()):
4452 minutes = d.draw(integers(min_value=0, max_value=59))
4453 data += "%02d" % minutes
4454 dt += timedelta(seconds=60 * minutes)
4455 if d.draw(booleans()):
4456 seconds = d.draw(integers(min_value=0, max_value=59))
4457 data += "%02d" % seconds
4458 dt += timedelta(seconds=seconds)
4459 if fractions is not None:
4460 dt += timedelta(microseconds=10**6 * fractions)
4461 elif fractions is not None:
4462 dt += timedelta(seconds=60 * fractions)
4463 elif fractions is not None:
4464 dt += timedelta(seconds=3600 * fractions)
4465 if fractions is not None:
4466 data += fractions_sign + str(fractions)[2:]
4467 if d.draw(booleans()):
4469 elif d.draw(booleans()):
4470 offset_hour = d.draw(integers(min_value=0, max_value=13))
4472 if d.draw(booleans()):
4477 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4478 data += "%02d" % offset_hour
4479 minutes_separator = d.draw(sampled_from((None, "", ":")))
4480 if minutes_separator is not None:
4481 offset_minute = d.draw(integers(min_value=0, max_value=59))
4482 dt -= timedelta(seconds=sign * 60 * offset_minute)
4483 data += "%s%02d" % (minutes_separator, offset_minute)
4484 data = data.encode("ascii")
4485 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4487 GeneralizedTime().decod(data_der)
4492 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4495 mktime(obj.todatetime().timetuple()),
4496 mktime(dt.timetuple()),
4500 obj.todatetime().timestamp()
4504 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4505 self.assertEqual(obj.ber_encoded, not dered)
4506 self.assertEqual(obj.bered, not dered)
4507 self.assertEqual(obj.ber_raw, None if dered else data)
4508 self.assertEqual(obj.encode() == data_der, dered)
4513 def test_invalid_ber(self):
4515 # "00010203040506.07",
4516 "-0010203040506.07",
4517 "0001-203040506.07",
4518 "000102-3040506.07",
4519 "00010203-40506.07",
4520 "0001020304-506.07",
4521 "000102030405-6.07",
4522 "00010203040506.-7",
4523 "+0010203040506.07",
4524 "0001+203040506.07",
4525 "000102+3040506.07",
4526 "00010203+40506.07",
4527 "0001020304+506.07",
4528 "000102030405+6.07",
4529 "00010203040506.+7",
4530 " 0010203040506.07",
4531 "0001 203040506.07",
4532 "000102 3040506.07",
4533 "00010203 40506.07",
4534 "0001020304 506.07",
4535 "000102030405 6.07",
4536 "00010203040506. 7",
4537 "001 0203040506.07",
4538 "00012 03040506.07",
4539 "0001023 040506.07",
4540 "000102034 0506.07",
4541 "00010203045 06.07",
4542 "0001020304056 .07",
4543 "00010203040506.7 ",
4623 "00010203040506.07+15",
4624 "00010203040506.07-15",
4625 "00010203040506.07+14:60",
4626 "00010203040506.07+1460",
4627 "00010203040506.07-1460",
4628 "00010203040506.07+00:60",
4629 "00010203040506.07-00:60",
4631 "00010203040506+15",
4632 "00010203040506-15",
4633 "00010203040506+14:60",
4634 "00010203040506+1460",
4635 "00010203040506-1460",
4636 "00010203040506+00:60",
4637 "00010203040506-00:60",
4646 with self.assertRaises(DecodeError):
4647 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4648 data = data.replace(".", ",")
4649 with self.assertRaises(DecodeError):
4650 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4654 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4655 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4657 binary(min_size=1, max_size=1),
4659 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4660 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4663 def test_junk(self, part0, part1, part2):
4664 junk = part0 + part1 + part2
4665 assume(not (set(junk) <= set(digits.encode("ascii"))))
4666 with self.assertRaises(DecodeError):
4667 GeneralizedTime().decode(
4668 GeneralizedTime.tag_default +
4669 len_encode(len(junk)) +
4675 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4676 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4678 binary(min_size=1, max_size=1),
4680 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4681 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4684 def test_junk_dm(self, part0, part1, part2):
4685 junk = part0 + part1 + part2
4686 assume(not (set(junk) <= set(digits.encode("ascii"))))
4687 with self.assertRaises(DecodeError):
4688 GeneralizedTime().decode(
4689 GeneralizedTime.tag_default +
4690 len_encode(len(junk)) +
4694 def test_ns_fractions(self):
4695 GeneralizedTime(b"20010101000000.000001Z")
4696 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4697 GeneralizedTime(b"20010101000000.0000001Z")
4699 def test_non_pure_integers(self):
4701 # b"20000102030405Z,
4708 b"20000102030405.+6Z",
4709 b"20000102030405.-6Z",
4716 b"20000102030405._6Z",
4717 b"20000102030405.6_Z",
4724 b"20000102030405. 6Z",
4731 b"20000102030405.6 Z",
4733 with self.assertRaises(DecodeError):
4734 GeneralizedTime(data)
4736 def test_aware(self):
4737 with assertRaisesRegex(self, ValueError, "only naive"):
4738 GeneralizedTime(datetime(2000, 1, 1, 1, tzinfo=UTC))
4741 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4742 base_klass = UTCTime
4744 min_datetime = datetime(2000, 1, 1)
4745 max_datetime = datetime(2049, 12, 31)
4746 evgen_mode_skip_value = False
4748 def additional_symmetric_check(self, value, obj_encoded):
4751 def test_repr_not_ready(self):
4752 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4755 def test_x690_vector_valid(self):
4763 def test_x690_vector_invalid(self):
4768 with self.assertRaises(DecodeError) as err:
4772 def test_go_vectors_invalid(self):
4798 # These ones are INVALID in *DER*, but accepted
4799 # by Go's encoding/asn1
4800 b"910506164540-0700",
4801 b"910506164540+0730",
4805 with self.assertRaises(DecodeError) as err:
4809 def test_go_vectors_valid(self):
4811 UTCTime(b"910506234540Z").todatetime(),
4812 datetime(1991, 5, 6, 23, 45, 40, 0),
4815 def test_non_pure_integers(self):
4844 with self.assertRaises(DecodeError):
4847 def test_x680_vector_valid_ber(self):
4849 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4850 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4851 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4852 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4854 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4855 obj = UTCTime().decod(data_der, ctx={"bered": True})
4856 self.assertEqual(obj, dt)
4857 self.assertEqual(obj.todatetime(), dt)
4858 self.assertTrue(obj.ber_encoded)
4859 self.assertTrue(obj.bered)
4860 self.assertEqual(obj.ber_raw, data)
4861 self.assertNotEqual(obj.encode(), data_der)
4864 def test_go_vectors_valid_ber(self):
4866 b"910506164540-0700",
4867 b"910506164540+0730",
4871 data = UTCTime.tag_default + len_encode(len(data)) + data
4872 obj = UTCTime().decod(data, ctx={"bered": True})
4873 self.assertTrue(obj.ber_encoded)
4874 self.assertTrue(obj.bered)
4875 self.assertNotEqual(obj.encode(), data)
4878 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4879 @given(data_strategy())
4880 def test_valid_ber(self, d):
4881 year = d.draw(integers(min_value=0, max_value=99))
4882 month = d.draw(integers(min_value=1, max_value=12))
4883 day = d.draw(integers(min_value=1, max_value=28))
4884 hours = d.draw(integers(min_value=0, max_value=23))
4885 minute = d.draw(integers(min_value=0, max_value=59))
4886 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4888 year + (2000 if year < 50 else 1900),
4895 if d.draw(booleans()):
4897 seconds = d.draw(integers(min_value=0, max_value=59))
4898 data += "%02d" % seconds
4899 dt += timedelta(seconds=seconds)
4900 if d.draw(booleans()):
4904 offset_hour = d.draw(integers(min_value=0, max_value=13))
4905 offset_minute = d.draw(integers(min_value=0, max_value=59))
4906 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4907 if d.draw(booleans()):
4913 data += "%02d%02d" % (offset_hour, offset_minute)
4914 data = data.encode("ascii")
4915 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4916 obj = UTCTime().decod(data_der, ctx={"bered": True})
4917 self.assertEqual(obj, dt)
4918 self.assertEqual(obj.todatetime(), dt)
4919 self.assertEqual(obj.ber_encoded, not dered)
4920 self.assertEqual(obj.bered, not dered)
4921 self.assertEqual(obj.ber_raw, None if dered else data)
4922 self.assertEqual(obj.encode() == data_der, dered)
4927 def test_invalid_ber(self):
4968 b"0001020304+0000Z",
4977 with self.assertRaises(DecodeError):
4978 UTCTime(data, ctx={"bered": True})
4979 data = data[:8] + data[8+2:]
4980 with self.assertRaises(DecodeError):
4981 UTCTime(data, ctx={"bered": True})
5026 b"000102030405+000",
5027 b"000102030405+000Z",
5028 b"000102030405+0000Z",
5029 b"000102030405+-101",
5030 b"000102030405+01-1",
5031 b"000102030405+0060",
5032 b"000102030405+1401",
5033 b"500101000002+0003",
5035 with self.assertRaises(DecodeError):
5036 UTCTime(data, ctx={"bered": True})
5038 @given(integers(min_value=0, max_value=49))
5039 def test_pre50(self, year):
5041 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5045 @given(integers(min_value=50, max_value=99))
5046 def test_post50(self, year):
5048 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5054 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5055 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5057 binary(min_size=1, max_size=1),
5059 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5060 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5063 def test_junk(self, part0, part1, part2):
5064 junk = part0 + part1 + part2
5065 assume(not (set(junk) <= set(digits.encode("ascii"))))
5066 with self.assertRaises(DecodeError):
5068 UTCTime.tag_default +
5069 len_encode(len(junk)) +
5073 def test_aware(self):
5074 with assertRaisesRegex(self, ValueError, "only naive"):
5075 UTCTime(datetime(2000, 1, 1, 1, tzinfo=UTC))
5079 def tlv_value_strategy(draw):
5080 tag_num = draw(integers(min_value=1))
5081 data = draw(binary())
5082 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5086 def any_values_strategy(draw, do_expl=False):
5087 value = draw(one_of(none(), tlv_value_strategy()))
5090 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5091 optional = draw(one_of(none(), booleans()))
5093 draw(integers(min_value=0)),
5094 draw(integers(min_value=0)),
5095 draw(integers(min_value=0)),
5097 return (value, expl, optional, _decoded)
5100 class AnyInherited(Any):
5104 class TestAny(CommonMixin, TestCase):
5107 def test_invalid_value_type(self):
5108 with self.assertRaises(InvalidValueType) as err:
5113 def test_optional(self, optional):
5114 obj = Any(optional=optional)
5115 self.assertEqual(obj.optional, optional)
5117 @given(tlv_value_strategy())
5118 def test_ready(self, value):
5120 self.assertFalse(obj.ready)
5123 pprint(obj, big_blobs=True, with_decode_path=True)
5124 with self.assertRaises(ObjNotReady) as err:
5127 with self.assertRaises(ObjNotReady) as err:
5130 self.assertTrue(obj.ready)
5133 pprint(obj, big_blobs=True, with_decode_path=True)
5136 def test_basic(self, value):
5137 integer_encoded = Integer(value).encode()
5139 Any(integer_encoded),
5140 Any(Integer(value)),
5141 Any(Any(Integer(value))),
5143 self.assertSequenceEqual(bytes(obj), integer_encoded)
5145 obj.decode(obj.encode())[0].vlen,
5146 len(integer_encoded),
5150 pprint(obj, big_blobs=True, with_decode_path=True)
5151 self.assertSequenceEqual(obj.encode(), integer_encoded)
5153 @given(tlv_value_strategy(), tlv_value_strategy())
5154 def test_comparison(self, value1, value2):
5155 for klass in (Any, AnyInherited):
5156 obj1 = klass(value1)
5157 obj2 = klass(value2)
5158 self.assertEqual(obj1 == obj2, value1 == value2)
5159 self.assertEqual(obj1 != obj2, value1 != value2)
5160 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5162 @given(data_strategy())
5163 def test_call(self, d):
5164 for klass in (Any, AnyInherited):
5170 ) = d.draw(any_values_strategy())
5171 obj_initial = klass(
5174 optional_initial or False,
5182 ) = d.draw(any_values_strategy(do_expl=True))
5183 obj = obj_initial(value, expl, optional)
5185 value_expected = None if value is None else value
5186 self.assertEqual(obj, value_expected)
5187 self.assertEqual(obj.expl_tag, expl or expl_initial)
5188 if obj.default is None:
5189 optional = optional_initial if optional is None else optional
5190 optional = False if optional is None else optional
5191 self.assertEqual(obj.optional, optional)
5193 def test_simultaneous_impl_expl(self):
5194 # override it, as Any does not have implicit tag
5197 def test_decoded(self):
5198 # override it, as Any does not have implicit tag
5201 @given(any_values_strategy())
5202 def test_copy(self, values):
5203 for klass in (Any, AnyInherited):
5204 obj = klass(*values)
5205 for copy_func in copy_funcs:
5206 obj_copied = copy_func(obj)
5207 self.assert_copied_basic_fields(obj, obj_copied)
5208 self.assertEqual(obj._value, obj_copied._value)
5210 @given(binary().map(OctetString))
5211 def test_stripped(self, value):
5213 with self.assertRaises(NotEnoughData):
5214 obj.decode(obj.encode()[:-1])
5217 tlv_value_strategy(),
5218 integers(min_value=1).map(tag_ctxc),
5220 def test_stripped_expl(self, value, tag_expl):
5221 obj = Any(value, expl=tag_expl)
5222 with self.assertRaises(NotEnoughData):
5223 obj.decode(obj.encode()[:-1])
5226 integers(min_value=31),
5227 integers(min_value=0),
5230 def test_bad_tag(self, tag, offset, decode_path):
5231 with self.assertRaises(DecodeError) as err:
5233 tag_encode(tag)[:-1],
5235 decode_path=decode_path,
5238 self.assertEqual(err.exception.offset, offset)
5239 self.assertEqual(err.exception.decode_path, decode_path)
5242 integers(min_value=128),
5243 integers(min_value=0),
5246 def test_bad_len(self, l, offset, decode_path):
5247 with self.assertRaises(DecodeError) as err:
5249 Any.tag_default + len_encode(l)[:-1],
5251 decode_path=decode_path,
5254 self.assertEqual(err.exception.offset, offset)
5255 self.assertEqual(err.exception.decode_path, decode_path)
5257 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5259 any_values_strategy(),
5260 integers().map(lambda x: Integer(x).encode()),
5261 integers(min_value=1).map(tag_ctxc),
5262 integers(min_value=0),
5266 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5267 for klass in (Any, AnyInherited):
5268 _, _, optional, _decoded = values
5269 obj = klass(value=value, optional=optional, _decoded=_decoded)
5272 pprint(obj, big_blobs=True, with_decode_path=True)
5273 self.assertFalse(obj.expled)
5274 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5275 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5276 obj_encoded = obj.encode()
5277 self.assertEqual(encode2pass(obj), obj_encoded)
5278 obj_expled = obj(value, expl=tag_expl)
5279 self.assertTrue(obj_expled.expled)
5280 tag_class, _, tag_num = tag_decode(tag_expl)
5281 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5283 list(obj_expled.pps())
5284 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5285 obj_expled_encoded = obj_expled.encode()
5286 ctx_copied = deepcopy(ctx_dummy)
5287 obj_decoded, tail = obj_expled.decode(
5288 obj_expled_encoded + tail_junk,
5292 self.assertDictEqual(ctx_copied, ctx_dummy)
5294 list(obj_decoded.pps())
5295 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5296 self.assertEqual(tail, tail_junk)
5297 self.assertEqual(obj_decoded, obj_expled)
5298 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5299 self.assertEqual(bytes(obj_decoded), bytes(obj))
5300 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5301 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5302 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5304 obj_decoded.expl_llen,
5305 len(len_encode(len(obj_encoded))),
5307 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5308 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5311 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5313 self.assertEqual(obj_decoded.expl_offset, offset)
5314 self.assertEqual(obj_decoded.tlen, 0)
5315 self.assertEqual(obj_decoded.llen, 0)
5316 self.assertEqual(obj_decoded.vlen, len(value))
5317 assert_exceeding_data(
5319 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5323 evgens = list(obj_expled.decode_evgen(
5324 obj_expled_encoded + tail_junk,
5326 decode_path=decode_path,
5329 self.assertEqual(len(evgens), 1)
5330 _decode_path, obj, tail = evgens[0]
5331 self.assertSequenceEqual(tail, tail_junk)
5332 self.assertEqual(_decode_path, decode_path)
5333 self.assertEqual(obj.expl_offset, offset)
5338 integers(min_value=1).map(tag_ctxc),
5339 integers(min_value=0, max_value=3),
5340 integers(min_value=0),
5344 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5345 chunk = Boolean(False, expl=expl).encode()
5347 OctetString.tag_default +
5349 b"".join([chunk] * chunks) +
5352 with self.assertRaises(LenIndefForm):
5356 decode_path=decode_path,
5358 obj, tail = Any().decode(
5361 decode_path=decode_path,
5362 ctx={"bered": True},
5364 self.assertSequenceEqual(tail, junk)
5365 self.assertEqual(obj.offset, offset)
5366 self.assertEqual(obj.tlvlen, len(encoded))
5367 self.assertTrue(obj.lenindef)
5368 self.assertFalse(obj.ber_encoded)
5369 self.assertTrue(obj.bered)
5371 self.assertTrue(obj.lenindef)
5372 self.assertFalse(obj.ber_encoded)
5373 self.assertTrue(obj.bered)
5376 pprint(obj, big_blobs=True, with_decode_path=True)
5377 with self.assertRaises(NotEnoughData) as err:
5381 decode_path=decode_path,
5382 ctx={"bered": True},
5384 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5385 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5387 class SeqOf(SequenceOf):
5388 schema = Boolean(expl=expl)
5390 class Seq(Sequence):
5392 ("type", ObjectIdentifier(defines=((("value",), {
5393 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5398 ("type", ObjectIdentifier("1.2.3")),
5399 ("value", Any(encoded)),
5401 seq_encoded = seq.encode()
5402 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5403 self.assertIsNotNone(seq_decoded["value"].defined)
5405 list(seq_decoded.pps())
5406 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5407 self.assertTrue(seq_decoded.bered)
5408 self.assertFalse(seq_decoded["type"].bered)
5409 self.assertTrue(seq_decoded["value"].bered)
5411 chunk = chunk[:-1] + b"\x01"
5412 chunks = b"".join([chunk] * (chunks + 1))
5413 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5415 ("type", ObjectIdentifier("1.2.3")),
5416 ("value", Any(encoded)),
5418 seq_encoded = seq.encode()
5419 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5420 self.assertIsNotNone(seq_decoded["value"].defined)
5422 list(seq_decoded.pps())
5423 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5424 self.assertTrue(seq_decoded.bered)
5425 self.assertFalse(seq_decoded["type"].bered)
5426 self.assertTrue(seq_decoded["value"].bered)
5430 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5432 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5433 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5435 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5436 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5438 min_size=len(names),
5439 max_size=len(names),
5442 (name, Integer(**tag_kwargs))
5443 for name, tag_kwargs in zip(names, tags)
5446 if value_required or draw(booleans()):
5447 value = draw(tuples(
5448 sampled_from([name for name, _ in schema]),
5449 integers().map(Integer),
5453 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5454 default = draw(one_of(
5456 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5458 optional = draw(one_of(none(), booleans()))
5460 draw(integers(min_value=0)),
5461 draw(integers(min_value=0)),
5462 draw(integers(min_value=0)),
5464 return (schema, value, expl, default, optional, _decoded)
5467 class ChoiceInherited(Choice):
5471 class TestChoice(CommonMixin, TestCase):
5473 schema = (("whatever", Boolean()),)
5476 def test_schema_required(self):
5477 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5480 def test_impl_forbidden(self):
5481 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5482 Choice(impl=b"whatever")
5484 def test_invalid_value_type(self):
5485 with self.assertRaises(InvalidValueType) as err:
5486 self.base_klass(123)
5488 with self.assertRaises(ObjUnknown) as err:
5489 self.base_klass(("whenever", Boolean(False)))
5491 with self.assertRaises(InvalidValueType) as err:
5492 self.base_klass(("whatever", Integer(123)))
5496 def test_optional(self, optional):
5497 obj = self.base_klass(
5498 default=self.base_klass(("whatever", Boolean(False))),
5501 self.assertTrue(obj.optional)
5504 def test_ready(self, value):
5505 obj = self.base_klass()
5506 self.assertFalse(obj.ready)
5509 pprint(obj, big_blobs=True, with_decode_path=True)
5510 self.assertIsNone(obj["whatever"])
5511 with self.assertRaises(ObjNotReady) as err:
5514 with self.assertRaises(ObjNotReady) as err:
5516 obj["whatever"] = Boolean()
5517 self.assertFalse(obj.ready)
5520 pprint(obj, big_blobs=True, with_decode_path=True)
5521 obj["whatever"] = Boolean(value)
5522 self.assertTrue(obj.ready)
5525 pprint(obj, big_blobs=True, with_decode_path=True)
5527 @given(booleans(), booleans())
5528 def test_comparison(self, value1, value2):
5529 class WahlInherited(self.base_klass):
5531 for klass in (self.base_klass, WahlInherited):
5532 obj1 = klass(("whatever", Boolean(value1)))
5533 obj2 = klass(("whatever", Boolean(value2)))
5534 self.assertEqual(obj1 == obj2, value1 == value2)
5535 self.assertEqual(obj1 != obj2, value1 != value2)
5536 self.assertEqual(obj1 == obj2._value, value1 == value2)
5537 self.assertFalse(obj1 == obj2._value[1])
5539 @given(data_strategy())
5540 def test_call(self, d):
5541 for klass in (Choice, ChoiceInherited):
5549 ) = d.draw(choice_values_strategy())
5552 schema = schema_initial
5554 value=value_initial,
5556 default=default_initial,
5557 optional=optional_initial or False,
5558 _decoded=_decoded_initial,
5567 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5568 obj = obj_initial(value, expl, default, optional)
5570 value_expected = default if value is None else value
5572 default_initial if value_expected is None
5575 self.assertEqual(obj.choice, value_expected[0])
5576 self.assertEqual(obj.value, int(value_expected[1]))
5577 self.assertEqual(obj.expl_tag, expl or expl_initial)
5578 default_expect = default_initial if default is None else default
5579 if default_expect is not None:
5580 self.assertEqual(obj.default.choice, default_expect[0])
5581 self.assertEqual(obj.default.value, int(default_expect[1]))
5582 if obj.default is None:
5583 optional = optional_initial if optional is None else optional
5584 optional = False if optional is None else optional
5587 self.assertEqual(obj.optional, optional)
5588 self.assertEqual(obj.specs, obj_initial.specs)
5590 def test_simultaneous_impl_expl(self):
5591 # override it, as Any does not have implicit tag
5594 def test_decoded(self):
5595 # override it, as Any does not have implicit tag
5598 @given(choice_values_strategy())
5599 def test_copy(self, values):
5600 _schema, value, expl, default, optional, _decoded = values
5602 class Wahl(self.base_klass):
5604 register_class(Wahl)
5609 optional=optional or False,
5612 for copy_func in copy_funcs:
5613 obj_copied = copy_func(obj)
5614 self.assertIsNone(obj.tag)
5615 self.assertIsNone(obj_copied.tag)
5616 # hack for assert_copied_basic_fields
5617 obj.tag = "whatever"
5618 obj_copied.tag = "whatever"
5619 self.assert_copied_basic_fields(obj, obj_copied)
5621 self.assertEqual(obj._value, obj_copied._value)
5622 self.assertEqual(obj.specs, obj_copied.specs)
5625 def test_stripped(self, value):
5626 obj = self.base_klass(("whatever", Boolean(value)))
5627 with self.assertRaises(NotEnoughData):
5628 obj.decode(obj.encode()[:-1])
5632 integers(min_value=1).map(tag_ctxc),
5634 def test_stripped_expl(self, value, tag_expl):
5635 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5636 with self.assertRaises(NotEnoughData):
5637 obj.decode(obj.encode()[:-1])
5639 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5640 @given(data_strategy())
5641 def test_symmetric(self, d):
5642 _schema, value, _, default, optional, _decoded = d.draw(
5643 choice_values_strategy(value_required=True)
5645 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5646 offset = d.draw(integers(min_value=0))
5647 tail_junk = d.draw(binary(max_size=5))
5648 decode_path = d.draw(decode_path_strat)
5650 class Wahl(self.base_klass):
5660 pprint(obj, big_blobs=True, with_decode_path=True)
5661 self.assertFalse(obj.expled)
5662 self.assertEqual(obj.tag_order, obj.value.tag_order)
5663 obj_encoded = obj.encode()
5664 self.assertEqual(encode2pass(obj), obj_encoded)
5665 obj_expled = obj(value, expl=tag_expl)
5666 self.assertTrue(obj_expled.expled)
5667 tag_class, _, tag_num = tag_decode(tag_expl)
5668 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5670 list(obj_expled.pps())
5671 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5672 obj_expled_encoded = obj_expled.encode()
5673 ctx_copied = deepcopy(ctx_dummy)
5674 obj_decoded, tail = obj_expled.decode(
5675 obj_expled_encoded + tail_junk,
5679 self.assertDictEqual(ctx_copied, ctx_dummy)
5681 list(obj_decoded.pps())
5682 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5683 self.assertEqual(tail, tail_junk)
5684 self.assertEqual(obj_decoded, obj_expled)
5685 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5686 self.assertEqual(obj_decoded.value, obj_expled.value)
5687 self.assertEqual(obj_decoded.choice, obj.choice)
5688 self.assertEqual(obj_decoded.value, obj.value)
5689 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5690 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5691 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5693 obj_decoded.expl_llen,
5694 len(len_encode(len(obj_encoded))),
5696 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5697 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5700 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5702 self.assertEqual(obj_decoded.expl_offset, offset)
5703 self.assertSequenceEqual(
5705 obj_decoded.value.fulloffset - offset:
5706 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5710 assert_exceeding_data(
5712 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5716 evgens = list(obj_expled.decode_evgen(
5717 obj_expled_encoded + tail_junk,
5719 decode_path=decode_path,
5722 self.assertEqual(len(evgens), 2)
5723 _decode_path, obj, tail = evgens[0]
5724 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5725 _decode_path, obj, tail = evgens[1]
5726 self.assertSequenceEqual(tail, tail_junk)
5727 self.assertEqual(_decode_path, decode_path)
5728 self.assertEqual(obj.expl_offset, offset)
5733 def test_set_get(self, value):
5736 ("erste", Boolean()),
5737 ("zweite", Integer()),
5740 with self.assertRaises(ObjUnknown) as err:
5741 obj["whatever"] = "whenever"
5742 with self.assertRaises(InvalidValueType) as err:
5743 obj["zweite"] = Boolean(False)
5744 obj["zweite"] = Integer(value)
5746 with self.assertRaises(ObjUnknown) as err:
5749 self.assertIsNone(obj["erste"])
5750 self.assertEqual(obj["zweite"], Integer(value))
5752 def test_tag_mismatch(self):
5755 ("erste", Boolean()),
5757 int_encoded = Integer(123).encode()
5758 bool_encoded = Boolean(False).encode()
5760 obj.decode(bool_encoded)
5761 with self.assertRaises(TagMismatch):
5762 obj.decode(int_encoded)
5764 def test_tag_mismatch_underlying(self):
5765 class SeqOfBoolean(SequenceOf):
5768 class SeqOfInteger(SequenceOf):
5773 ("erste", SeqOfBoolean()),
5776 int_encoded = SeqOfInteger((Integer(123),)).encode()
5777 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5779 obj.decode(bool_encoded)
5780 with self.assertRaises(TagMismatch) as err:
5781 obj.decode(int_encoded)
5782 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5786 def seq_values_strategy(draw, seq_klass, do_expl=False):
5788 if draw(booleans()):
5790 value._value = draw(dictionaries(
5793 booleans().map(Boolean),
5794 integers().map(Integer),
5798 if draw(booleans()):
5799 schema = list(draw(dictionaries(
5802 booleans().map(Boolean),
5803 integers().map(Integer),
5809 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5811 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5813 if draw(booleans()):
5814 default = seq_klass()
5815 default._value = draw(dictionaries(
5818 booleans().map(Boolean),
5819 integers().map(Integer),
5822 optional = draw(one_of(none(), booleans()))
5824 draw(integers(min_value=0)),
5825 draw(integers(min_value=0)),
5826 draw(integers(min_value=0)),
5828 return (value, schema, impl, expl, default, optional, _decoded)
5832 def sequence_strategy(draw, seq_klass):
5833 inputs = draw(lists(
5835 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5836 tuples(just(Integer), integers(), one_of(none(), integers())),
5841 integers(min_value=1),
5842 min_size=len(inputs),
5843 max_size=len(inputs),
5846 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5847 for tag, expled in zip(tags, draw(lists(
5849 min_size=len(inputs),
5850 max_size=len(inputs),
5854 for i, optional in enumerate(draw(lists(
5855 sampled_from(("required", "optional", "empty")),
5856 min_size=len(inputs),
5857 max_size=len(inputs),
5859 if optional in ("optional", "empty"):
5860 inits[i]["optional"] = True
5861 if optional == "empty":
5863 empties = set(empties)
5864 names = list(draw(sets(
5866 min_size=len(inputs),
5867 max_size=len(inputs),
5870 for i, (klass, value, default) in enumerate(inputs):
5871 schema.append((names[i], klass(default=default, **inits[i])))
5872 seq_name = draw(text_letters())
5873 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5876 for i, (klass, value, default) in enumerate(inputs):
5883 "default_value": None if spec.default is None else default,
5887 expect["optional"] = True
5889 expect["presented"] = True
5890 expect["value"] = value
5892 expect["optional"] = True
5893 if default is not None and default == value:
5894 expect["presented"] = False
5895 seq[name] = klass(value)
5896 expects.append(expect)
5901 def sequences_strategy(draw, seq_klass):
5902 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5904 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5905 for tag, expled in zip(tags, draw(lists(
5912 i for i, is_default in enumerate(draw(lists(
5918 names = list(draw(sets(
5923 seq_expectses = draw(lists(
5924 sequence_strategy(seq_klass=seq_klass),
5928 seqs = [seq for seq, _ in seq_expectses]
5930 for i, (name, seq) in enumerate(zip(names, seqs)):
5933 seq(default=(seq if i in defaulted else None), **inits[i]),
5935 seq_name = draw(text_letters())
5936 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5939 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5942 "expects": expects_inner,
5945 seq_outer[name] = seq_inner
5946 if seq_outer.specs[name].default is None:
5947 expect["presented"] = True
5948 expect_outers.append(expect)
5949 return seq_outer, expect_outers
5952 class SeqMixing(object):
5953 def test_invalid_value_type(self):
5954 with self.assertRaises(InvalidValueType) as err:
5955 self.base_klass(123)
5958 def test_invalid_value_type_set(self):
5959 class Seq(self.base_klass):
5960 schema = (("whatever", Boolean()),)
5962 with self.assertRaises(InvalidValueType) as err:
5963 seq["whatever"] = Integer(123)
5967 def test_optional(self, optional):
5968 obj = self.base_klass(default=self.base_klass(), optional=optional)
5969 self.assertTrue(obj.optional)
5971 @given(data_strategy())
5972 def test_ready(self, d):
5974 str(i): v for i, v in enumerate(d.draw(lists(
5981 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5988 for name in d.draw(permutations(
5989 list(ready.keys()) + list(non_ready.keys()),
5991 schema_input.append((name, Boolean()))
5993 class Seq(self.base_klass):
5994 schema = tuple(schema_input)
5996 for name in ready.keys():
5998 seq[name] = Boolean()
5999 self.assertFalse(seq.ready)
6002 pprint(seq, big_blobs=True, with_decode_path=True)
6003 for name, value in ready.items():
6004 seq[name] = Boolean(value)
6005 self.assertFalse(seq.ready)
6008 pprint(seq, big_blobs=True, with_decode_path=True)
6009 with self.assertRaises(ObjNotReady) as err:
6012 with self.assertRaises(ObjNotReady) as err:
6014 for name, value in non_ready.items():
6015 seq[name] = Boolean(value)
6016 self.assertTrue(seq.ready)
6019 pprint(seq, big_blobs=True, with_decode_path=True)
6021 @given(data_strategy())
6022 def test_call(self, d):
6023 class SeqInherited(self.base_klass):
6025 for klass in (self.base_klass, SeqInherited):
6034 ) = d.draw(seq_values_strategy(seq_klass=klass))
6035 obj_initial = klass(
6041 optional_initial or False,
6052 ) = d.draw(seq_values_strategy(
6054 do_expl=impl_initial is None,
6056 obj = obj_initial(value, impl, expl, default, optional)
6057 value_expected = default if value is None else value
6059 default_initial if value_expected is None
6062 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
6063 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6064 self.assertEqual(obj.expl_tag, expl or expl_initial)
6066 {} if obj.default is None else obj.default._value,
6067 getattr(default_initial if default is None else default, "_value", {}),
6069 if obj.default is None:
6070 optional = optional_initial if optional is None else optional
6071 optional = False if optional is None else optional
6074 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6075 self.assertEqual(obj.optional, optional)
6077 @given(data_strategy())
6078 def test_copy(self, d):
6079 class SeqInherited(self.base_klass):
6081 register_class(SeqInherited)
6082 for klass in (self.base_klass, SeqInherited):
6083 values = d.draw(seq_values_strategy(seq_klass=klass))
6084 obj = klass(*values)
6085 for copy_func in copy_funcs:
6086 obj_copied = copy_func(obj)
6087 self.assert_copied_basic_fields(obj, obj_copied)
6088 self.assertEqual(obj.specs, obj_copied.specs)
6089 self.assertEqual(obj._value, obj_copied._value)
6091 @given(data_strategy())
6092 def test_stripped(self, d):
6093 value = d.draw(integers())
6094 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6096 class Seq(self.base_klass):
6098 schema = (("whatever", Integer()),)
6100 seq["whatever"] = Integer(value)
6101 with self.assertRaises(NotEnoughData):
6102 seq.decode(seq.encode()[:-1])
6104 @given(data_strategy())
6105 def test_stripped_expl(self, d):
6106 value = d.draw(integers())
6107 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6109 class Seq(self.base_klass):
6111 schema = (("whatever", Integer()),)
6113 seq["whatever"] = Integer(value)
6114 with self.assertRaises(NotEnoughData):
6115 seq.decode(seq.encode()[:-1])
6117 @given(integers(min_value=3), binary(min_size=2))
6118 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6119 junk = tag_encode(junk_tag_num) + junk
6121 _, _, len_encoded = tag_strip(memoryview(junk))
6122 len_decode(len_encoded)
6128 class Seq(self.base_klass):
6130 ("whatever", Integer()),
6132 ("whenever", Integer()),
6135 seq["whatever"] = Integer(123)
6136 seq["junk"] = Any(junk)
6137 seq["whenever"] = Integer(123)
6138 with self.assertRaises(DecodeError):
6139 seq.decode(seq.encode())
6142 integers(min_value=31),
6143 integers(min_value=0),
6146 def test_bad_tag(self, tag, offset, decode_path):
6147 with self.assertRaises(DecodeError) as err:
6148 self.base_klass().decode(
6149 tag_encode(tag)[:-1],
6151 decode_path=decode_path,
6154 self.assertEqual(err.exception.offset, offset)
6155 self.assertEqual(err.exception.decode_path, decode_path)
6158 integers(min_value=128),
6159 integers(min_value=0),
6162 def test_bad_len(self, l, offset, decode_path):
6163 with self.assertRaises(DecodeError) as err:
6164 self.base_klass().decode(
6165 self.base_klass.tag_default + len_encode(l)[:-1],
6167 decode_path=decode_path,
6170 self.assertEqual(err.exception.offset, offset)
6171 self.assertEqual(err.exception.decode_path, decode_path)
6173 def _assert_expects(self, seq, expects):
6174 for expect in expects:
6176 seq.specs[expect["name"]].optional,
6179 if expect["default_value"] is not None:
6181 seq.specs[expect["name"]].default,
6182 expect["default_value"],
6184 if expect["presented"]:
6185 self.assertIn(expect["name"], seq)
6186 self.assertEqual(seq[expect["name"]], expect["value"])
6188 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6189 @given(data_strategy())
6190 def test_symmetric(self, d):
6191 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6192 tail_junk = d.draw(binary(max_size=5))
6193 decode_path = d.draw(decode_path_strat)
6194 self.assertTrue(seq.ready)
6195 self.assertFalse(seq.decoded)
6196 self._assert_expects(seq, expects)
6199 pprint(seq, big_blobs=True, with_decode_path=True)
6200 self.assertTrue(seq.ready)
6201 seq_encoded = seq.encode()
6202 self.assertEqual(encode2pass(seq), seq_encoded)
6203 seq_encoded_cer = encode_cer(seq)
6204 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6205 self.assertSequenceEqual(
6206 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6209 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6210 self.assertFalse(seq_decoded.lenindef)
6211 self.assertFalse(seq_decoded.ber_encoded)
6212 self.assertFalse(seq_decoded.bered)
6214 t, _, lv = tag_strip(seq_encoded)
6215 _, _, v = len_decode(lv)
6216 seq_encoded_lenindef = t + LENINDEF + v + EOC
6217 with self.assertRaises(DecodeError):
6218 seq.decode(seq_encoded_lenindef)
6219 ctx_copied = deepcopy(ctx_dummy)
6220 ctx_copied["bered"] = True
6221 seq_decoded_lenindef, tail_lenindef = seq.decode(
6222 seq_encoded_lenindef + tail_junk,
6225 del ctx_copied["bered"]
6226 self.assertDictEqual(ctx_copied, ctx_dummy)
6227 self.assertTrue(seq_decoded_lenindef.lenindef)
6228 self.assertTrue(seq_decoded_lenindef.bered)
6229 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6230 self.assertTrue(seq_decoded_lenindef.lenindef)
6231 self.assertTrue(seq_decoded_lenindef.bered)
6232 with self.assertRaises(DecodeError):
6233 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6234 with self.assertRaises(DecodeError):
6235 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6236 repr(seq_decoded_lenindef)
6237 list(seq_decoded_lenindef.pps())
6238 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6239 self.assertTrue(seq_decoded_lenindef.ready)
6241 for decoded, decoded_tail, encoded in (
6242 (seq_decoded, tail, seq_encoded),
6243 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6245 self.assertEqual(decoded_tail, tail_junk)
6246 self._assert_expects(decoded, expects)
6247 self.assertEqual(seq, decoded)
6248 self.assertEqual(decoded.encode(), seq_encoded)
6249 self.assertEqual(decoded.tlvlen, len(encoded))
6250 for expect in expects:
6251 if not expect["presented"]:
6252 self.assertNotIn(expect["name"], decoded)
6254 self.assertIn(expect["name"], decoded)
6255 obj = decoded[expect["name"]]
6256 self.assertTrue(obj.decoded)
6257 offset = obj.expl_offset if obj.expled else obj.offset
6258 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6259 self.assertSequenceEqual(
6260 seq_encoded[offset:offset + tlvlen],
6264 evgens = list(seq.decode_evgen(
6265 encoded + decoded_tail,
6266 decode_path=decode_path,
6267 ctx={"bered": True},
6269 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6270 for _decode_path, obj, _ in evgens[:-1]:
6271 self.assertEqual(_decode_path[:-1], decode_path)
6274 _decode_path, obj, tail = evgens[-1]
6275 self.assertEqual(_decode_path, decode_path)
6279 assert_exceeding_data(
6281 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6285 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6286 @given(data_strategy())
6287 def test_symmetric_with_seq(self, d):
6288 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6289 self.assertTrue(seq.ready)
6290 seq_encoded = seq.encode()
6291 self.assertEqual(encode2pass(seq), seq_encoded)
6292 seq_decoded, tail = seq.decode(seq_encoded)
6293 self.assertEqual(tail, b"")
6294 self.assertTrue(seq.ready)
6295 self.assertEqual(seq, seq_decoded)
6296 self.assertEqual(seq_decoded.encode(), seq_encoded)
6297 for expect_outer in expect_outers:
6298 if not expect_outer["presented"]:
6299 self.assertNotIn(expect_outer["name"], seq_decoded)
6301 self.assertIn(expect_outer["name"], seq_decoded)
6302 obj = seq_decoded[expect_outer["name"]]
6303 self.assertTrue(obj.decoded)
6304 offset = obj.expl_offset if obj.expled else obj.offset
6305 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6306 self.assertSequenceEqual(
6307 seq_encoded[offset:offset + tlvlen],
6310 self._assert_expects(obj, expect_outer["expects"])
6312 @given(data_strategy())
6313 def test_default_disappears(self, d):
6314 _schema = list(d.draw(dictionaries(
6316 sets(integers(), min_size=2, max_size=2),
6320 class Seq(self.base_klass):
6322 (n, Integer(default=d))
6323 for n, (_, d) in _schema
6326 for name, (value, _) in _schema:
6327 seq[name] = Integer(value)
6328 self.assertEqual(len(seq._value), len(_schema))
6329 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6330 self.assertGreater(len(seq.encode()), len(empty_seq))
6331 for name, (_, default) in _schema:
6332 seq[name] = Integer(default)
6333 self.assertEqual(len(seq._value), 0)
6334 self.assertSequenceEqual(seq.encode(), empty_seq)
6336 @given(data_strategy())
6337 def test_encoded_default_not_accepted(self, d):
6338 _schema = list(d.draw(dictionaries(
6343 tags = [tag_encode(tag) for tag in d.draw(sets(
6344 integers(min_value=1),
6345 min_size=len(_schema),
6346 max_size=len(_schema),
6350 schema = (("int", Integer()),)
6352 class SeqWithoutDefault(self.base_klass):
6355 for (n, _), t in zip(_schema, tags)
6357 seq_without_default = SeqWithoutDefault()
6358 for name, value in _schema:
6359 seq_without_default[name] = Wahl(("int", Integer(value)))
6360 seq_encoded = seq_without_default.encode()
6361 seq_without_default.decode(seq_encoded)
6363 len(list(seq_without_default.decode_evgen(seq_encoded))),
6364 len(_schema) * 2 + 1,
6367 class SeqWithDefault(self.base_klass):
6369 (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
6370 for (n, v), t in zip(_schema, tags)
6372 seq_with_default = SeqWithDefault()
6373 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6374 seq_with_default.decode(seq_encoded)
6375 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6376 list(seq_with_default.decode_evgen(seq_encoded))
6377 for ctx in ({"bered": True}, {"allow_default_values": True}):
6378 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6379 self.assertTrue(seq_decoded.ber_encoded)
6380 self.assertTrue(seq_decoded.bered)
6381 seq_decoded = copy(seq_decoded)
6382 self.assertTrue(seq_decoded.ber_encoded)
6383 self.assertTrue(seq_decoded.bered)
6384 for name, value in _schema:
6385 self.assertEqual(seq_decoded[name], seq_with_default[name])
6386 self.assertEqual(seq_decoded[name].value, value)
6388 len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
6392 seq_without_default = SeqWithoutDefault()
6393 for name, value in _schema:
6394 seq_without_default[name] = Wahl(("int", Integer(value + 1)))
6395 seq_encoded = seq_without_default.encode()
6396 seq_with_default.decode(seq_encoded)
6398 len(list(seq_with_default.decode_evgen(seq_encoded))),
6402 @given(data_strategy())
6403 def test_missing_from_spec(self, d):
6404 names = list(d.draw(sets(text_letters(), min_size=2)))
6405 tags = [tag_encode(tag) for tag in d.draw(sets(
6406 integers(min_value=1),
6407 min_size=len(names),
6408 max_size=len(names),
6410 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6412 class SeqFull(self.base_klass):
6413 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6414 seq_full = SeqFull()
6415 for i, name in enumerate(names):
6416 seq_full[name] = Integer(i)
6417 seq_encoded = seq_full.encode()
6418 altered = names_tags[:-2] + names_tags[-1:]
6420 class SeqMissing(self.base_klass):
6421 schema = [(n, Integer(impl=t)) for n, t in altered]
6422 seq_missing = SeqMissing()
6423 with self.assertRaises(TagMismatch):
6424 seq_missing.decode(seq_encoded)
6425 with self.assertRaises(TagMismatch):
6426 list(seq_missing.decode_evgen(seq_encoded))
6428 def test_bered(self):
6429 class Seq(self.base_klass):
6430 schema = (("underlying", Boolean()),)
6431 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6432 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6433 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6434 self.assertFalse(decoded.ber_encoded)
6435 self.assertFalse(decoded.lenindef)
6436 self.assertTrue(decoded.bered)
6437 decoded = copy(decoded)
6438 self.assertFalse(decoded.ber_encoded)
6439 self.assertFalse(decoded.lenindef)
6440 self.assertTrue(decoded.bered)
6442 class Seq(self.base_klass):
6443 schema = (("underlying", OctetString()),)
6445 tag_encode(form=TagFormConstructed, num=4) +
6447 OctetString(b"whatever").encode() +
6450 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6451 with self.assertRaises(DecodeError):
6452 Seq().decode(encoded)
6453 with self.assertRaises(DecodeError):
6454 list(Seq().decode_evgen(encoded))
6455 list(Seq().decode_evgen(encoded, ctx={"bered": True}))
6456 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6457 self.assertFalse(decoded.ber_encoded)
6458 self.assertFalse(decoded.lenindef)
6459 self.assertTrue(decoded.bered)
6460 decoded = copy(decoded)
6461 self.assertFalse(decoded.ber_encoded)
6462 self.assertFalse(decoded.lenindef)
6463 self.assertTrue(decoded.bered)
6466 class TestSequence(SeqMixing, CommonMixin, TestCase):
6467 base_klass = Sequence
6473 def test_remaining(self, value, junk):
6474 class Seq(Sequence):
6476 ("whatever", Integer()),
6478 int_encoded = Integer(value).encode()
6480 Sequence.tag_default,
6481 len_encode(len(int_encoded + junk)),
6484 with assertRaisesRegex(self, DecodeError, "remaining"):
6485 Seq().decode(junked)
6487 @given(sets(text_letters(), min_size=2))
6488 def test_obj_unknown(self, names):
6489 missing = names.pop()
6491 class Seq(Sequence):
6492 schema = [(n, Boolean()) for n in names]
6494 with self.assertRaises(ObjUnknown) as err:
6497 with self.assertRaises(ObjUnknown) as err:
6498 seq[missing] = Boolean()
6501 def test_x690_vector(self):
6502 class Seq(Sequence):
6504 ("name", IA5String()),
6507 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6508 self.assertEqual(seq["name"], "Smith")
6509 self.assertEqual(seq["ok"], True)
6512 class TestSet(SeqMixing, CommonMixin, TestCase):
6515 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6516 @given(data_strategy())
6517 def test_sorted(self, d):
6518 class DummySeq(Sequence):
6519 schema = (("null", Null()),)
6521 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6522 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6523 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6524 tag_nums -= set([dummy_seq_tag_num])
6525 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6526 _schema.append(("seq", DummySeq()))
6529 schema = d.draw(permutations(_schema))
6531 for name, _ in _schema:
6533 seq[name] = OctetString(name.encode("ascii"))
6534 seq["seq"] = DummySeq((("null", Null()),))
6536 seq_encoded = seq.encode()
6537 seq_decoded, _ = seq.decode(seq_encoded)
6538 seq_encoded_expected = []
6539 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6540 if tag_num == dummy_seq_tag_num:
6541 seq_encoded_expected.append(seq["seq"].encode())
6543 seq_encoded_expected.append(seq[str(tag_num)].encode())
6544 self.assertSequenceEqual(
6545 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6546 b"".join(seq_encoded_expected),
6549 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6550 encoded += seq["seq"].encode()
6551 seq_encoded = b"".join((
6553 len_encode(len(encoded)),
6556 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6557 seq.decode(seq_encoded)
6558 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6559 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6560 self.assertTrue(seq_decoded.ber_encoded)
6561 self.assertTrue(seq_decoded.bered)
6562 seq_decoded = copy(seq_decoded)
6563 self.assertTrue(seq_decoded.ber_encoded)
6564 self.assertTrue(seq_decoded.bered)
6566 def test_same_value_twice(self):
6569 ("bool", Boolean()),
6573 encoded = b"".join((
6574 Integer(123).encode(),
6575 Integer(234).encode(),
6576 Boolean(True).encode(),
6578 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6579 with self.assertRaises(TagMismatch):
6580 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6584 def seqof_values_strategy(draw, schema=None, do_expl=False):
6586 schema = draw(sampled_from((Boolean(), Integer())))
6587 bound_min, bound_max = sorted(draw(sets(
6588 integers(min_value=0, max_value=10),
6592 if isinstance(schema, Boolean):
6593 values_generator = booleans().map(Boolean)
6594 elif isinstance(schema, Integer):
6595 values_generator = integers().map(Integer)
6596 values_generator = lists(
6601 values = draw(one_of(none(), values_generator))
6605 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6607 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6608 default = draw(one_of(none(), values_generator))
6609 optional = draw(one_of(none(), booleans()))
6611 draw(integers(min_value=0)),
6612 draw(integers(min_value=0)),
6613 draw(integers(min_value=0)),
6618 (bound_min, bound_max),
6627 class SeqOfMixing(object):
6628 def test_invalid_value_type(self):
6629 with self.assertRaises(InvalidValueType) as err:
6630 self.base_klass(123)
6633 def test_invalid_values_type(self):
6634 class SeqOf(self.base_klass):
6636 with self.assertRaises(InvalidValueType) as err:
6637 SeqOf([Integer(123), Boolean(False), Integer(234)])
6640 def test_schema_required(self):
6641 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6642 self.base_klass.__mro__[1]()
6644 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6645 def test_comparison(self, value1, value2, tag1, tag2):
6646 class SeqOf(self.base_klass):
6648 obj1 = SeqOf([Boolean(value1)])
6649 obj2 = SeqOf([Boolean(value2)])
6650 self.assertEqual(obj1 == obj2, value1 == value2)
6651 self.assertEqual(obj1 != obj2, value1 != value2)
6652 self.assertEqual(obj1 == list(obj2), value1 == value2)
6653 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6654 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6655 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6656 self.assertEqual(obj1 == obj2, tag1 == tag2)
6657 self.assertEqual(obj1 != obj2, tag1 != tag2)
6659 @given(lists(booleans()))
6660 def test_iter(self, values):
6661 class SeqOf(self.base_klass):
6663 obj = SeqOf([Boolean(value) for value in values])
6664 self.assertEqual(len(obj), len(values))
6665 for i, value in enumerate(obj):
6666 self.assertEqual(value, values[i])
6668 @given(data_strategy())
6669 def test_ready(self, d):
6670 ready = [Integer(v) for v in d.draw(lists(
6677 range(d.draw(integers(min_value=1, max_value=5)))
6680 class SeqOf(self.base_klass):
6682 values = d.draw(permutations(ready + non_ready))
6684 for value in values:
6686 self.assertFalse(seqof.ready)
6689 pprint(seqof, big_blobs=True, with_decode_path=True)
6690 with self.assertRaises(ObjNotReady) as err:
6693 with self.assertRaises(ObjNotReady) as err:
6695 for i, value in enumerate(values):
6696 self.assertEqual(seqof[i], value)
6697 if not seqof[i].ready:
6698 seqof[i] = Integer(i)
6699 self.assertTrue(seqof.ready)
6702 pprint(seqof, big_blobs=True, with_decode_path=True)
6704 def test_spec_mismatch(self):
6705 class SeqOf(self.base_klass):
6708 seqof.append(Integer(123))
6709 with self.assertRaises(ValueError):
6710 seqof.append(Boolean(False))
6711 with self.assertRaises(ValueError):
6712 seqof[0] = Boolean(False)
6714 @given(data_strategy())
6715 def test_bounds_satisfied(self, d):
6716 class SeqOf(self.base_klass):
6718 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6719 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6720 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6721 SeqOf(value=value, bounds=(bound_min, bound_max))
6723 @given(data_strategy())
6724 def test_bounds_unsatisfied(self, d):
6725 class SeqOf(self.base_klass):
6727 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6728 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6729 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6730 with self.assertRaises(BoundsError) as err:
6731 SeqOf(value=value, bounds=(bound_min, bound_max))
6733 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6734 SeqOf(bounds=(bound_min, bound_max)).decode(
6735 SeqOf(value).encode()
6738 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6739 SeqOf(bounds=(bound_min, bound_max)).decode(
6740 encode2pass(SeqOf(value))
6742 value = [Boolean(True)] * d.draw(integers(
6743 min_value=bound_max + 1,
6744 max_value=bound_max + 10,
6746 with self.assertRaises(BoundsError) as err:
6747 SeqOf(value=value, bounds=(bound_min, bound_max))
6749 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6750 SeqOf(bounds=(bound_min, bound_max)).decode(
6751 SeqOf(value).encode()
6754 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6755 SeqOf(bounds=(bound_min, bound_max)).decode(
6756 encode2pass(SeqOf(value))
6759 @given(integers(min_value=1, max_value=10))
6760 def test_out_of_bounds(self, bound_max):
6761 class SeqOf(self.base_klass):
6763 bounds = (0, bound_max)
6765 for _ in range(bound_max):
6766 seqof.append(Integer(123))
6767 with self.assertRaises(BoundsError):
6768 seqof.append(Integer(123))
6770 @given(data_strategy())
6771 def test_call(self, d):
6781 ) = d.draw(seqof_values_strategy())
6783 class SeqOf(self.base_klass):
6784 schema = schema_initial
6785 obj_initial = SeqOf(
6786 value=value_initial,
6787 bounds=bounds_initial,
6790 default=default_initial,
6791 optional=optional_initial or False,
6792 _decoded=_decoded_initial,
6803 ) = d.draw(seqof_values_strategy(
6804 schema=schema_initial,
6805 do_expl=impl_initial is None,
6807 if (default is None) and (obj_initial.default is not None):
6810 (bounds is None) and
6811 (value is not None) and
6812 (bounds_initial is not None) and
6813 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6817 (bounds is None) and
6818 (default is not None) and
6819 (bounds_initial is not None) and
6820 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6832 value_expected = default if value is None else value
6834 default_initial if value_expected is None
6837 value_expected = () if value_expected is None else value_expected
6838 self.assertEqual(obj, value_expected)
6839 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6840 self.assertEqual(obj.expl_tag, expl or expl_initial)
6843 default_initial if default is None else default,
6845 if obj.default is None:
6846 optional = optional_initial if optional is None else optional
6847 optional = False if optional is None else optional
6850 self.assertEqual(obj.optional, optional)
6852 (obj._bound_min, obj._bound_max),
6853 bounds or bounds_initial or (0, float("+inf")),
6856 @given(seqof_values_strategy())
6857 def test_copy(self, values):
6858 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6860 class SeqOf(self.base_klass):
6862 register_class(SeqOf)
6869 optional=optional or False,
6872 for copy_func in copy_funcs:
6873 obj_copied = copy_func(obj)
6874 self.assert_copied_basic_fields(obj, obj_copied)
6875 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6876 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6877 self.assertEqual(obj._value, obj_copied._value)
6881 integers(min_value=1).map(tag_encode),
6883 def test_stripped(self, values, tag_impl):
6884 class SeqOf(self.base_klass):
6885 schema = OctetString()
6886 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6887 with self.assertRaises(NotEnoughData):
6888 obj.decode(obj.encode()[:-1])
6892 integers(min_value=1).map(tag_ctxc),
6894 def test_stripped_expl(self, values, tag_expl):
6895 class SeqOf(self.base_klass):
6896 schema = OctetString()
6897 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6898 with self.assertRaises(NotEnoughData):
6899 obj.decode(obj.encode()[:-1])
6902 integers(min_value=31),
6903 integers(min_value=0),
6906 def test_bad_tag(self, tag, offset, decode_path):
6907 with self.assertRaises(DecodeError) as err:
6908 self.base_klass().decode(
6909 tag_encode(tag)[:-1],
6911 decode_path=decode_path,
6914 self.assertEqual(err.exception.offset, offset)
6915 self.assertEqual(err.exception.decode_path, decode_path)
6918 integers(min_value=128),
6919 integers(min_value=0),
6922 def test_bad_len(self, l, offset, decode_path):
6923 with self.assertRaises(DecodeError) as err:
6924 self.base_klass().decode(
6925 self.base_klass.tag_default + len_encode(l)[:-1],
6927 decode_path=decode_path,
6930 self.assertEqual(err.exception.offset, offset)
6931 self.assertEqual(err.exception.decode_path, decode_path)
6933 @given(binary(min_size=1))
6934 def test_tag_mismatch(self, impl):
6935 assume(impl != self.base_klass.tag_default)
6936 with self.assertRaises(TagMismatch):
6937 self.base_klass(impl=impl).decode(self.base_klass().encode())
6939 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6941 seqof_values_strategy(schema=Integer()),
6942 lists(integers().map(Integer)),
6943 integers(min_value=1).map(tag_ctxc),
6944 integers(min_value=0),
6948 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6949 _, _, _, _, _, default, optional, _decoded = values
6951 class SeqOf(self.base_klass):
6961 pprint(obj, big_blobs=True, with_decode_path=True)
6962 self.assertFalse(obj.expled)
6963 obj_encoded = obj.encode()
6964 self.assertEqual(encode2pass(obj), obj_encoded)
6965 obj_encoded_cer = encode_cer(obj)
6966 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6967 self.assertSequenceEqual(
6968 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6971 obj_expled = obj(value, expl=tag_expl)
6972 self.assertTrue(obj_expled.expled)
6974 list(obj_expled.pps())
6975 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6976 obj_expled_encoded = obj_expled.encode()
6977 ctx_copied = deepcopy(ctx_dummy)
6978 obj_decoded, tail = obj_expled.decode(
6979 obj_expled_encoded + tail_junk,
6983 self.assertDictEqual(ctx_copied, ctx_dummy)
6985 list(obj_decoded.pps())
6986 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6987 self.assertEqual(tail, tail_junk)
6988 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6989 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6990 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6991 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6993 obj_decoded.expl_llen,
6994 len(len_encode(len(obj_encoded))),
6996 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6997 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
7000 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
7002 self.assertEqual(obj_decoded.expl_offset, offset)
7003 for obj_inner in obj_decoded:
7004 self.assertIn(obj_inner, obj_decoded)
7005 self.assertSequenceEqual(
7008 obj_inner.offset - offset:
7009 obj_inner.offset + obj_inner.tlvlen - offset
7013 t, _, lv = tag_strip(obj_encoded)
7014 _, _, v = len_decode(lv)
7015 obj_encoded_lenindef = t + LENINDEF + v + EOC
7016 with self.assertRaises(DecodeError):
7017 obj.decode(obj_encoded_lenindef)
7018 obj_decoded_lenindef, tail_lenindef = obj.decode(
7019 obj_encoded_lenindef + tail_junk,
7020 ctx={"bered": True},
7022 self.assertTrue(obj_decoded_lenindef.lenindef)
7023 self.assertTrue(obj_decoded_lenindef.bered)
7024 obj_decoded_lenindef = copy(obj_decoded_lenindef)
7025 self.assertTrue(obj_decoded_lenindef.lenindef)
7026 self.assertTrue(obj_decoded_lenindef.bered)
7027 repr(obj_decoded_lenindef)
7028 list(obj_decoded_lenindef.pps())
7029 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
7030 self.assertEqual(tail_lenindef, tail_junk)
7031 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
7032 with self.assertRaises(DecodeError):
7033 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
7034 with self.assertRaises(DecodeError):
7035 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
7037 evgens = list(obj.decode_evgen(
7038 obj_encoded_lenindef + tail_junk,
7039 decode_path=decode_path,
7040 ctx={"bered": True},
7042 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
7043 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
7044 self.assertEqual(_decode_path, decode_path + (str(i),))
7047 _decode_path, obj, tail = evgens[-1]
7048 self.assertEqual(_decode_path, decode_path)
7052 assert_exceeding_data(
7054 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
7058 def test_bered(self):
7059 class SeqOf(self.base_klass):
7061 encoded = Boolean(False).encode()
7062 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
7063 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7064 with self.assertRaises(DecodeError):
7065 SeqOf().decode(encoded)
7066 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7067 self.assertFalse(decoded.ber_encoded)
7068 self.assertFalse(decoded.lenindef)
7069 self.assertTrue(decoded.bered)
7070 decoded = copy(decoded)
7071 self.assertFalse(decoded.ber_encoded)
7072 self.assertFalse(decoded.lenindef)
7073 self.assertTrue(decoded.bered)
7075 class SeqOf(self.base_klass):
7076 schema = OctetString()
7077 encoded = OctetString(b"whatever").encode()
7079 tag_encode(form=TagFormConstructed, num=4) +
7081 OctetString(b"whatever").encode() +
7084 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7085 with self.assertRaises(DecodeError):
7086 SeqOf().decode(encoded)
7087 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7088 self.assertFalse(decoded.ber_encoded)
7089 self.assertFalse(decoded.lenindef)
7090 self.assertTrue(decoded.bered)
7091 decoded = copy(decoded)
7092 self.assertFalse(decoded.ber_encoded)
7093 self.assertFalse(decoded.lenindef)
7094 self.assertTrue(decoded.bered)
7097 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
7098 class SeqOf(SequenceOf):
7102 def _test_symmetric_compare_objs(self, obj1, obj2):
7103 self.assertEqual(obj1, obj2)
7104 self.assertSequenceEqual(list(obj1), list(obj2))
7106 def test_iterator_pickling(self):
7107 class SeqOf(SequenceOf):
7109 register_class(SeqOf)
7112 seqof = seqof(iter(six_xrange(10)))
7113 with assertRaisesRegex(self, ValueError, "iterator"):
7116 def test_iterator_bounds(self):
7117 class SeqOf(SequenceOf):
7123 for i in six_xrange(n):
7126 seqof = SeqOf(gen(n))
7127 self.assertTrue(seqof.ready)
7128 with self.assertRaises(BoundsError):
7130 self.assertFalse(seqof.ready)
7131 seqof = seqof(gen(n))
7132 self.assertTrue(seqof.ready)
7133 with self.assertRaises(BoundsError):
7135 self.assertFalse(seqof.ready)
7137 def test_iterator_twice(self):
7138 class SeqOf(SequenceOf):
7140 bounds = (1, float("+inf"))
7143 for i in six_xrange(10):
7145 seqof = SeqOf(gen())
7146 self.assertTrue(seqof.ready)
7148 self.assertFalse(seqof.ready)
7149 register_class(SeqOf)
7152 def test_iterator_2pass(self):
7153 class SeqOf(SequenceOf):
7155 bounds = (1, float("+inf"))
7158 for i in six_xrange(10):
7160 seqof = SeqOf(gen())
7161 self.assertTrue(seqof.ready)
7162 _, state = seqof.encode1st()
7163 self.assertFalse(seqof.ready)
7164 seqof = seqof(gen())
7165 self.assertTrue(seqof.ready)
7167 seqof.encode2nd(buf.write, iter(state))
7168 self.assertSequenceEqual(
7169 [int(i) for i in seqof.decod(buf.getvalue())],
7173 def test_non_ready_bound_min(self):
7174 class SeqOf(SequenceOf):
7176 bounds = (1, float("+inf"))
7178 self.assertFalse(seqof.ready)
7181 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7186 def _test_symmetric_compare_objs(self, obj1, obj2):
7187 self.assertSetEqual(
7188 set(int(v) for v in obj1),
7189 set(int(v) for v in obj2),
7192 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7193 @given(data_strategy())
7194 def test_sorted(self, d):
7195 values = [OctetString(v) for v in d.draw(lists(binary()))]
7198 schema = OctetString()
7200 seq_encoded = seq.encode()
7201 seq_decoded, _ = seq.decode(seq_encoded)
7202 self.assertSequenceEqual(
7203 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7204 b"".join(sorted([v.encode() for v in values])),
7207 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7208 @given(data_strategy())
7209 def test_unsorted(self, d):
7210 values = [OctetString(v).encode() for v in d.draw(sets(
7211 binary(min_size=1, max_size=5),
7215 values = d.draw(permutations(values))
7216 assume(values != sorted(values))
7217 encoded = b"".join(values)
7218 seq_encoded = b"".join((
7220 len_encode(len(encoded)),
7225 schema = OctetString()
7227 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7228 seq.decode(seq_encoded)
7230 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7231 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7232 self.assertTrue(seq_decoded.ber_encoded)
7233 self.assertTrue(seq_decoded.bered)
7234 seq_decoded = copy(seq_decoded)
7235 self.assertTrue(seq_decoded.ber_encoded)
7236 self.assertTrue(seq_decoded.bered)
7237 self.assertSequenceEqual(
7238 [obj.encode() for obj in seq_decoded],
7243 class TestGoMarshalVectors(TestCase):
7245 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7246 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7247 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7248 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7249 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7251 class Seq(Sequence):
7253 ("erste", Integer()),
7254 ("zweite", Integer(optional=True))
7257 seq["erste"] = Integer(64)
7258 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7259 seq["erste"] = Integer(0x123456)
7260 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7261 seq["erste"] = Integer(64)
7262 seq["zweite"] = Integer(65)
7263 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7265 class NestedSeq(Sequence):
7269 seq["erste"] = Integer(127)
7270 seq["zweite"] = None
7271 nested = NestedSeq()
7272 nested["nest"] = seq
7273 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7275 self.assertSequenceEqual(
7276 OctetString(b"\x01\x02\x03").encode(),
7277 hexdec("0403010203"),
7280 class Seq(Sequence):
7282 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7285 seq["erste"] = Integer(64)
7286 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7288 class Seq(Sequence):
7290 ("erste", Integer(expl=tag_ctxc(5))),
7293 seq["erste"] = Integer(64)
7294 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7296 class Seq(Sequence):
7299 impl=tag_encode(0, klass=TagClassContext),
7304 seq["erste"] = Null()
7305 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7307 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7309 self.assertSequenceEqual(
7310 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7311 hexdec("170d3730303130313030303030305a"),
7313 self.assertSequenceEqual(
7314 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7315 hexdec("170d3039313131353232353631365a"),
7317 self.assertSequenceEqual(
7318 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7319 hexdec("180f32313030303430353132303130315a"),
7322 class Seq(Sequence):
7324 ("erste", GeneralizedTime()),
7327 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7328 self.assertSequenceEqual(
7330 hexdec("3011180f32303039313131353232353631365a"),
7333 self.assertSequenceEqual(
7334 BitString((1, b"\x80")).encode(),
7337 self.assertSequenceEqual(
7338 BitString((12, b"\x81\xF0")).encode(),
7339 hexdec("03030481f0"),
7342 self.assertSequenceEqual(
7343 ObjectIdentifier("1.2.3.4").encode(),
7344 hexdec("06032a0304"),
7346 self.assertSequenceEqual(
7347 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7348 hexdec("06092a864888932d010105"),
7350 self.assertSequenceEqual(
7351 ObjectIdentifier("2.100.3").encode(),
7352 hexdec("0603813403"),
7355 self.assertSequenceEqual(
7356 PrintableString("test").encode(),
7357 hexdec("130474657374"),
7359 self.assertSequenceEqual(
7360 PrintableString("x" * 127).encode(),
7361 hexdec("137F" + "78" * 127),
7363 self.assertSequenceEqual(
7364 PrintableString("x" * 128).encode(),
7365 hexdec("138180" + "78" * 128),
7367 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7369 class Seq(Sequence):
7371 ("erste", IA5String()),
7374 seq["erste"] = IA5String("test")
7375 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7377 class Seq(Sequence):
7379 ("erste", PrintableString()),
7382 seq["erste"] = PrintableString("test")
7383 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7384 # Asterisk is actually not allowable
7385 PrintableString._allowable_chars |= set(b"*")
7386 seq["erste"] = PrintableString("test*")
7387 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7388 PrintableString._allowable_chars -= set(b"*")
7390 class Seq(Sequence):
7392 ("erste", Any(optional=True)),
7393 ("zweite", Integer()),
7396 seq["zweite"] = Integer(64)
7397 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7402 seq.append(Integer(10))
7403 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7405 class _SeqOf(SequenceOf):
7406 schema = PrintableString()
7408 class SeqOf(SequenceOf):
7411 _seqof.append(PrintableString("1"))
7413 seqof.append(_seqof)
7414 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7416 class Seq(Sequence):
7418 ("erste", Integer(default=1)),
7421 seq["erste"] = Integer(0)
7422 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7423 seq["erste"] = Integer(1)
7424 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7425 seq["erste"] = Integer(2)
7426 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7429 class TestPP(TestCase):
7430 @given(data_strategy())
7431 def test_oid_printing(self, d):
7433 str(ObjectIdentifier(k)): v * 2
7434 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7436 chosen = d.draw(sampled_from(sorted(oids)))
7437 chosen_id = oids[chosen]
7438 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7439 self.assertNotIn(chosen_id, pp_console_row(pp))
7442 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7446 class TestAutoAddSlots(TestCase):
7448 class Inher(Integer):
7451 with self.assertRaises(AttributeError):
7453 inher.unexistent = "whatever"
7456 class TestOIDDefines(TestCase):
7457 @given(data_strategy())
7458 def runTest(self, d):
7459 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7460 value_name_chosen = d.draw(sampled_from(value_names))
7462 ObjectIdentifier(oid)
7463 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7465 oid_chosen = d.draw(sampled_from(oids))
7466 values = d.draw(lists(
7468 min_size=len(value_names),
7469 max_size=len(value_names),
7471 for definable_class in (Any, OctetString, BitString):
7473 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7474 oid: Integer() for oid in oids[:-1]
7477 for i, value_name in enumerate(value_names):
7478 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7480 class Seq(Sequence):
7483 for value_name, value in zip(value_names, values):
7484 seq[value_name] = definable_class(Integer(value).encode())
7485 seq["type"] = oid_chosen
7486 seq, _ = Seq().decode(seq.encode())
7487 for value_name in value_names:
7488 if value_name == value_name_chosen:
7490 self.assertIsNone(seq[value_name].defined)
7491 if value_name_chosen in oids[:-1]:
7492 self.assertIsNotNone(seq[value_name_chosen].defined)
7493 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7494 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7497 pprint(seq, big_blobs=True, with_decode_path=True)
7500 class TestDefinesByPath(TestCase):
7501 def test_generated(self):
7502 class Seq(Sequence):
7504 ("type", ObjectIdentifier()),
7505 ("value", OctetString(expl=tag_ctxc(123))),
7508 class SeqInner(Sequence):
7510 ("typeInner", ObjectIdentifier()),
7511 ("valueInner", Any()),
7514 class PairValue(SetOf):
7517 class Pair(Sequence):
7519 ("type", ObjectIdentifier()),
7520 ("value", PairValue()),
7523 class Pairs(SequenceOf):
7530 type_octet_stringed,
7532 ObjectIdentifier(oid)
7533 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7535 seq_integered = Seq()
7536 seq_integered["type"] = type_integered
7537 seq_integered["value"] = OctetString(Integer(123).encode())
7538 seq_integered_raw = seq_integered.encode()
7542 (type_octet_stringed, OctetString(b"whatever")),
7543 (type_integered, Integer(123)),
7544 (type_octet_stringed, OctetString(b"whenever")),
7545 (type_integered, Integer(234)),
7547 for t, v in pairs_input:
7550 ("value", PairValue((Any(v),))),
7552 seq_inner = SeqInner()
7553 seq_inner["typeInner"] = type_innered
7554 seq_inner["valueInner"] = Any(pairs)
7555 seq_sequenced = Seq()
7556 seq_sequenced["type"] = type_sequenced
7557 seq_sequenced["value"] = OctetString(seq_inner.encode())
7558 seq_sequenced_raw = seq_sequenced.encode()
7560 list(seq_sequenced.pps())
7561 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7563 defines_by_path = []
7564 ctx_copied = deepcopy(ctx_dummy)
7565 seq_integered, _ = Seq().decode(
7569 self.assertDictEqual(ctx_copied, ctx_dummy)
7570 self.assertIsNone(seq_integered["value"].defined)
7571 defines_by_path.append(
7572 (("type",), ((("value",), {
7573 type_integered: Integer(),
7574 type_sequenced: SeqInner(),
7577 ctx_copied["defines_by_path"] = defines_by_path
7578 seq_integered, _ = Seq().decode(
7582 del ctx_copied["defines_by_path"]
7583 self.assertDictEqual(ctx_copied, ctx_dummy)
7584 self.assertIsNotNone(seq_integered["value"].defined)
7585 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7586 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7587 self.assertTrue(seq_integered_raw[
7588 seq_integered["value"].defined[1].offset:
7589 ].startswith(Integer(123).encode()))
7591 list(seq_integered.pps())
7592 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7594 ctx_copied["defines_by_path"] = defines_by_path
7595 seq_sequenced, _ = Seq().decode(
7599 del ctx_copied["defines_by_path"]
7600 self.assertDictEqual(ctx_copied, ctx_dummy)
7601 self.assertIsNotNone(seq_sequenced["value"].defined)
7602 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7603 seq_inner = seq_sequenced["value"].defined[1]
7604 self.assertIsNone(seq_inner["valueInner"].defined)
7606 list(seq_sequenced.pps())
7607 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7609 defines_by_path.append((
7610 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7611 ((("valueInner",), {type_innered: Pairs()}),),
7613 ctx_copied["defines_by_path"] = defines_by_path
7614 seq_sequenced, _ = Seq().decode(
7618 del ctx_copied["defines_by_path"]
7619 self.assertDictEqual(ctx_copied, ctx_dummy)
7620 self.assertIsNotNone(seq_sequenced["value"].defined)
7621 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7622 seq_inner = seq_sequenced["value"].defined[1]
7623 self.assertIsNotNone(seq_inner["valueInner"].defined)
7624 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7625 pairs = seq_inner["valueInner"].defined[1]
7627 self.assertIsNone(pair["value"][0].defined)
7629 list(seq_sequenced.pps())
7630 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7632 defines_by_path.append((
7635 DecodePathDefBy(type_sequenced),
7637 DecodePathDefBy(type_innered),
7642 type_integered: Integer(),
7643 type_octet_stringed: OctetString(),
7646 ctx_copied["defines_by_path"] = defines_by_path
7647 seq_sequenced, _ = Seq().decode(
7651 del ctx_copied["defines_by_path"]
7652 self.assertDictEqual(ctx_copied, ctx_dummy)
7653 self.assertIsNotNone(seq_sequenced["value"].defined)
7654 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7655 seq_inner = seq_sequenced["value"].defined[1]
7656 self.assertIsNotNone(seq_inner["valueInner"].defined)
7657 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7658 pairs_got = seq_inner["valueInner"].defined[1]
7659 for pair_input, pair_got in zip(pairs_input, pairs_got):
7660 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7661 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7663 list(seq_sequenced.pps())
7664 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7666 @given(oid_strategy(), integers())
7667 def test_simple(self, oid, tgt):
7668 class Inner(Sequence):
7670 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7671 ObjectIdentifier(oid): Integer(),
7675 class Outer(Sequence):
7678 ("tgt", OctetString()),
7682 inner["oid"] = ObjectIdentifier(oid)
7684 outer["inner"] = inner
7685 outer["tgt"] = OctetString(Integer(tgt).encode())
7686 decoded, _ = Outer().decode(outer.encode())
7687 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7689 def test_remaining_data(self):
7690 oid = ObjectIdentifier("1.2.3")
7692 class Seq(Sequence):
7694 ("oid", ObjectIdentifier(defines=((("tgt",), {
7697 ("tgt", OctetString()),
7702 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7704 with assertRaisesRegex(self, DecodeError, "remaining data"):
7705 Seq().decode(seq.encode())
7707 def test_remaining_data_seqof(self):
7708 oid = ObjectIdentifier("1.2.3")
7711 schema = OctetString()
7713 class Seq(Sequence):
7715 ("oid", ObjectIdentifier(defines=((("tgt",), {
7723 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7725 with assertRaisesRegex(self, DecodeError, "remaining data"):
7726 Seq().decode(seq.encode())
7729 class TestAbsDecodePath(TestCase):
7731 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7732 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7734 def test_concat(self, decode_path, rel_path):
7735 dp = abs_decode_path(decode_path, rel_path)
7736 self.assertSequenceEqual(dp, decode_path + rel_path)
7740 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7741 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7743 def test_abs(self, decode_path, rel_path):
7744 self.assertSequenceEqual(
7745 abs_decode_path(decode_path, ("/",) + rel_path),
7750 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7751 integers(min_value=1, max_value=3),
7752 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7754 def test_dots(self, decode_path, number_of_dots, rel_path):
7755 self.assertSequenceEqual(
7756 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7757 decode_path[:-number_of_dots] + rel_path,
7761 class TestStrictDefaultExistence(TestCase):
7762 @given(data_strategy())
7763 def runTest(self, d):
7764 count = d.draw(integers(min_value=1, max_value=10))
7765 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7767 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7768 for i in range(count)
7770 for klass in (Sequence, Set):
7774 for i in range(count):
7775 seq["int%d" % i] = Integer(123)
7777 chosen_choice = "int%d" % chosen
7778 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7779 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7781 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7782 self.assertTrue(decoded.ber_encoded)
7783 self.assertTrue(decoded.bered)
7784 decoded = copy(decoded)
7785 self.assertTrue(decoded.ber_encoded)
7786 self.assertTrue(decoded.bered)
7787 decoded, _ = seq.decode(raw, ctx={"bered": True})
7788 self.assertTrue(decoded.ber_encoded)
7789 self.assertTrue(decoded.bered)
7790 decoded = copy(decoded)
7791 self.assertTrue(decoded.ber_encoded)
7792 self.assertTrue(decoded.bered)
7795 class TestX690PrefixedType(TestCase):
7797 self.assertSequenceEqual(
7798 VisibleString("Jones").encode(),
7799 hexdec("1A054A6F6E6573"),
7803 self.assertSequenceEqual(
7806 impl=tag_encode(3, klass=TagClassApplication),
7808 hexdec("43054A6F6E6573"),
7812 self.assertSequenceEqual(
7816 impl=tag_encode(3, klass=TagClassApplication),
7820 hexdec("A20743054A6F6E6573"),
7824 self.assertSequenceEqual(
7828 impl=tag_encode(3, klass=TagClassApplication),
7830 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7832 hexdec("670743054A6F6E6573"),
7836 self.assertSequenceEqual(
7837 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7838 hexdec("82054A6F6E6573"),
7842 class TestExplOOB(TestCase):
7844 expl = tag_ctxc(123)
7845 raw = Integer(123).encode() + Integer(234).encode()
7846 raw = b"".join((expl, len_encode(len(raw)), raw))
7847 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7848 Integer(expl=expl).decode(raw)
7849 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7852 class TestPickleDifferentVersion(TestCase):
7854 pickled = pickle_dumps(Integer(123), pickle_proto)
7856 version_orig = pyderasn.__version__
7857 pyderasn.__version__ += "different"
7858 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7859 pickle_loads(pickled)
7860 pyderasn.__version__ = version_orig
7861 pickle_loads(pickled)
7864 class TestCERSetOrdering(TestCase):
7865 def test_vectors(self):
7866 """Taken from X.690-201508
7870 ("c", Integer(impl=tag_ctxp(2))),
7871 ("d", Integer(impl=tag_ctxp(4))),
7876 ("g", Integer(impl=tag_ctxp(5))),
7877 ("h", Integer(impl=tag_ctxp(6))),
7882 ("j", Integer(impl=tag_ctxp(0))),
7893 ("a", Integer(impl=tag_ctxp(3))),
7894 ("b", B(expl=tag_ctxc(1))),
7899 ("a", Integer(123)),
7900 ("b", B(("d", Integer(234)))),
7901 ("e", E(("f", F(("g", Integer(345)))))),
7903 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7904 self.assertSequenceEqual(
7905 [i.__class__.__name__ for i in order],
7906 ("E", "B", "Integer"),