You've already forked RecordFlux
mirror of
https://github.com/AdaCore/RecordFlux.git
synced 2026-02-12 13:01:56 -08:00
195 lines
10 KiB
Python
195 lines
10 KiB
Python
"""Ensure that the test specifications contain the expected errors."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
from collections.abc import Sequence
|
|
|
|
import pytest
|
|
|
|
from rflx import specification
|
|
from rflx.rapidflux import RecordFluxError
|
|
from tests.const import IDE_DIR
|
|
|
|
|
|
def assert_error(filename: pathlib.Path, expected: Sequence[str]) -> None:
|
|
p = specification.Parser()
|
|
with pytest.raises(RecordFluxError) as excinfo: # noqa: PT012
|
|
error = RecordFluxError()
|
|
|
|
try:
|
|
p.parse(filename)
|
|
except RecordFluxError as e:
|
|
error.extend(e.entries)
|
|
|
|
try:
|
|
p.create_model()
|
|
except RecordFluxError as e:
|
|
error.extend(e.entries)
|
|
|
|
error.propagate()
|
|
|
|
assert str(excinfo.value).split("\n") == expected
|
|
|
|
|
|
def test_multiple_errors() -> None:
|
|
path = IDE_DIR / "multiple_errors.rflx"
|
|
assert_error(
|
|
path,
|
|
[
|
|
f'{path}:6:9: error: illegal prefix "RFLX" in package identifier "RFLX_Invalid"',
|
|
f'{path}:295:5: error: inconsistent package identifier "Inconsistent"',
|
|
f'{path}:6:9: note: previous identifier was "RFLX_Invalid"',
|
|
f"{path}:6:9: error: source file name does not match the package name"
|
|
' "RFLX_Invalid"',
|
|
f"{path}:6:9: help: either rename the file to "
|
|
'"rflx_invalid.rflx" or change the package name to "Multiple_Errors"',
|
|
f'{path}:6:9: help: rename to "Multiple_Errors"',
|
|
f'{path}:295:5: help: rename to "Multiple_Errors"',
|
|
f'{path}:6:9: error: illegal prefix "RFLX" in package identifier "RFLX_Invalid"',
|
|
f'{path}:295:5: error: inconsistent package identifier "Inconsistent"',
|
|
f'{path}:6:9: note: previous identifier was "RFLX_Invalid"',
|
|
f"{path}:6:9: error: source file name does not match the package name"
|
|
' "RFLX_Invalid"',
|
|
f"{path}:6:9: help: either rename the file to "
|
|
'"rflx_invalid.rflx" or change the package name to "Multiple_Errors"',
|
|
f'{path}:6:9: help: rename to "Multiple_Errors"',
|
|
f'{path}:295:5: help: rename to "Multiple_Errors"',
|
|
f'{path}:6:9: error: illegal identifier "RFLX_Invalid"',
|
|
f'{path}:6:9: note: identifiers starting with "RFLX_" are reserved for internal use',
|
|
f'{path}:72:18: error: undefined field "X"',
|
|
f'{path}:13:25: error: first of "Range2" contains variable',
|
|
f'{path}:13:34: error: last of "Range2" contains variable',
|
|
f'{path}:16:25: error: range of "Range3" negative',
|
|
f'{path}:19:51: error: size of "Range4" contains variable',
|
|
f'{path}:22:47: error: size of "Range5" too small',
|
|
f"{path}:22:30: help: at least 8 bits are required to store the upper bound",
|
|
f'{path}:25:27: error: undefined element type "RFLX_Invalid::Undef"',
|
|
f'{path}:38:28: error: duplicate literal "E2_2"',
|
|
f"{path}:38:22: note: previous occurrence",
|
|
f'{path}:38:9: error: size of "E2" too small',
|
|
f'{path}:41:46: error: duplicate enumeration value "2"',
|
|
f"{path}:41:35: note: previous occurrence",
|
|
f'{path}:64:10: error: unreachable field "Z"',
|
|
f'{path}:64:10: error: duplicate link from "Z" to "Final"',
|
|
f"{path}:64:16: note: duplicate link",
|
|
f"{path}:64:26: note: duplicate link",
|
|
f'{path}:70:14: error: undefined type "RFLX_Invalid::Undef_Type"',
|
|
f'{path}:77:9: error: unsupported element type size of sequence "A3"',
|
|
f'{path}:76:9: help: type "E6" has size 4, must be multiple of 8',
|
|
f'{path}:84:30: error: invalid First for field "Final"',
|
|
f"{path}:87:9: error: message size must be multiple of 8 bit",
|
|
f'{path}:89:10: note: on path "Field"',
|
|
f'{path}:94:44: error: size of opaque field "Data" not multiple of 8 bit',
|
|
f"{path}:94:44: help: sizes are expressed in bits, not bytes",
|
|
f'{path}:94:44: help: did you mean "Length * 8"?',
|
|
f'{path}:97:8: error: undefined type "RFLX_Invalid::PDU1" in refinement',
|
|
f'{path}:97:40: error: undefined type "RFLX_Invalid::SDU2" in refinement '
|
|
'of "RFLX_Invalid::PDU1"',
|
|
f'{path}:100:8: error: undefined type "RFLX_Invalid::PDU1" in refinement',
|
|
f'{path}:100:26: error: undefined type "RFLX_Invalid::SDU2" in refinement '
|
|
'of "RFLX_Invalid::PDU1"',
|
|
f'{path}:103:8: error: undefined type "RFLX_Invalid::Undef_PDU" in refinement',
|
|
f'{path}:103:31: error: type "RFLX_Invalid::R" cannot be used in refinement '
|
|
"because it's not a message type",
|
|
f'{path}:106:8: error: undefined type "RFLX_Invalid::PDU1" in refinement',
|
|
f'{path}:106:26: error: undefined type "RFLX_Invalid::Undef_Type" in '
|
|
'refinement of "RFLX_Invalid::PDU1"',
|
|
f'{path}:109:8: error: undefined type "RFLX_Invalid::PDU1" in refinement',
|
|
f'{path}:109:33: error: type "RFLX_Invalid::R" cannot be used in refinement '
|
|
"because it's not a message type",
|
|
f'{path}:115:21: error: undefined base message "RFLX_Invalid::PDU1"'
|
|
" in derived message",
|
|
f'{path}:116:21: error: undefined base message "RFLX_Invalid::PDU1"'
|
|
" in derived message",
|
|
f'{path}:119:21: error: undefined base message "RFLX_Invalid::Undef_Type"'
|
|
" in derived message",
|
|
f"{path}:122:9: error: invalid derivation",
|
|
f"{path}:8:9: note: base type must be a message",
|
|
f'{path}:125:21: error: undefined base message "RFLX_Invalid::Ref1"'
|
|
" in derived message",
|
|
f'{path}:140:19: error: invalid use of size attribute for "1"',
|
|
f'{path}:156:10: error: name conflict for "F2_F1"',
|
|
f'{path}:147:9: note: when merging message "RFLX_Invalid::M4"',
|
|
f'{path}:154:10: note: into field "F2"',
|
|
f'{path}:164:10: error: field "Data1" has no satisfiable condition at any outgoing '
|
|
"link",
|
|
f'{path}:161:10: note: on path "Length"',
|
|
f'{path}:162:18: note: on path "Data1"',
|
|
f"{path}:168:19: note: unsatisfied \"3 * R'Size = Data1'Size\"",
|
|
f'{path}:8:9: note: unsatisfied "R\'Size = 16"',
|
|
f'{path}:8:9: note: unsatisfied "Length <= 23"',
|
|
f'{path}:163:29: note: unsatisfied "Data1\'Size = Length"',
|
|
f'{path}:175:36: error: undefined element type "RFLX_Invalid::M5"',
|
|
f'{path}:181:17: error: undefined type "RFLX_Invalid::M5_Sequence"',
|
|
f'{path}:192:10: error: conflicting conditions for field "F1"',
|
|
f"{path}:196:19: note: condition 0 (F1 -> F2): F1 < 80",
|
|
f"{path}:194:19: note: condition 1 (F1 -> Final): F1 > 50",
|
|
f'{path}:204:10: error: unreachable field "F2"',
|
|
f'{path}:220:29: error: fixed size field "F1" does not permit a size aspect',
|
|
f"{path}:219:18: help: modify this field's type, or alternatively, "
|
|
"remove the size aspect",
|
|
f"{path}:187:25: note: associated type size defined here",
|
|
f"{path}:229:30: error: illegal first aspect on initial link",
|
|
f'{path}:238:19: error: undefined variable "F1"',
|
|
f'{path}:247:29: error: negative size for field "F2"',
|
|
f'{path}:244:10: note: on path "F1"',
|
|
f'{path}:247:29: error: size of opaque field "F2" not multiple of 8 bit',
|
|
f"{path}:247:29: help: sizes are expressed in bits, not bytes",
|
|
f'{path}:247:29: help: did you mean "(F1 - 2 ** 33) * 8"?',
|
|
f"{path}:242:9: error: negative start for end of message",
|
|
f'{path}:244:10: note: on path "F1"',
|
|
f'{path}:245:18: note: on path "F2"',
|
|
f"{path}:245:18: note: unsatisfied \"F2'Last = (F1'Last + 1 + (F1 - 2 ** 33)) - 1\"",
|
|
f"{path}:244:10: note: unsatisfied \"F1'Last = (Message'First + 32) - 1\"",
|
|
f'{path}:187:9: note: unsatisfied "F1 <= 4294967295"',
|
|
f"{path}:248:10: note: unsatisfied \"F2'Last + 1 >= Message'First\"",
|
|
f'{path}:254:10: error: unconstrained field "F1" without size aspect',
|
|
f'{path}:260:9: error: field "F3" not congruent with overlaid field "F2"',
|
|
f"{path}:263:10: note: unsatisfied \"F2'Last = (F1'Last + 1 + 8) - 1\"",
|
|
f"{path}:262:18: note: unsatisfied \"F2'First = F1'Last + 1\"",
|
|
f"{path}:264:13: note: unsatisfied \"(F2'First + 16) - 1 = F2'Last\"",
|
|
f"{path}:276:29: error: size aspect for final field",
|
|
f"{path}:279:9: error: unnecessary always-valid aspect"
|
|
' on "Unnecessary_Always_Valid_Enum"',
|
|
f'{path}:290:30: error: undefined variable "Undef_Var"',
|
|
f'{path}:28:9: error: name conflict for type "RFLX_Invalid::R"',
|
|
f'{path}:8:9: note: previous occurrence of "RFLX_Invalid::R"',
|
|
f'{path}:31:9: error: illegal redefinition of built-in type "Boolean"',
|
|
f"{path}:44:9: error: conflicting literals: False, True",
|
|
'__BUILTINS__:1:1: note: previous occurrence of "False"',
|
|
'__BUILTINS__:1:1: note: previous occurrence of "True"',
|
|
f"{path}:34:9: error: conflicting literals: Foo",
|
|
f'{path}:31:21: note: previous occurrence of "Foo"',
|
|
f"{path}:47:9: error: conflicting literals: Bar, Foo",
|
|
f'{path}:31:26: note: previous occurrence of "Bar"',
|
|
f'{path}:31:21: note: previous occurrence of "Foo"',
|
|
f"{path}:47:9: error: conflicting literals: Foo",
|
|
f'{path}:34:30: note: previous occurrence of "Foo"',
|
|
f'{path}:47:21: error: literal "E4" conflicts with type declaration',
|
|
f'{path}:44:9: note: conflicting type "RFLX_Invalid::E4"',
|
|
],
|
|
)
|
|
|
|
|
|
def test_parse_error_aggregate_non_number() -> None:
|
|
path = IDE_DIR / "parse_error_aggregate_non_number.rflx"
|
|
assert_error(
|
|
path,
|
|
[
|
|
f"{path}:10:39: error: Expected ';', got 'First'",
|
|
],
|
|
)
|
|
|
|
|
|
def test_parse_error_invalid_location() -> None:
|
|
path = IDE_DIR / "parse_error_invalid_location.rflx"
|
|
assert_error(
|
|
path,
|
|
[
|
|
f'{path}:7:21: error: invalid aspect "Invalid"',
|
|
f"{path}:3:9: error: message size must be multiple of 8 bit",
|
|
f'{path}:5:10: note: on path "Y"',
|
|
],
|
|
)
|