示例#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
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
 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
    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
 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
 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
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
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
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
 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
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
    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
    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
 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"$",
    )