Exemple #1
0
def create_array_inner_message() -> Message:
    length_type = ModularInteger("Arrays.Length", Pow(Number(2), Number(8)))

    structure = [
        Link(INITIAL, Field("Length")),
        Link(Field("Length"),
             Field("Payload"),
             length=Mul(Variable("Length"), Number(8))),
        Link(Field("Payload"), FINAL),
    ]

    types = {Field("Length"): length_type, Field("Payload"): Payload()}

    return Message("Arrays.Inner_Message", structure, types)
Exemple #2
0
def test_opaque_valid_byte_aligned_dynamic_mul() -> None:
    Message(
        "P.M",
        [
            Link(INITIAL, Field("L")),
            Link(Field("L"), Field("O1"), length=Mul(Number(8),
                                                     Variable("L"))),
            Link(Field("O1"), FINAL),
        ],
        {
            Field("L"): MODULAR_INTEGER,
            Field("O1"): Opaque()
        },
    )
Exemple #3
0
def test_exclusive_prefixed_enum_valid() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"),
             FINAL,
             condition=Equal(Variable("F1"), Variable("ONE"))),
        Link(Field("F1"),
             Field("F2"),
             condition=Equal(Variable("F1"), Variable("P.TWO"))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"):
        ENUMERATION,
        Field("F2"):
        Enumeration(
            "P2.Enumeration",
            [("ONE", Number(2)), ("TWO", Number(1))],
            Number(8),
            False,
        ),
    }
    Message("P.M", structure, types)
Exemple #4
0
 def bounded_composite_setter_preconditions(
     self, message: Message, field: Field
 ) -> Sequence[Expr]:
     return [
         Call(
             "Field_Condition",
             [Name("Ctx"), NamedAggregate(("Fld", Name(field.affixed_name)))]
             + ([Name("Length")] if length_dependent_condition(message) else []),
         ),
         GreaterEqual(
             Call("Available_Space", [Name("Ctx"), Name(field.affixed_name)]), Name("Length"),
         ),
         LessEqual(
             Add(Call("Field_First", [Name("Ctx"), Name(field.affixed_name)]), Name("Length"),),
             Div(Last(self.types.bit_index), Number(2)),
         ),
         Or(
             *[
                 And(
                     *[
                         Call("Valid", [Name("Ctx"), Name(field.affixed_name)])
                         for field in message.fields
                         if Variable(field.name) in l.condition.variables()
                     ],
                     l.condition.simplified(
                         {
                             Variable(field.name): Call(f"Get_{field.name}", [Name("Ctx")])
                             for field in message.fields
                             if Variable(field.name) in l.condition.variables()
                         }
                     ),
                 )
                 for l in message.incoming(field)
                 if Last("Message") in l.length
             ]
         ),
     ]
Exemple #5
0
 def public_substitution(self, message: Message) -> Mapping[Name, Expr]:
     return {
         **{First("Message"): Selected(Name("Ctx"), "First")},
         **{Last("Message"): Selected(Name("Ctx"), "Last")},
         **{
             First(f.name): Call("Field_First", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Last(f.name): Call("Field_Last", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Length(f.name): Call("Field_Length", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Variable(f.name): Call(
                 self.types.bit_length, [Call(f"Get_{f.name}", [Name("Ctx")])]
             )
             for f, t in message.types.items()
             if not isinstance(t, Enumeration)
         },
         **{
             Variable(f.name): Call(
                 self.types.bit_length, [Call("Convert", [Call(f"Get_{f.name}", [Name("Ctx")])])]
             )
             for f, t in message.types.items()
             if isinstance(t, Enumeration)
         },
         **{
             Variable(l): Call(self.types.bit_length, [Call("Convert", [Name(l)])])
             for l in itertools.chain.from_iterable(
                 t.literals.keys() for t in message.types.values() if isinstance(t, Enumeration)
             )
         },
     }
Exemple #6
0
def test_prefixed_message() -> None:
    assert_equal(
        UnprovenMessage(
            "P.M",
            [
                Link(INITIAL, Field("F1")),
                Link(
                    Field("F1"),
                    Field("F2"),
                    LessEqual(Variable("F1"), Number(100)),
                    first=First("F1"),
                ),
                Link(
                    Field("F1"),
                    Field("F3"),
                    GreaterEqual(Variable("F1"), Number(200)),
                    first=First("F1"),
                ),
                Link(Field("F2"), FINAL),
                Link(Field("F3"), Field("F4"), length=Variable("F3")),
                Link(Field("F4"), FINAL),
            ],
            {
                Field("F1"): deepcopy(MODULAR_INTEGER),
                Field("F2"): deepcopy(MODULAR_INTEGER),
                Field("F3"): deepcopy(RANGE_INTEGER),
                Field("F4"): Opaque(),
            },
        ).prefixed("X_"),
        UnprovenMessage(
            "P.M",
            [
                Link(INITIAL, Field("X_F1")),
                Link(
                    Field("X_F1"),
                    Field("X_F2"),
                    LessEqual(Variable("X_F1"), Number(100)),
                    first=First("X_F1"),
                ),
                Link(
                    Field("X_F1"),
                    Field("X_F3"),
                    GreaterEqual(Variable("X_F1"), Number(200)),
                    first=First("X_F1"),
                ),
                Link(Field("X_F2"), FINAL),
                Link(Field("X_F3"), Field("X_F4"), length=Variable("X_F3")),
                Link(Field("X_F4"), FINAL),
            ],
            {
                Field("X_F1"): deepcopy(MODULAR_INTEGER),
                Field("X_F2"): deepcopy(MODULAR_INTEGER),
                Field("X_F3"): deepcopy(RANGE_INTEGER),
                Field("X_F4"): Opaque(),
            },
        ),
    )
Exemple #7
0
def test_dot_graph_with_double_edge(tmp_path: Path) -> None:
    f_type = ModularInteger("P::T", Pow(Number(2), Number(32)))
    m = Message(
        "P::M",
        structure=[
            Link(INITIAL, Field("X")),
            Link(Field("X"), FINAL, Greater(Variable("X"), Number(100))),
            Link(Field("X"), FINAL, Less(Variable("X"), Number(50))),
        ],
        types={Field("X"): f_type},
    )
    expected = """
        digraph "P::M" {
            graph [bgcolor="#00000000", pad="0.1", ranksep="0.1 equally", splines=true,
                   truecolor=true];
            edge [color="#6f6f6f", fontcolor="#6f6f6f", fontname="Fira Code", penwidth="2.5"];
            node [color="#6f6f6f", fillcolor="#009641", fontcolor="#ffffff", fontname=Arimo,
                  shape=box, style="rounded,filled", width="1.5"];
            Initial [fillcolor="#ffffff", label="", shape=circle, width="0.5"];
            X;
            intermediate_0 [color="#6f6f6f", fontcolor="#6f6f6f", fontname="Fira Code", height=0,
                            label="(⊤, 32, ⋆)", penwidth=0, style="", width=0];
            Initial -> intermediate_0 [arrowhead=none];
            intermediate_0 -> X [minlen=1];
            intermediate_1 [color="#6f6f6f", fontcolor="#6f6f6f", fontname="Fira Code", height=0,
                            label="(X < 50, 0, ⋆)", penwidth=0, style="", width=0];
            X -> intermediate_1 [arrowhead=none];
            intermediate_1 -> Final [minlen=1];
            intermediate_2 [color="#6f6f6f", fontcolor="#6f6f6f", fontname="Fira Code", height=0,
                            label="(X > 100, 0, ⋆)", penwidth=0, style="", width=0];
            X -> intermediate_2 [arrowhead=none];
            intermediate_2 -> Final [minlen=1];
            Final [fillcolor="#6f6f6f", label="", shape=circle, width="0.5"];
        }
        """

    assert_graph(create_message_graph(m), expected, tmp_path)
Exemple #8
0
def test_aggregate_equal_array_valid_length() -> None:
    structure = [
        Link(INITIAL, Field("Magic"), length=Number(14)),
        Link(
            Field("Magic"),
            FINAL,
            condition=NotEqual(Variable("Magic"),
                               Aggregate(Number(1), Number(2))),
        ),
    ]
    types = {
        Field("Magic"): Array("P.Arr", ModularInteger("P.Modular",
                                                      Number(128))),
    }
    Message("P.M", structure, types)
Exemple #9
0
def test_invalid_negative_field_length_modular() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2"), length=Sub(Variable("F1"), Number(2))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): Opaque(),
    }
    assert_message_model_error(
        structure,
        types,
        r'^model: error: negative length for field "F2" [(]F1 -> F2[)]$',
    )
Exemple #10
0
def test_message_invalid_relation_to_aggregate() -> None:
    structure = [
        Link(INITIAL, Field("F1"), length=Number(16)),
        Link(
            Field("F1"),
            FINAL,
            LessEqual(Variable("F1"), Aggregate(Number(1), Number(2)),
                      Location((100, 20))),
        ),
    ]
    types = {Field("F1"): Opaque()}
    assert_message_model_error(
        structure,
        types,
        r'^<stdin>:100:20: model: error: invalid relation " <= " between Opaque and Aggregate$',
    )
Exemple #11
0
 def test_if_simplified(self) -> None:
     self.assertEqual(
         If(
             [
                 (Variable("X"), Number(21)),
                 (Variable("Y"), Add(Number(21), Number(21))),
                 (Add(Number(21), Number(21)), Variable("Z")),
             ]
         ).simplified(),
         If(
             [
                 (Variable("X"), Number(21)),
                 (Variable("Y"), Number(42)),
                 (Number(42), Variable("Z")),
             ]
         ),
     )
     self.assertEqual(If([(TRUE, Variable("X"))]).simplified(), Variable("X"))
Exemple #12
0
 def test_if_variables(self) -> None:
     self.assertEqual(
         If(
             [
                 (Variable("X"), Number(21)),
                 (Variable("Y"), Add(Number(21), Number(21))),
                 (Add(Number(21), Number(21)), Variable("Z")),
             ]
         ).variables(),
         [Variable("X"), Variable("Y"), Variable("Z")],
     )
Exemple #13
0
def test_invalid_negative_field_length_range_integer() -> None:
    o = Field(ID("O", location=Location((44, 3))))
    structure = [
        Link(INITIAL, Field("L")),
        Link(
            Field("L"),
            o,
            length=Mul(Number(8), Sub(Variable("L"), Number(50))),
        ),
        Link(o, FINAL),
    ]
    types = {Field("L"): RANGE_INTEGER, o: Opaque()}
    assert_message_model_error(
        structure,
        types,
        r'^<stdin>:44:3: model: error: negative length for field "O" [(]L -> O[)]$',
    )
Exemple #14
0
def test_message_invalid_element_in_relation_to_aggregate() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(
            Field("F1"),
            FINAL,
            Equal(Variable("F1"), Aggregate(Number(1), Number(2)),
                  Location((14, 7))),
        ),
    ]
    types = {Field("F1"): MODULAR_INTEGER}
    assert_message_model_error(
        structure,
        types,
        r'^<stdin>:14:7: model: error: invalid relation " = " '
        r"between Aggregate and ModularInteger$",
    )
Exemple #15
0
def test_message_subsequent_variable() -> None:
    f1 = Field("F1")
    f2 = Field("F2")
    t = ModularInteger("P.T", Pow(Number(2), Number(32)))
    structure = [
        Link(INITIAL, f1),
        Link(f1, f2,
             Equal(Variable("F2", location=Location((1024, 57))), Number(42))),
        Link(f2, FINAL),
    ]

    types = {Field("F1"): t, Field("F2"): t}
    assert_message_model_error(
        structure,
        types,
        '^<stdin>:1024:57: model: error: subsequent field "F2" referenced',
    )
Exemple #16
0
 def __update_simplified_mapping(self) -> None:
     field_values: Mapping[Name, Expr] = {
         **{
             Variable(k): v.typeval.expr
             for k, v in self._fields.items() if isinstance(
                 v.typeval, ScalarValue) and v.set
         },
         **{
             Length(k): v.typeval.size
             for k, v in self._fields.items() if v.set
         },
         **{First(k): v.first
            for k, v in self._fields.items() if v.set},
         **{Last(k): v.last
            for k, v in self._fields.items() if v.set},
     }
     self._simplified_mapping = {**field_values, **self.__type_literals}
Exemple #17
0
def test_aggregate_inequal_valid_length() -> None:
    structure = [
        Link(INITIAL, Field("Magic"), length=Number(40)),
        Link(
            Field("Magic"),
            FINAL,
            condition=NotEqual(
                Variable("Magic"),
                Aggregate(Number(1), Number(2), Number(3), Number(4),
                          Number(4)),
            ),
        ),
    ]
    types = {
        Field("Magic"): Opaque(),
    }
    Message("P.M", structure, types)
Exemple #18
0
def create_array_messages_message() -> Message:
    structure = [
        Link(INITIAL, Field("Length")),
        Link(Field("Length"),
             Field("Messages"),
             length=Mul(Variable("Length"), Number(8))),
        Link(Field("Messages"), FINAL),
    ]

    types = {
        Field("Length"):
        ModularInteger("Arrays.Length", Pow(Number(2), Number(8))),
        Field("Messages"):
        Array("Arrays.Inner_Messages", Reference("Arrays.Inner_Message")),
    }

    return Message("Arrays.Messages_Message", structure, types)
Exemple #19
0
def test_log_expr_str() -> None:
    assert_equal(
        str(And(Variable("A"), Or(Variable("B"), Variable("C")), Variable("D"))),
        multilinestr(
            """A
               and (B
                    or C)
               and D"""
        ),
    )
    assert_equal(
        str(AndThen(Variable("A"), OrElse(Variable("B"), Variable("C")), Variable("D"))),
        multilinestr(
            """A
               and then (B
                         or else C)
               and then D"""
        ),
    )
Exemple #20
0
 def test_case_variables(self) -> None:
     self.assertEqual(
         Case(
             Add(Number(21), Number(21)),
             [
                 (Variable("X"), Number(21)),
                 (Variable("Y"), Add(Number(21), Number(21))),
                 (Add(Number(21), Number(21)), Variable("Z")),
             ],
         ).variables(),
         [Variable("X"), Variable("Y"), Variable("Z")],
     )
Exemple #21
0
 def unbounded_composite_setter_preconditions(
         message: Message, field: Field) -> Sequence[Expr]:
     return [
         Call(
             "Field_Condition",
             [
                 Variable("Ctx"),
                 NamedAggregate(("Fld", Variable(field.affixed_name)))
             ] + ([
                 Call(
                     "Field_Length",
                     [Variable("Ctx"),
                      Variable(field.affixed_name)],
                 )
             ] if common.length_dependent_condition(message) else []),
         ),
         common.sufficient_space_for_field_condition(
             Variable(field.affixed_name)),
         Equal(
             Mod(
                 Call("Field_First",
                      [Variable("Ctx"),
                       Variable(field.affixed_name)]),
                 Size(const.TYPES_BYTE),
             ),
             Number(1),
         ),
         Equal(
             Mod(
                 Call("Field_Length",
                      [Variable("Ctx"),
                       Variable(field.affixed_name)]),
                 Size(const.TYPES_BYTE),
             ),
             Number(0),
         ),
     ]
Exemple #22
0
 def valid_predecessors_invariant() -> Expr:
     return AndThen(
         *[
             If(
                 [
                     (
                         Call(
                             "Structural_Valid",
                             [Indexed(Variable("Cursors"), Variable(f.affixed_name))],
                         ),
                         Or(
                             *[
                                 AndThen(
                                     Call(
                                         "Structural_Valid"
                                         if l.source in composite_fields
                                         else "Valid",
                                         [
                                             Indexed(
                                                 Variable("Cursors"),
                                                 Variable(l.source.affixed_name),
                                             )
                                         ],
                                     ),
                                     Equal(
                                         Selected(
                                             Indexed(
                                                 Variable("Cursors"), Variable(f.affixed_name),
                                             ),
                                             "Predecessor",
                                         ),
                                         Variable(l.source.affixed_name),
                                     ),
                                     l.condition.substituted(
                                         substitution(message, embedded=True)
                                     ),
                                 ).simplified()
                                 for l in message.incoming(f)
                             ]
                         ),
                     )
                 ]
             )
             for f in message.fields
             if f not in message.direct_successors(INITIAL)
         ]
     )
Exemple #23
0
    def create_valid_message_function(message: Message) -> UnitPart:
        specification = FunctionSpecification("Valid_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [Precondition(Call("Has_Buffer", [Variable("Ctx")]))],
                )
            ],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    valid_message_condition(message).substituted(
                        common.substitution(message)).simplified(),
                )
            ],
        )
Exemple #24
0
def test_tlv_message_with_not_operator() -> None:
    message = Message(
        "TLV::Message_With_Not_Operator",
        [
            Link(INITIAL, Field("Tag")),
            Link(
                Field("Tag"),
                Field("Length"),
                Not(Not(Not(NotEqual(Variable("Tag"), Variable("Msg_Data"))))),
            ),
            Link(
                Field("Tag"),
                FINAL,
                Not(
                    Not(
                        Not(
                            Or(
                                Not(
                                    Not(
                                        Equal(Variable("Tag"),
                                              Variable("Msg_Data")))),
                                Not(
                                    Equal(Variable("Tag"),
                                          Variable("Msg_Error"))),
                            )))),
            ),
            Link(Field("Length"),
                 Field("Value"),
                 size=Mul(Variable("Length"), Number(8))),
            Link(Field("Value"), FINAL),
        ],
        {
            Field("Tag"): TLV_TAG,
            Field("Length"): TLV_LENGTH,
            Field("Value"): OPAQUE
        },
    )

    model = PyRFLX(model=Model([TLV_TAG, TLV_LENGTH, message]))
    pkg = model.package("TLV")
    msg = pkg.new_message("Message_With_Not_Operator")
    test_bytes = b"\x01\x00\x04\x00\x00\x00\x00"
    msg.parse(test_bytes)
    assert msg.valid_message
    assert msg.bytestring == test_bytes
Exemple #25
0
def test_opaque_length_not_multiple_of_8_dynamic() -> None:
    with pytest.raises(
            RecordFluxError,
            match=
            r'^<stdin>:44:3: model: error: length of opaque field "O" not multiple of 8 bit'
            " [(]L -> O[)]",
    ):
        o = Field(ID("O", location=Location((44, 3))))
        Message(
            "P.M",
            [
                Link(INITIAL, Field("L")),
                Link(Field("L"), o, length=Variable("L")),
                Link(o, FINAL)
            ],
            {
                Field("L"): MODULAR_INTEGER,
                o: Opaque()
            },
        )
Exemple #26
0
def test_invalid_type_condition_range_high() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"),
             Field("F2"),
             condition=Greater(Variable("F1"), Number(200))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): RANGE_INTEGER,
        Field("F2"): RANGE_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: contradicting condition in "P.M"\n'
        r'model: info: on path: "F1"\n'
        r'model: info: unsatisfied "F1 <= 100"\n'
        r'model: info: unsatisfied "F1 > 200"',
    )
Exemple #27
0
def test_invalid_type_condition_modular_lower() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"),
             Field("F2"),
             condition=Less(Variable("F1"), Number(0))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: contradicting condition in "P.M"\n'
        r'model: info: on path: "F1"\n'
        r'model: info: unsatisfied "F1 >= 0"\n'
        r'model: info: unsatisfied "F1 < 0"',
    )
Exemple #28
0
def test_aggregate_inequal_invalid_length() -> None:
    structure = [
        Link(INITIAL, Field("Magic"), length=Number(40)),
        Link(
            Field("Magic"),
            FINAL,
            condition=NotEqual(Variable("Magic"),
                               Aggregate(Number(1), Number(2))),
        ),
    ]
    types = {
        Field("Magic"): Opaque(),
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: contradicting condition in "P.M"\n'
        r'model: info: on path: "Magic"\n'
        r'model: info: unsatisfied "2 [*] 8 = Magic\'Length"\n'
        r'model: info: unsatisfied "Magic\'Length = 40"',
    )
Exemple #29
0
def test_opaque_aggregate_out_of_range() -> None:
    f = Field("F")
    with pytest.raises(
            RecordFluxError,
            match=
            r"^<stdin>:44:3: model: error: aggregate element out of range 0 .. 255",
    ):
        Message(
            "P.M",
            [
                Link(INITIAL, f, length=Number(24)),
                Link(
                    f,
                    FINAL,
                    condition=Equal(
                        Variable("F"),
                        Aggregate(Number(1), Number(2),
                                  Number(256, location=Location((44, 3)))),
                    ),
                ),
            ],
            {Field("F"): Opaque()},
        )
Exemple #30
0
 def test_case_simplified(self) -> None:
     self.assertEqual(
         Case(
             Add(Number(21), Number(21)),
             [
                 (Variable("X"), Number(21)),
                 (Variable("Y"), Add(Number(21), Number(21))),
                 (Add(Number(21), Number(21)), Variable("Z")),
             ],
         ).simplified(),
         Case(
             Number(42),
             [
                 (Variable("X"), Number(21)),
                 (Variable("Y"), Number(42)),
                 (Number(42), Variable("Z")),
             ],
         ),
     )