Ejemplo n.º 1
0
def test_parsing_model(tmp_path_factory: TempPathFactory,
                       model: Model) -> None:
    tmp_path = tmp_path_factory.mktemp(test_parsing_model.__name__)
    model.write_specification_files(tmp_path)
    parser = Parser()
    parser.parse(tmp_path / "test.rflx")
    parsed_model = parser.create_model()
    assert parsed_model.types == model.types
    assert parsed_model == model
Ejemplo n.º 2
0
def test_write_specification_files_missing_deps(tmp_path: Path) -> None:
    s = ModularInteger("P::S", Number(65536))
    t = ModularInteger("P::T", Number(256))
    v = mty.Sequence("P::V", element_type=t)
    m = Message("P::M", [Link(INITIAL, Field("Foo")), Link(Field("Foo"), FINAL)], {Field("Foo"): t})
    Model([s, v, m]).write_specification_files(tmp_path)
    expected_path = tmp_path / Path("p.rflx")
    assert list(tmp_path.glob("*.rflx")) == [expected_path]
    assert expected_path.read_text() == textwrap.dedent(
        """\
        package P is

           type S is mod 65536;

           type T is mod 256;

           type V is sequence of P::T;

           type M is
              message
                 Foo : P::T;
              end message;

        end P;"""
    )
Ejemplo n.º 3
0
def test_write_specification_file_multiple_packages_missing_deps(tmp_path: Path) -> None:
    t = ModularInteger("P::T", Number(256))
    u = mty.Sequence("R::U", element_type=t)
    u1 = mty.Sequence("Q::U1", element_type=t)
    v = ModularInteger("R::V", Number(65536))
    links = [
        Link(INITIAL, Field("Victor")),
        Link(Field("Victor"), Field("Uniform")),
        Link(Field("Uniform"), FINAL),
    ]
    fields = {Field("Victor"): v, Field("Uniform"): u}
    m = Message("R::M", links, fields)
    Model([u1, m, u, v]).write_specification_files(tmp_path)
    p_path, q_path, r_path = (tmp_path / Path(pkg + ".rflx") for pkg in ("p", "q", "r"))
    assert set(tmp_path.glob("*.rflx")) == {p_path, q_path, r_path}
    assert p_path.read_text() == textwrap.dedent(
        """\
        package P is

           type T is mod 256;

        end P;"""
    )
    assert q_path.read_text() == textwrap.dedent(
        """\
        with P;

        package Q is

           type U1 is sequence of P::T;

        end Q;"""
    )
    assert r_path.read_text() == textwrap.dedent(
        """\
        with P;

        package R is

           type V is mod 65536;

           type U is sequence of P::T;

           type M is
              message
                 Victor : R::V
                    then Uniform
                       with Size => Message'Last - Victor'Last;
                 Uniform : R::U;
              end message;

        end R;"""
    )
Ejemplo n.º 4
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])
Ejemplo n.º 5
0
 def create_model(self) -> Model:
     error = RecordFluxError()
     for specification in self.__specifications:
         if specification.package.identifier in self.__evaluated_specifications:
             continue
         self.__evaluated_specifications.add(
             specification.package.identifier)
         try:
             self.__evaluate_specification(specification)
         except RecordFluxError as e:
             error.extend(e)
     try:
         result = Model(list(self.__types.values()))
     except RecordFluxError as e:
         error.extend(e)
     error.propagate()
     return result
Ejemplo n.º 6
0
 def _create_model(self, files: List[Path], skip_model_verification: bool,
                   split_disjunctions: bool) -> Model:
     for f in files:
         if not f.is_file():
             raise ValidationError(f'specification file not found: "{f}"')
     parser = Parser(skip_model_verification)
     parser.parse(*files)
     model = parser.create_model()
     if split_disjunctions:
         messages: Dict[ID, Message] = {}
         for t in model.types:
             if isinstance(t, Message):
                 messages[t.identifier] = self._expand_message_links(
                     t, messages)
         model = Model(
             [self._replace_messages(t, messages) for t in model.types])
     return model
Ejemplo n.º 7
0
def models(draw: Draw) -> Model:
    types_: ty.List[Type] = []

    def append_types(message: Message) -> None:
        types_.append(message)
        for t in message.types.values():
            if isinstance(t, Opaque):
                continue
            types_.append(t)
            if isinstance(t, Sequence):
                if isinstance(t.element_type, Message):
                    append_types(t.element_type)
                else:
                    types_.append(t.element_type)

    refinement = draw(refinements(unique_qualified_identifiers()))

    types_.append(refinement)
    for m in [refinement.sdu, refinement.pdu]:
        append_types(m)
    for t in [*INTERNAL_TYPES.values(), *BUILTIN_TYPES.values()]:
        types_.append(t)

    return Model(list(reversed(types_)))
Ejemplo n.º 8
0
    Field,
    Link,
    Message,
    Model,
    ModularInteger,
    RangeInteger,
    Refinement,
    Sequence,
    Session,
    State,
    Transition,
    UnprovenMessage,
)

NULL_MESSAGE = Message("Null::Message", [], {}, skip_proof=True)
NULL_MODEL = Model([NULL_MESSAGE])

TLV_TAG = Enumeration(
    "TLV::Tag", [("Msg_Data", Number(1)), ("Msg_Error", Number(3))], Number(8), always_valid=False
)
TLV_LENGTH = ModularInteger("TLV::Length", Pow(Number(2), Number(16)))
TLV_MESSAGE = Message(
    "TLV::Message",
    [
        Link(INITIAL, Field("Tag")),
        Link(Field("Tag"), Field("Length"), Equal(Variable("Tag"), Variable("Msg_Data"))),
        Link(Field("Tag"), FINAL, 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},
Ejemplo n.º 9
0
def test_consistency_specification_parsing_generation(tmp_path: Path) -> None:
    tag = Enumeration(
        "Test::Tag",
        [("Msg_Data", expr.Number(1)), ("Msg_Error", expr.Number(3))],
        expr.Number(8),
        always_valid=False,
    )
    length = ModularInteger("Test::Length",
                            expr.Pow(expr.Number(2), expr.Number(16)))
    message = Message(
        "Test::Message",
        [
            Link(INITIAL, Field("Tag")),
            Link(
                Field("Tag"),
                Field("Length"),
                expr.Equal(expr.Variable("Tag"), expr.Variable("Msg_Data")),
            ),
            Link(Field("Tag"), FINAL,
                 expr.Equal(expr.Variable("Tag"), expr.Variable("Msg_Error"))),
            Link(
                Field("Length"),
                Field("Value"),
                size=expr.Mul(expr.Variable("Length"), expr.Number(8)),
            ),
            Link(Field("Value"), FINAL),
        ],
        {
            Field("Tag"): tag,
            Field("Length"): length,
            Field("Value"): OPAQUE
        },
        skip_proof=True,
    )
    session = Session(
        "Test::Session",
        "A",
        "C",
        [
            State(
                "A",
                declarations=[],
                actions=[stmt.Read("X", expr.Variable("M"))],
                transitions=[
                    Transition("B"),
                ],
            ),
            State(
                "B",
                declarations=[
                    decl.VariableDeclaration("Z", BOOLEAN.identifier,
                                             expr.Variable("Y")),
                ],
                actions=[],
                transitions=[
                    Transition(
                        "C",
                        condition=expr.And(
                            expr.Equal(expr.Variable("Z"), expr.TRUE),
                            expr.Equal(expr.Call("G", [expr.Variable("F")]),
                                       expr.TRUE),
                        ),
                        description="rfc1149.txt+45:4-47:8",
                    ),
                    Transition("A"),
                ],
                description="rfc1149.txt+51:4-52:9",
            ),
            State("C"),
        ],
        [
            decl.VariableDeclaration("M", "Test::Message"),
            decl.VariableDeclaration("Y", BOOLEAN.identifier, expr.FALSE),
        ],
        [
            decl.ChannelDeclaration("X", readable=True, writable=True),
            decl.TypeDeclaration(Private("Test::T")),
            decl.FunctionDeclaration("F", [], "Test::T"),
            decl.FunctionDeclaration("G", [decl.Argument("P", "Test::T")],
                                     BOOLEAN.identifier),
        ],
        [BOOLEAN, OPAQUE, tag, length, message],
    )
    model = Model(types=[BOOLEAN, OPAQUE, tag, length, message],
                  sessions=[session])
    model.write_specification_files(tmp_path)
    p = parser.Parser()
    p.parse(tmp_path / "test.rflx")
    parsed_model = p.create_model()
    assert parsed_model.types == model.types
    assert parsed_model.sessions == model.sessions
    assert parsed_model == model
Ejemplo n.º 10
0
def assert_model_error(types: Sequence[Type], regex: str) -> None:
    with pytest.raises(RecordFluxError, match=regex):
        Model([*BUILTIN_TYPES.values(), *types])
Ejemplo n.º 11
0
def test_write_specification_files_line_too_long(tmp_path: Path) -> None:
    t = ModularInteger("P::" + "T" * 120, Number(256))
    Model([t]).write_specification_files(tmp_path)
    expected_path = tmp_path / Path("p.rflx")
    assert list(tmp_path.glob("*.rflx")) == [expected_path]
    assert expected_path.read_text().startswith("-- style: disable = line-length\n\npackage P is")
Ejemplo n.º 12
0
def test_init_introduce_type_dependencies(types: List[Type], model: Model) -> None:
    assert Model(types).types == model.types
Ejemplo n.º 13
0
    INITIAL,
    Array,
    DerivedMessage,
    Enumeration,
    Field,
    Link,
    Message,
    Model,
    ModularInteger,
    Opaque,
    RangeInteger,
    Refinement,
)

NULL_MESSAGE = Message("Null.Message", [], {})
NULL_MODEL = Model([NULL_MESSAGE])

TLV_TAG = Enumeration("TLV.Tag", [("Msg_Data", Number(1)),
                                  ("Msg_Error", Number(3))], Number(2), False)
TLV_LENGTH = ModularInteger("TLV.Length", Pow(Number(2), Number(14)))
TLV_MESSAGE = Message(
    "TLV.Message",
    [
        Link(INITIAL, Field("Tag")),
        Link(Field("Tag"), Field("Length"),
             Equal(Variable("Tag"), Variable("Msg_Data"))),
        Link(Field("Tag"), FINAL, Equal(Variable("Tag"),
                                        Variable("Msg_Error"))),
        Link(Field("Length"),
             Field("Value"),
             length=Mul(Variable("Length"), Number(8))),
Ejemplo n.º 14
0
def test_unexpected_type() -> None:
    class TestType(Type):
        pass

    with pytest.raises(AssertionError, match='unexpected type "TestType"'):
        Generator().generate(Model([TestType("P.T")]))