예제 #1
0
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),
        ],
    )
예제 #2
0
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)
예제 #3
0
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')
예제 #4
0
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
예제 #5
0
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",
    )
예제 #6
0
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
예제 #7
0
 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_
예제 #8
0
        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")),
예제 #9
0
파일: models.py 프로젝트: senier/RecordFlux
def create_null_message_in_tlv_message() -> Refinement:
    return Refinement("In_TLV", "TLV.Message", Field("Value"), "Null.Message")
예제 #10
0
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
예제 #11
0
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"$',
    )
예제 #12
0
        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",
    [
예제 #13
0
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])