def test_derived_message_proven() -> None: message = DerivedMessage( "P.M", Message( "X.M", [Link(INITIAL, Field("F")), Link(Field("F"), FINAL)], {Field("F"): MODULAR_INTEGER}, ), ) assert message.proven() == message
def test_derived_message_incorrect_base_name() -> None: with pytest.raises( RecordFluxError, match= '^<stdin>:40:8: model: error: unexpected format of type name "M"$' ): DerivedMessage("P.M", Message("M", [], {}, location=Location((40, 8))))
def test_type_derivation_refinements() -> None: message_foo = Message( "Test.Foo", [Link(INITIAL, Field("Baz"), length=Number(48)), Link(Field("Baz"), FINAL)], {Field("Baz"): Opaque()}, ) message_bar = DerivedMessage("Test.Bar", message_foo) assert_refinements_string( """ package Test is type Foo is message null then Baz with Length => 48; Baz : Opaque; end message; for Foo use (Baz => Foo); type Bar is new Foo; for Bar use (Baz => Bar); end Test; """, [ Refinement("Test", message_foo, Field("Baz"), message_foo), Refinement("Test", message_bar, Field("Baz"), message_bar), ], )
def test_message_in_message() -> None: length = ModularInteger("Message_In_Message.Length", Pow(Number(2), Number(16))) length_value = Message( "Message_In_Message.Length_Value", [ Link(INITIAL, Field("Length")), Link(Field("Length"), Field("Value"), length=Mul(Number(8), Variable("Length"))), Link(Field("Value"), FINAL), ], {Field("Length"): length, Field("Value"): Opaque()}, ) derived_length_value = DerivedMessage("Message_In_Message.Derived_Length_Value", length_value) message = Message( "Message_In_Message.Message", [ Link(INITIAL, Field("Foo_Length")), Link(Field("Foo_Value"), Field("Bar_Length")), Link(Field("Bar_Value"), FINAL), Link( Field("Foo_Length"), Field("Foo_Value"), length=Mul(Variable("Foo_Length"), Number(8)), ), Link( Field("Bar_Length"), Field("Bar_Value"), length=Mul(Variable("Bar_Length"), Number(8)), ), ], { Field("Foo_Length"): length, Field("Foo_Value"): Opaque(), Field("Bar_Length"): length, Field("Bar_Value"): Opaque(), }, ) derived_message = DerivedMessage("Message_In_Message.Derived_Message", message) assert_messages_files( [f"{TESTDIR}/message_in_message.rflx"], [length_value, derived_length_value, message, derived_message], )
def convert_to_messages(spec: Specification) -> Dict[str, Message]: types: Dict[str, Type] = {Payload().name: Payload()} messages: Dict[str, Message] = {} for t in spec.package.types: if t.name in types: raise ParserError(f'duplicate type "{t.name}"') t.full_name = f"{spec.package.identifier}.{t.name}" if isinstance(t, (ModularInteger, RangeInteger, Enumeration)): pass elif isinstance(t, Array): t.element_type.full_name = t.element_type.full_name.replace( "__PACKAGE__", spec.package.identifier) if t.element_type.name not in types: raise ParserError( f'undefined type "{t.element_type.name}" in "{t.name}"') if not isinstance(types[t.element_type.name], MessageSpec): element_type_size = types[ t.element_type.name].size.simplified() if not isinstance(element_type_size, Number) or int(element_type_size) % 8 != 0: raise ParserError( f"unsupported size ({element_type_size}) of element type " f'"{t.element_type.name}" in "{t.name}" ' "(no multiple of 8)") t = Array(t.full_name, types[t.element_type.name]) elif isinstance(t, MessageSpec): messages[t.full_name] = create_message(t.full_name, types, t.components, t.name) elif isinstance(t, DerivationSpec): base = t.base if base not in types and base not in messages: raise ParserError(f'undefined type "{t.base}" in "{t.name}"') base = qualified_type_name( t.base, spec.package.identifier, messages, f'unsupported type "{t.base}" in "{t.name}"', ) messages[t.full_name] = DerivedMessage(t.full_name, base, messages[base].structure, messages[base].types) t = MessageSpec(t.full_name, []) elif isinstance(t, Refinement): continue else: raise NotImplementedError(f'unsupported type "{type(t).__name__}"') types[t.name] = t return messages
def test_type_derivation_message() -> None: t = ModularInteger("Test.T", Number(256)) structure = [Link(INITIAL, Field("Baz")), Link(Field("Baz"), FINAL)] types = {Field("Baz"): t} message_foo = Message("Test.Foo", structure, types) message_bar = DerivedMessage("Test.Bar", message_foo) assert_messages_string( """ package Test is type T is mod 256; type Foo is message Baz : T; end message; type Bar is new Foo; end Test; """, [message_foo, message_bar], )
SEQUENCE_SEQUENCE_SIZE_DEFINED_BY_MESSAGE_SIZE, ] ) EXPRESSION_MESSAGE = Message( "Expression::Message", [ Link(INITIAL, Field("Payload"), size=Number(16)), Link(Field("Payload"), FINAL, Equal(Variable("Payload"), Aggregate(Number(1), Number(2)))), ], {Field("Payload"): OPAQUE}, skip_proof=True, ) EXPRESSION_MODEL = Model([EXPRESSION_MESSAGE]) DERIVATION_MESSAGE = DerivedMessage("Derivation::Message", TLV_MESSAGE) DERIVATION_MODEL = Model([DERIVATION_MESSAGE]) VALID_MESSAGE = UnprovenMessage( "P::M", [ Link(INITIAL, Field("F"), size=Number(16)), Link(Field("F"), FINAL), ], {Field("F"): OPAQUE}, ) INVALID_MESSAGE = UnprovenMessage( "P::M", [ Link(INITIAL, Field("F")),
def create_derivation_message() -> Message: return DerivedMessage("Derivation.Message", ARRAY_MESSAGE.full_name, ARRAY_MESSAGE.structure, ARRAY_MESSAGE.types)
ARRAYS_AV_ENUMERATION, ARRAYS_AV_ENUMERATION_VECTOR, ARRAYS_MESSAGE, ARRAYS_INNER_MESSAGE, ARRAYS_INNER_MESSAGES, ARRAYS_MESSAGES_MESSAGE, ]) EXPRESSION_MESSAGE = Message( "Expression.Message", [ Link(INITIAL, Field("Payload"), length=Number(16)), Link(Field("Payload"), FINAL, Equal(Variable("Payload"), Aggregate(Number(1), Number(2)))), ], {Field("Payload"): Opaque()}, ) EXPRESSION_MODEL = Model([EXPRESSION_MESSAGE]) DERIVATION_MESSAGE = DerivedMessage("Derivation.Message", ARRAYS_MESSAGE) DERIVATION_MODEL = Model([*ARRAYS_MODEL.types, DERIVATION_MESSAGE]) MODULAR_INTEGER = ModularInteger("P.Modular", Number(256)) RANGE_INTEGER = RangeInteger("P.Range", Number(1), Number(100), Number(8)) ENUMERATION = Enumeration( "P.Enumeration", [("ZERO", Number(0)), ("ONE", Number(1)), ("TWO", Number(2))], Number(8), False, )