diff --git a/conformance-tests/2023-09/EXPR/jobs/expr2.2.6--repr-py-newline-roundtrip.test.yaml b/conformance-tests/2023-09/EXPR/jobs/expr2.2.6--repr-py-newline-roundtrip.test.yaml new file mode 100644 index 0000000..8fb5d2d --- /dev/null +++ b/conformance-tests/2023-09/EXPR/jobs/expr2.2.6--repr-py-newline-roundtrip.test.yaml @@ -0,0 +1,38 @@ +# Expression Language §2.2.6 defines repr_py as following Python's repr, so a +# control character in the value must be escaped in the emitted literal. +# +# repr_py("a\nb") is handed to ast.literal_eval, CPython's own parser, and the +# result compared to the input. Paired with +# WRAP_ACTIONS/jobs/wrap-repr-py-escapes-newline-in-wrapped-args, which pins the +# same rule through RFC 0008's forwarding pattern. +# +# The round-trip must print NEWLINE:PASS. A repr that quotes without escaping +# emits a raw newline, and CPython raises SyntaxError before the comparison runs. +# The failure marker is split across two literals because Windows echoes the +# child command line into the output the harness scans for forbidden strings. +template: + specificationVersion: jobtemplate-2023-09 + extensions: + - EXPR + name: TestJob + steps: + - name: Step1 + let: + - 'q = repr_py("a\nb")' + script: + actions: + onRun: + command: python + args: + - -c + - | + import ast + import sys + got = ast.literal_eval(sys.argv[1]) + print("NEWLINE:" + ("PASS" if got == "a\nb" else "FA" "IL got=" + repr(got))) + - "{{ q }}" +expected: + output: + - NEWLINE:PASS + forbidden: + - FAIL diff --git a/conformance-tests/2023-09/WRAP_ACTIONS/jobs/wrap-repr-py-escapes-newline-in-wrapped-args.test.yaml b/conformance-tests/2023-09/WRAP_ACTIONS/jobs/wrap-repr-py-escapes-newline-in-wrapped-args.test.yaml new file mode 100644 index 0000000..94e7b1a --- /dev/null +++ b/conformance-tests/2023-09/WRAP_ACTIONS/jobs/wrap-repr-py-escapes-newline-in-wrapped-args.test.yaml @@ -0,0 +1,50 @@ +# Expression Language §2.2.6 defines repr_py as following Python's repr, and RFC +# 0008's reference forwarding pattern round-trips WrappedAction.Args through it. +# +# The wrapped action's arg is a two-line python -c program, the suite's own +# portable-fixture convention. All three hooks forward it. Paired with +# EXPR/jobs/expr2.2.6--repr-py-newline-roundtrip, which pins the same rule +# without the forwarding layer. +# +# The grand-child must run and print GRAND_CHILD_RAN. A repr that quotes without +# escaping embeds the newline raw, and the generated program dies with +# SyntaxError before reaching subprocess.run. +template: + specificationVersion: jobtemplate-2023-09 + name: WrapReprPyEscapesNewlineInWrappedArgs + steps: + - name: Step1 + script: + actions: + onRun: + command: python + args: + - "-c" + - "import sys\nprint('GRAND_CHILD_RAN')" +environments: +- specificationVersion: environment-2023-09 + extensions: + - WRAP_ACTIONS + - EXPR + environment: + name: WrapEnv + script: + actions: + onWrapEnvEnter: + command: python + args: + - "-c" + - "import subprocess,sys; sys.exit(subprocess.run([{{repr_py(WrappedAction.Command)}}]+{{repr_py(WrappedAction.Args)}}).returncode)" + onWrapTaskRun: + command: python + args: + - "-c" + - "import subprocess,sys; sys.exit(subprocess.run([{{repr_py(WrappedAction.Command)}}]+{{repr_py(WrappedAction.Args)}}).returncode)" + onWrapEnvExit: + command: python + args: + - "-c" + - "import subprocess,sys; sys.exit(subprocess.run([{{repr_py(WrappedAction.Command)}}]+{{repr_py(WrappedAction.Args)}}).returncode)" +expected: + output: + - GRAND_CHILD_RAN