# coding: utf-8
-# PyDERASN -- Python ASN.1 DER codec with abstract structures
+# PyDERASN -- Python ASN.1 DER/BER codec with abstract structures
# Copyright (C) 2017-2018 Sergey Matveev <stargrave@stargrave.org>
#
# This program is free software: you can redistribute it and/or modify
from pyderasn import InvalidValueType
from pyderasn import len_decode
from pyderasn import len_encode
+from pyderasn import LENINDEF
from pyderasn import NotEnoughData
from pyderasn import Null
from pyderasn import NumericString
TagClassUniversal,
))
tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
+decode_path_strat = lists(integers(), max_size=3).map(
+ lambda decode_path: tuple(str(dp) for dp in decode_path)
+)
class TestHex(TestCase):
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Boolean().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_expl_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Boolean(expl=Boolean.tag_default).decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Boolean().decode(
Boolean.tag_default + len_encode(l)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_expl_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Boolean(expl=Boolean.tag_default).decode(
Boolean.tag_default + len_encode(l)[:-1],
self.assertTrue(obj.bered)
self.assertFalse(obj.lenindef)
+ @given(
+ integers(min_value=1).map(tag_ctxc),
+ binary().filter(lambda x: not x.startswith(EOC)),
+ )
+ def test_ber_expl_no_eoc(self, expl, junk):
+ encoded = expl + LENINDEF + Boolean(False).encode()
+ with assertRaisesRegex(self, DecodeError, "no EOC"):
+ Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
+ obj, tail = Boolean(expl=expl).decode(
+ encoded + EOC + junk,
+ ctx={"bered": True},
+ )
+ self.assertTrue(obj.expl_lenindef)
+ self.assertSequenceEqual(tail, junk)
+
@given(
integers(min_value=1).map(tag_ctxc),
lists(
for value in values:
encoded += (
expl +
- b"\x80" +
+ LENINDEF +
Boolean(value).encode() +
EOC
)
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Integer().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Integer().decode(
Integer.tag_default + len_encode(l)[:-1],
@given(
sets(integers(), min_size=2, max_size=2),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
value, bound_min = list(sorted(ints))
class Int(Integer):
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
BitString().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
BitString().decode(
BitString.tag_default + len_encode(l)[:-1],
max_size=3,
),
lists(booleans(), min_size=1),
+ binary(),
)
- def test_constructed(self, impl, chunk_inputs, chunk_last_bits):
+ def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk):
def chunk_constructed(contents):
return (
tag_encode(form=TagFormConstructed, num=3) +
- b"\x80" +
+ LENINDEF +
b"".join(BitString(content).encode() for content in contents) +
EOC
)
bit_len_expected += chunk_last.bit_len
encoded_indefinite = (
tag_encode(form=TagFormConstructed, num=impl) +
- b"\x80" +
+ LENINDEF +
b"".join(chunks) +
chunk_last.encode() +
EOC
(False, encoded_definite),
):
obj, tail = BitString(impl=tag_encode(impl)).decode(
- encoded, ctx={"bered": True}
+ encoded + junk,
+ ctx={"bered": True},
)
- self.assertSequenceEqual(tail, b"")
+ self.assertSequenceEqual(tail, junk)
self.assertEqual(obj.bit_len, bit_len_expected)
self.assertSequenceEqual(bytes(obj), payload_expected)
self.assertTrue(obj.bered)
self.assertEqual(obj.lenindef, lenindef_expected)
self.assertEqual(len(encoded), obj.tlvlen)
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ )
+ def test_ber_definite_too_short(self, offset, decode_path):
+ with assertRaisesRegex(self, DecodeError, "longer than data") as err:
+ BitString().decode(
+ tag_encode(3, form=TagFormConstructed) + len_encode(1),
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path)
+ self.assertEqual(err.exception.offset, offset)
+
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ )
+ def test_ber_definite_no_data(self, offset, decode_path):
+ with assertRaisesRegex(self, DecodeError, "zero length") as err:
+ BitString().decode(
+ tag_encode(3, form=TagFormConstructed) + len_encode(0),
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path)
+ self.assertEqual(err.exception.offset, offset)
+
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ integers(min_value=1, max_value=3),
+ )
+ def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
+ bs = BitString(b"data").encode()
+ with self.assertRaises(NotEnoughData) as err:
+ BitString().decode(
+ tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
+ self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
+
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ integers(min_value=1, max_value=3),
+ )
+ def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
+ bs = BitString(b"data").encode()
+ bs_longer = BitString(b"data-longer").encode()
+ with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
+ BitString().decode(
+ (
+ tag_encode(3, form=TagFormConstructed) +
+ len_encode((chunks + 1) * len(bs)) +
+ chunks * bs +
+ bs_longer
+ ),
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
+ self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
+
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ )
+ def test_ber_indefinite_no_chunks(self, offset, decode_path):
+ with assertRaisesRegex(self, DecodeError, "no chunks") as err:
+ BitString().decode(
+ tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path)
+ self.assertEqual(err.exception.offset, offset)
+
+ @given(data_strategy())
+ def test_ber_indefinite_not_multiple(self, d):
+ bs_short = BitString("'A'H").encode()
+ bs_full = BitString("'AA'H").encode()
+ chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
+ chunks.append(bs_short)
+ d.draw(permutations(chunks))
+ chunks.append(bs_short)
+ offset = d.draw(integers(min_value=0))
+ decode_path = d.draw(decode_path_strat)
+ with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
+ BitString().decode(
+ (
+ tag_encode(3, form=TagFormConstructed) +
+ LENINDEF +
+ b"".join(chunks) +
+ EOC
+ ),
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(
+ err.exception.decode_path,
+ decode_path + (str(chunks.index(bs_short)),),
+ )
+ self.assertEqual(
+ err.exception.offset,
+ offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
+ )
+
def test_x690_vector(self):
vector = BitString("'0A3B5F291CD'H")
obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
OctetString().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
OctetString().decode(
OctetString.tag_default + len_encode(l)[:-1],
@given(
sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
value, bound_min = list(sorted(ints))
class String(OctetString):
min_size=1,
max_size=3,
),
+ binary(),
)
- def test_constructed(self, impl, chunk_inputs):
+ def test_constructed(self, impl, chunk_inputs, junk):
def chunk_constructed(contents):
return (
tag_encode(form=TagFormConstructed, num=4) +
- b"\x80" +
+ LENINDEF +
b"".join(OctetString(content).encode() for content in contents) +
EOC
)
payload_expected += payload
encoded_indefinite = (
tag_encode(form=TagFormConstructed, num=impl) +
- b"\x80" +
+ LENINDEF +
b"".join(chunks) +
EOC
)
(False, encoded_definite),
):
obj, tail = OctetString(impl=tag_encode(impl)).decode(
- encoded, ctx={"bered": True}
+ encoded + junk,
+ ctx={"bered": True},
)
- self.assertSequenceEqual(tail, b"")
+ self.assertSequenceEqual(tail, junk)
self.assertSequenceEqual(bytes(obj), payload_expected)
self.assertTrue(obj.bered)
self.assertEqual(obj.lenindef, lenindef_expected)
self.assertEqual(len(encoded), obj.tlvlen)
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ )
+ def test_ber_definite_too_short(self, offset, decode_path):
+ with assertRaisesRegex(self, DecodeError, "longer than data") as err:
+ OctetString().decode(
+ tag_encode(4, form=TagFormConstructed) + len_encode(1),
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path)
+ self.assertEqual(err.exception.offset, offset)
+
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ integers(min_value=1, max_value=3),
+ )
+ def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
+ bs = OctetString(b"data").encode()
+ with self.assertRaises(NotEnoughData) as err:
+ OctetString().decode(
+ tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
+ self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
+
+ @given(
+ integers(min_value=0),
+ decode_path_strat,
+ integers(min_value=1, max_value=3),
+ )
+ def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
+ bs = OctetString(b"data").encode()
+ bs_longer = OctetString(b"data-longer").encode()
+ with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
+ OctetString().decode(
+ (
+ tag_encode(4, form=TagFormConstructed) +
+ len_encode((chunks + 1) * len(bs)) +
+ chunks * bs +
+ bs_longer
+ ),
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
+ self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
+
@composite
def null_values_strategy(draw, do_expl=False):
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Null().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Null().decode(
Null.tag_default + len_encode(l)[:-1],
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
ObjectIdentifier().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
ObjectIdentifier().decode(
ObjectIdentifier.tag_default + len_encode(l)[:-1],
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
self.base_klass().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
self.base_klass().decode(
self.base_klass.tag_default + len_encode(l)[:-1],
@given(
sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
value, bound_min = list(sorted(ints))
class String(self.base_klass):
@given(
sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
value, bound_min = list(sorted(ints))
class String(self.base_klass):
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Any().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
Any().decode(
Any.tag_default + len_encode(l)[:-1],
self.assertEqual(obj_decoded.llen, 0)
self.assertEqual(obj_decoded.vlen, len(value))
+ @given(
+ integers(min_value=1).map(tag_ctxc),
+ integers(min_value=0, max_value=3),
+ integers(min_value=0),
+ decode_path_strat,
+ binary(),
+ )
+ def test_indefinite(self, expl, chunks, offset, decode_path, junk):
+ chunk = Boolean(False, expl=expl).encode()
+ encoded = (
+ OctetString.tag_default +
+ LENINDEF +
+ b"".join([chunk] * chunks) +
+ EOC
+ )
+ obj, tail = Any().decode(
+ encoded + junk,
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertSequenceEqual(tail, junk)
+ self.assertEqual(obj.offset, offset)
+ self.assertEqual(obj.tlvlen, len(encoded))
+ with self.assertRaises(NotEnoughData) as err:
+ Any().decode(
+ encoded[:-1],
+ offset=offset,
+ decode_path=decode_path,
+ ctx={"bered": True},
+ )
+ self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
+ self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
+
@composite
def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
self.base_klass().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
self.base_klass().decode(
self.base_klass.tag_default + len_encode(l)[:-1],
self._assert_expects(seq, expects)
repr(seq)
pprint(seq)
+ self.assertTrue(seq.ready)
seq_encoded = seq.encode()
seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
- self.assertEqual(tail, tail_junk)
- self.assertTrue(seq.ready)
- self._assert_expects(seq_decoded, expects)
- self.assertEqual(seq, seq_decoded)
- self.assertEqual(seq_decoded.encode(), seq_encoded)
- for expect in expects:
- if not expect["presented"]:
- self.assertNotIn(expect["name"], seq_decoded)
- continue
- self.assertIn(expect["name"], seq_decoded)
- obj = seq_decoded[expect["name"]]
- self.assertTrue(obj.decoded)
- offset = obj.expl_offset if obj.expled else obj.offset
- tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
- self.assertSequenceEqual(
- seq_encoded[offset:offset + tlvlen],
- obj.encode(),
- )
+ self.assertFalse(seq_decoded.lenindef)
+
+ t, _, lv = tag_strip(seq_encoded)
+ _, _, v = len_decode(lv)
+ seq_encoded_lenindef = t + LENINDEF + v + EOC
+ seq_decoded_lenindef, tail_lenindef = seq.decode(
+ seq_encoded_lenindef + tail_junk,
+ ctx={"bered": True},
+ )
+ self.assertTrue(seq_decoded_lenindef.lenindef)
+ with self.assertRaises(DecodeError):
+ seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
+ with self.assertRaises(DecodeError):
+ seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
+ repr(seq_decoded_lenindef)
+ pprint(seq_decoded_lenindef)
+ self.assertTrue(seq_decoded_lenindef.ready)
+
+ for decoded, decoded_tail, encoded in (
+ (seq_decoded, tail, seq_encoded),
+ (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
+ ):
+ self.assertEqual(decoded_tail, tail_junk)
+ self._assert_expects(decoded, expects)
+ self.assertEqual(seq, decoded)
+ self.assertEqual(decoded.encode(), seq_encoded)
+ self.assertEqual(decoded.tlvlen, len(encoded))
+ for expect in expects:
+ if not expect["presented"]:
+ self.assertNotIn(expect["name"], decoded)
+ continue
+ self.assertIn(expect["name"], decoded)
+ obj = decoded[expect["name"]]
+ self.assertTrue(obj.decoded)
+ offset = obj.expl_offset if obj.expled else obj.offset
+ tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
+ self.assertSequenceEqual(
+ seq_encoded[offset:offset + tlvlen],
+ obj.encode(),
+ )
@settings(max_examples=LONG_TEST_MAX_EXAMPLES)
@given(data_strategy())
@given(
integers(min_value=31),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_tag(self, tag, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
self.base_klass().decode(
tag_encode(tag)[:-1],
@given(
integers(min_value=128),
integers(min_value=0),
- lists(integers()),
+ decode_path_strat,
)
def test_bad_len(self, l, offset, decode_path):
- decode_path = tuple(str(i) for i in decode_path)
with self.assertRaises(DecodeError) as err:
self.base_klass().decode(
self.base_klass.tag_default + len_encode(l)[:-1],
],
)
+ t, _, lv = tag_strip(obj_encoded)
+ _, _, v = len_decode(lv)
+ obj_encoded_lenindef = t + LENINDEF + v + EOC
+ obj_decoded_lenindef, tail_lenindef = obj.decode(
+ obj_encoded_lenindef + tail_junk,
+ ctx={"bered": True},
+ )
+ self.assertTrue(obj_decoded_lenindef.lenindef)
+ repr(obj_decoded_lenindef)
+ pprint(obj_decoded_lenindef)
+ self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
+ with self.assertRaises(DecodeError):
+ obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
+ with self.assertRaises(DecodeError):
+ obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
+
class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
class SeqOf(SequenceOf):