+
+
+class TestOIDDefines(TestCase):
+ @given(data_strategy())
+ def runTest(self, d):
+ value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
+ value_name_chosen = d.draw(sampled_from(value_names))
+ oids = [
+ ObjectIdentifier(oid)
+ for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
+ ]
+ oid_chosen = d.draw(sampled_from(oids))
+ values = d.draw(lists(
+ integers(),
+ 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))))
+
+ 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)
+
+
+class TestDefinesByPath(TestCase):
+ def test_generated(self):
+ class Seq(Sequence):
+ schema = (
+ ("type", ObjectIdentifier()),
+ ("value", OctetString(expl=tag_ctxc(123))),
+ )
+
+ class SeqInner(Sequence):
+ schema = (
+ ("typeInner", ObjectIdentifier()),
+ ("valueInner", Any()),
+ )
+
+ class PairValue(SetOf):
+ schema = Any()
+
+ class Pair(Sequence):
+ schema = (
+ ("type", ObjectIdentifier()),
+ ("value", PairValue()),
+ )
+
+ class Pairs(SequenceOf):
+ schema = Pair()
+
+ (
+ type_integered,
+ type_sequenced,
+ type_innered,
+ type_octet_stringed,
+ ) = [
+ ObjectIdentifier(oid)
+ for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
+ ]
+ seq_integered = Seq()
+ seq_integered["type"] = type_integered
+ seq_integered["value"] = OctetString(Integer(123).encode())
+ seq_integered_raw = seq_integered.encode()
+
+ pairs = Pairs()
+ pairs_input = (
+ (type_octet_stringed, OctetString(b"whatever")),
+ (type_integered, Integer(123)),
+ (type_octet_stringed, OctetString(b"whenever")),
+ (type_integered, Integer(234)),
+ )
+ for t, v in pairs_input:
+ pair = Pair()
+ pair["type"] = t
+ pair["value"] = PairValue((Any(v),))
+ pairs.append(pair)
+ seq_inner = SeqInner()
+ seq_inner["typeInner"] = type_innered
+ seq_inner["valueInner"] = Any(pairs)
+ seq_sequenced = Seq()
+ seq_sequenced["type"] = type_sequenced
+ seq_sequenced["value"] = OctetString(seq_inner.encode())
+ seq_sequenced_raw = seq_sequenced.encode()
+
+ defines_by_path = []
+ seq_integered, _ = Seq().decode(seq_integered_raw)
+ self.assertIsNone(seq_integered["value"].defined)
+ defines_by_path.append(
+ (("type",), ((("value",), {
+ type_integered: Integer(),
+ type_sequenced: SeqInner(),
+ }),))
+ )
+ seq_integered, _ = Seq().decode(
+ seq_integered_raw,
+ ctx={"defines_by_path": defines_by_path},
+ )
+ self.assertIsNotNone(seq_integered["value"].defined)
+ self.assertEqual(seq_integered["value"].defined[0], type_integered)
+ self.assertEqual(seq_integered["value"].defined[1], Integer(123))
+ self.assertTrue(seq_integered_raw[
+ seq_integered["value"].defined[1].offset:
+ ].startswith(Integer(123).encode()))
+
+ seq_sequenced, _ = Seq().decode(
+ seq_sequenced_raw,
+ ctx={"defines_by_path": defines_by_path},
+ )
+ self.assertIsNotNone(seq_sequenced["value"].defined)
+ self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
+ seq_inner = seq_sequenced["value"].defined[1]
+ self.assertIsNone(seq_inner["valueInner"].defined)
+
+ defines_by_path.append((
+ ("value", DecodePathDefBy(type_sequenced), "typeInner"),
+ ((("valueInner",), {type_innered: Pairs()}),),
+ ))
+ seq_sequenced, _ = Seq().decode(
+ seq_sequenced_raw,
+ ctx={"defines_by_path": defines_by_path},
+ )
+ self.assertIsNotNone(seq_sequenced["value"].defined)
+ self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
+ seq_inner = seq_sequenced["value"].defined[1]
+ self.assertIsNotNone(seq_inner["valueInner"].defined)
+ self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
+ pairs = seq_inner["valueInner"].defined[1]
+ for pair in pairs:
+ self.assertIsNone(pair["value"][0].defined)
+
+ defines_by_path.append((
+ (
+ "value",
+ DecodePathDefBy(type_sequenced),
+ "valueInner",
+ DecodePathDefBy(type_innered),
+ any,
+ "type",
+ ),
+ ((("value",), {
+ type_integered: Integer(),
+ type_octet_stringed: OctetString(),
+ }),),
+ ))
+ seq_sequenced, _ = Seq().decode(
+ seq_sequenced_raw,
+ ctx={"defines_by_path": defines_by_path},
+ )
+ self.assertIsNotNone(seq_sequenced["value"].defined)
+ self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
+ seq_inner = seq_sequenced["value"].defined[1]
+ self.assertIsNotNone(seq_inner["valueInner"].defined)
+ self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
+ pairs_got = seq_inner["valueInner"].defined[1]
+ for pair_input, pair_got in zip(pairs_input, pairs_got):
+ self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
+ self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
+
+ @given(oid_strategy(), integers())
+ def test_simple(self, oid, tgt):
+ class Inner(Sequence):
+ schema = (
+ ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
+ ObjectIdentifier(oid): Integer(),
+ }),))),
+ )
+
+ class Outer(Sequence):
+ schema = (
+ ("inner", Inner()),
+ ("tgt", OctetString()),
+ )
+
+ inner = Inner()
+ inner["oid"] = ObjectIdentifier(oid)
+ outer = Outer()
+ outer["inner"] = inner
+ outer["tgt"] = OctetString(Integer(tgt).encode())
+ decoded, _ = Outer().decode(outer.encode())
+ self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
+
+
+class TestAbsDecodePath(TestCase):
+ @given(
+ lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
+ 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,
+ )
+
+ @given(
+ lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
+ lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
+ )
+ def test_abs(self, decode_path, rel_path):
+ self.assertSequenceEqual(
+ abs_decode_path(decode_path, ("/",) + rel_path),
+ rel_path,
+ )
+
+ @given(
+ lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
+ integers(min_value=1, max_value=3),
+ lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
+ )
+ def test_dots(self, decode_path, number_of_dots, rel_path):
+ self.assertSequenceEqual(
+ abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
+ decode_path[:-number_of_dots] + rel_path,
+ )
+
+
+class TestStrictDefaultExistence(TestCase):
+ @given(data_strategy())
+ def runTest(self, d):
+ count = d.draw(integers(min_value=1, max_value=10))
+ chosen = d.draw(integers(min_value=0, max_value=count - 1))
+ _schema = [
+ ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
+ for i in range(count)
+ ]
+
+ class Seq(Sequence):
+ schema = _schema
+ seq = Seq()
+ for i in range(count):
+ seq["int%d" % i] = Integer(123)
+ raw = seq.encode()
+ chosen = "int%d" % chosen
+ seq.specs[chosen] = seq.specs[chosen](default=123)
+ seq.decode(raw)
+ with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
+ seq.decode(raw, ctx={"strict_default_existence": True})
+
+
+class TestX690PrefixedType(TestCase):
+ def runTest(self):
+ self.assertSequenceEqual(
+ VisibleString("Jones").encode(),
+ hexdec("1A054A6F6E6573"),
+ )
+ self.assertSequenceEqual(
+ VisibleString(
+ "Jones",
+ impl=tag_encode(3, klass=TagClassApplication),
+ ).encode(),
+ hexdec("43054A6F6E6573"),
+ )
+ self.assertSequenceEqual(
+ Any(
+ VisibleString(
+ "Jones",
+ impl=tag_encode(3, klass=TagClassApplication),
+ ),
+ expl=tag_ctxc(2),
+ ).encode(),
+ hexdec("A20743054A6F6E6573"),
+ )
+ self.assertSequenceEqual(
+ OctetString(
+ VisibleString(
+ "Jones",
+ impl=tag_encode(3, klass=TagClassApplication),
+ ).encode(),
+ impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
+ ).encode(),
+ hexdec("670743054A6F6E6573"),
+ )
+ self.assertSequenceEqual(
+ VisibleString("Jones", impl=tag_ctxp(2)).encode(),
+ hexdec("82054A6F6E6573"),
+ )