# coding: utf-8
-# PyDERASN -- Python ASN.1 DER/BER codec with abstract structures
+# PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
# Copyright (C) 2017-2020 Sergey Matveev <stargrave@stargrave.org>
#
# This program is free software: you can redistribute it and/or modify
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
+from copy import copy
from copy import deepcopy
from datetime import datetime
+from datetime import timedelta
+from importlib import import_module
+from io import BytesIO
+from operator import attrgetter
+from os import environ
+from os import urandom
+from random import random
from string import ascii_letters
from string import digits
from string import printable
from string import whitespace
+from time import mktime
+from time import time
from unittest import TestCase
from hypothesis import assume
from six import PY2
from six import text_type
from six import unichr as six_unichr
+from six.moves import xrange as six_xrange
+from six.moves.cPickle import dumps as pickle_dumps
+from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
+from six.moves.cPickle import loads as pickle_loads
from pyderasn import _pp
from pyderasn import abs_decode_path
from pyderasn import Choice
from pyderasn import DecodeError
from pyderasn import DecodePathDefBy
+from pyderasn import encode2pass
+from pyderasn import encode_cer
from pyderasn import Enumerated
from pyderasn import EOC
from pyderasn import EOC_LEN
from pyderasn import VisibleString
+max_examples = environ.get("MAX_EXAMPLES")
settings.register_profile("local", settings(
deadline=5000,
+ **({"max_examples": int(max_examples)} if max_examples else {})
))
settings.load_profile("local")
LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
lambda decode_path: tuple(str(dp) for dp in decode_path)
)
ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
+copy_funcs = (
+ copy,
+ lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
+)
+self_module = import_module(__name__)
+
+
+def register_class(klass):
+ klassname = klass.__name__ + str(time()).replace(".", "")
+ klass.__name__ = klassname
+ klass.__qualname__ = klassname
+ setattr(self_module, klassname, klass)
def assert_exceeding_data(self, call, junk):
- if len(junk) > 0:
- with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)):
- call()
+ if len(junk) <= 0:
+ return
+ with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
+ call()
+ repr(err)
class TestHex(TestCase):
obj = Inherited()
self.assertSequenceEqual(obj.impl, impl_tag)
self.assertFalse(obj.expled)
+ if obj.ready:
+ tag_class, _, tag_num = tag_decode(impl_tag)
+ self.assertEqual(obj.tag_order, (tag_class, tag_num))
- @given(binary())
+ @given(binary(min_size=1))
def test_expl_inherited(self, expl_tag):
class Inherited(self.base_klass):
expl = expl_tag
obj = Inherited()
self.assertSequenceEqual(obj.expl, expl_tag)
self.assertTrue(obj.expled)
+ if obj.ready:
+ tag_class, _, tag_num = tag_decode(expl_tag)
+ self.assertEqual(obj.tag_order, (tag_class, tag_num))
def assert_copied_basic_fields(self, obj, obj_copied):
self.assertEqual(obj, obj_copied)
self.assertEqual(obj.offset, obj_copied.offset)
self.assertEqual(obj.llen, obj_copied.llen)
self.assertEqual(obj.vlen, obj_copied.vlen)
+ if obj.ready:
+ self.assertEqual(obj.tag_order, obj_copied.tag_order)
@composite
pprint(obj, big_blobs=True, with_decode_path=True)
with self.assertRaises(ObjNotReady) as err:
obj.encode()
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
repr(err.exception)
obj = Boolean(value)
self.assertTrue(obj.ready)
list(obj.pps())
pprint(obj, big_blobs=True, with_decode_path=True)
- @given(booleans(), booleans(), binary(), binary())
+ @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
def test_comparison(self, value1, value2, tag1, tag2):
for klass in (Boolean, BooleanInherited):
obj1 = klass(value1)
def test_copy(self, values):
for klass in (Boolean, BooleanInherited):
obj = klass(*values)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
@given(
booleans(),
obj = Boolean(value, impl=tag_impl)
with self.assertRaises(NotEnoughData):
obj.decode(obj.encode()[:-1])
+ with self.assertRaises(NotEnoughData):
+ obj.decode(encode2pass(obj)[:-1])
@given(
booleans(),
obj = Boolean(value, expl=tag_expl)
with self.assertRaises(NotEnoughData):
obj.decode(obj.encode()[:-1])
+ with self.assertRaises(NotEnoughData):
+ obj.decode(encode2pass(obj)[:-1])
@given(
integers(min_value=31),
integers(min_value=1).map(tag_ctxc),
integers(min_value=0),
binary(max_size=5),
+ decode_path_strat,
)
- def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+ def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
for klass in (Boolean, BooleanInherited):
_, _, _, default, optional, _decoded = values
obj = klass(
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
+ self.assertSequenceEqual(encode_cer(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
- obj_expled_encoded = obj_expled.encode()
+ obj_expled_cer = encode_cer(obj_expled)
+ self.assertNotEqual(obj_expled_cer, obj_encoded)
+ self.assertSequenceEqual(
+ obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
+ obj_expled.encode(),
+ )
+ obj_expled_hex_encoded = obj_expled.hexencode()
ctx_copied = deepcopy(ctx_dummy)
- obj_decoded, tail = obj_expled.decode(
- obj_expled_encoded + tail_junk,
+ obj_decoded, tail = obj_expled.hexdecode(
+ obj_expled_hex_encoded + hexenc(tail_junk),
offset=offset,
ctx=ctx_copied,
)
self.assertNotEqual(obj_decoded, obj)
self.assertEqual(bool(obj_decoded), bool(obj_expled))
self.assertEqual(bool(obj_decoded), bool(obj))
- self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
+ self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
self.assertEqual(
self.assertEqual(obj_decoded.expl_offset, offset)
assert_exceeding_data(
self,
- lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
+ lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ hexdec(obj_expled_hex_encoded) + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj, obj_decoded)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
@given(integers(min_value=2))
def test_invalid_len(self, l):
with self.assertRaises(InvalidLength):
len_encode(1),
int2byte(value),
)))
- obj, _ = Boolean().decode(
- b"".join((
- Boolean.tag_default,
- len_encode(1),
- int2byte(value),
- )),
- ctx={"bered": True},
- )
+ encoded = b"".join((
+ Boolean.tag_default,
+ len_encode(1),
+ int2byte(value),
+ ))
+ obj, _ = Boolean().decode(encoded, ctx={"bered": True})
+ list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
self.assertTrue(bool(obj))
self.assertTrue(obj.ber_encoded)
self.assertFalse(obj.lenindef)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertFalse(obj.lenindef)
self.assertTrue(obj.bered)
self.assertFalse(obj.lenindef)
self.assertFalse(obj.ber_encoded)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.expl_lenindef)
self.assertFalse(obj.lenindef)
self.assertFalse(obj.ber_encoded)
with self.assertRaises(LenIndefForm):
SeqOf().decode(encoded)
seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
+ list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
self.assertSequenceEqual(tail, b"")
self.assertSequenceEqual([bool(v) for v in seqof], values)
self.assertSetEqual(
pprint(obj, big_blobs=True, with_decode_path=True)
with self.assertRaises(ObjNotReady) as err:
obj.encode()
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
repr(err.exception)
obj = Integer(value)
self.assertTrue(obj.ready)
pprint(obj, big_blobs=True, with_decode_path=True)
hash(obj)
- @given(integers(), integers(), binary(), binary())
+ @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
def test_comparison(self, value1, value2, tag1, tag2):
for klass in (Integer, IntegerInherited):
obj1 = klass(value1)
Integer(values[0]).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ Integer(bounds=(values[1], values[2])).decode(
+ encode2pass(Integer(values[0]))
+ )
with self.assertRaises(BoundsError) as err:
Integer(value=values[2], bounds=(values[0], values[1]))
repr(err.exception)
Integer(values[2]).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ Integer(bounds=(values[0], values[1])).decode(
+ encode2pass(Integer(values[2]))
+ )
@given(data_strategy())
def test_call(self, d):
def test_copy(self, values):
for klass in (Integer, IntegerInherited):
obj = klass(*values)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj.specs, obj_copied.specs)
- self.assertEqual(obj._bound_min, obj_copied._bound_min)
- self.assertEqual(obj._bound_max, obj_copied._bound_max)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj.specs, obj_copied.specs)
+ self.assertEqual(obj._bound_min, obj_copied._bound_min)
+ self.assertEqual(obj._bound_max, obj_copied._bound_max)
+ self.assertEqual(obj._value, obj_copied._value)
@given(
integers(),
integers(min_value=1).map(tag_ctxc),
integers(min_value=0),
binary(max_size=5),
+ decode_path_strat,
)
- def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+ def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
for klass in (Integer, IntegerInherited):
_, _, _, _, default, optional, _, _decoded = values
obj = klass(
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
+ self.assertSequenceEqual(encode_cer(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
obj_expled_encoded = obj_expled.encode()
+ obj_expled_cer = encode_cer(obj_expled)
+ self.assertNotEqual(obj_expled_cer, obj_encoded)
+ self.assertSequenceEqual(
+ obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
+ obj_expled_encoded,
+ )
ctx_copied = deepcopy(ctx_dummy)
obj_decoded, tail = obj_expled.decode(
obj_expled_encoded + tail_junk,
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj, obj_decoded)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
def test_go_vectors_valid(self):
for data, expect in ((
(b"\x00", 0),
with self.assertRaises(ObjNotReady) as err:
obj.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
obj = BitString(value)
self.assertTrue(obj.ready)
repr(obj)
class BS(klass):
schema = _schema
+ register_class(BS)
obj = BS(
value=value,
impl=impl,
optional=optional or False,
_decoded=_decoded,
)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj.specs, obj_copied.specs)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj.specs, obj_copied.specs)
+ self.assertEqual(obj._value, obj_copied._value)
@given(
binary(),
tail_junk = d.draw(binary(max_size=5))
tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
offset = d.draw(integers(min_value=0))
+ decode_path = d.draw(decode_path_strat)
for klass in (BitString, BitStringInherited):
class BS(klass):
schema = _schema
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
+ self.assertSequenceEqual(encode_cer(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
obj_expled_encoded = obj_expled.encode()
+ obj_expled_cer = encode_cer(obj_expled)
+ self.assertNotEqual(obj_expled_cer, obj_encoded)
+ self.assertSequenceEqual(
+ obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
+ obj_expled_encoded,
+ )
ctx_copied = deepcopy(ctx_dummy)
obj_decoded, tail = obj_expled.decode(
obj_expled_encoded + tail_junk,
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
@given(integers(min_value=1, max_value=255))
def test_bad_zero_value(self, pad_size):
with self.assertRaises(DecodeError):
self.assertTrue(obj[9])
self.assertFalse(obj[17])
+ @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
@given(
integers(min_value=1, max_value=30),
lists(
),
lists(booleans(), min_size=1),
binary(),
+ decode_path_strat,
)
- def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk):
+ def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
def chunk_constructed(contents):
return (
tag_encode(form=TagFormConstructed, num=3) +
EOC
)
chunks = []
+ chunks_len_expected = []
payload_expected = b""
bit_len_expected = 0
for chunk_input in chunk_inputs:
chunks.append(BitString(chunk_input).encode())
payload_expected += chunk_input
bit_len_expected += len(chunk_input) * 8
+ chunks_len_expected.append(len(chunk_input) + 1)
else:
chunks.append(chunk_constructed(chunk_input))
payload = b"".join(chunk_input)
payload_expected += payload
bit_len_expected += len(payload) * 8
+ for c in chunk_input:
+ chunks_len_expected.append(len(c) + 1)
+ chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
chunk_last = BitString("'%s'B" % "".join(
"1" if bit else "0" for bit in chunk_last_bits
))
+ chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
payload_expected += bytes(chunk_last)
bit_len_expected += chunk_last.bit_len
encoded_indefinite = (
self.assertTrue(obj.ber_encoded)
self.assertEqual(obj.lenindef, lenindef_expected)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertEqual(obj.lenindef, lenindef_expected)
self.assertTrue(obj.bered)
self.assertEqual(len(encoded), obj.tlvlen)
+ repr(obj)
+ list(obj.pps())
+ pprint(obj, big_blobs=True, with_decode_path=True)
+
+ evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
+ encoded,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ ))
+ self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
+ for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
+ self.assertGreater(len(dp), len(decode_path))
+ self.assertEqual(obj.vlen, chunk_len_expected)
@given(
integers(min_value=0),
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.lenindef)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.lenindef)
self.assertTrue(obj.bered)
+ @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
+ @given(integers(min_value=1000, max_value=3000))
+ def test_cer(self, data_len):
+ data = urandom(data_len)
+ encoded = encode_cer(BitString(data))
+ ctx = {"bered": True}
+ self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
+ evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
+ evgens_expected = data_len // 999
+ if evgens_expected * 999 != data_len:
+ evgens_expected += 1
+ evgens_expected += 1
+ self.assertEqual(len(evgens), evgens_expected)
+ for (_, obj, _) in evgens[:-2]:
+ self.assertEqual(obj.vlen, 1000)
+ _, obj, _ = evgens[-2]
+ self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
+
@composite
def octet_string_values_strategy(draw, do_expl=False):
with self.assertRaises(ObjNotReady) as err:
obj.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
obj = OctetString(value)
self.assertTrue(obj.ready)
repr(obj)
OctetString(value).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ OctetString(bounds=(bound_min, bound_max)).decode(
+ encode2pass(OctetString(value))
+ )
value = d.draw(binary(min_size=bound_max + 1))
with self.assertRaises(BoundsError) as err:
OctetString(value=value, bounds=(bound_min, bound_max))
OctetString(value).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ OctetString(bounds=(bound_min, bound_max)).decode(
+ encode2pass(OctetString(value))
+ )
@given(data_strategy())
def test_call(self, d):
def test_copy(self, values):
for klass in (OctetString, OctetStringInherited):
obj = klass(*values)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj._bound_min, obj_copied._bound_min)
- self.assertEqual(obj._bound_max, obj_copied._bound_max)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj._bound_min, obj_copied._bound_min)
+ self.assertEqual(obj._bound_max, obj_copied._bound_max)
+ self.assertEqual(obj._value, obj_copied._value)
@given(
binary(),
integers(min_value=1).map(tag_ctxc),
integers(min_value=0),
binary(max_size=5),
+ decode_path_strat,
)
- def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+ def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
for klass in (OctetString, OctetStringInherited):
_, _, _, _, default, optional, _decoded = values
obj = klass(
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
+ self.assertSequenceEqual(encode_cer(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
obj_expled_encoded = obj_expled.encode()
+ obj_expled_cer = encode_cer(obj_expled)
+ self.assertNotEqual(obj_expled_cer, obj_encoded)
+ self.assertSequenceEqual(
+ obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
+ obj_expled_encoded,
+ )
ctx_copied = deepcopy(ctx_dummy)
obj_decoded, tail = obj_expled.decode(
obj_expled_encoded + tail_junk,
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
+ @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
@given(
integers(min_value=1, max_value=30),
lists(
max_size=3,
),
binary(),
+ decode_path_strat,
)
- def test_constructed(self, impl, chunk_inputs, junk):
+ def test_constructed(self, impl, chunk_inputs, junk, decode_path):
def chunk_constructed(contents):
return (
tag_encode(form=TagFormConstructed, num=4) +
EOC
)
chunks = []
+ chunks_len_expected = []
payload_expected = b""
for chunk_input in chunk_inputs:
if isinstance(chunk_input, binary_type):
chunks.append(OctetString(chunk_input).encode())
payload_expected += chunk_input
+ chunks_len_expected.append(len(chunk_input))
else:
chunks.append(chunk_constructed(chunk_input))
payload = b"".join(chunk_input)
payload_expected += payload
+ for c in chunk_input:
+ chunks_len_expected.append(len(c))
+ chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
encoded_indefinite = (
tag_encode(form=TagFormConstructed, num=impl) +
LENINDEF +
self.assertTrue(obj.ber_encoded)
self.assertEqual(obj.lenindef, lenindef_expected)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertEqual(obj.lenindef, lenindef_expected)
self.assertTrue(obj.bered)
self.assertEqual(len(encoded), obj.tlvlen)
+ repr(obj)
+ list(obj.pps())
+ pprint(obj, big_blobs=True, with_decode_path=True)
+
+ evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
+ encoded,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ ))
+ self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
+ for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
+ self.assertGreater(len(dp), len(decode_path))
+ self.assertEqual(obj.vlen, chunk_len_expected)
@given(
integers(min_value=0),
self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
+ @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
+ @given(integers(min_value=1001, max_value=3000))
+ def test_cer(self, data_len):
+ data = urandom(data_len)
+ encoded = encode_cer(OctetString(data))
+ ctx = {"bered": True}
+ self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
+ evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
+ evgens_expected = data_len // 1000
+ if evgens_expected * 1000 != data_len:
+ evgens_expected += 1
+ evgens_expected += 1
+ self.assertEqual(len(evgens), evgens_expected)
+ for (_, obj, _) in evgens[:-2]:
+ self.assertEqual(obj.vlen, 1000)
+ _, obj, _ = evgens[-2]
+ self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
+
@composite
def null_values_strategy(draw, do_expl=False):
list(obj.pps())
pprint(obj, big_blobs=True, with_decode_path=True)
- @given(binary(), binary())
+ @given(binary(min_size=1), binary(min_size=1))
def test_comparison(self, tag1, tag2):
for klass in (Null, NullInherited):
obj1 = klass(impl=tag1)
optional=optional or False,
_decoded=_decoded,
)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
@given(integers(min_value=1).map(tag_encode))
def test_stripped(self, tag_impl):
integers(min_value=1).map(tag_ctxc),
integers(min_value=0),
binary(max_size=5),
+ decode_path_strat,
)
- def test_symmetric(self, values, tag_expl, offset, tail_junk):
+ def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
for klass in (Null, NullInherited):
_, _, optional, _decoded = values
obj = klass(optional=optional, _decoded=_decoded)
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
+ self.assertSequenceEqual(encode_cer(obj), obj_encoded)
obj_expled = obj(expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
obj_expled_encoded = obj_expled.encode()
+ obj_expled_cer = encode_cer(obj_expled)
+ self.assertNotEqual(obj_expled_cer, obj_encoded)
+ self.assertSequenceEqual(
+ obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
+ obj_expled_encoded,
+ )
ctx_copied = deepcopy(ctx_dummy)
obj_decoded, tail = obj_expled.decode(
obj_expled_encoded + tail_junk,
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj, obj_decoded)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
@given(integers(min_value=1))
def test_invalid_len(self, l):
with self.assertRaises(InvalidLength):
with self.assertRaises(ObjNotReady) as err:
obj.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
obj = ObjectIdentifier(value)
self.assertTrue(obj.ready)
self.assertFalse(obj.ber_encoded)
pprint(obj, big_blobs=True, with_decode_path=True)
hash(obj)
- @given(oid_strategy(), oid_strategy(), binary(), binary())
+ @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
def test_comparison(self, value1, value2, tag1, tag2):
for klass in (ObjectIdentifier, ObjectIdentifierInherited):
obj1 = klass(value1)
optional=optional,
_decoded=_decoded,
)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj._value, obj_copied._value)
@settings(max_examples=LONG_TEST_MAX_EXAMPLES)
@given(
integers(min_value=1).map(tag_ctxc),
integers(min_value=0),
binary(max_size=5),
+ decode_path_strat,
)
- def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+ def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
for klass in (ObjectIdentifier, ObjectIdentifierInherited):
_, _, _, default, optional, _decoded = values
obj = klass(
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
+ self.assertSequenceEqual(encode_cer(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
obj_expled_encoded = obj_expled.encode()
+ obj_expled_cer = encode_cer(obj_expled)
+ self.assertNotEqual(obj_expled_cer, obj_encoded)
+ self.assertSequenceEqual(
+ obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
+ obj_expled_encoded,
+ )
ctx_copied = deepcopy(ctx_dummy)
obj_decoded, tail = obj_expled.decode(
obj_expled_encoded + tail_junk,
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj, obj_decoded)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
@given(
oid_strategy().map(ObjectIdentifier),
oid_strategy().map(ObjectIdentifier),
obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.bered)
with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
ObjectIdentifier().decode(tampered)
+ @given(data_strategy())
+ def test_negative_arcs(self, d):
+ oid = list(d.draw(oid_strategy()))
+ if len(oid) == 2:
+ return
+ idx = d.draw(integers(min_value=3, max_value=len(oid)))
+ oid[idx - 1] *= -1
+ if oid[idx - 1] == 0:
+ oid[idx - 1] = -1
+ with self.assertRaises(InvalidOID):
+ ObjectIdentifier(tuple(oid))
+ with self.assertRaises(InvalidOID):
+ ObjectIdentifier(".".join(str(i) for i in oid))
+
+ @given(data_strategy())
+ def test_plused_arcs(self, d):
+ oid = [str(arc) for arc in d.draw(oid_strategy())]
+ idx = d.draw(integers(min_value=0, max_value=len(oid)))
+ oid[idx - 1] = "+" + oid[idx - 1]
+ with self.assertRaises(InvalidOID):
+ ObjectIdentifier(".".join(str(i) for i in oid))
+
@given(data_strategy())
def test_nonnormalized_arcs(self, d):
arcs = d.draw(lists(
obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.bered)
with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
list(obj.pps())
pprint(obj, big_blobs=True, with_decode_path=True)
- @given(integers(), integers(), binary(), binary())
+ @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
def test_comparison(self, value1, value2, tag1, tag2):
class E(Enumerated):
schema = (
class E(Enumerated):
schema = schema_input
+ register_class(E)
obj = E(
value=value,
impl=impl,
optional=optional,
_decoded=_decoded,
)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj.specs, obj_copied.specs)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj.specs, obj_copied.specs)
@settings(max_examples=LONG_TEST_MAX_EXAMPLES)
@given(data_strategy())
offset = d.draw(integers(min_value=0))
value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
tail_junk = d.draw(binary(max_size=5))
+ decode_path = d.draw(decode_path_strat)
class E(Enumerated):
schema = schema_input
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj, obj_decoded)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
@composite
def string_values_strategy(draw, alphabet, do_expl=False):
repr(err.exception)
def text_alphabet(self):
- if self.base_klass.encoding in ("ascii", "iso-8859-1"):
- return printable + whitespace
- return None
+ return "".join(six_unichr(c) for c in six_xrange(256))
@given(booleans())
def test_optional(self, optional):
with self.assertRaises(ObjNotReady) as err:
obj.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
value = d.draw(text(alphabet=self.text_alphabet()))
obj = self.base_klass(value)
self.assertTrue(obj.ready)
self.base_klass(value).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ self.base_klass(bounds=(bound_min, bound_max)).decode(
+ encode2pass(self.base_klass(value))
+ )
value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
with self.assertRaises(BoundsError) as err:
self.base_klass(value=value, bounds=(bound_min, bound_max))
self.base_klass(value).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ self.base_klass(bounds=(bound_min, bound_max)).decode(
+ encode2pass(self.base_klass(value))
+ )
@given(data_strategy())
def test_call(self, d):
def test_copy(self, d):
values = d.draw(string_values_strategy(self.text_alphabet()))
obj = self.base_klass(*values)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj._bound_min, obj_copied._bound_min)
- self.assertEqual(obj._bound_max, obj_copied._bound_max)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj._bound_min, obj_copied._bound_min)
+ self.assertEqual(obj._bound_max, obj_copied._bound_max)
+ self.assertEqual(obj._value, obj_copied._value)
@given(data_strategy())
def test_stripped(self, d):
tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
offset = d.draw(integers(min_value=0))
tail_junk = d.draw(binary(max_size=5))
+ decode_path = d.draw(decode_path_strat)
_, _, _, _, default, optional, _decoded = values
obj = self.base_klass(
value=value,
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
tail_junk,
)
-
-class TestUTF8String(StringMixin, CommonMixin, TestCase):
- base_klass = UTF8String
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ if not getattr(self, "evgen_mode_skip_value", True):
+ self.assertEqual(obj, obj_decoded)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
cyrillic_letters = text(
)
+class TestUTF8String(StringMixin, CommonMixin, TestCase):
+ base_klass = UTF8String
+
+ @given(cyrillic_letters)
+ def test_byte_per_primitive(self, chars):
+ char = chars[0]
+ char_raw = char.encode("utf-8")
+ encoded = b"".join((
+ self.base_klass().tag_constructed,
+ LENINDEF,
+ OctetString(char_raw[:1]).encode(),
+ OctetString(char_raw[1:2]).encode(),
+ EOC,
+ ))
+ self.assertEqual(
+ self.base_klass().decod(encoded, ctx={"bered": True}),
+ char,
+ )
+
+
class UnicodeDecodeErrorMixin(object):
@given(cyrillic_letters)
def test_unicode_decode_error(self, cyrillic_text):
@given(text(alphabet=ascii_letters, min_size=1, max_size=5))
def test_non_numeric(self, non_numeric_text):
- with assertRaisesRegex(self, DecodeError, "non-numeric"):
+ with assertRaisesRegex(self, DecodeError, "alphabet value"):
self.base_klass(non_numeric_text)
@given(
self.assertEqual(err.exception.offset, offset)
self.assertEqual(err.exception.decode_path, decode_path)
+ def test_byte_per_primitive(self):
+ encoded = b"".join((
+ self.base_klass().tag_constructed,
+ LENINDEF,
+ OctetString(b"1").encode(),
+ OctetString(b"2").encode(),
+ EOC,
+ ))
+ self.assertEqual(
+ self.base_klass().decod(encoded, ctx={"bered": True}),
+ "12",
+ )
+
class TestPrintableString(
UnicodeDecodeErrorMixin,
@given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
def test_non_printable(self, non_printable_text):
- with assertRaisesRegex(self, DecodeError, "non-printable"):
+ with assertRaisesRegex(self, DecodeError, "alphabet value"):
self.base_klass(non_printable_text)
@given(
self.assertEqual(err.exception.offset, offset)
self.assertEqual(err.exception.decode_path, decode_path)
+ def test_allowable_invalid_chars(self):
+ for c, kwargs in (
+ ("*", {"allow_asterisk": True}),
+ ("&", {"allow_ampersand": True}),
+ ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
+ ):
+ s = "hello invalid"
+ obj = self.base_klass(s)
+ for prop in kwargs.keys():
+ self.assertFalse(getattr(obj, prop))
+ s += c
+ with assertRaisesRegex(self, DecodeError, "alphabet value"):
+ self.base_klass(s)
+ self.base_klass(s, **kwargs)
+ klass = self.base_klass(**kwargs)
+ obj = klass(s)
+ for prop in kwargs.keys():
+ self.assertTrue(getattr(obj, prop))
+ obj = copy(obj)
+ obj(s)
+ for prop in kwargs.keys():
+ self.assertTrue(getattr(obj, prop))
+
class TestTeletexString(
UnicodeDecodeErrorMixin,
):
base_klass = IA5String
+ def text_alphabet(self):
+ return "".join(six_unichr(c) for c in six_xrange(128))
+
+ @given(integers(min_value=128, max_value=255))
+ def test_alphabet_bad(self, code):
+ with self.assertRaises(DecodeError):
+ self.base_klass().decod(
+ self.base_klass.tag_default +
+ len_encode(1) +
+ bytes(bytearray([code])),
+ )
+
class TestGraphicString(
UnicodeDecodeErrorMixin,
):
base_klass = VisibleString
+ def text_alphabet(self):
+ return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+
def test_x690_vector(self):
obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
self.assertSequenceEqual(tail, b"")
self.assertTrue(obj.ber_encoded)
self.assertFalse(obj.lenindef)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertFalse(obj.lenindef)
self.assertTrue(obj.bered)
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.lenindef)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.ber_encoded)
self.assertTrue(obj.lenindef)
self.assertTrue(obj.bered)
+ @given(one_of((
+ integers(min_value=0, max_value=ord(" ") - 1),
+ integers(min_value=ord("~") + 1, max_value=255),
+ )))
+ def test_alphabet_bad(self, code):
+ with self.assertRaises(DecodeError):
+ self.base_klass().decod(
+ self.base_klass.tag_default +
+ len_encode(1) +
+ bytes(bytearray([code])),
+ )
+
+ @given(
+ sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
+ integers(min_value=0),
+ decode_path_strat,
+ )
+ def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
+ value, bound_min = list(sorted(ints))
+
+ class String(self.base_klass):
+ bounds = (bound_min, bound_min)
+ with self.assertRaises(DecodeError) as err:
+ String().decode(
+ self.base_klass(b"1" * value).encode(),
+ offset=offset,
+ decode_path=decode_path,
+ )
+ repr(err.exception)
+ self.assertEqual(err.exception.offset, offset)
+ self.assertEqual(err.exception.decode_path, decode_path)
+
class TestGeneralString(
UnicodeDecodeErrorMixin,
with self.assertRaises(ObjNotReady) as err:
obj.encode()
repr(err.exception)
- value = d.draw(datetimes(min_value=self.min_datetime))
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
+ value = d.draw(datetimes(
+ min_value=self.min_datetime,
+ max_value=self.max_datetime,
+ ))
obj = self.base_klass(value)
self.assertTrue(obj.ready)
repr(obj)
max_datetime=self.max_datetime,
))
obj = self.base_klass(*values)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj._value, obj_copied._value)
@given(data_strategy())
def test_stripped(self, d):
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
self.additional_symmetric_check(value, obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
omit_ms = False
min_datetime = datetime(1900, 1, 1)
max_datetime = datetime(9999, 12, 31)
+ evgen_mode_skip_value = False
def additional_symmetric_check(self, value, obj_encoded):
if value.microsecond > 0:
self.assertFalse(obj_encoded.endswith(b"0Z"))
+ def test_repr_not_ready(self):
+ unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
+ repr(GeneralizedTime())
+
def test_x690_vector_valid(self):
for data in ((
b"19920521000000Z",
datetime(2010, 1, 2, 3, 4, 5, 0),
)
+ def test_go_vectors_valid_ber(self):
+ for data in ((
+ b"20100102030405+0607",
+ b"20100102030405-0607",
+ )):
+ GeneralizedTime(data, ctx={"bered": True})
+
+ def test_utc_offsets(self):
+ """Some know equal UTC offsets
+ """
+ dts = [
+ GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
+ for data in (
+ "200101011830Z",
+ "200101012230+04",
+ "200101011130-0700",
+ "200101011500-03:30",
+ )
+ ]
+ self.assertEqual(dts[0], dts[1])
+ self.assertEqual(dts[0], dts[2])
+ self.assertEqual(dts[0], dts[3])
+
+ @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
+ @given(data_strategy())
+ def test_valid_ber(self, d):
+ min_year = 1901 if PY2 else 2
+ year = d.draw(integers(min_value=min_year, max_value=9999))
+ month = d.draw(integers(min_value=1, max_value=12))
+ day = d.draw(integers(min_value=1, max_value=28))
+ hours = d.draw(integers(min_value=0, max_value=23))
+ data = "%04d%02d%02d%02d" % (year, month, day, hours)
+ dt = datetime(year, month, day, hours)
+ fractions_sign = d.draw(sampled_from(" ,."))
+ fractions = None
+ if fractions_sign != " ":
+ fractions = random()
+ if d.draw(booleans()):
+ minutes = d.draw(integers(min_value=0, max_value=59))
+ data += "%02d" % minutes
+ dt += timedelta(seconds=60 * minutes)
+ if d.draw(booleans()):
+ seconds = d.draw(integers(min_value=0, max_value=59))
+ data += "%02d" % seconds
+ dt += timedelta(seconds=seconds)
+ if fractions is not None:
+ dt += timedelta(microseconds=10**6 * fractions)
+ elif fractions is not None:
+ dt += timedelta(seconds=60 * fractions)
+ elif fractions is not None:
+ dt += timedelta(seconds=3600 * fractions)
+ if fractions is not None:
+ data += fractions_sign + str(fractions)[2:]
+ if d.draw(booleans()):
+ data += "Z"
+ elif d.draw(booleans()):
+ offset_hour = d.draw(integers(min_value=0, max_value=13))
+ sign = 1
+ if d.draw(booleans()):
+ data += "-"
+ sign = -1
+ else:
+ data += "+"
+ dt -= timedelta(seconds=sign * 3600 * offset_hour)
+ data += "%02d" % offset_hour
+ minutes_separator = d.draw(sampled_from((None, "", ":")))
+ if minutes_separator is not None:
+ offset_minute = d.draw(integers(min_value=0, max_value=59))
+ dt -= timedelta(seconds=sign * 60 * offset_minute)
+ data += "%s%02d" % (minutes_separator, offset_minute)
+ data = data.encode("ascii")
+ data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
+ try:
+ GeneralizedTime().decod(data_der)
+ except DecodeError:
+ dered = False
+ else:
+ dered = True
+ obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
+ if dt.year > 1970:
+ self.assertEqual(
+ mktime(obj.todatetime().timetuple()),
+ mktime(dt.timetuple()),
+ )
+ elif not PY2:
+ self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
+ self.assertEqual(obj.ber_encoded, not dered)
+ self.assertEqual(obj.bered, not dered)
+ self.assertEqual(obj.ber_raw, None if dered else data)
+ self.assertEqual(obj.encode() == data_der, dered)
+ repr(obj)
+ bytes(obj)
+ str(obj)
+
+ def test_invalid_ber(self):
+ for data in ((
+ # "00010203040506.07",
+ "-0010203040506.07",
+ "0001-203040506.07",
+ "000102-3040506.07",
+ "00010203-40506.07",
+ "0001020304-506.07",
+ "000102030405-6.07",
+ "00010203040506.-7",
+ "+0010203040506.07",
+ "0001+203040506.07",
+ "000102+3040506.07",
+ "00010203+40506.07",
+ "0001020304+506.07",
+ "000102030405+6.07",
+ "00010203040506.+7",
+ " 0010203040506.07",
+ "0001 203040506.07",
+ "000102 3040506.07",
+ "00010203 40506.07",
+ "0001020304 506.07",
+ "000102030405 6.07",
+ "00010203040506. 7",
+ "001 0203040506.07",
+ "00012 03040506.07",
+ "0001023 040506.07",
+ "000102034 0506.07",
+ "00010203045 06.07",
+ "0001020304056 .07",
+ "00010203040506.7 ",
+ "00010203040506.",
+ "0001020304050607",
+
+ "-0010203040506",
+ "0001-203040506",
+ "000102-3040506",
+ "00010203-40506",
+ "0001020304-506",
+ "000102030405-6",
+ "0001+203040506",
+ "000102+3040506",
+ "00010203+40506",
+ "0001020304+506",
+ "000102030405+6",
+ " 0010203040506",
+ "0001 203040506",
+ "000102 3040506",
+ "00010203 40506",
+ "0001020304 506",
+ "000102030405 6",
+ "001 0203040506",
+ "00012 03040506",
+ "0001023 040506",
+ "000102034 0506",
+ "00010203045 06",
+ "0001020304056 ",
+
+ "-00102030405.07",
+ "0001-2030405.07",
+ "000102-30405.07",
+ "00010203-405.07",
+ "0001020304-5.07",
+ "000102030405.-7",
+ "+00102030405.07",
+ "0001+2030405.07",
+ "00010203+405.07",
+ "0001020304+5.07",
+ "000102030405.+7",
+ " 00102030405.07",
+ "0001 2030405.07",
+ "000102 30405.07",
+ "00010203 405.07",
+ "0001020304 5.07",
+ "000102030405. 7",
+ "001 02030405.07",
+ "00012 030405.07",
+ "0001023 0405.07",
+ "000102034 05.07",
+ "00010203045 .07",
+ "000102030405.7 ",
+ "000102030405.",
+
+ "-001020304.07",
+ "0001-20304.07",
+ "000102-304.07",
+ "00010203-4.07",
+ "0001020304.-7",
+ "+001020304.07",
+ "0001+20304.07",
+ "00010203+4.07",
+ "0001020304.+7",
+ " 001020304.07",
+ "0001 20304.07",
+ "000102 304.07",
+ "00010203 4.07",
+ "0001020304. 7",
+ "001 020304.07",
+ "00012 0304.07",
+ "0001023 04.07",
+ "000102034 .07",
+ "0001020304.7 ",
+ "0001020304.",
+
+ "00010203",
+ "00010203040506Y",
+ "0001010100+0001",
+ "0001010100+00:01",
+ "0001010100+01",
+
+ "00010203040506.07+15",
+ "00010203040506.07-15",
+ "00010203040506.07+14:60",
+ "00010203040506.07+1460",
+ "00010203040506.07-1460",
+ "00010203040506.07+00:60",
+ "00010203040506.07-00:60",
+
+ "00010203040506+15",
+ "00010203040506-15",
+ "00010203040506+14:60",
+ "00010203040506+1460",
+ "00010203040506-1460",
+ "00010203040506+00:60",
+ "00010203040506-00:60",
+
+ "0001020304050.07",
+ "00010203040.07",
+ "000102030.07",
+ "0001020304050",
+ "00010203040",
+ "000102030",
+ )):
+ with self.assertRaises(DecodeError):
+ GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
+ data = data.replace(".", ",")
+ with self.assertRaises(DecodeError):
+ GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
+
@given(
binary(
min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
GeneralizedTime(b"20010101000000.0000001Z")
+ def test_non_pure_integers(self):
+ for data in ((
+ # b"20000102030405Z,
+ b"+2000102030405Z",
+ b"2000+102030405Z",
+ b"200001+2030405Z",
+ b"20000102+30405Z",
+ b"2000010203+405Z",
+ b"200001020304+5Z",
+ b"20000102030405.+6Z",
+ b"20000102030405.-6Z",
+ b"_2000102030405Z",
+ b"2000_102030405Z",
+ b"200001_2030405Z",
+ b"20000102_30405Z",
+ b"2000010203_405Z",
+ b"200001020304_5Z",
+ b"20000102030405._6Z",
+ b"20000102030405.6_Z",
+ b" 2000102030405Z",
+ b"2000 102030405Z",
+ b"200001 2030405Z",
+ b"20000102 30405Z",
+ b"2000010203 405Z",
+ b"200001020304 5Z",
+ b"20000102030405. 6Z",
+ b"200 0102030405Z",
+ b"20001 02030405Z",
+ b"2000012 030405Z",
+ b"200001023 0405Z",
+ b"20000102034 05Z",
+ b"2000010203045 Z",
+ b"20000102030405.6 Z",
+ )):
+ with self.assertRaises(DecodeError):
+ GeneralizedTime(data)
+
class TestUTCTime(TimeMixin, CommonMixin, TestCase):
base_klass = UTCTime
omit_ms = True
min_datetime = datetime(2000, 1, 1)
max_datetime = datetime(2049, 12, 31)
+ evgen_mode_skip_value = False
def additional_symmetric_check(self, value, obj_encoded):
pass
+ def test_repr_not_ready(self):
+ unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
+ repr(UTCTime())
+
def test_x690_vector_valid(self):
for data in ((
b"920521000000Z",
datetime(1991, 5, 6, 23, 45, 40, 0),
)
+ def test_non_pure_integers(self):
+ for data in ((
+ # b"000102030405Z",
+ b"+10102030405Z",
+ b"00+102030405Z",
+ b"0001+2030405Z",
+ b"000102+30405Z",
+ b"00010203+405Z",
+ b"0001020304+5Z",
+ b"_10102030405Z",
+ b"00_102030405Z",
+ b"0001_2030405Z",
+ b"000102_30405Z",
+ b"00010203_405Z",
+ b"0001020304_5Z",
+ b"00010203045_Z",
+ b" 10102030405Z",
+ b"00 102030405Z",
+ b"0001 2030405Z",
+ b"000102 30405Z",
+ b"00010203 405Z",
+ b"0001020304 5Z",
+ b"1 0102030405Z",
+ b"001 02030405Z",
+ b"00012 030405Z",
+ b"0001023 0405Z",
+ b"000102034 05Z",
+ b"00010203045 Z",
+ )):
+ with self.assertRaises(DecodeError):
+ UTCTime(data)
+
+ def test_x680_vector_valid_ber(self):
+ for data, dt in ((
+ (b"8201021200Z", datetime(1982, 1, 2, 12)),
+ (b"8201020700-0500", datetime(1982, 1, 2, 12)),
+ (b"0101021200Z", datetime(2001, 1, 2, 12)),
+ (b"0101020700-0500", datetime(2001, 1, 2, 12)),
+ )):
+ data_der = UTCTime.tag_default + len_encode(len(data)) + data
+ obj = UTCTime().decod(data_der, ctx={"bered": True})
+ self.assertEqual(obj, dt)
+ self.assertEqual(obj.todatetime(), dt)
+ self.assertTrue(obj.ber_encoded)
+ self.assertTrue(obj.bered)
+ self.assertEqual(obj.ber_raw, data)
+ self.assertNotEqual(obj.encode(), data_der)
+ repr(obj)
+
+ def test_go_vectors_valid_ber(self):
+ for data in ((
+ b"910506164540-0700",
+ b"910506164540+0730",
+ b"9105062345Z",
+ b"5105062345Z",
+ )):
+ data = UTCTime.tag_default + len_encode(len(data)) + data
+ obj = UTCTime().decod(data, ctx={"bered": True})
+ self.assertTrue(obj.ber_encoded)
+ self.assertTrue(obj.bered)
+ self.assertNotEqual(obj.encode(), data)
+ repr(obj)
+
+ @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
+ @given(data_strategy())
+ def test_valid_ber(self, d):
+ year = d.draw(integers(min_value=0, max_value=99))
+ month = d.draw(integers(min_value=1, max_value=12))
+ day = d.draw(integers(min_value=1, max_value=28))
+ hours = d.draw(integers(min_value=0, max_value=23))
+ minute = d.draw(integers(min_value=0, max_value=59))
+ data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
+ dt = datetime(
+ year + (2000 if year < 50 else 1900),
+ month,
+ day,
+ hours,
+ minute,
+ )
+ dered = False
+ if d.draw(booleans()):
+ dered = True
+ seconds = d.draw(integers(min_value=0, max_value=59))
+ data += "%02d" % seconds
+ dt += timedelta(seconds=seconds)
+ if d.draw(booleans()):
+ data += "Z"
+ else:
+ dered = False
+ offset_hour = d.draw(integers(min_value=0, max_value=13))
+ offset_minute = d.draw(integers(min_value=0, max_value=59))
+ offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
+ if d.draw(booleans()):
+ dt += offset
+ data += "-"
+ else:
+ dt -= offset
+ data += "+"
+ data += "%02d%02d" % (offset_hour, offset_minute)
+ data = data.encode("ascii")
+ data_der = UTCTime.tag_default + len_encode(len(data)) + data
+ obj = UTCTime().decod(data_der, ctx={"bered": True})
+ self.assertEqual(obj, dt)
+ self.assertEqual(obj.todatetime(), dt)
+ self.assertEqual(obj.ber_encoded, not dered)
+ self.assertEqual(obj.bered, not dered)
+ self.assertEqual(obj.ber_raw, None if dered else data)
+ self.assertEqual(obj.encode() == data_der, dered)
+ repr(obj)
+ bytes(obj)
+ str(obj)
+
+ def test_invalid_ber(self):
+ for data in ((
+ # b"0001020304Z",
+ b"-101020304Z",
+ b"00-1020304Z",
+ b"0001-20304Z",
+ b"000102-304Z",
+ b"000102-104Z",
+ b"00000203-4Z",
+ b"+101020304Z",
+ b"00+1020304Z",
+ b"0001+20304Z",
+ b"000102+304Z",
+ b"000102+104Z",
+ b"00000203+4Z",
+ b" 101020304Z",
+ b"00 1020304Z",
+ b"0001 20304Z",
+ b"000102 304Z",
+ b"000102 104Z",
+ b"00000203 4Z",
+ b"1 01020304Z",
+ b"001 020304Z",
+ b"00012 0304Z",
+ b"0001023 04Z",
+ b"0001021 04Z",
+ b"000002034 Z",
+ b"0013020304Z",
+ b"0001000304Z",
+ b"0001320304Z",
+ b"0001022404Z",
+ b"0001020360Z",
+ b"0002300304Z",
+ b"0001020304",
+ b"0001020304T",
+ b"0001020304+",
+ b"0001020304-",
+ b"0001020304+0",
+ b"0001020304+00",
+ b"0001020304+000",
+ b"0001020304+000Z",
+ b"0001020304+0000Z",
+ b"0001020304+-101",
+ b"0001020304+01-1",
+ b"0001020304+0060",
+ b"0001020304+1401",
+ b"5001010000+0001",
+ b"000102030Z",
+ b"0001020Z",
+ )):
+ with self.assertRaises(DecodeError):
+ UTCTime(data, ctx={"bered": True})
+ data = data[:8] + data[8+2:]
+ with self.assertRaises(DecodeError):
+ UTCTime(data, ctx={"bered": True})
+
+ for data in ((
+ # b"000102030405Z",
+ b"-10102030405Z",
+ b"00-102030405Z",
+ b"0001-2030405Z",
+ b"000102-30405Z",
+ b"000102-10405Z",
+ b"00000203-405Z",
+ b"0000020304-5Z",
+ b"+10102030405Z",
+ b"00+102030405Z",
+ b"0001+2030405Z",
+ b"000102+30405Z",
+ b"000102+10405Z",
+ b"00000203+405Z",
+ b"0000020304+5Z",
+ b" 10102030405Z",
+ b"00 102030405Z",
+ b"0001 2030405Z",
+ b"000102 30405Z",
+ b"000102 10405Z",
+ b"00000203 405Z",
+ b"0000020304 5Z",
+ b"1 0102030405Z",
+ b"001 02030405Z",
+ b"00012 030405Z",
+ b"0001023 0405Z",
+ b"0001021 0405Z",
+ b"000002034 05Z",
+ b"00000203045 Z",
+ b"001302030405Z",
+ b"000100030405Z",
+ b"000132030405Z",
+ b"000102240405Z",
+ b"000102036005Z",
+ b"000230030405Z",
+ b"000102030460Z",
+ b"000102030405",
+ b"000102030405T",
+ b"000102030405+",
+ b"000102030405-",
+ b"000102030405+0",
+ b"000102030405+00",
+ b"000102030405+000",
+ b"000102030405+000Z",
+ b"000102030405+0000Z",
+ b"000102030405+-101",
+ b"000102030405+01-1",
+ b"000102030405+0060",
+ b"000102030405+1401",
+ b"500101000002+0003",
+ )):
+ with self.assertRaises(DecodeError):
+ UTCTime(data, ctx={"bered": True})
+
@given(integers(min_value=0, max_value=49))
def test_pre50(self, year):
self.assertEqual(
)
+@composite
+def tlv_value_strategy(draw):
+ tag_num = draw(integers(min_value=1))
+ data = draw(binary())
+ return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
+
+
@composite
def any_values_strategy(draw, do_expl=False):
- value = draw(one_of(none(), binary()))
+ value = draw(one_of(none(), tlv_value_strategy()))
expl = None
if do_expl:
expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
obj = Any(optional=optional)
self.assertEqual(obj.optional, optional)
- @given(binary())
+ @given(tlv_value_strategy())
def test_ready(self, value):
obj = Any()
self.assertFalse(obj.ready)
with self.assertRaises(ObjNotReady) as err:
obj.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
obj = Any(value)
self.assertTrue(obj.ready)
repr(obj)
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertSequenceEqual(obj.encode(), integer_encoded)
- @given(binary(), binary())
+ @given(tlv_value_strategy(), tlv_value_strategy())
def test_comparison(self, value1, value2):
for klass in (Any, AnyInherited):
obj1 = klass(value1)
def test_copy(self, values):
for klass in (Any, AnyInherited):
obj = klass(*values)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj._value, obj_copied._value)
@given(binary().map(OctetString))
def test_stripped(self, value):
obj.decode(obj.encode()[:-1])
@given(
- binary(),
+ tlv_value_strategy(),
integers(min_value=1).map(tag_ctxc),
)
def test_stripped_expl(self, value, tag_expl):
integers(min_value=1).map(tag_ctxc),
integers(min_value=0),
binary(max_size=5),
+ decode_path_strat,
)
- def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+ def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
for klass in (Any, AnyInherited):
_, _, optional, _decoded = values
obj = klass(value=value, optional=optional, _decoded=_decoded)
list(obj.pps())
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
+ tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
+ self.assertEqual(obj.tag_order, (tag_class, tag_num))
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
+ tag_class, _, tag_num = tag_decode(tag_expl)
+ self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 1)
+ _decode_path, obj, tail = evgens[0]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
@given(
integers(min_value=1).map(tag_ctxc),
integers(min_value=0, max_value=3),
self.assertTrue(obj.lenindef)
self.assertFalse(obj.ber_encoded)
self.assertTrue(obj.bered)
- obj = obj.copy()
+ obj = copy(obj)
self.assertTrue(obj.lenindef)
self.assertFalse(obj.ber_encoded)
self.assertTrue(obj.bered)
with self.assertRaises(ObjNotReady) as err:
obj.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(obj)
obj["whatever"] = Boolean()
self.assertFalse(obj.ready)
repr(obj)
class Wahl(self.base_klass):
schema = _schema
+ register_class(Wahl)
obj = Wahl(
value=value,
expl=expl,
optional=optional or False,
_decoded=_decoded,
)
- obj_copied = obj.copy()
- self.assertIsNone(obj.tag)
- self.assertIsNone(obj_copied.tag)
- # hack for assert_copied_basic_fields
- obj.tag = "whatever"
- obj_copied.tag = "whatever"
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj._value, obj_copied._value)
- self.assertEqual(obj.specs, obj_copied.specs)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assertIsNone(obj.tag)
+ self.assertIsNone(obj_copied.tag)
+ # hack for assert_copied_basic_fields
+ obj.tag = "whatever"
+ obj_copied.tag = "whatever"
+ self.assert_copied_basic_fields(obj, obj_copied)
+ obj.tag = None
+ self.assertEqual(obj._value, obj_copied._value)
+ self.assertEqual(obj.specs, obj_copied.specs)
@given(booleans())
def test_stripped(self, value):
tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
offset = d.draw(integers(min_value=0))
tail_junk = d.draw(binary(max_size=5))
+ decode_path = d.draw(decode_path_strat)
class Wahl(self.base_klass):
schema = _schema
list(obj.pps())
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
+ self.assertEqual(obj.tag_order, obj.value.tag_order)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
+ tag_class, _, tag_num = tag_decode(tag_expl)
+ self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
repr(obj_expled)
list(obj_expled.pps())
pprint(obj_expled, big_blobs=True, with_decode_path=True)
tail_junk,
)
+ evgens = list(obj_expled.decode_evgen(
+ obj_expled_encoded + tail_junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx_copied,
+ ))
+ self.assertEqual(len(evgens), 2)
+ _decode_path, obj, tail = evgens[0]
+ self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
+ _decode_path, obj, tail = evgens[1]
+ self.assertSequenceEqual(tail, tail_junk)
+ self.assertEqual(_decode_path, decode_path)
+ self.assertEqual(obj.expl_offset, offset)
+ repr(obj)
+ list(obj.pps())
+
@given(integers())
def test_set_get(self, value):
class Wahl(Choice):
with self.assertRaises(ObjNotReady) as err:
seq.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(seq)
for name, value in non_ready.items():
seq[name] = Boolean(value)
self.assertTrue(seq.ready)
def test_copy(self, d):
class SeqInherited(self.base_klass):
pass
+ register_class(SeqInherited)
for klass in (self.base_klass, SeqInherited):
values = d.draw(seq_values_strategy(seq_klass=klass))
obj = klass(*values)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj.specs, obj_copied.specs)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj.specs, obj_copied.specs)
+ self.assertEqual(obj._value, obj_copied._value)
@given(data_strategy())
def test_stripped(self, d):
with self.assertRaises(NotEnoughData):
seq.decode(seq.encode()[:-1])
- @given(binary(min_size=2))
- def test_non_tag_mismatch_raised(self, junk):
+ @given(integers(min_value=3), binary(min_size=2))
+ def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
+ junk = tag_encode(junk_tag_num) + junk
try:
_, _, len_encoded = tag_strip(memoryview(junk))
len_decode(len_encoded)
def test_symmetric(self, d):
seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
tail_junk = d.draw(binary(max_size=5))
+ decode_path = d.draw(decode_path_strat)
self.assertTrue(seq.ready)
self.assertFalse(seq.decoded)
self._assert_expects(seq, expects)
pprint(seq, big_blobs=True, with_decode_path=True)
self.assertTrue(seq.ready)
seq_encoded = seq.encode()
+ self.assertEqual(encode2pass(seq), seq_encoded)
+ seq_encoded_cer = encode_cer(seq)
+ self.assertNotEqual(seq_encoded_cer, seq_encoded)
+ self.assertSequenceEqual(
+ seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
+ seq_encoded,
+ )
seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
self.assertFalse(seq_decoded.lenindef)
self.assertFalse(seq_decoded.ber_encoded)
t, _, lv = tag_strip(seq_encoded)
_, _, v = len_decode(lv)
seq_encoded_lenindef = t + LENINDEF + v + EOC
+ with self.assertRaises(DecodeError):
+ seq.decode(seq_encoded_lenindef)
ctx_copied = deepcopy(ctx_dummy)
ctx_copied["bered"] = True
seq_decoded_lenindef, tail_lenindef = seq.decode(
self.assertDictEqual(ctx_copied, ctx_dummy)
self.assertTrue(seq_decoded_lenindef.lenindef)
self.assertTrue(seq_decoded_lenindef.bered)
- seq_decoded_lenindef = seq_decoded_lenindef.copy()
+ seq_decoded_lenindef = copy(seq_decoded_lenindef)
self.assertTrue(seq_decoded_lenindef.lenindef)
self.assertTrue(seq_decoded_lenindef.bered)
with self.assertRaises(DecodeError):
obj.encode(),
)
+ evgens = list(seq.decode_evgen(
+ encoded + decoded_tail,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ ))
+ self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
+ for _decode_path, obj, _ in evgens[:-1]:
+ self.assertEqual(_decode_path[:-1], decode_path)
+ repr(obj)
+ list(obj.pps())
+ _decode_path, obj, tail = evgens[-1]
+ self.assertEqual(_decode_path, decode_path)
+ repr(obj)
+ list(obj.pps())
+
assert_exceeding_data(
self,
lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
self.assertTrue(seq.ready)
seq_encoded = seq.encode()
+ self.assertEqual(encode2pass(seq), seq_encoded)
seq_decoded, tail = seq.decode(seq_encoded)
self.assertEqual(tail, b"")
self.assertTrue(seq.ready)
min_size=1,
)).items())
tags = [tag_encode(tag) for tag in d.draw(sets(
- integers(min_value=0),
+ integers(min_value=1),
min_size=len(_schema),
max_size=len(_schema),
))]
+ class Wahl(Choice):
+ schema = (("int", Integer()),)
+
class SeqWithoutDefault(self.base_klass):
schema = [
- (n, Integer(impl=t))
+ (n, Wahl(expl=t))
for (n, _), t in zip(_schema, tags)
]
seq_without_default = SeqWithoutDefault()
for name, value in _schema:
- seq_without_default[name] = Integer(value)
+ seq_without_default[name] = Wahl(("int", Integer(value)))
seq_encoded = seq_without_default.encode()
+ seq_without_default.decode(seq_encoded)
+ self.assertEqual(
+ len(list(seq_without_default.decode_evgen(seq_encoded))),
+ len(_schema) * 2 + 1,
+ )
class SeqWithDefault(self.base_klass):
schema = [
- (n, Integer(default=v, impl=t))
+ (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
for (n, v), t in zip(_schema, tags)
]
seq_with_default = SeqWithDefault()
with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
seq_with_default.decode(seq_encoded)
+ with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
+ list(seq_with_default.decode_evgen(seq_encoded))
for ctx in ({"bered": True}, {"allow_default_values": True}):
seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
self.assertTrue(seq_decoded.ber_encoded)
self.assertTrue(seq_decoded.bered)
- seq_decoded = seq_decoded.copy()
+ seq_decoded = copy(seq_decoded)
self.assertTrue(seq_decoded.ber_encoded)
self.assertTrue(seq_decoded.bered)
for name, value in _schema:
self.assertEqual(seq_decoded[name], seq_with_default[name])
- self.assertEqual(seq_decoded[name], value)
+ self.assertEqual(seq_decoded[name].value, value)
+ self.assertEqual(
+ len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
+ len(_schema) + 1,
+ )
+
+ seq_without_default = SeqWithoutDefault()
+ for name, value in _schema:
+ seq_without_default[name] = Wahl(("int", Integer(value + 1)))
+ seq_encoded = seq_without_default.encode()
+ seq_with_default.decode(seq_encoded)
+ self.assertEqual(
+ len(list(seq_with_default.decode_evgen(seq_encoded))),
+ len(_schema) + 1,
+ )
@given(data_strategy())
def test_missing_from_spec(self, d):
names = list(d.draw(sets(text_letters(), min_size=2)))
tags = [tag_encode(tag) for tag in d.draw(sets(
- integers(min_value=0),
+ integers(min_value=1),
min_size=len(names),
max_size=len(names),
))]
seq_missing = SeqMissing()
with self.assertRaises(TagMismatch):
seq_missing.decode(seq_encoded)
+ with self.assertRaises(TagMismatch):
+ list(seq_missing.decode_evgen(seq_encoded))
def test_bered(self):
class Seq(self.base_klass):
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
- decoded = decoded.copy()
+ decoded = copy(decoded)
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
with self.assertRaises(DecodeError):
Seq().decode(encoded)
+ with self.assertRaises(DecodeError):
+ list(Seq().decode_evgen(encoded))
+ list(Seq().decode_evgen(encoded, ctx={"bered": True}))
decoded, _ = Seq().decode(encoded, ctx={"bered": True})
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
- decoded = decoded.copy()
+ decoded = copy(decoded)
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
@settings(max_examples=LONG_TEST_MAX_EXAMPLES)
@given(data_strategy())
def test_sorted(self, d):
- tags = [
- tag_encode(tag) for tag in
- d.draw(sets(integers(min_value=1), min_size=1, max_size=10))
- ]
+ class DummySeq(Sequence):
+ schema = (("null", Null()),)
+
+ tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
+ _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
+ assume(any(i > dummy_seq_tag_num for i in tag_nums))
+ tag_nums -= set([dummy_seq_tag_num])
+ _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
+ _schema.append(("seq", DummySeq()))
class Seq(Set):
- schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
+ schema = d.draw(permutations(_schema))
seq = Seq()
- for name, _ in Seq.schema:
- seq[name] = OctetString(b"")
+ for name, _ in _schema:
+ if name != "seq":
+ seq[name] = OctetString(name.encode("ascii"))
+ seq["seq"] = DummySeq((("null", Null()),))
+
seq_encoded = seq.encode()
seq_decoded, _ = seq.decode(seq_encoded)
+ seq_encoded_expected = []
+ for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
+ if tag_num == dummy_seq_tag_num:
+ seq_encoded_expected.append(seq["seq"].encode())
+ else:
+ seq_encoded_expected.append(seq[str(tag_num)].encode())
self.assertSequenceEqual(
seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
- b"".join(sorted([seq[name].encode() for name, _ in Seq.schema])),
+ b"".join(seq_encoded_expected),
)
- @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
- @given(data_strategy())
- def test_unsorted(self, d):
- tags = [
- tag_encode(tag) for tag in
- d.draw(sets(integers(min_value=1), min_size=2, max_size=5))
- ]
- tags = d.draw(permutations(tags))
- assume(tags != sorted(tags))
- encoded = b"".join(OctetString(t, impl=t).encode() for t in tags)
+ encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
+ encoded += seq["seq"].encode()
seq_encoded = b"".join((
Set.tag_default,
len_encode(len(encoded)),
encoded,
))
-
- class Seq(Set):
- schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
- seq = Seq()
with assertRaisesRegex(self, DecodeError, "unordered SET"):
seq.decode(seq_encoded)
for ctx in ({"bered": True}, {"allow_unordered_set": True}):
seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
self.assertTrue(seq_decoded.ber_encoded)
self.assertTrue(seq_decoded.bered)
- seq_decoded = seq_decoded.copy()
+ seq_decoded = copy(seq_decoded)
self.assertTrue(seq_decoded.ber_encoded)
self.assertTrue(seq_decoded.bered)
- self.assertSequenceEqual(
- [bytes(seq_decoded[str(i)]) for i, t in enumerate(tags)],
- tags,
+
+ def test_same_value_twice(self):
+ class Seq(Set):
+ schema = (
+ ("bool", Boolean()),
+ ("int", Integer()),
)
+ encoded = b"".join((
+ Integer(123).encode(),
+ Integer(234).encode(),
+ Boolean(True).encode(),
+ ))
+ encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
+ with self.assertRaises(TagMismatch):
+ Seq().decod(encoded, ctx={"allow_unordered_set": True})
+
@composite
def seqof_values_strategy(draw, schema=None, do_expl=False):
with assertRaisesRegex(self, ValueError, "schema must be specified"):
self.base_klass.__mro__[1]()
- @given(booleans(), booleans(), binary(), binary())
+ @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
def test_comparison(self, value1, value2, tag1, tag2):
class SeqOf(self.base_klass):
schema = Boolean()
with self.assertRaises(ObjNotReady) as err:
seqof.encode()
repr(err.exception)
+ with self.assertRaises(ObjNotReady) as err:
+ encode2pass(seqof)
for i, value in enumerate(values):
self.assertEqual(seqof[i], value)
if not seqof[i].ready:
SeqOf(value).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ SeqOf(bounds=(bound_min, bound_max)).decode(
+ encode2pass(SeqOf(value))
+ )
value = [Boolean(True)] * d.draw(integers(
min_value=bound_max + 1,
max_value=bound_max + 10,
SeqOf(value).encode()
)
repr(err.exception)
+ with assertRaisesRegex(self, DecodeError, "bounds") as err:
+ SeqOf(bounds=(bound_min, bound_max)).decode(
+ encode2pass(SeqOf(value))
+ )
@given(integers(min_value=1, max_value=10))
def test_out_of_bounds(self, bound_max):
class SeqOf(self.base_klass):
schema = _schema
+ register_class(SeqOf)
obj = SeqOf(
value=value,
bounds=bounds,
optional=optional or False,
_decoded=_decoded,
)
- obj_copied = obj.copy()
- self.assert_copied_basic_fields(obj, obj_copied)
- self.assertEqual(obj._bound_min, obj_copied._bound_min)
- self.assertEqual(obj._bound_max, obj_copied._bound_max)
- self.assertEqual(obj._value, obj_copied._value)
+ for copy_func in copy_funcs:
+ obj_copied = copy_func(obj)
+ self.assert_copied_basic_fields(obj, obj_copied)
+ self.assertEqual(obj._bound_min, obj_copied._bound_min)
+ self.assertEqual(obj._bound_max, obj_copied._bound_max)
+ self.assertEqual(obj._value, obj_copied._value)
@given(
lists(binary()),
integers(min_value=1).map(tag_ctxc),
integers(min_value=0),
binary(max_size=5),
+ decode_path_strat,
)
- def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+ def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
_, _, _, _, _, default, optional, _decoded = values
class SeqOf(self.base_klass):
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertFalse(obj.expled)
obj_encoded = obj.encode()
+ self.assertEqual(encode2pass(obj), obj_encoded)
+ obj_encoded_cer = encode_cer(obj)
+ self.assertNotEqual(obj_encoded_cer, obj_encoded)
+ self.assertSequenceEqual(
+ obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
+ obj_encoded,
+ )
obj_expled = obj(value, expl=tag_expl)
self.assertTrue(obj_expled.expled)
repr(obj_expled)
t, _, lv = tag_strip(obj_encoded)
_, _, v = len_decode(lv)
obj_encoded_lenindef = t + LENINDEF + v + EOC
+ with self.assertRaises(DecodeError):
+ obj.decode(obj_encoded_lenindef)
obj_decoded_lenindef, tail_lenindef = obj.decode(
obj_encoded_lenindef + tail_junk,
ctx={"bered": True},
)
self.assertTrue(obj_decoded_lenindef.lenindef)
self.assertTrue(obj_decoded_lenindef.bered)
- obj_decoded_lenindef = obj_decoded_lenindef.copy()
+ obj_decoded_lenindef = copy(obj_decoded_lenindef)
self.assertTrue(obj_decoded_lenindef.lenindef)
self.assertTrue(obj_decoded_lenindef.bered)
repr(obj_decoded_lenindef)
with self.assertRaises(DecodeError):
obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
+ evgens = list(obj.decode_evgen(
+ obj_encoded_lenindef + tail_junk,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ ))
+ self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
+ for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
+ self.assertEqual(_decode_path, decode_path + (str(i),))
+ repr(obj)
+ list(obj.pps())
+ _decode_path, obj, tail = evgens[-1]
+ self.assertEqual(_decode_path, decode_path)
+ repr(obj)
+ list(obj.pps())
+
assert_exceeding_data(
self,
lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
- decoded = decoded.copy()
+ decoded = copy(decoded)
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
- decoded = decoded.copy()
+ decoded = copy(decoded)
self.assertFalse(decoded.ber_encoded)
self.assertFalse(decoded.lenindef)
self.assertTrue(decoded.bered)
self.assertEqual(obj1, obj2)
self.assertSequenceEqual(list(obj1), list(obj2))
+ def test_iterator_pickling(self):
+ class SeqOf(SequenceOf):
+ schema = Integer()
+ register_class(SeqOf)
+ seqof = SeqOf()
+ pickle_dumps(seqof)
+ seqof = seqof(iter(six_xrange(10)))
+ with assertRaisesRegex(self, ValueError, "iterator"):
+ pickle_dumps(seqof)
+
+ def test_iterator_bounds(self):
+ class SeqOf(SequenceOf):
+ schema = Integer()
+ bounds = (10, 20)
+ seqof = None
+
+ def gen(n):
+ for i in six_xrange(n):
+ yield Integer(i)
+ for n in (9, 21):
+ seqof = SeqOf(gen(n))
+ self.assertTrue(seqof.ready)
+ with self.assertRaises(BoundsError):
+ seqof.encode()
+ self.assertFalse(seqof.ready)
+ seqof = seqof(gen(n))
+ self.assertTrue(seqof.ready)
+ with self.assertRaises(BoundsError):
+ encode_cer(seqof)
+ self.assertFalse(seqof.ready)
+
+ def test_iterator_twice(self):
+ class SeqOf(SequenceOf):
+ schema = Integer()
+ bounds = (1, float("+inf"))
+
+ def gen():
+ for i in six_xrange(10):
+ yield Integer(i)
+ seqof = SeqOf(gen())
+ self.assertTrue(seqof.ready)
+ seqof.encode()
+ self.assertFalse(seqof.ready)
+ register_class(SeqOf)
+ pickle_dumps(seqof)
+
+ def test_iterator_2pass(self):
+ class SeqOf(SequenceOf):
+ schema = Integer()
+ bounds = (1, float("+inf"))
+
+ def gen():
+ for i in six_xrange(10):
+ yield Integer(i)
+ seqof = SeqOf(gen())
+ self.assertTrue(seqof.ready)
+ _, state = seqof.encode1st()
+ self.assertFalse(seqof.ready)
+ seqof = seqof(gen())
+ self.assertTrue(seqof.ready)
+ buf = BytesIO()
+ seqof.encode2nd(buf.write, iter(state))
+ self.assertSequenceEqual(
+ [int(i) for i in seqof.decod(buf.getvalue())],
+ list(gen()),
+ )
+
+ def test_non_ready_bound_min(self):
+ class SeqOf(SequenceOf):
+ schema = Integer()
+ bounds = (1, float("+inf"))
+ seqof = SeqOf()
+ self.assertFalse(seqof.ready)
+
class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
class SeqOf(SetOf):
seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
self.assertTrue(seq_decoded.ber_encoded)
self.assertTrue(seq_decoded.bered)
- seq_decoded = seq_decoded.copy()
+ seq_decoded = copy(seq_decoded)
self.assertTrue(seq_decoded.ber_encoded)
self.assertTrue(seq_decoded.bered)
self.assertSequenceEqual(
min_size=len(value_names),
max_size=len(value_names),
))
- _schema = [
- ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
- oid: Integer() for oid in oids[:-1]
- }),))),
- ]
- for i, value_name in enumerate(value_names):
- _schema.append((value_name, Any(expl=tag_ctxp(i))))
+ for definable_class in (Any, OctetString, BitString):
+ _schema = [
+ ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
+ oid: Integer() for oid in oids[:-1]
+ }),))),
+ ]
+ for i, value_name in enumerate(value_names):
+ _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
- class Seq(Sequence):
- schema = _schema
- seq = Seq()
- for value_name, value in zip(value_names, values):
- seq[value_name] = Any(Integer(value).encode())
- seq["type"] = oid_chosen
- seq, _ = Seq().decode(seq.encode())
- for value_name in value_names:
- if value_name == value_name_chosen:
- continue
- self.assertIsNone(seq[value_name].defined)
- if value_name_chosen in oids[:-1]:
- self.assertIsNotNone(seq[value_name_chosen].defined)
- self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
- self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
- repr(seq)
- list(seq.pps())
- pprint(seq, big_blobs=True, with_decode_path=True)
+ class Seq(Sequence):
+ schema = _schema
+ seq = Seq()
+ for value_name, value in zip(value_names, values):
+ seq[value_name] = definable_class(Integer(value).encode())
+ seq["type"] = oid_chosen
+ seq, _ = Seq().decode(seq.encode())
+ for value_name in value_names:
+ if value_name == value_name_chosen:
+ continue
+ self.assertIsNone(seq[value_name].defined)
+ if value_name_chosen in oids[:-1]:
+ self.assertIsNotNone(seq[value_name_chosen].defined)
+ self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
+ self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
+ repr(seq)
+ list(seq.pps())
+ pprint(seq, big_blobs=True, with_decode_path=True)
class TestDefinesByPath(TestCase):
(type_integered, Integer(234)),
)
for t, v in pairs_input:
- pair = Pair()
- pair["type"] = t
- pair["value"] = PairValue((Any(v),))
- pairs.append(pair)
+ pairs.append(Pair((
+ ("type", t),
+ ("value", PairValue((Any(v),))),
+ )))
seq_inner = SeqInner()
seq_inner["typeInner"] = type_innered
seq_inner["valueInner"] = Any(pairs)
decoded, _ = Outer().decode(outer.encode())
self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
+ def test_remaining_data(self):
+ oid = ObjectIdentifier("1.2.3")
+
+ class Seq(Sequence):
+ schema = (
+ ("oid", ObjectIdentifier(defines=((("tgt",), {
+ oid: Integer(),
+ }),))),
+ ("tgt", OctetString()),
+ )
+
+ seq = Seq((
+ ("oid", oid),
+ ("tgt", OctetString(Integer(123).encode() + b"junk")),
+ ))
+ with assertRaisesRegex(self, DecodeError, "remaining data"):
+ Seq().decode(seq.encode())
+
+ def test_remaining_data_seqof(self):
+ oid = ObjectIdentifier("1.2.3")
+
+ class SeqOf(SetOf):
+ schema = OctetString()
+
+ class Seq(Sequence):
+ schema = (
+ ("oid", ObjectIdentifier(defines=((("tgt",), {
+ oid: Integer(),
+ }),))),
+ ("tgt", SeqOf()),
+ )
+
+ seq = Seq((
+ ("oid", oid),
+ ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
+ ))
+ with assertRaisesRegex(self, DecodeError, "remaining data"):
+ Seq().decode(seq.encode())
+
class TestAbsDecodePath(TestCase):
@given(
lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
)
def test_concat(self, decode_path, rel_path):
- self.assertSequenceEqual(
- abs_decode_path(decode_path, rel_path),
- decode_path + rel_path,
- )
+ dp = abs_decode_path(decode_path, rel_path)
+ self.assertSequenceEqual(dp, decode_path + rel_path)
+ repr(dp)
@given(
lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
self.assertTrue(decoded.ber_encoded)
self.assertTrue(decoded.bered)
- decoded = decoded.copy()
+ decoded = copy(decoded)
self.assertTrue(decoded.ber_encoded)
self.assertTrue(decoded.bered)
decoded, _ = seq.decode(raw, ctx={"bered": True})
self.assertTrue(decoded.ber_encoded)
self.assertTrue(decoded.bered)
- decoded = decoded.copy()
+ decoded = copy(decoded)
self.assertTrue(decoded.ber_encoded)
self.assertTrue(decoded.bered)
class TestX690PrefixedType(TestCase):
- def runTest(self):
+ def test_1(self):
self.assertSequenceEqual(
VisibleString("Jones").encode(),
hexdec("1A054A6F6E6573"),
)
+
+ def test_2(self):
self.assertSequenceEqual(
VisibleString(
"Jones",
).encode(),
hexdec("43054A6F6E6573"),
)
+
+ def test_3(self):
self.assertSequenceEqual(
Any(
VisibleString(
).encode(),
hexdec("A20743054A6F6E6573"),
)
+
+ def test_4(self):
self.assertSequenceEqual(
OctetString(
VisibleString(
).encode(),
hexdec("670743054A6F6E6573"),
)
+
+ def test_5(self):
self.assertSequenceEqual(
VisibleString("Jones", impl=tag_ctxp(2)).encode(),
hexdec("82054A6F6E6573"),
with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
Integer(expl=expl).decode(raw)
Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
+
+
+class TestPickleDifferentVersion(TestCase):
+ def runTest(self):
+ pickled = pickle_dumps(Integer(123), pickle_proto)
+ import pyderasn
+ version_orig = pyderasn.__version__
+ pyderasn.__version__ += "different"
+ with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
+ pickle_loads(pickled)
+ pyderasn.__version__ = version_orig
+ pickle_loads(pickled)
+
+
+class TestCERSetOrdering(TestCase):
+ def test_vectors(self):
+ """Taken from X.690-201508
+ """
+ class B(Choice):
+ schema = (
+ ("c", Integer(impl=tag_ctxp(2))),
+ ("d", Integer(impl=tag_ctxp(4))),
+ )
+
+ class F(Choice):
+ schema = (
+ ("g", Integer(impl=tag_ctxp(5))),
+ ("h", Integer(impl=tag_ctxp(6))),
+ )
+
+ class I(Choice):
+ schema = (
+ ("j", Integer(impl=tag_ctxp(0))),
+ )
+
+ class E(Choice):
+ schema = (
+ ("f", F()),
+ ("i", I()),
+ )
+
+ class A(Set):
+ schema = (
+ ("a", Integer(impl=tag_ctxp(3))),
+ ("b", B(expl=tag_ctxc(1))),
+ ("e", E()),
+ )
+
+ a = A((
+ ("a", Integer(123)),
+ ("b", B(("d", Integer(234)))),
+ ("e", E(("f", F(("g", Integer(345)))))),
+ ))
+ order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
+ self.assertSequenceEqual(
+ [i.__class__.__name__ for i in order],
+ ("E", "B", "Integer"),
+ )