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', )
def test_field_coverage_2(monkeypatch: Any) -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2")), Link(Field("F2"), Field("F4"), Greater(Variable("F1"), Number(100))), Link( Field("F2"), Field("F3"), LessEqual(Variable("F1"), Number(100)), first=Add(Last("F2"), Number(64)), ), Link(Field("F3"), Field("F4")), Link(Field("F4"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): MODULAR_INTEGER, Field("F3"): MODULAR_INTEGER, Field("F4"): MODULAR_INTEGER, } monkeypatch.setattr(Message, "_AbstractMessage__verify_conditions", lambda x: None) assert_message_model_error( structure, types, r"^" r"model: error: path does not cover whole message\n" r'model: info: on path: "F1"\n' r'model: info: on path: "F2"\n' r'model: info: on path: "F3"\n' r'model: info: on path: "F4"' r"$", )
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"', )
def test_message_multiple_duplicate_links() -> None: t = ModularInteger("P.T", Number(2)) x = Field(ID("X", location=Location((1, 5)))) y = Field(ID("Y", location=Location((2, 5)))) structure = [ Link(INITIAL, x), Link(x, y), Link(x, FINAL, location=Location((3, 16))), Link(x, FINAL, location=Location((4, 18))), Link(y, FINAL, location=Location((5, 20))), Link(y, FINAL, location=Location((6, 22))), ] types = {Field("X"): t, Field("Y"): t} assert_message_model_error( structure, types, f'^<stdin>:1:5: model: error: duplicate link from "X" to "{FINAL.name}"\n' f"<stdin>:3:16: model: info: duplicate link\n" f"<stdin>:4:18: model: info: duplicate link\n" f'<stdin>:2:5: model: error: duplicate link from "Y" to "{FINAL.name}"\n' f"<stdin>:5:20: model: info: duplicate link\n" f"<stdin>:6:22: model: info: duplicate link", )
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"$", )
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"$", )
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"$", )
def test_conditionally_unreachable_field_range_first() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), Greater(First("F1"), First("Message"))), Link(Field("F2"), FINAL), ] types = { Field("F1"): RANGE_INTEGER, Field("F2"): RANGE_INTEGER, } 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"', )
def test_conditionally_unreachable_field_enum_last() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), Equal(Last("F1"), Last("Message"))), Link(Field("F2"), FINAL), ] types = { Field("F1"): ENUMERATION, Field("F2"): ENUMERATION, } assert_message_model_error( structure, types, r"^" r'model: error: unreachable field "F2" in "P.M"\n' r"model: info: path 0 [(]F1 -> F2[)]:\n" r'model: info: unsatisfied "F2\'Last = [(][(][(]F1\'Last [+] 1[)] [+] 8[)][)] - 1"\n' r'model: info: unsatisfied "Message\'Last >= F2\'Last"\n' r'model: info: unsatisfied "F1\'Last = Message\'Last"\n' r'model: error: unreachable field "Final" in "P.M"\n' r"model: info: path 0 [(]F1 -> F2 -> Final[)]:\n" r'model: info: unsatisfied "F2\'Last = [(][(][(]F1\'Last [+] 1[)] [+] 8[)][)] - 1"\n' r'model: info: unsatisfied "Message\'Last >= F2\'Last"\n' r'model: info: unsatisfied "F1\'Last = Message\'Last"', )
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"', )
def test_no_path_to_final_transitive() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2")), Link(Field("F2"), Field("F3"), Greater(Variable("F1"), Number(100))), Link(Field("F3"), FINAL), Link(Field("F2"), Field("F4"), LessEqual(Variable("F1"), Number(100))), Link(Field("F4"), Field("F5")), Link(Field("F5"), Field("F6")), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): MODULAR_INTEGER, Field("F3"): MODULAR_INTEGER, Field("F4"): MODULAR_INTEGER, Field("F5"): MODULAR_INTEGER, Field("F6"): MODULAR_INTEGER, } assert_message_model_error( structure, types, r"^" r'model: error: no path to FINAL for field "F4" in "P.M"\n' r'model: error: no path to FINAL for field "F5" in "P.M"\n' r'model: error: no path to FINAL for field "F6" in "P.M"' r"$", )
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"$', )
def test_invalid_length_forward_reference() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), length=Variable("F2")), Link(Field("F2"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): Opaque(), } assert_message_model_error( structure, types, '^model: error: subsequent field "F2" referenced$')
def test_message_invalid_use_of_length_attribute() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), FINAL, Equal(Length("F1"), Number(32), Location((400, 17)))), ] types = {Field("F1"): MODULAR_INTEGER} assert_message_model_error( structure, types, r'^<stdin>:400:17: model: error: invalid use of length attribute for "F1"$', )
def test_array_no_length() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2")), Link(Field("F2"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): ARRAYS_MODULAR_VECTOR, } assert_message_model_error( structure, types, '^model: error: unconstrained field "F2" without length expression$')
def test_payload_no_length() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2")), Link(Field("F2"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): Opaque(), } assert_message_model_error( structure, types, r'^model: error: unconstrained field "F2" without length expression$')
def test_message_unused_type() -> None: t = ModularInteger("P.T", Number(2)) structure = [ Link(INITIAL, Field("X")), Link(Field("X"), FINAL), ] types = {Field("X"): t, Field(ID("Y", Location((5, 6)))): t} assert_message_model_error( structure, types, '^<stdin>:5:6: model: error: unused field "Y" in "P.M"$')
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$')
def test_no_valid_path() -> None: f1 = Field(ID("F1", Location((10, 5)))) f2 = Field(ID("F2", Location((11, 6)))) f3 = Field(ID("F3", Location((12, 7)))) structure = [ Link(INITIAL, f1), Link(f1, f2, condition=LessEqual(Variable("F1"), Number(80), Location( (20, 2)))), Link(f1, f3, condition=Greater(Variable("F1"), Number(80), Location((21, 3)))), Link(f2, f3, condition=Greater(Variable("F1"), Number(80), Location((22, 4)))), Link(f3, FINAL, condition=LessEqual(Variable("F1"), Number(80), Location( (23, 5)))), ] types = { Field("F1"): RANGE_INTEGER, Field("F2"): RANGE_INTEGER, Field("F3"): RANGE_INTEGER, } assert_message_model_error( structure, types, r"^" r'<stdin>:11:6: model: error: unreachable field "F2" in "P.M"\n' r"<stdin>:11:6: model: info: path 0 [(]F1 -> F2[)]:\n" r'<stdin>:20:2: model: info: unsatisfied "F1 <= 80"\n' r'<stdin>:11:6: model: info: unsatisfied "F1 > 80"\n' r'<stdin>:12:7: model: error: unreachable field "F3" in "P.M"\n' r"<stdin>:12:7: model: info: path 0 [(]F1 -> F2 -> F3[)]:\n" r'<stdin>:20:2: model: info: unsatisfied "F1 <= 80"\n' r'<stdin>:22:4: model: info: unsatisfied "F1 > 80"\n' r"<stdin>:12:7: model: info: path 1 [(]F1 -> F3[)]:\n" r'<stdin>:21:3: model: info: unsatisfied "F1 > 80"\n' r'<stdin>:12:7: model: info: unsatisfied "F1 <= 80"\n' r'model: error: unreachable field "Final" in "P.M"\n' r"model: info: path 0 [(]F1 -> F2 -> F3 -> Final[)]:\n" r'<stdin>:20:2: model: info: unsatisfied "F1 <= 80"\n' r'<stdin>:22:4: model: info: unsatisfied "F1 > 80"\n' r"model: info: path 1 [(]F1 -> F3 -> Final[)]:\n" r'<stdin>:21:3: model: info: unsatisfied "F1 > 80"\n' r'<stdin>:23:5: model: info: unsatisfied "F1 <= 80"', )
def test_invalid_fixed_size_field_with_length() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), length=Number(300)), Link(Field("F2"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): MODULAR_INTEGER, } assert_message_model_error( structure, types, r'^model: error: fixed size field "F2" with length expression$', )
def test_message_unreachable_field() -> None: structure = [ Link(INITIAL, Field("X")), Link(Field("X"), Field("Z")), Link(Field(ID("Y", Location((20, 3)))), Field("Z")), Link(Field("Z"), FINAL), ] types = {Field("X"): BOOLEAN, Field("Y"): BOOLEAN, Field("Z"): BOOLEAN} assert_message_model_error( structure, types, '^<stdin>:20:3: model: error: unreachable field "Y" in "P.M"$', )
def test_invalid_negative_field_length_modular() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), length=Sub(Variable("F1"), Number(2))), Link(Field("F2"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): Opaque(), } assert_message_model_error( structure, types, r'^model: error: negative length for field "F2" [(]F1 -> F2[)]$', )
def test_opaque_equal_scalar() -> None: structure = [ Link(INITIAL, Field("Length")), Link(Field("Length"), Field("Data"), length=Variable("Length")), Link(Field("Data"), FINAL, condition=Equal(Variable("Data"), Number(42))), ] types = {Field("Length"): RANGE_INTEGER, Field("Data"): Opaque()} assert_message_model_error( structure, types, r"^" r'model: error: invalid relation " = " between Opaque and Number' r"$", )
def test_length_attribute_final() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2")), Link(Field("F2"), FINAL, length=Number(100, location=Location((4, 12)))), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): MODULAR_INTEGER, } assert_message_model_error( structure, types, '^<stdin>:4:12: model: error: length attribute for final field in "P.M"$' )
def test_message_invalid_relation_to_aggregate() -> None: structure = [ Link(INITIAL, Field("F1"), length=Number(16)), Link( Field("F1"), FINAL, LessEqual(Variable("F1"), Aggregate(Number(1), Number(2)), Location((100, 20))), ), ] types = {Field("F1"): Opaque()} assert_message_model_error( structure, types, r'^<stdin>:100:20: model: error: invalid relation " <= " between Opaque and Aggregate$', )
def test_message_invalid_element_in_relation_to_aggregate() -> None: structure = [ Link(INITIAL, Field("F1")), Link( Field("F1"), FINAL, Equal(Variable("F1"), Aggregate(Number(1), Number(2)), Location((14, 7))), ), ] types = {Field("F1"): MODULAR_INTEGER} assert_message_model_error( structure, types, r'^<stdin>:14:7: model: error: invalid relation " = " ' r"between Aggregate and ModularInteger$", )
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"$', )
def test_message_subsequent_variable() -> None: f1 = Field("F1") f2 = Field("F2") t = ModularInteger("P.T", Pow(Number(2), Number(32))) structure = [ Link(INITIAL, f1), Link(f1, f2, Equal(Variable("F2", location=Location((1024, 57))), Number(42))), Link(f2, FINAL), ] types = {Field("F1"): t, Field("F2"): t} assert_message_model_error( structure, types, '^<stdin>:1024:57: model: error: subsequent field "F2" referenced', )
def test_invalid_first_is_last() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), first=Last(ID("F1", Location((11, 20))))), Link(Field("F2"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): MODULAR_INTEGER, } assert_message_model_error( structure, types, r'^<stdin>:11:20: model: error: invalid First for field "F2"$', )
def test_invalid_negative_field_length_range_integer() -> None: o = Field(ID("O", location=Location((44, 3)))) structure = [ Link(INITIAL, Field("L")), Link( Field("L"), o, length=Mul(Number(8), Sub(Variable("L"), Number(50))), ), Link(o, FINAL), ] types = {Field("L"): RANGE_INTEGER, o: Opaque()} assert_message_model_error( structure, types, r'^<stdin>:44:3: model: error: negative length for field "O" [(]L -> O[)]$', )