# 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
from datetime import datetime
from datetime import timedelta
from importlib import import_module
+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 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 Choice
from pyderasn import DecodeError
from pyderasn import DecodePathDefBy
+from pyderasn import encode_cer
from pyderasn import Enumerated
from pyderasn import EOC
from pyderasn import EOC_LEN
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(min_size=1))
def test_expl_inherited(self, 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
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.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_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.hexdecode(
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)
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(
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.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),
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.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 = (
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),
decode_path_strat,
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):
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.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 +
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),
decode_path_strat,
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):
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.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):
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.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),
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
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):
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,
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):
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,
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:
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
)
+@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)
pprint(obj, big_blobs=True, with_decode_path=True)
self.assertSequenceEqual(obj.encode(), integer_encoded)
- @given(binary(min_size=1), binary(min_size=1))
+ @given(tlv_value_strategy(), tlv_value_strategy())
def test_comparison(self, value1, value2):
for klass in (Any, AnyInherited):
obj1 = klass(value1)
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()
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),
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()
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(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()
+ 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)
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}),
@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 = 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):
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()
+ 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)
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.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_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):
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"),
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"),
+ )