示例#1
0
def test_unexpected_mathematical_operator() -> None:
    with pytest.raises(ParseFatalException, match=r"^unexpected mathematical operator"):
        grammar.parse_mathematical_expression(
            "",
            0,
            [[Number(1, location=Location((1, 1))), "//", Number(1, location=Location((1, 8)))]],
        )
示例#2
0
def test_aggregate_equal_array_invalid_length() -> None:
    magic = Field(ID("Magic", Location((3, 5))))
    structure = [
        Link(INITIAL, magic, length=Number(40, location=Location((19, 17)))),
        Link(
            magic,
            FINAL,
            condition=NotEqual(Variable("Magic"),
                               Aggregate(Number(1), Number(2)),
                               Location((17, 3))),
        ),
    ]
    types = {
        Field("Magic"):
        Array(
            "P.Arr",
            ModularInteger("P.Modular",
                           Number(128),
                           location=Location((66, 3)))),
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'<stdin>:17:3: model: error: contradicting condition in "P.M"\n'
        r'<stdin>:3:5: model: info: on path: "Magic"\n'
        r'<stdin>:17:3: model: info: unsatisfied "2 [*] Modular\'Length = Magic\'Length"\n'
        r'<stdin>:66:3: model: info: unsatisfied "Modular\'Length = 7"\n'
        r'<stdin>:19:17: model: info: unsatisfied "Magic\'Length = 40"',
    )
示例#3
0
def test_merge_message_error_name_conflict() -> None:
    m2_f2 = Field(ID("F2", Location((10, 5))))

    m2 = UnprovenMessage(
        "P.M2",
        [Link(INITIAL, m2_f2), Link(m2_f2, FINAL)],
        {Field("F2"): MODULAR_INTEGER},
        Location((15, 3)),
    )

    m1_f1 = Field(ID("F1", Location((20, 8))))
    m1_f1_f2 = Field(ID("F1_F2", Location((30, 5))))

    m1 = UnprovenMessage(
        "P.M1",
        [Link(INITIAL, m1_f1),
         Link(m1_f1, m1_f1_f2),
         Link(m1_f1_f2, FINAL)],
        {
            Field("F1"): m2,
            Field("F1_F2"): MODULAR_INTEGER
        },
        Location((2, 9)),
    )

    assert_type_error(
        m1.merged(),
        r"^"
        r'<stdin>:30:5: model: error: name conflict for "F1_F2" in "P.M1"\n'
        r'<stdin>:15:3: model: info: when merging message "P.M2"\n'
        r'<stdin>:20:8: model: info: into field "F1"$',
    )
示例#4
0
def test_conditionally_unreachable_field_outgoing_multi() -> None:
    f2 = Field(ID("F2", Location((90, 12))))
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), f2,
             LessEqual(Variable("F1"), Number(32), Location((66, 3)))),
        Link(Field("F1"), Field("F3"), Greater(Variable("F1"), Number(32))),
        Link(
            f2,
            Field("F3"),
            And(
                Greater(Variable("F1"), Number(32)),
                LessEqual(Variable("F1"), Number(48)),
                location=Location((22, 34)),
            ),
        ),
        Link(f2, FINAL, Greater(Variable("F1"), Number(48))),
        Link(Field("F3"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
        Field("F3"): MODULAR_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'<stdin>:90:12: model: error: unreachable field "F2" in "P.M"\n'
        r"<stdin>:90:12: model: info: path 0 [(]F1 -> F2[)]:\n"
        r'<stdin>:66:3: model: info: unsatisfied "F1 <= 32"\n'
        r'<stdin>:90:12: model: info: unsatisfied "[(]F1 > 32 and F1 <= 48[)] or F1 > 48"',
    )
示例#5
0
def test_exclusive_conflict() -> None:
    f1 = Field(ID("F1", Location((8, 4))))
    structure = [
        Link(INITIAL, f1),
        Link(f1,
             FINAL,
             condition=Greater(Variable("F1"), Number(50), Location((10, 5)))),
        Link(f1,
             Field("F2"),
             condition=Less(Variable("F1"), Number(80), Location((11, 7)))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): RANGE_INTEGER,
        Field("F2"): RANGE_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'<stdin>:8:4: model: error: conflicting conditions for field "F1"\n'
        r"<stdin>:10:5: model: info: condition 0 [(]F1 -> Final[)]: F1 > 50\n"
        r"<stdin>:11:7: model: info: condition 1 [(]F1 -> F2[)]: F1 < 80"
        r"$",
    )
示例#6
0
def test_exclusive_with_length_invalid() -> None:
    f1 = Field(ID("F1", Location((98, 10))))
    structure = [
        Link(INITIAL, f1, length=Number(32)),
        Link(f1,
             FINAL,
             condition=Equal(Length("F1"), Number(32), Location((10, 2)))),
        Link(f1,
             Field("F2"),
             condition=Equal(Length("F1"), Number(32), Location((12, 4)))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): Opaque(),
        Field("F2"): RANGE_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'<stdin>:98:10: model: error: conflicting conditions for field "F1"\n'
        r"<stdin>:10:2: model: info: condition 0 [(]F1 -> Final[)]: F1\'Length = 32\n"
        r"<stdin>:12:4: model: info: condition 1 [(]F1 -> F2[)]: F1\'Length = 32"
        r"$",
    )
示例#7
0
def test_message_unsupported_expression() -> None:
    x = Field("X")

    structure = [
        Link(INITIAL, x),
        Link(
            x,
            FINAL,
            condition=LessEqual(
                Pow(
                    Number(2),
                    Add(Variable("X", location=Location((10, 23))), Number(1)),
                    location=Location((10, 19)),
                ),
                Number(1024),
            ),
        ),
    ]

    types = {x: MODULAR_INTEGER}

    assert_message_model_error(
        structure,
        types,
        '^<stdin>:10:19: model: error: unsupported expression in "P.M"\n'
        '<stdin>:10:23: model: info: variable "X" in exponent',
    )
示例#8
0
def test_refinement_invalid_field_type() -> None:
    x = Field(ID("X", Location((20, 10))))

    message = Message("P.M",
                      [Link(INITIAL, x), Link(x, FINAL)], {x: MODULAR_INTEGER})

    assert_type_error(
        Refinement("P", message, Field(ID("X", Location((33, 22)))), message),
        r'^<stdin>:33:22: model: error: invalid type of field "X" in refinement of "P.M"\n'
        r"<stdin>:20:10: model: info: expected field of type Opaque",
    )
示例#9
0
def test_enumeration_invalid_literal() -> None:
    assert_type_error(
        Enumeration("P.T", [("A B", Number(1))], Number(8), False,
                    Location(((1, 2)))),
        r'^<stdin>:1:2: model: error: invalid literal name "A B" in "T"$',
    )
    assert_type_error(
        Enumeration("P.T", [("A.B", Number(1))], Number(8), False,
                    Location((6, 4))),
        r'^<stdin>:6:4: model: error: invalid literal name "A.B" in "T"$',
    )
示例#10
0
def test_type_name() -> None:
    t = ModularInteger("Package.Type_Name", Number(256))
    assert t.name == "Type_Name"
    assert t.package == ID("Package")
    assert_type_error(
        ModularInteger("X", Number(256), Location((10, 20))),
        r'^<stdin>:10:20: model: error: unexpected format of type name "X"$',
    )
    assert_type_error(
        ModularInteger("X.Y.Z", Number(256), Location((10, 20))),
        '^<stdin>:10:20: model: error: unexpected format of type name "X.Y.Z"$',
    )
示例#11
0
def test_invalid_enumeration_type_duplicate_elements() -> None:
    assert_type_error(
        Enumeration(
            "P.T",
            [(ID("Foo", Location((3, 27))), Number(1)),
             (ID("Foo", Location((3, 32))), Number(2))],
            Number(1),
            False,
        ),
        r'<stdin>:3:32: model: error: duplicate literal "Foo"\n'
        r"<stdin>:3:27: model: info: previous occurrence",
    )
示例#12
0
def test_conflicting_refinements() -> None:
    r1 = copy(models.REFINEMENT)
    r1.location = Location((10, 20))
    r2 = copy(models.REFINEMENT)
    r2.location = Location((10, 30))

    assert_model_error(
        [models.MESSAGE, r1, r2],
        r"^"
        r'<stdin>:10:30: model: error: conflicting refinement of "P::M" with "P::M"\n'
        r"<stdin>:10:20: model: info: previous occurrence of refinement"
        r"$",
    )
示例#13
0
def test_name_conflict_types() -> None:
    assert_model_error(
        [
            ModularInteger(ID("P::T"), Number(256), location=Location((10, 20))),
            RangeInteger(
                ID("P::T"), Number(1), Number(100), Number(8), location=Location((11, 30))
            ),
        ],
        r"^"
        r'<stdin>:11:30: model: error: name conflict for type "P::T"\n'
        r'<stdin>:10:20: model: info: previous occurrence of "P::T"'
        r"$",
    )
示例#14
0
def test_field_locations() -> None:
    f2 = Field(ID("F2", Location((2, 2))))
    f3 = Field(ID("F3", Location((3, 2))))

    message = UnprovenMessage(
        "P.M",
        [Link(INITIAL, f2), Link(f2, f3),
         Link(f3, FINAL)],
        {
            Field("F2"): MODULAR_INTEGER,
            Field("F3"): MODULAR_INTEGER
        },
        Location((17, 9)),
    )
    assert message.fields == (f2, f3)
示例#15
0
def test_array_unsupported_element_type() -> None:
    assert_type_error(
        Array(
            "P.A",
            ModularInteger("P.B", Pow(Number(2), Number(4)), Location((3, 4))),
            Location((5, 4)),
        ),
        r'^<stdin>:5:4: model: error: unsupported element type size of array "A"\n'
        r'<stdin>:3:4: model: info: type "B" has size 4, must be multiple of 8$',
    )
    assert_type_error(
        Array("P.A", BOOLEAN, Location((5, 4))),
        r'^<stdin>:5:4: model: error: unsupported element type size of array "A"\n'
        r'__BUILTINS__:0:0: model: info: type "Boolean" has size 1, must be multiple of 8$',
    )
示例#16
0
def test_enumeration_invalid_literal_value() -> None:
    assert_type_error(
        Enumeration("P.T", [("A", Number(2**63))], Number(64), False,
                    Location((10, 5))),
        r'^<stdin>:10:5: model: error: enumeration value of "T"'
        r" outside of permitted range \(0 .. 2\*\*63 - 1\)$",
    )
示例#17
0
def test_range_invalid_size_exceeds_limit() -> None:
    # ISSUE: Componolit/RecordFlux#238
    assert_type_error(
        RangeInteger("P.T", Number(0), Number(256), Number(128),
                     Location((50, 3))),
        r'^<stdin>:50:3: model: error: size of "T" exceeds limit \(2\*\*64\)$',
    )
示例#18
0
def test_opaque_not_byte_aligned_dynamic() -> None:
    with pytest.raises(
            RecordFluxError,
            match=
            r'^<stdin>:44:3: model: error: opaque field "O2" not aligned to'
            r" 8 bit boundary [(]L1 -> O1 -> L2 -> O2[)]",
    ):
        o2 = Field(ID("O2", location=Location((44, 3))))
        Message(
            "P.M",
            [
                Link(INITIAL, Field("L1")),
                Link(
                    Field("L1"),
                    Field("O1"),
                    length=Variable("L1"),
                    condition=Equal(Mod(Variable("L1"), Number(8)), Number(0)),
                ),
                Link(Field("O1"), Field("L2")),
                Link(Field("L2"), o2, length=Number(128)),
                Link(o2, FINAL),
            ],
            {
                Field("L1"): MODULAR_INTEGER,
                Field("L2"): ModularInteger("P.T", Number(4)),
                Field("O1"): Opaque(),
                o2: Opaque(),
            },
        )
示例#19
0
def test_conflicting_literal_builtin_type() -> None:
    assert_model_error(
        [
            Enumeration(
                "P.T",
                [
                    (ID("E1", Location((3, 27))), Number(1)),
                    (ID("Boolean", Location((3, 31))), Number(2)),
                ],
                Number(8),
                False,
            ),
        ],
        r'<stdin>:3:31: model: error: literal conflicts with type "Boolean"\n'
        r"__BUILTINS__:0:0: model: info: conflicting type declaration",
    )
示例#20
0
def test_array_aggregate_invalid_element_type() -> None:
    inner = Message(
        "P.I",
        [Link(INITIAL, Field("F")),
         Link(Field("F"), FINAL)],
        {Field("F"): MODULAR_INTEGER},
    )
    array_type = Array("P.Array", inner)

    f = Field("F")
    with pytest.raises(
            RecordFluxError,
            match=r"^<stdin>:90:10: model: error: invalid array element type"
            ' "P.I" for aggregate comparison$',
    ):
        Message(
            "P.M",
            [
                Link(INITIAL, f, length=Number(18)),
                Link(
                    f,
                    FINAL,
                    condition=Equal(
                        Variable("F"),
                        Aggregate(Number(1), Number(2), Number(64)),
                        Location((90, 10)),
                    ),
                ),
            ],
            {Field("F"): array_type},
        )
示例#21
0
def test_array_aggregate_out_of_range() -> None:
    array_type = Array("P.Array", ModularInteger("P.Element", Number(64)))

    f = Field("F")
    with pytest.raises(
            RecordFluxError,
            match=
            r"^<stdin>:44:3: model: error: aggregate element out of range 0 .. 63",
    ):
        Message(
            "P.M",
            [
                Link(INITIAL, f, length=Number(18)),
                Link(
                    f,
                    FINAL,
                    condition=Equal(
                        Variable("F"),
                        Aggregate(Number(1), Number(2),
                                  Number(64, location=Location((44, 3)))),
                    ),
                ),
            ],
            {Field("F"): array_type},
        )
示例#22
0
def test_name_conflict_sessions() -> None:
    s1 = copy(models.SESSION)
    s1.location = Location((10, 20))
    s2 = copy(models.SESSION)
    s2.location = Location((10, 30))

    with pytest.raises(
        RecordFluxError,
        match=(
            r"^"
            r'<stdin>:10:30: model: error: name conflict for session "P::S"\n'
            r'<stdin>:10:20: model: info: previous occurrence of "P::S"'
            r"$"
        ),
    ):
        Model([], [s1, s2])
示例#23
0
def parse_mathematical_expression(string: str, location: int,
                                  tokens: ParseResults) -> Expr:
    result: List[Expr] = tokens[0]
    while len(result) > 1:
        left = result.pop(0)
        operator = result.pop(0)
        right = result.pop(0)
        assert left.location, f'expression "{left}" without location'
        assert right.location, f'expression "{right}" without location'
        assert left.location.source == right.location.source, "expression with different source"
        locn = Location(left.location.start, left.location.source,
                        left.location.end)
        expression: Expr
        if operator == "+":
            expression = Add(left, right)
            expression.location = locn
        elif operator == "-":
            expression = Sub(left, right, locn)
        elif operator == "*":
            expression = Mul(left, right)
            expression.location = locn
        elif operator == "/":
            expression = Div(left, right, locn)
        elif operator == "**":
            expression = Pow(left, right, locn)
        else:
            raise ParseFatalException(string, location,
                                      "unexpected mathematical operator")
        result.insert(0, expression)
    return result[0]
示例#24
0
def test_derived_message_incorrect_base_name() -> None:
    with pytest.raises(
            RecordFluxError,
            match=
            '^<stdin>:40:8: model: error: unexpected format of type name "M"$'
    ):
        DerivedMessage("P.M", Message("M", [], {}, location=Location((40, 8))))
示例#25
0
def test_message_incorrect_name() -> None:
    with pytest.raises(
            RecordFluxError,
            match=
            '^<stdin>:10:8: model: error: unexpected format of type name "M"$'
    ):
        Message("M", [], {}, Location((10, 8)))
示例#26
0
def test_private_type_declaration() -> None:
    string = "type X is private"
    expected = decl.TypeDeclaration(
        model.Private("Package::X", location=Location((1, 1), None, (1, 17)))
    )
    actual = parse_formal_declaration(string)
    assert actual == expected
    assert actual.location
示例#27
0
def test_message_missing_type() -> None:
    x = Field(ID("X", Location((5, 6))))
    structure = [Link(INITIAL, x), Link(x, FINAL)]

    assert_message_model_error(
        structure,
        {},
        '^<stdin>:5:6: model: error: missing type for field "X" in "P.M"$',
    )
示例#28
0
def test_array_invalid_element_type() -> None:
    assert_type_error(
        Array("P.A", Array("P.B", MODULAR_INTEGER, Location((3, 4))),
              Location((5, 4))),
        r'^<stdin>:5:4: model: error: invalid element type of array "A"\n'
        r'<stdin>:3:4: model: info: type "B" must be scalar or non-null message$',
    )
    assert_type_error(
        Array("P.A", Message("P.B", [], {}, Location((3, 4))), Location(
            (5, 4))),
        r'^<stdin>:5:4: model: error: invalid element type of array "A"\n'
        r'<stdin>:3:4: model: info: type "B" must be scalar or non-null message$',
    )
    assert_type_error(
        Array("P.A", OPAQUE, Location((5, 4))),
        r'^<stdin>:5:4: model: error: invalid element type of array "A"\n'
        r'__BUILTINS__:0:0: model: info: type "Opaque" must be scalar or non-null message$',
    )
示例#29
0
def test_parsed_field_locations() -> None:
    p = Parser()
    p.parse_string(
        """
           package Test is
              type T is mod 2**8;
              type M is
                 message
                    F1 : T;
                    F2 : T;
                 end message;
           end Test;
        """
    )
    m = p.create_model()
    assert m.messages[0].fields == (
        Field(ID("F1", Location((6, 21), end=(6, 22)))),
        Field(ID("F2", Location((7, 21), end=(7, 22)))),
    )
示例#30
0
def test_message_duplicate_link() -> None:
    t = ModularInteger("P.T", Number(2))
    x = Field(ID("X", location=Location((1, 5))))

    structure = [
        Link(INITIAL, x),
        Link(x, FINAL, location=Location((4, 42))),
        Link(x, FINAL, location=Location((5, 42))),
    ]

    types = {Field("X"): t}

    assert_message_model_error(
        structure,
        types,
        f'^<stdin>:1:5: model: error: duplicate link from "X" to "{FINAL.name}"\n'
        f"<stdin>:4:42: model: info: duplicate link\n"
        f"<stdin>:5:42: model: info: duplicate link",
    )