コード例 #1
0
def test_merge_message_simple_derived() -> None:
    assert_equal(
        deepcopy(M_SMPL_REF_DERI).merged(),
        UnprovenDerivedMessage(
            "P.Smpl_Ref_Deri",
            M_SMPL_REF,
            [
                Link(INITIAL, Field("NR_F1"), length=Number(16)),
                Link(Field("NR_F3"), FINAL,
                     Equal(Variable("NR_F3"), Variable("P.ONE"))),
                Link(Field("NR_F4"), FINAL),
                Link(Field("NR_F1"), Field("NR_F2")),
                Link(
                    Field("NR_F2"),
                    Field("NR_F3"),
                    LessEqual(Variable("NR_F2"), Number(100)),
                    first=First("NR_F2"),
                ),
                Link(
                    Field("NR_F2"),
                    Field("NR_F4"),
                    GreaterEqual(Variable("NR_F2"), Number(200)),
                    first=First("NR_F2"),
                ),
            ],
            {
                Field("NR_F1"): Opaque(),
                Field("NR_F2"): deepcopy(MODULAR_INTEGER),
                Field("NR_F3"): deepcopy(ENUMERATION),
                Field("NR_F4"): deepcopy(RANGE_INTEGER),
            },
        ),
    )
コード例 #2
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_slice_simplified() -> None:
    assert_equal(
        Slice(
            Variable("Buffer"), First("Buffer"), Add(Last("Buffer"), Add(Number(21), Number(21))),
        ).simplified(),
        Slice(Variable("Buffer"), First("Buffer"), Add(Last("Buffer"), Number(42))),
    )
コード例 #3
0
def test_conditionally_unreachable_field_enum_first() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2"), Greater(First("F1"), First("Message"))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): ENUMERATION,
        Field("F2"): ENUMERATION,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: unreachable field "F1" in "P.M"\n'
        r"model: info: path 0 [(]F1[)]:\n"
        r'model: info: unsatisfied "F1\'First = Message\'First"\n'
        r'model: info: unsatisfied "F1\'First > Message\'First"\n'
        r'model: error: unreachable field "F2" in "P.M"\n'
        r"model: info: path 0 [(]F1 -> F2[)]:\n"
        r'model: info: unsatisfied "F1\'First = Message\'First"\n'
        r'model: info: unsatisfied "F1\'First > Message\'First"\n'
        r'model: error: unreachable field "Final" in "P.M"\n'
        r"model: info: path 0 [(]F1 -> F2 -> Final[)]:\n"
        r'model: info: unsatisfied "F1\'First = Message\'First"\n'
        r'model: info: unsatisfied "F1\'First > Message\'First"',
    )
コード例 #4
0
ファイル: test_expression.py プロジェクト: senier/RecordFlux
 def test_slice_simplified(self) -> None:
     self.assertEqual(
         Slice(
             "Buffer", First("Buffer"), Add(Last("Buffer"), Add(Number(21), Number(21)))
         ).simplified(),
         Slice("Buffer", First("Buffer"), Add(Last("Buffer"), Number(42))),
     )
コード例 #5
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(),
            },
        ),
    )
コード例 #6
0
def test_merge_message_recursive() -> None:
    assert_equal(
        deepcopy(M_DBL_REF).merged(),
        UnprovenMessage(
            "P.Dbl_Ref",
            [
                Link(INITIAL, Field("SR_NR_F1"), length=Number(16)),
                Link(
                    Field("SR_NR_F3"),
                    Field("NR_F1"),
                    Equal(Variable("SR_NR_F3"), Variable("P.ONE")),
                    length=Number(16),
                ),
                Link(Field("SR_NR_F4"), Field("NR_F1"), length=Number(16)),
                Link(Field("NR_F3"), FINAL,
                     Equal(Variable("NR_F3"), Variable("P.ONE"))),
                Link(Field("NR_F4"), FINAL),
                Link(Field("SR_NR_F1"), Field("SR_NR_F2")),
                Link(
                    Field("SR_NR_F2"),
                    Field("SR_NR_F3"),
                    LessEqual(Variable("SR_NR_F2"), Number(100)),
                    first=First("SR_NR_F2"),
                ),
                Link(
                    Field("SR_NR_F2"),
                    Field("SR_NR_F4"),
                    GreaterEqual(Variable("SR_NR_F2"), Number(200)),
                    first=First("SR_NR_F2"),
                ),
                Link(Field("NR_F1"), Field("NR_F2")),
                Link(
                    Field("NR_F2"),
                    Field("NR_F3"),
                    LessEqual(Variable("NR_F2"), Number(100)),
                    first=First("NR_F2"),
                ),
                Link(
                    Field("NR_F2"),
                    Field("NR_F4"),
                    GreaterEqual(Variable("NR_F2"), Number(200)),
                    first=First("NR_F2"),
                ),
            ],
            {
                Field("SR_NR_F1"): Opaque(),
                Field("SR_NR_F2"): deepcopy(MODULAR_INTEGER),
                Field("SR_NR_F3"): deepcopy(ENUMERATION),
                Field("SR_NR_F4"): deepcopy(RANGE_INTEGER),
                Field("NR_F1"): Opaque(),
                Field("NR_F2"): deepcopy(MODULAR_INTEGER),
                Field("NR_F3"): deepcopy(ENUMERATION),
                Field("NR_F4"): deepcopy(RANGE_INTEGER),
            },
        ),
    )
コード例 #7
0
ファイル: common.py プロジェクト: senier/RecordFlux
    def substitution(self, message: Message, prefix: bool = True) -> Mapping[Name, Expr]:
        def prefixed(name: str) -> Expr:
            return Selected(Name("Ctx"), name) if prefix else Name(name)

        first = prefixed("First")
        last = prefixed("Last")
        cursors = prefixed("Cursors")

        return {
            **{First("Message"): first},
            **{Last("Message"): last},
            **{
                First(f.name): Selected(Indexed(cursors, Name(f.affixed_name)), "First")
                for f in message.fields
            },
            **{
                Last(f.name): Selected(Indexed(cursors, Name(f.affixed_name)), "Last")
                for f in message.fields
            },
            **{
                Length(f.name): Add(
                    Sub(
                        Selected(Indexed(cursors, Name(f.affixed_name)), "Last"),
                        Selected(Indexed(cursors, Name(f.affixed_name)), "First"),
                    ),
                    Number(1),
                )
                for f in message.fields
            },
            **{
                Variable(f.name): Call(
                    self.types.bit_length,
                    [Selected(Indexed(cursors, Name(f.affixed_name)), f"Value.{f.name}_Value")],
                )
                for f, t in message.types.items()
                if not isinstance(t, Enumeration)
            },
            **{
                Variable(f.name): Call(
                    self.types.bit_length,
                    [Selected(Indexed(cursors, Name(f.affixed_name)), f"Value.{f.name}_Value")],
                )
                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)
                )
            },
        }
コード例 #8
0
ファイル: model.py プロジェクト: senier/RecordFlux
 def __link_expression(self, link: Link) -> Expr:
     name = link.target.name
     return And(
         *[
             Equal(First(name), self.__target_first(link)),
             Equal(Length(name), self.__target_length(link)),
             Equal(Last(name), self.__target_last(link)),
             GreaterEqual(First("Message"), Number(0)),
             GreaterEqual(Last("Message"), Last(name)),
             GreaterEqual(Last("Message"), First("Message")),
             Equal(Length("Message"), Add(Sub(Last("Message"), First("Message")), Number(1))),
             link.condition,
         ]
     )
コード例 #9
0
def test_no_verification_icmp_checksum(
        icmp_checksum_message_value: MessageValue,
        icmp_message: Message) -> None:
    test_data = (
        b"\x47\xb4\x67\x5e\x00\x00\x00\x00"
        b"\x4a\xfc\x0d\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17"
        b"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27"
        b"\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37")
    icmp_checksum_unv = MessageValue(
        icmp_message.copy(
            structure=[
                Link(l.source,
                     l.target,
                     condition=And(l.condition, ValidChecksum("Checksum")))
                if l.target == FINAL else l for l in icmp_message.structure
            ],
            checksums={
                ID("Checksum"): [
                    ValueRange(First("Tag"), Sub(First("Checksum"),
                                                 Number(1))),
                    Size("Checksum"),
                    ValueRange(Add(Last("Checksum"), Number(1)),
                               Last("Message")),
                ]
            },
        ),
        skip_verification=True,
    )
    icmp_checksum_message_value.set_checksum_function(
        {"Checksum": icmp_checksum_function})
    icmp_checksum_message_value.set("Tag", "Echo_Request")
    icmp_checksum_message_value.set("Code_Zero", 0)
    icmp_checksum_message_value.set("Identifier", 5)
    icmp_checksum_message_value.set("Sequence_Number", 1)
    icmp_checksum_message_value.set("Data", test_data)
    icmp_checksum_unv.set_checksum_function(
        {"Checksum": icmp_checksum_function})
    icmp_checksum_unv.set("Tag", "Echo_Request")
    icmp_checksum_unv.set("Code_Zero", 0)
    icmp_checksum_unv.set("Checksum", 0)
    icmp_checksum_unv.set("Identifier", 5)
    icmp_checksum_unv.set("Sequence_Number", 1)
    icmp_checksum_unv.set("Data", test_data)
    icmp_checksum_unv.update_checksums()
    assert icmp_checksum_unv.valid_message
    assert icmp_checksum_unv.get(
        "Checksum") == icmp_checksum_message_value.get("Checksum")
    assert icmp_checksum_unv.bytestring == icmp_checksum_message_value.bytestring
コード例 #10
0
def test_incongruent_overlay() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2")),
        Link(Field("F2"), Field("F3"), first=First("F1")),
        Link(Field("F3"), Field("F4")),
        Link(Field("F4"), FINAL),
    ]
    u8 = ModularInteger("P.U8", Number(256))
    u16 = ModularInteger("P.U16", Number(65536))
    types = {
        Field("F1"): u8,
        Field("F2"): u8,
        Field("F3"): u16,
        Field("F4"): u16,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: field "F3" not congruent with overlaid field "F1"\n'
        r'model: info: unsatisfied "F1\'First = Message\'First"\n'
        r'model: info: unsatisfied "F1\'Last = [(][(]Message\'First [+] 8[)][)] - 1"\n'
        r'model: info: unsatisfied "[(][(]F1\'First [+] 16[)][)] - 1 = F1\'Last"'
        r"$",
    )
コード例 #11
0
ファイル: test_model.py プロジェクト: senier/RecordFlux
 def test_message_incoming(self) -> None:
     self.assertEqual(ETHERNET_FRAME.incoming(INITIAL), [])
     self.assertEqual(
         ETHERNET_FRAME.incoming(Field("Type_Length")),
         [
             Link(
                 Field("Type_Length_TPID"),
                 Field("Type_Length"),
                 NotEqual(Variable("Type_Length_TPID"), Number(0x8100, 16)),
                 first=First("Type_Length_TPID"),
             ),
             Link(Field("TCI"), Field("Type_Length")),
         ],
     )
     self.assertEqual(
         ETHERNET_FRAME.incoming(FINAL),
         [
             Link(
                 Field("Payload"),
                 FINAL,
                 And(
                     GreaterEqual(Div(Length("Payload"), Number(8)), Number(46)),
                     LessEqual(Div(Length("Payload"), Number(8)), Number(1500)),
                 ),
             )
         ],
     )
コード例 #12
0
def parse_attribute(string: str, location: int, tokens: list) -> Attribute:
    if tokens[2] == 'First':
        return First(tokens[0])
    if tokens[2] == 'Last':
        return Last(tokens[0])
    if tokens[2] == 'Length':
        return Length(tokens[0])
    raise ParseFatalException(string, location, 'unexpected attribute')
コード例 #13
0
def create_facts(facts: Dict[Attribute, MathExpr],
                 edge: Edge) -> Dict[Attribute, MathExpr]:
    facts = dict(facts)
    facts[Length(edge.target.name)] = edge.length.simplified(facts)
    facts[First(edge.target.name)] = edge.first.simplified(facts)
    facts[Last(edge.target.name)] = Add(edge.first, edge.length,
                                        Number(-1)).simplified(facts)
    return facts
コード例 #14
0
def parse_attribute(string: str, location: int,
                    tokens: ParseResults) -> Attribute:
    if tokens[2] == "First":
        return First(tokens[0])
    if tokens[2] == "Last":
        return Last(tokens[0])
    if tokens[2] == "Length":
        return Length(tokens[0])
    raise ParseFatalException(string, location, "unexpected attribute")
コード例 #15
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_aggregate_substituted() -> None:
    assert_equal(
        Aggregate(First("X")).substituted(
            lambda x: Number(42) if x == Aggregate(First("X")) else x
        ),
        Number(42),
    )
    assert_equal(
        Aggregate(First("X")).substituted(lambda x: Number(42) if x == First("X") else x),
        Aggregate(Number(42)),
    )
    assert_equal(
        Aggregate(Variable("X")).substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (Aggregate(*(x.elements + [Variable("Y")])) if isinstance(x, Aggregate) else x)
        ),
        Aggregate(Variable("P_X"), Variable("P_Y")),
    )
コード例 #16
0
def test_valid_first() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2"), first=First("F1")),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
    }
    Message("P.M", structure, types)
コード例 #17
0
def test_valid_use_message_first_last() -> None:
    structure = [
        Link(
            INITIAL,
            Field("Verify_Data"),
            length=Add(Sub(Last("Message"), First("Message")), Number(1)),
        ),
        Link(Field("Verify_Data"), FINAL),
    ]
    types = {Field("Verify_Data"): Opaque()}
    Message("P.M", structure, types)
コード例 #18
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_named_aggregate_substituted() -> None:
    assert_equal(
        NamedAggregate(("First", First("X"))).substituted(
            lambda x: Number(42) if x == NamedAggregate(("First", First("X"))) else x
        ),
        Number(42),
    )
    assert_equal(
        NamedAggregate(("First", First("X"))).substituted(
            lambda x: Number(42) if x == First("X") else x
        ),
        NamedAggregate(("First", Number(42))),
    )
    assert_equal(
        NamedAggregate(("First", First("X"))).substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (
                NamedAggregate(*[*x.elements, (ID("Last"), Last("Y"))])
                if isinstance(x, NamedAggregate)
                else x
            )
        ),
        NamedAggregate(("First", First("P_X")), ("Last", Last("P_Y"))),
    )
コード例 #19
0
    def test_pdu_fields_invalid_self_reference(self) -> None:
        t = ModularInteger('T', Number(2))

        initial = InitialNode()
        n1 = Node('X', t)
        n2 = Node('Y', t)

        initial.edges = [Edge(n1, TRUE)]
        n1.edges = [Edge(n2, first=First('Y'))]
        n2.edges = [Edge(FINAL)]

        with self.assertRaisesRegex(ExpressionError, 'self-reference to "Y\'First"'):
            PDU('Z', initial).fields()
コード例 #20
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_attribute() -> None:
    assert isinstance(Size("X"), Attribute)
    assert isinstance(Length("X"), Attribute)
    assert isinstance(First("X"), Attribute)
    assert isinstance(Last("X"), Attribute)
    assert isinstance(Range("X"), Attribute)
    assert isinstance(Old("X"), Attribute)
    assert isinstance(Result("X"), Attribute)
    assert isinstance(Constrained("X"), Attribute)
    assert First("X") == First(Variable("X"))
    assert First("X") == First(ID("X"))
    assert First("X") == First(Variable(ID("X")))
コード例 #21
0
def test_invalid_first_forward_reference() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2"), first=First("F3")),
        Link(Field("F2"), Field("F3")),
        Link(Field("F3"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
        Field("F3"): MODULAR_INTEGER,
    }
    assert_message_model_error(
        structure, types, '^model: error: subsequent field "F3" referenced$')
コード例 #22
0
ファイル: common.py プロジェクト: senier/RecordFlux
 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)
             )
         },
     }
コード例 #23
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_attribute_substituted() -> None:
    assert_equal(First("X").substituted(lambda x: Number(42) if x == First("X") else x), Number(42))
    assert_equal(
        -First("X").substituted(lambda x: Number(42) if x == First("X") else x), Number(-42)
    )
    assert_equal(
        First("X").substituted(lambda x: Call("Y") if x == Variable("X") else x), First(Call("Y")),
    )
    assert_equal(
        -First("X").substituted(lambda x: Call("Y") if x == Variable("X") else x),
        -First(Call("Y")),
    )
    assert_equal(
        -First("X").substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (Last(x.prefix) if isinstance(x, First) else x)
        ),
        -Last(Variable("P_X")),
    )
コード例 #24
0
    def test_field_coverage_1(self) -> None:
        foo_type = ModularInteger("P.Foo", Pow(Number(2), Number(32)))
        structure = [
            Link(INITIAL, Field("F1")),
            Link(Field("F1"),
                 Field("F2"),
                 first=Add(First("Message"), Number(64))),
            Link(Field("F2"), FINAL),
        ]

        types = {Field("F1"): foo_type, Field("F2"): foo_type}
        with mock.patch("rflx.model.Message._Message__verify_conditions",
                        lambda x: None):
            with self.assertRaisesRegex(
                    ModelError, "^path F1 -> F2 does not cover whole message"):
                Message("P.M", structure, types)
コード例 #25
0
ファイル: model.py プロジェクト: senier/RecordFlux
    def __prove_coverage(self) -> None:
        """
        Prove that the fields of a message cover all message bits, i.e. there are no holes in the
        message definition.

        Idea: Let f be the bits covered by the message. By definition
            (1) f >= Message'First and f <= Message'Last
        holds. For every field add a conjunction of the form
            (2) Not(f >= Field'First and f <= Field'Last),
        effectively pruning the range that this field covers from the bit range of the message. For
        the overall expression, prove that it is false for all f, i.e. no bits are left.
        """
        for path in [p[:-1] for p in self.__paths[FINAL] if p]:
            # Calculate (1)
            message_range = And(
                GreaterEqual(Variable("f"), First("Message")),
                LessEqual(Variable("f"), Last("Message")),
            )
            # Calculate (2) for all fields
            fields = And(
                *[
                    Not(
                        And(
                            GreaterEqual(Variable("f"), self.__target_first(l)),
                            LessEqual(Variable("f"), self.__target_last(l)),
                        )
                    )
                    for l in path
                ]
            )
            # Define that the end of the last field of a path is the end of the message
            last_field = Equal(self.__target_last(path[-1]), Last("Message"))
            # Constraints for links and types
            path_expressions = self.__with_constraints(
                And(*[self.__link_expression(l) for l in path])
            )

            # Coverage expression must be False, i.e. no bits left
            coverage = Not(And(*[fields, last_field, path_expressions, message_range]))
            result = coverage.forall()
            if result != ProofResult.sat:
                path_message = " -> ".join([l.target.name for l in path])
                message = str(coverage).replace("\n\t", "")
                raise ModelError(
                    f"path {path_message} does not cover whole message"
                    f' in "{self.full_name}" ({result}: {message})'
                )
コード例 #26
0
ファイル: model.py プロジェクト: senier/RecordFlux
    def __prove_field_positions(self) -> None:
        for f in self.__fields:
            for p, l in [(p, p[-1]) for p in self.__paths[f] if p]:
                path_expressions = And(*[self.__link_expression(l) for l in p])
                length = self.__target_length(l)
                positive = If(
                    [
                        (
                            And(
                                self.__type_constraints(And(path_expressions, length)),
                                path_expressions,
                            ),
                            GreaterEqual(length, Number(0)),
                        )
                    ],
                    TRUE,
                )
                result = positive.forall()
                if result != ProofResult.sat:
                    path_message = " -> ".join([l.target.name for l in p])
                    message = str(positive.simplified()).replace("\n\t", "")
                    raise ModelError(
                        f'negative length for field "{f.name}" on path {path_message}'
                        f' in "{self.full_name}" ({result}: {message})'
                    )

                first = self.__target_first(l)
                start = If(
                    [
                        (
                            And(
                                self.__type_constraints(And(path_expressions, first)),
                                path_expressions,
                            ),
                            GreaterEqual(first, First("Message")),
                        )
                    ],
                    TRUE,
                )
                result = start.forall()
                if result != ProofResult.sat:
                    path_message = " -> ".join([l.target.name for l in p])
                    message = str(start.simplified()).replace("\n\t", "")
                    raise ModelError(
                        f'start of field "{f.name}" on path {path_message} before'
                        f' message start in "{self.full_name} ({result}: {message})'
                    )
コード例 #27
0
ファイル: typevalue.py プロジェクト: kug1977/RecordFlux
 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}
コード例 #28
0
    def test_field_after_message_start(self) -> None:
        foo_type = ModularInteger("P.Foo", Pow(Number(2), Number(32)))
        structure = [
            Link(INITIAL, Field("F1")),
            Link(Field("F1"),
                 Field("F2"),
                 first=Sub(First("Message"), Number(1000))),
            Link(Field("F2"), FINAL),
        ]

        types = {Field("F1"): foo_type, Field("F2"): foo_type}
        with mock.patch("rflx.model.Message._Message__verify_conditions",
                        lambda x: None):
            with self.assertRaisesRegex(
                    ModelError, '^start of field "F2" on path F1 -> F2 before'
                    " message start"):
                Message("P.M", structure, types)
コード例 #29
0
def test_invalid_first() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"),
             Field("F2"),
             first=Add(First("F1"), Number(8), location=Location((5, 14)))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r'^<stdin>:5:14: model: error: invalid First for field "F2"$',
    )
コード例 #30
0
def test_field_after_message_start(monkeypatch: Any) -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"),
             Field("F2"),
             first=Sub(First("Message"), Number(1000))),
        Link(Field("F2"), FINAL),
    ]

    types = {Field("F1"): MODULAR_INTEGER, Field("F2"): MODULAR_INTEGER}
    monkeypatch.setattr(Message, "_AbstractMessage__verify_conditions",
                        lambda x: None)
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: negative start for field "F2" [(]F1 -> F2[)]\n'
        r'model: info: unsatisfied "Message\'First - 1000 >= Message\'First"'
        r"$",
    )