Beispiel #1
0
def fixture_icmp_checksum_message_first(icmp_message: model.Message) -> pyrflx.MessageValue:
    return pyrflx.MessageValue(
        icmp_message.copy(
            structure=[
                model.Link(
                    l.source,
                    l.target,
                    condition=expr.And(l.condition, expr.ValidChecksum("Checksum")),
                )
                if l.target == model.FINAL
                else l
                for l in icmp_message.structure
            ],
            checksums={
                ID("Checksum"): [
                    expr.ValueRange(
                        expr.First("Message"), expr.Sub(expr.First("Checksum"), expr.Number(1))
                    ),
                    expr.Size("Checksum"),
                    expr.ValueRange(
                        expr.Add(expr.Last("Checksum"), expr.Number(1)), expr.Last("Message")
                    ),
                ]
            },
        )
    )
Beispiel #2
0
def test_named_aggregate_rflx_expr() -> None:
    assert ada.NamedAggregate(
        ("X", ada.Number(1)),
        (ada.ValueRange(ada.Number(2), ada.Number(3)), ada.Variable("Y")),
    ).rflx_expr() == expr.NamedAggregate(
        ("X", expr.Number(1)),
        (expr.ValueRange(expr.Number(2), expr.Number(3)), expr.Variable("Y")),
    )
Beispiel #3
0
 def size(pair: FieldPair) -> expr.Expr:
     max_size = 2**29 - 1
     if isinstance(pair.target_type, (Opaque, Sequence)):
         if isinstance(pair.source_type, Integer):
             if pair.source_type.last.value <= max_size:
                 return expr.Mul(expr.Variable(pair.source.name), expr.Number(8))
         return expr.Number(
             draw(st.integers(min_value=1, max_value=max_size).map(lambda x: x * 8))
         )
     return expr.UNDEFINED
Beispiel #4
0
def modular_integers(
    draw: Draw,
    unique_identifiers: ty.Generator[ID, None, None],
    multiple_of_8: bool = False,
    align_to_8: int = 0,
) -> ModularInteger:
    return ModularInteger(
        next(unique_identifiers),
        expr.Pow(expr.Number(2), expr.Number(draw(sizes(multiple_of_8, align_to_8)))),
    )
Beispiel #5
0
def range_integers(
    draw: Draw,
    unique_identifiers: ty.Generator[ID, None, None],
    multiple_of_8: bool = False,
    align_to_8: int = 0,
) -> RangeInteger:
    size = draw(sizes(multiple_of_8, align_to_8))
    max_value = min(2**size - 1, 2**63 - 1)
    first = draw(st.integers(min_value=0, max_value=max_value))
    last = draw(st.integers(min_value=first, max_value=max_value))
    return RangeInteger(
        next(unique_identifiers), expr.Number(first), expr.Number(last), expr.Number(size)
    )
Beispiel #6
0
def enumerations(
    draw: Draw,
    unique_identifiers: ty.Generator[ID, None, None],
    multiple_of_8: bool = False,
    align_to_8: int = 0,
) -> Enumeration:
    @st.composite
    def literal_identifiers(_: ty.Callable[[], object]) -> str:
        assert unique_identifiers
        return str(next(unique_identifiers).name)

    size = draw(sizes(multiple_of_8, align_to_8))
    literals = draw(
        st.lists(
            st.tuples(
                literal_identifiers(),
                st.builds(
                    expr.Number, st.integers(min_value=0, max_value=min(2**size - 1, 2**63 - 1))
                ),
            ),
            unique_by=(lambda x: x[0], lambda x: x[1]),  # type: ignore[no-any-return]
            min_size=1,
            max_size=2**size,
        )
    )

    return Enumeration(
        next(unique_identifiers),
        literals,
        expr.Number(size),
        draw(st.booleans()) if len(literals) < 2**size else False,
    )
Beispiel #7
0
def test_substitution_relation_aggregate(
    relation: Callable[[expr.Expr, expr.Expr], expr.Relation], left: expr.Expr, right: expr.Expr
) -> None:
    equal_call = expr.Call(
        "Equal",
        [
            expr.Variable("Ctx"),
            expr.Variable("F_Value"),
            expr.Aggregate(
                expr.Val(expr.Variable("Types.Byte"), expr.Number(1)),
                expr.Val(expr.Variable("Types.Byte"), expr.Number(2)),
            ),
        ],
    )

    assert_equal(
        relation(left, right).substituted(common.substitution(TLV_MESSAGE)),
        equal_call if relation == expr.Equal else expr.Not(equal_call),
    )
Beispiel #8
0
 def field_size(field: model.Field) -> expr.Expr:
     if public:
         return expr.Call(
             "Field_Size", [expr.Variable("Ctx"), expr.Variable(field.affixed_name)]
         )
     return expr.Add(
         expr.Sub(
             expr.Selected(expr.Indexed(cursors, expr.Variable(field.affixed_name)), "Last"),
             expr.Selected(expr.Indexed(cursors, expr.Variable(field.affixed_name)), "First"),
         ),
         expr.Number(1),
     )
Beispiel #9
0
def test_verified(tmp_path: Path) -> None:
    m1 = model.Message(
        "P::M",
        [
            model.Link(model.INITIAL, model.Field("A")),
            model.Link(model.Field("A"), model.FINAL),
        ],
        {
            model.Field("A"):
            model.ModularInteger("P::T",
                                 expr.Pow(expr.Number(2), expr.Number(8)))
        },
    )
    m2 = model.Message(
        "P::M",
        [
            model.Link(model.INITIAL, model.Field("B")),
            model.Link(model.Field("B"), model.FINAL),
        ],
        {
            model.Field("B"):
            model.ModularInteger("P::T",
                                 expr.Pow(expr.Number(2), expr.Number(8)))
        },
    )
    m3 = model.Message(
        "P::M",
        [
            model.Link(model.INITIAL, model.Field("A")),
            model.Link(model.Field("A"), model.FINAL),
        ],
        {
            model.Field("A"):
            model.ModularInteger("P::T",
                                 expr.Pow(expr.Number(2), expr.Number(16)))
        },
    )
    cache.CACHE_DIR = tmp_path
    c = cache.Cache()
    assert not c.is_verified(m1)
    assert not c.is_verified(m2)
    assert not c.is_verified(m3)
    c.add_verified(m1)
    assert c.is_verified(m1)
    assert not c.is_verified(m2)
    assert not c.is_verified(m3)
    c.add_verified(m2)
    assert c.is_verified(m1)
    assert c.is_verified(m2)
    assert not c.is_verified(m3)
    c.add_verified(m3)
    assert c.is_verified(m1)
    assert c.is_verified(m2)
    assert c.is_verified(m3)
    c.add_verified(m1)
    assert c.is_verified(m1)
    assert c.is_verified(m2)
    assert c.is_verified(m3)
Beispiel #10
0
    def constraints(self,
                    name: str,
                    proof: bool = False,
                    same_package: bool = True) -> ty.Sequence[expr.Expr]:
        if proof:
            return [
                expr.Less(expr.Variable(name),
                          self._modulus,
                          location=self.location),
                expr.GreaterEqual(expr.Variable(name),
                                  expr.Number(0),
                                  location=self.location),
                expr.Equal(expr.Size(name), self.size, location=self.location),
            ]

        raise NotImplementedError
Beispiel #11
0
 def condition(pair: FieldPair) -> expr.Expr:
     if isinstance(pair.source_type, Integer):
         first = pair.source_type.first.value
         last = pair.source_type.last.value
         if last - first > 0:
             return expr.Equal(
                 expr.Variable(pair.source.name),
                 expr.Number(draw(st.integers(min_value=first, max_value=last))),
             )
     elif isinstance(pair.source_type, Enumeration) and len(pair.source_type.literals) > 1:
         return expr.Equal(
             expr.Variable(pair.source.name),
             expr.Variable(
                 list(pair.source_type.literals.keys())[
                     draw(st.integers(min_value=0, max_value=len(pair.source_type.literals) - 1))
                 ]
             ),
         )
     return expr.TRUE
Beispiel #12
0
def test_ipv4_parsing_ipv4(ipv4_packet_value: pyrflx.MessageValue) -> None:
    with open(CAPTURED_DIR / "ipv4_udp.raw", "rb") as file:
        msg_as_bytes: bytes = file.read()
    ipv4_packet_value.parse(msg_as_bytes)
    assert ipv4_packet_value.get("Version") == 4
    assert ipv4_packet_value.get("IHL") == 5
    assert ipv4_packet_value.get("DSCP") == 0
    assert ipv4_packet_value.get("ECN") == 0
    assert ipv4_packet_value.get("Total_Length") == 44
    assert ipv4_packet_value.get("Identification") == 1
    assert ipv4_packet_value.get("Flag_R") == "False"
    assert ipv4_packet_value.get("Flag_DF") == "False"
    assert ipv4_packet_value.get("Flag_MF") == "False"
    assert ipv4_packet_value.get("Fragment_Offset") == 0
    assert ipv4_packet_value.get("TTL") == 64
    assert ipv4_packet_value.get("Protocol") == "IPv4::P_UDP"
    assert ipv4_packet_value.get("Header_Checksum") == int("7CBE", 16)
    assert ipv4_packet_value.get("Source") == int("7f000001", 16)
    assert ipv4_packet_value.get("Destination") == int("7f000001", 16)
    assert ipv4_packet_value._fields["Payload"].typeval.size == expr.Number(192)
Beispiel #13
0
    def __init__(self,
                 identifier: StrID,
                 modulus: expr.Expr,
                 location: Location = None) -> None:
        super().__init__(identifier, expr.UNDEFINED, location)

        modulus_num = modulus.simplified()

        if not isinstance(modulus_num, expr.Number):
            self.error.extend([(
                f'modulus of "{self.name}" contains variable',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )
            return

        modulus_int = int(modulus_num)

        # https://github.com/Componolit/RecordFlux/issues/1077
        # size of integers is limited to 63bits

        if modulus_int > 2**const.MAX_SCALAR_SIZE:
            self.error.extend([(
                f'modulus of "{self.name}" exceeds limit (2**{const.MAX_SCALAR_SIZE})',
                Subsystem.MODEL,
                Severity.ERROR,
                modulus.location,
            )], )
        if modulus_int == 0 or (modulus_int & (modulus_int - 1)) != 0:
            self.error.extend([(
                f'modulus of "{self.name}" not power of two',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )

        self._modulus = modulus
        self._size = expr.Number((modulus_int - 1).bit_length())
Beispiel #14
0
    def __init__(
        self,
        identifier: StrID,
        first: expr.Expr,
        last: expr.Expr,
        size: expr.Expr,
        location: Location = None,
    ) -> None:
        super().__init__(identifier, size, location)

        first_num = first.simplified()
        last_num = last.simplified()
        size_num = size.simplified()

        if not isinstance(first_num, expr.Number):
            self.error.extend([(
                f'first of "{self.name}" contains variable',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )

        if not isinstance(last_num, expr.Number):
            self.error.extend([(
                f'last of "{self.name}" contains variable',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )
            return
        if int(last_num) >= 2**const.MAX_SCALAR_SIZE:
            self.error.extend([(
                f'last of "{self.name}" exceeds limit (2**{const.MAX_SCALAR_SIZE} - 1)',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )

        if not isinstance(size_num, expr.Number):
            self.error.extend([(
                f'size of "{self.name}" contains variable',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )

        if self.error.check():
            return

        assert isinstance(first_num, expr.Number)
        assert isinstance(last_num, expr.Number)
        assert isinstance(size_num, expr.Number)

        if first_num < expr.Number(0):
            self.error.extend([(
                f'first of "{self.name}" negative',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )
        if first_num > last_num:
            self.error.extend([(
                f'range of "{self.name}" negative',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )

        if int(last_num).bit_length() > int(size_num):
            self.error.extend([(
                f'size of "{self.name}" too small',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )

        # https://github.com/Componolit/RecordFlux/issues/1077
        # size of integers is limited to 63bits

        if int(size_num) > const.MAX_SCALAR_SIZE:
            self.error.extend([(
                f'size of "{self.name}" exceeds limit (2**{const.MAX_SCALAR_SIZE})',
                Subsystem.MODEL,
                Severity.ERROR,
                self.location,
            )], )

        self._first_expr = first
        self._first = first_num
        self._last_expr = last
        self._last = last_num
Beispiel #15
0
def numbers(draw: Draw, min_value: int = 0, max_value: int = None) -> expr.Number:
    return expr.Number(draw(st.integers(min_value=min_value, max_value=max_value)))
Beispiel #16
0
def substitution_facts(
    message: model.Message,
    prefix: str,
    embedded: bool = False,
    public: bool = False,
    target_type: Optional[ID] = const.TYPES_BASE_INT,
) -> Mapping[expr.Name, expr.Expr]:
    def prefixed(name: str) -> expr.Expr:
        return expr.Variable(ID("Ctx") * name) if not embedded else expr.Variable(name)

    first = prefixed("First")
    last = expr.Call("Written_Last", [expr.Variable("Ctx")]) if public else prefixed("Written_Last")
    cursors = prefixed("Cursors")

    def field_first(field: model.Field) -> expr.Expr:
        if public:
            return expr.Call(
                "Field_First", [expr.Variable("Ctx"), expr.Variable(field.affixed_name)]
            )
        return expr.Selected(expr.Indexed(cursors, expr.Variable(field.affixed_name)), "First")

    def field_last(field: model.Field) -> expr.Expr:
        if public:
            return expr.Call(
                "Field_Last", [expr.Variable("Ctx"), expr.Variable(field.affixed_name)]
            )
        return expr.Selected(expr.Indexed(cursors, expr.Variable(field.affixed_name)), "Last")

    def field_size(field: model.Field) -> expr.Expr:
        if public:
            return expr.Call(
                "Field_Size", [expr.Variable("Ctx"), expr.Variable(field.affixed_name)]
            )
        return expr.Add(
            expr.Sub(
                expr.Selected(expr.Indexed(cursors, expr.Variable(field.affixed_name)), "Last"),
                expr.Selected(expr.Indexed(cursors, expr.Variable(field.affixed_name)), "First"),
            ),
            expr.Number(1),
        )

    def parameter_value(parameter: model.Field, parameter_type: model.Type) -> expr.Expr:
        if isinstance(parameter_type, model.Enumeration):
            if embedded:
                return expr.Call("To_Base_Integer", [expr.Variable(parameter.name)])
            return expr.Call("To_Base_Integer", [expr.Variable("Ctx" * parameter.identifier)])
        if isinstance(parameter_type, model.Scalar):
            if embedded:
                return expr.Variable(parameter.name)
            return expr.Variable("Ctx" * parameter.identifier)

        assert False, f'unexpected type "{type(parameter_type).__name__}"'

    def field_value(field: model.Field, field_type: model.Type) -> expr.Expr:
        if isinstance(field_type, model.Enumeration):
            if public:
                return expr.Call(
                    "To_Base_Integer", [expr.Call(f"Get_{field.name}", [expr.Variable("Ctx")])]
                )
            return expr.Selected(
                expr.Indexed(cursors, expr.Variable(field.affixed_name)),
                "Value",
            )
        if isinstance(field_type, model.Scalar):
            if public:
                return expr.Call(f"Get_{field.name}", [expr.Variable("Ctx")])
            return expr.Selected(
                expr.Indexed(cursors, expr.Variable(field.affixed_name)),
                "Value",
            )
        if isinstance(field_type, model.Composite):
            return expr.Variable(field.name)

        assert False, f'unexpected type "{type(field_type).__name__}"'

    def type_conversion(expression: expr.Expr) -> expr.Expr:
        return expr.Call(target_type, [expression]) if target_type else expression

    return {
        **{expr.First("Message"): type_conversion(first)},
        **{expr.Last("Message"): type_conversion(last)},
        **{expr.Size("Message"): type_conversion(expr.Add(last, -first, expr.Number(1)))},
        **{expr.First(f.name): type_conversion(field_first(f)) for f in message.fields},
        **{expr.Last(f.name): type_conversion(field_last(f)) for f in message.fields},
        **{expr.Size(f.name): type_conversion(field_size(f)) for f in message.fields},
        **{
            expr.Variable(p.identifier): type_conversion(parameter_value(p, t))
            for p, t in message.parameter_types.items()
        },
        **{
            expr.Variable(f.name): type_conversion(field_value(f, t))
            for f, t in message.field_types.items()
        },
        **{
            expr.Literal(l): type_conversion(expr.Call("To_Base_Integer", [expr.Variable(l)]))
            for t in message.types.values()
            if isinstance(t, model.Enumeration) and t != model.BOOLEAN
            for l in t.literals.keys()
        },
        **{
            expr.Literal(t.package * l): type_conversion(
                expr.Call("To_Base_Integer", [expr.Variable(prefix * t.package * l)])
            )
            for t in message.types.values()
            if isinstance(t, model.Enumeration) and t != model.BOOLEAN
            for l in t.literals.keys()
        },
        # https://github.com/Componolit/RecordFlux/issues/276
        **{expr.ValidChecksum(f): expr.TRUE for f in message.checksums},
    }
Beispiel #17
0
def message_structure_invariant(
    message: model.Message, prefix: str, link: model.Link = None, embedded: bool = False
) -> Expr:
    def prefixed(name: str) -> expr.Expr:
        return expr.Selected(expr.Variable("Ctx"), name) if not embedded else expr.Variable(name)

    if not link:
        return message_structure_invariant(
            message, prefix, message.outgoing(model.INITIAL)[0], embedded
        )

    source = link.source
    target = link.target

    if target == model.FINAL:
        return TRUE

    field_type = message.types[target]
    condition = link.condition.substituted(substitution(message, prefix, embedded)).simplified()
    size = (
        field_type.size
        if isinstance(field_type, model.Scalar)
        else link.size.substituted(
            substitution(message, prefix, embedded, target_type=const.TYPES_BIT_LENGTH)
        ).simplified()
    )
    first = (
        prefixed("First")
        if source == model.INITIAL
        else link.first.substituted(
            substitution(message, prefix, embedded, target_type=const.TYPES_BIT_INDEX)
        )
        .substituted(
            mapping={
                expr.UNDEFINED: expr.Add(
                    expr.Selected(
                        expr.Indexed(prefixed("Cursors"), expr.Variable(source.affixed_name)),
                        "Last",
                    ),
                    expr.Number(1),
                )
            }
        )
        .simplified()
    )
    invariant = [
        message_structure_invariant(message, prefix, l, embedded) for l in message.outgoing(target)
    ]

    return If(
        [
            (
                AndThen(
                    Call(
                        "Structural_Valid",
                        [Indexed(prefixed("Cursors").ada_expr(), Variable(target.affixed_name))],
                    ),
                    *([condition.ada_expr()] if condition != expr.TRUE else []),
                ),
                AndThen(
                    Equal(
                        Add(
                            Sub(
                                Selected(
                                    Indexed(
                                        prefixed("Cursors").ada_expr(),
                                        Variable(target.affixed_name),
                                    ),
                                    "Last",
                                ),
                                Selected(
                                    Indexed(
                                        prefixed("Cursors").ada_expr(),
                                        Variable(target.affixed_name),
                                    ),
                                    "First",
                                ),
                            ),
                            Number(1),
                        ),
                        size.ada_expr(),
                    ),
                    Equal(
                        Selected(
                            Indexed(
                                prefixed("Cursors").ada_expr(),
                                Variable(target.affixed_name),
                            ),
                            "Predecessor",
                        ),
                        Variable(source.affixed_name),
                    ),
                    Equal(
                        Selected(
                            Indexed(
                                prefixed("Cursors").ada_expr(),
                                Variable(target.affixed_name),
                            ),
                            "First",
                        ),
                        first.ada_expr(),
                    ),
                    *[i for i in invariant if i != TRUE],
                ),
            )
        ]
    )
Beispiel #18
0

def test_derivation_spec() -> None:
    generator = generate(DERIVATION_MODEL)
    assert_specification(generator)


def test_derivation_body() -> None:
    generator = generate(DERIVATION_MODEL)
    assert_body(generator)


@pytest.mark.parametrize(
    "left,right",
    [
        (expr.Variable("Value"), expr.Aggregate(expr.Number(1), expr.Number(2))),
        (expr.Aggregate(expr.Number(1), expr.Number(2)), expr.Variable("Value")),
    ],
)
@pytest.mark.parametrize("relation", [expr.Equal, expr.NotEqual])
def test_substitution_relation_aggregate(
    relation: Callable[[expr.Expr, expr.Expr], expr.Relation], left: expr.Expr, right: expr.Expr
) -> None:
    equal_call = expr.Call(
        "Equal",
        [
            expr.Variable("Ctx"),
            expr.Variable("F_Value"),
            expr.Aggregate(
                expr.Val(expr.Variable("Types.Byte"), expr.Number(1)),
                expr.Val(expr.Variable("Types.Byte"), expr.Number(2)),
Beispiel #19
0
 def value_count(self) -> expr.Number:
     return self.last - self.first + expr.Number(1)
Beispiel #20
0
 def element_size(self) -> expr.Expr:
     return expr.Number(8)
Beispiel #21
0
def test_number_rflx_expr() -> None:
    assert ada.Number(42).rflx_expr() == expr.Number(42)
Beispiel #22
0
    def type_(self) -> rty.Type:
        return rty.Private(str(self.identifier))


OPAQUE = Opaque(
    location=Location((0, 0), Path(str(const.BUILTINS_PACKAGE)), (0, 0)))

INTERNAL_TYPES = {
    OPAQUE.identifier: OPAQUE,
}

BOOLEAN = Enumeration(
    const.BUILTINS_PACKAGE * "Boolean",
    [
        (ID("False", Location((0, 0), Path(str(const.BUILTINS_PACKAGE)),
                              (0, 0))), expr.Number(0)),
        (ID("True", Location((0, 0), Path(str(const.BUILTINS_PACKAGE)),
                             (0, 0))), expr.Number(1)),
    ],
    expr.Number(1),
    always_valid=False,
    location=rty.BOOLEAN.location,
)

BUILTIN_TYPES = {
    BOOLEAN.identifier: BOOLEAN,
}

BUILTIN_LITERALS = {l for t in BUILTIN_TYPES.values() for l in t.literals}

Beispiel #23
0
 def last(self) -> expr.Number:
     modulus = self.modulus.simplified()
     assert isinstance(modulus, expr.Number)
     return modulus - expr.Number(1)
Beispiel #24
0
 def first(self) -> expr.Number:
     return expr.Number(0)
Beispiel #25
0
        ("X::Y", ID("X::Y")),
        ("X2::Y2", ID("X2::Y2")),
        ("X_Y::Z", ID("X_Y::Z")),
        ("X_Y_3::Z_4", ID("X_Y_3::Z_4")),
    ],
)
def test_qualified_identifier(string: str, expected: ID) -> None:
    actual = parse_id(string, lang.GrammarRule.qualified_identifier_rule)
    assert actual == expected
    assert actual.location


@pytest.mark.parametrize(
    "string,expected",
    [
        ("1000", expr.Number(1000)),
        ("1_000", expr.Number(1000)),
        ("16#6664#", expr.Number(26212)),
        ("16#66_64#", expr.Number(26212)),
        ("-1000", expr.Number(-1000)),
        ("-1_000", expr.Number(-1000)),
        ("-16#6664#", expr.Number(-26212)),
        ("-16#66_64#", expr.Number(-26212)),
    ],
)
def test_expression_numeric_literal(string: str, expected: expr.Expr) -> None:
    actual = parse_math_expression(string, extended=False)
    assert actual == expected
    assert actual.location

Beispiel #26
0
 def value_count(self) -> expr.Number:
     if self.always_valid:
         size_num = self.size.simplified()
         assert isinstance(size_num, expr.Number)
         return expr.Number(2**int(size_num))
     return expr.Number(len(self.literals))
Beispiel #27
0
def test_consistency_specification_parsing_generation(tmp_path: Path) -> None:
    tag = Enumeration(
        "Test::Tag",
        [("Msg_Data", expr.Number(1)), ("Msg_Error", expr.Number(3))],
        expr.Number(8),
        always_valid=False,
    )
    length = ModularInteger("Test::Length",
                            expr.Pow(expr.Number(2), expr.Number(16)))
    message = Message(
        "Test::Message",
        [
            Link(INITIAL, Field("Tag")),
            Link(
                Field("Tag"),
                Field("Length"),
                expr.Equal(expr.Variable("Tag"), expr.Variable("Msg_Data")),
            ),
            Link(Field("Tag"), FINAL,
                 expr.Equal(expr.Variable("Tag"), expr.Variable("Msg_Error"))),
            Link(
                Field("Length"),
                Field("Value"),
                size=expr.Mul(expr.Variable("Length"), expr.Number(8)),
            ),
            Link(Field("Value"), FINAL),
        ],
        {
            Field("Tag"): tag,
            Field("Length"): length,
            Field("Value"): OPAQUE
        },
        skip_proof=True,
    )
    session = Session(
        "Test::Session",
        "A",
        "C",
        [
            State(
                "A",
                declarations=[],
                actions=[stmt.Read("X", expr.Variable("M"))],
                transitions=[
                    Transition("B"),
                ],
            ),
            State(
                "B",
                declarations=[
                    decl.VariableDeclaration("Z", BOOLEAN.identifier,
                                             expr.Variable("Y")),
                ],
                actions=[],
                transitions=[
                    Transition(
                        "C",
                        condition=expr.And(
                            expr.Equal(expr.Variable("Z"), expr.TRUE),
                            expr.Equal(expr.Call("G", [expr.Variable("F")]),
                                       expr.TRUE),
                        ),
                        description="rfc1149.txt+45:4-47:8",
                    ),
                    Transition("A"),
                ],
                description="rfc1149.txt+51:4-52:9",
            ),
            State("C"),
        ],
        [
            decl.VariableDeclaration("M", "Test::Message"),
            decl.VariableDeclaration("Y", BOOLEAN.identifier, expr.FALSE),
        ],
        [
            decl.ChannelDeclaration("X", readable=True, writable=True),
            decl.TypeDeclaration(Private("Test::T")),
            decl.FunctionDeclaration("F", [], "Test::T"),
            decl.FunctionDeclaration("G", [decl.Argument("P", "Test::T")],
                                     BOOLEAN.identifier),
        ],
        [BOOLEAN, OPAQUE, tag, length, message],
    )
    model = Model(types=[BOOLEAN, OPAQUE, tag, length, message],
                  sessions=[session])
    model.write_specification_files(tmp_path)
    p = parser.Parser()
    p.parse(tmp_path / "test.rflx")
    parsed_model = p.create_model()
    assert parsed_model.types == model.types
    assert parsed_model.sessions == model.sessions
    assert parsed_model == model
Beispiel #28
0
def test_aggregate_rflx_expr() -> None:
    assert ada.Aggregate(ada.Number(1),
                         ada.Number(2)).rflx_expr() == expr.Aggregate(
                             expr.Number(1), expr.Number(2))