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 refinements(draw: Draw, unique_identifiers: ty.Generator[ID, None, None]) -> Refinement: pdu = draw(messages(unique_identifiers)) opaque_fields = [f for f, t in pdu.types.items() if isinstance(t, Opaque)] assume(opaque_fields) field = draw(st.sampled_from(opaque_fields)) sdu = draw(messages(unique_identifiers)) return Refinement("Test", pdu, field, sdu)
def parse_type(string: str, location: int, tokens: list) -> Type: try: if tokens[3] == 'mod': return ModularInteger(tokens[1], *tokens[4:6]) if tokens[3] == 'range': tokens[6] = tokens[6]['size'] return RangeInteger(tokens[1], *tokens[4:7]) if tokens[3] == 'message': return Message(tokens[1], tokens[4]) if tokens[3] == '(': elements = dict(tokens[4:-2]) aspects = tokens[-1] if len(elements) < len(tokens[4:-2]): raise ModelError(f'"{tokens[1]}" contains duplicate elements') if 'always_valid' not in aspects: aspects['always_valid'] = False return Enumeration(tokens[1], elements, aspects['size'], aspects['always_valid']) if tokens[3] == 'new': if len(tokens) == 7: tokens.append(TRUE) return Refinement(tokens[1], *tokens[4:]) if tokens[3] == 'array of': return Array(tokens[1], tokens[4]) except ModelError as e: raise ParseFatalException(string, location, e) raise ParseFatalException(string, location, 'unexpected type')
def convert_to_refinements(spec: Specification, messages: Dict[str, Message]) -> List[Refinement]: refinements: List[Refinement] = [] for t in spec.package.types: if isinstance(t, Refinement): pdu = qualified_type_name( t.pdu, spec.package.identifier, messages.keys(), f'undefined type "{t.pdu}" in refinement', ) if t.field not in messages[pdu].fields: raise ParserError( f'invalid field "{t.field.name}" in refinement of "{t.pdu}"' ) sdu = qualified_type_name( t.sdu, spec.package.identifier, messages.keys(), f'undefined type "{t.sdu}" in refinement of "{t.pdu}"', ) refinement = Refinement(spec.package.identifier, pdu, t.field, sdu, t.condition) if refinement in refinements: raise ParserError( f'duplicate refinement of field "{t.field.name}" with "{t.sdu}"' f' in "{t.pdu}"') refinements.append(refinement) for variable in t.condition.variables(): literals = [ l for e in messages[pdu].types.values() if isinstance(e, Enumeration) for l in e.literals.keys() ] if (Field(str(variable.name)) not in messages[pdu].fields and str(variable.name) not in literals): raise ParserError( f'unknown field or literal "{variable.name}" in refinement' f' condition of "{t.pdu}"') elif isinstance(t, DerivationSpec): for r in refinements: if r.pdu == f"{t.base}" or r.pdu == f"{spec.package.identifier}.{t.base}": pdu = f"{spec.package.identifier}.{t.name}" refinements.append( Refinement(spec.package.identifier, pdu, r.field, r.sdu)) return refinements
def test_refinement_invalid_field_type() -> None: x = Field(ID("X", Location((20, 10)))) message = Message("P.M", [Link(INITIAL, x), Link(x, FINAL)], {x: MODULAR_INTEGER}) assert_type_error( Refinement("P", message, Field(ID("X", Location((33, 22)))), message), r'^<stdin>:33:22: model: error: invalid type of field "X" in refinement of "P.M"\n' r"<stdin>:20:10: model: info: expected field of type Opaque", )
def convert_to_refinements(spec: Specification, pdus: Dict[str, PDU]) -> Dict[str, Refinement]: refinements: Dict[str, Refinement] = {} for t in spec.package.types: if isinstance(t, Refinement): pdu = t.pdu if pdu not in pdus: pdu = f'{spec.package.identifier}.{t.pdu}' if pdu not in pdus: raise ParserError(f'unknown type "{t.pdu}"') sdu = t.sdu if sdu != 'null' and sdu not in pdus: sdu = f'{spec.package.identifier}.{t.sdu}' if sdu not in pdus: raise ParserError(f'unknown type "{t.sdu}"') name = f'{spec.package.identifier}.{t.name}' if name in refinements: raise ParserError(f'duplicate refinement "{t.name}"') refinements[name] = Refinement(name, pdu, t.field, sdu, t.condition) return refinements
def _replace_messages(type_: mty.Type, messages: Dict[ID, Message]) -> mty.Type: """Recursively replace messages.""" if isinstance(type_, Message): return messages[type_.identifier] if isinstance(type_, Refinement): return Refinement( type_.package, messages[type_.pdu.identifier], type_.field, messages[type_.sdu.identifier], type_.condition, type_.location, ) if isinstance(type_, mty.Sequence) and isinstance( type_.element_type, Message): return mty.Sequence( type_.identifier, messages[type_.element_type.identifier], type_.location, ) return type_
Link(Field("Checksum"), FINAL, ValidChecksum("Checksum")), ], { Field("Tag"): TLV_WITH_CHECKSUM_TAG, Field("Length"): TLV_WITH_CHECKSUM_LENGTH, Field("Value"): OPAQUE, Field("Checksum"): TLV_WITH_CHECKSUM_CHECKSUM, }, checksums={ID("Checksum"): [Variable("Tag"), Size("Value"), Variable("Value")]}, skip_proof=True, ) TLV_WITH_CHECKSUM_MODEL = Model( [TLV_WITH_CHECKSUM_TAG, TLV_WITH_CHECKSUM_LENGTH, TLV_WITH_CHECKSUM_MESSAGE] ) NULL_MESSAGE_IN_TLV_MESSAGE = Refinement("In_TLV", TLV_MESSAGE, Field("Value"), NULL_MESSAGE) NULL_MESSAGE_IN_TLV_MESSAGE_MODEL = Model( [TLV_TAG, TLV_LENGTH, TLV_MESSAGE, NULL_MESSAGE, NULL_MESSAGE_IN_TLV_MESSAGE] ) ETHERNET_ADDRESS = ModularInteger("Ethernet::Address", Pow(Number(2), Number(48))) ETHERNET_TYPE_LENGTH = RangeInteger( "Ethernet::Type_Length", Number(46), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16) ) ETHERNET_TPID = RangeInteger("Ethernet::TPID", Number(0x8100, 16), Number(0x8100, 16), Number(16)) ETHERNET_TCI = ModularInteger("Ethernet::TCI", Pow(Number(2), Number(16))) ETHERNET_FRAME = Message( "Ethernet::Frame", [ Link(INITIAL, Field("Destination")), Link(Field("Destination"), Field("Source")),
def create_null_message_in_tlv_message() -> Refinement: return Refinement("In_TLV", "TLV.Message", Field("Value"), "Null.Message")
def create_refinement(refinement: RefinementSpec, types: Mapping[ID, Type]) -> Refinement: messages = message_types(types) refinement.pdu = qualified_type_name(refinement.pdu, refinement.package) if refinement.pdu not in messages: fail( f'undefined type "{refinement.pdu}" in refinement', Subsystem.PARSER, Severity.ERROR, refinement.location, ) pdu = messages[refinement.pdu] error = RecordFluxError() for variable in refinement.condition.variables(): literals = [ l for e in pdu.types.values() if isinstance(e, Enumeration) for l in e.literals.keys() ] + [ e.package * l for e in types.values() if isinstance(e, Enumeration) for l in e.literals.keys() ] if Field(str(variable.name) ) not in pdu.fields and variable.identifier not in literals: error.append( f'unknown field or literal "{variable.identifier}" in refinement' f' condition of "{refinement.pdu}"', Subsystem.PARSER, Severity.ERROR, variable.location, ) if Field(refinement.field) not in pdu.fields: error.append( f'invalid field "{refinement.field}" in refinement', Subsystem.PARSER, Severity.ERROR, refinement.field.location, ) error.propagate() refinement.sdu = qualified_type_name(refinement.sdu, refinement.package) if refinement.sdu not in messages: error.append( f'undefined type "{refinement.sdu}" in refinement of "{refinement.pdu}"', Subsystem.PARSER, Severity.ERROR, refinement.sdu.location, ) error.propagate() sdu = messages[refinement.sdu] result = Refinement( refinement.package, pdu, Field(refinement.field), sdu, refinement.condition, refinement.location, ) result.error.extend(error) if result in types.values(): result.error.append( f'duplicate refinement with "{refinement.sdu}"', Subsystem.PARSER, Severity.ERROR, refinement.location, ) result.error.append( "previous occurrence", Subsystem.PARSER, Severity.INFO, types[result.identifier].location, ) return result
def test_refinement_invalid_package() -> None: assert_type_error( Refinement(ID("A.B", Location((22, 10))), ETHERNET_FRAME, Field("Payload"), ETHERNET_FRAME), r'^<stdin>:22:10: model: error: unexpected format of package name "A.B"$', )
Link(Field("Tag"), FINAL, Equal(Variable("Tag"), Variable("Msg_Error"))), Link(Field("Length"), Field("Value"), length=Mul(Variable("Length"), Number(8))), Link(Field("Value"), FINAL), ], { Field("Tag"): TLV_TAG, Field("Length"): TLV_LENGTH, Field("Value"): Opaque() }, ) TLV_MODEL = Model([TLV_TAG, TLV_LENGTH, TLV_MESSAGE]) NULL_MESSAGE_IN_TLV_MESSAGE = Refinement("In_TLV", TLV_MESSAGE, Field("Value"), NULL_MESSAGE) NULL_MESSAGE_IN_TLV_MESSAGE_MODEL = Model([ TLV_TAG, TLV_LENGTH, TLV_MESSAGE, NULL_MESSAGE, NULL_MESSAGE_IN_TLV_MESSAGE ]) ETHERNET_ADDRESS = ModularInteger("Ethernet.Address", Pow(Number(2), Number(48))) ETHERNET_TYPE_LENGTH = RangeInteger("Ethernet.Type_Length", Number(46), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16)) ETHERNET_TPID = RangeInteger("Ethernet.TPID", Number(0x8100, 16), Number(0x8100, 16), Number(16)) ETHERNET_TCI = ModularInteger("Ethernet.TCI", Pow(Number(2), Number(16))) ETHERNET_FRAME = Message( "Ethernet.Frame", [
def parse_refinement(string: str, location: int, tokens: ParseResults) -> Type: if "constraint" not in tokens: tokens.append(TRUE) return Refinement("", tokens[0], Field(tokens[1]), tokens[2], tokens[3])