diff --git a/tests/data/specs/in_p1.rflx b/tests/data/specs/in_p1.rflx new file mode 100644 index 0000000000..6a61ef2b33 --- /dev/null +++ b/tests/data/specs/in_p1.rflx @@ -0,0 +1,9 @@ +with P1; +with P2; +with P3; +package In_P1 is + for P1::Frame use (Payload => P2::Packet) + if Kind = 1; + for P1::Frame use (Payload => P3::Packet) + if Kind = 2; +end In_P1; diff --git a/tests/data/specs/p1.rflx b/tests/data/specs/p1.rflx new file mode 100644 index 0000000000..b993899f61 --- /dev/null +++ b/tests/data/specs/p1.rflx @@ -0,0 +1,9 @@ +package P1 is + type Kind is mod 2**16; + type Frame is + message + Kind : Kind; + Payload : Opaque + with Size => Message'Last - Kind'Last; + end message; +end P1; diff --git a/tests/data/specs/p2.rflx b/tests/data/specs/p2.rflx new file mode 100644 index 0000000000..df3f2bbfff --- /dev/null +++ b/tests/data/specs/p2.rflx @@ -0,0 +1,11 @@ +with P4; +package P2 is + type Length is mod 2**16; + type Packet is + message + Length : Length; + Protocol : P4::Protocol_Number; + Payload : Opaque + with Size => 8 * Length; + end message; +end P2; diff --git a/tests/data/specs/p3.rflx b/tests/data/specs/p3.rflx new file mode 100644 index 0000000000..73715c03c3 --- /dev/null +++ b/tests/data/specs/p3.rflx @@ -0,0 +1,9 @@ +with P2; +package P3 is + type T is mod 2**32; + type Packet is + message + F1 : T; + F2 : P2::Length; + end message; +end P3; diff --git a/tests/data/specs/p4.rflx b/tests/data/specs/p4.rflx new file mode 100644 index 0000000000..9476623609 --- /dev/null +++ b/tests/data/specs/p4.rflx @@ -0,0 +1,3 @@ +package P4 is + type Protocol_Number is mod 2**16; +end P4; diff --git a/tests/unit/specification/parser_test.py b/tests/unit/specification/parser_test.py index 0f9cd42b4e..fc7e1bf0f6 100644 --- a/tests/unit/specification/parser_test.py +++ b/tests/unit/specification/parser_test.py @@ -2421,3 +2421,65 @@ def test_parse_error_invalid_range_aspect() -> None: ) def test_parse_error_invalid_enum(spec: str, error: str) -> None: assert_error_string(spec, error) + + +def test_complex_dependencies() -> None: + + p4_protocol_number = model.ModularInteger( + "P4::Protocol_Number", expr.Pow(expr.Number(2), expr.Number(16)) + ) + + p1_kind = model.ModularInteger("P1::Kind", expr.Pow(expr.Number(2), expr.Number(16))) + + p1_packet_structure = [ + model.Link(model.INITIAL, model.Field("Kind")), + model.Link( + model.Field("Kind"), + model.Field("Payload"), + size=expr.Sub(expr.Last("Message"), expr.Last("Kind")), + ), + model.Link(model.Field("Payload"), model.FINAL), + ] + + p1_packet_types = { + Field("Kind"): p1_kind, + Field("Payload"): OPAQUE, + } + + p1_packet = model.Message("P1::Frame", p1_packet_structure, p1_packet_types) + + p2_length = model.ModularInteger("P2::Length", expr.Pow(expr.Number(2), expr.Number(16))) + + p2_packet_structure = [ + model.Link(model.INITIAL, model.Field("Length")), + model.Link(model.Field("Length"), model.Field("Protocol")), + model.Link( + model.Field("Protocol"), + model.Field("Payload"), + size=expr.Mul(expr.Number(8), expr.Variable("Length")), + ), + model.Link(model.Field("Payload"), model.FINAL), + ] + + p2_packet_types = { + Field("Length"): p2_length, + Field("Protocol"): p4_protocol_number, + Field("Payload"): OPAQUE, + } + + p2_packet = model.Message("P2::Packet", p2_packet_structure, p2_packet_types) + + p3_packet_structure = [ + model.Link(model.INITIAL, model.Field("F1")), + model.Link(model.Field("F1"), model.Field("F2")), + model.Link(model.Field("F2"), model.FINAL), + ] + + p3_packet_types = { + Field("F1"): model.ModularInteger("P3::T", expr.Pow(expr.Number(2), expr.Number(32))), + Field("F2"): p2_length, + } + + p3_packet = model.Message("P3::Packet", p3_packet_structure, p3_packet_types) + + assert_messages_files([f"{SPEC_DIR}/in_p1.rflx"], [p2_packet, p3_packet, p1_packet])