diff --git a/docs/releases.rst b/docs/releases.rst index 3638aaf4e7..c8848afa4a 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -12,6 +12,11 @@ generate the XUnit file. It doesn't do any extra modifications to the XML tree using an ``ElementTree`` anymore. Also the schema is now validated against the XSD. +The values in the generated ``tmt-report-results.yaml`` file are +now wrapped in double quotes, and any double quotes within the +values are escaped to ensure that the resulting file is always +valid YAML. + The :ref:`/plugins/report/junit` report plugin now validates all the XML flavors against their respective XSD schemas and tries to prettify the final XML output. These functionalities are always disabled for ``custom`` flavors. diff --git a/tests/execute/restraint/report-result/data/report.sh b/tests/execute/restraint/report-result/data/report.sh index b33364f1e0..53f3088161 100755 --- a/tests/execute/restraint/report-result/data/report.sh +++ b/tests/execute/restraint/report-result/data/report.sh @@ -13,21 +13,21 @@ rlJournalStart rlRun "rstrnt-report-result --server http://test-example.com report SKIP" 0 "Generating Restraint report of skipped test." rlRun "ls $RESULT_FILE" 0 "Result report successfully generated." rlRun -s "cat $RESULT_FILE" - rlAssertGrep 'result: skip' $rlRun_LOG + rlAssertGrep 'result: "skip"' $rlRun_LOG rlRun "rm -f $RESULT_FILE" 0 "Result report successfully deleted." rlRun "rstrnt-report-result --server http://test-example.com --port 55 --disable-plugin avc --message 'Example output message.' -o /tmp/example_output.txt report PASS 66" 0 "Generating Restraint report of passed test." rlRun -s "cat $RESULT_FILE" - rlAssertGrep "- report_example_output.txt" $rlRun_LOG - rlAssertGrep 'name: /report' $rlRun_LOG - rlAssertGrep 'result: pass' $rlRun_LOG + rlAssertGrep '- "report_example_output.txt"' $rlRun_LOG + rlAssertGrep 'name: "/report"' $rlRun_LOG + rlAssertGrep 'result: "pass"' $rlRun_LOG rlRun "rm -f $RESULT_FILE" 0 "Result report successfully deleted." rlRun "rstrnt-report-result --server http://test-example.com report WARN" 0 "Generating Restraint report of warned test." rlRun -s "cat $RESULT_FILE" - rlAssertGrep 'result: warn' $rlRun_LOG + rlAssertGrep 'result: "warn"' $rlRun_LOG rlRun "rm -f $RESULT_FILE" 0 "Result report successfully deleted." rlRun "rstrnt-report-result --server http://test-example.com report FAIL" 0 "Generating Restraint report of failed test." rlRun -s "cat $RESULT_FILE" - rlAssertGrep 'result: fail' $rlRun_LOG + rlAssertGrep 'result: "fail"' $rlRun_LOG rlRun "rm -f $RESULT_FILE" 0 "Result report successfully deleted." rlPhaseEnd @@ -35,21 +35,21 @@ rlJournalStart rlRun "rhts-report-result rhts-report SKIP /tmp/example_output.txt" 0 "Generating RHTS report of skipped test without optional metric." rlRun "ls $RESULT_FILE" 0 "Result report successfully generated." rlRun -s "cat $RESULT_FILE" - rlAssertGrep 'result: skip' $rlRun_LOG + rlAssertGrep 'result: "skip"' $rlRun_LOG rlRun "rm -f $RESULT_FILE" 0 "Result report successfully deleted." rlRun "rhts-report-result rhts-report PASS /tmp/example_output.txt 66" 0 "Generating RHTS report of passed test." rlRun -s "cat $RESULT_FILE" - rlAssertGrep "- rhts-report_example_output.txt" $rlRun_LOG - rlAssertGrep 'name: /rhts-report' $rlRun_LOG - rlAssertGrep 'result: pass' $rlRun_LOG + rlAssertGrep '- "rhts-report_example_output.txt"' $rlRun_LOG + rlAssertGrep 'name: "/rhts-report"' $rlRun_LOG + rlAssertGrep 'result: "pass"' $rlRun_LOG rlRun "rm -f $RESULT_FILE" 0 "Result report successfully deleted." rlRun "rhts-report-result rhts-report WARN /tmp/example_output.txt 66" 0 "Generating RHTS report of warned test." rlRun -s "cat $RESULT_FILE" - rlAssertGrep 'result: warn' $rlRun_LOG + rlAssertGrep 'result: "warn"' $rlRun_LOG rlRun "rm -f $RESULT_FILE" 0 "Result report successfully deleted." rlRun "rhts-report-result rhts-report FAIL /tmp/example_output.txt 66" 0 "Generating RHTS report of failed test." rlRun -s "cat $RESULT_FILE" - rlAssertGrep 'result: fail' $rlRun_LOG + rlAssertGrep 'result: "fail"' $rlRun_LOG rlPhaseEnd rlPhaseStartCleanup diff --git a/tests/execute/result/main.fmf b/tests/execute/result/main.fmf index 97bf9981ee..e5d21e3e30 100644 --- a/tests/execute/result/main.fmf +++ b/tests/execute/result/main.fmf @@ -7,3 +7,6 @@ /repeated: summary: Repeated test should provide multiple results test: ./repeated.sh +/special: + summary: Test special characters generated to tmt-report-results.yaml + test: ./special.sh diff --git a/tests/execute/result/special.sh b/tests/execute/result/special.sh new file mode 100755 index 0000000000..24ae52736a --- /dev/null +++ b/tests/execute/result/special.sh @@ -0,0 +1,26 @@ +#!/bin/bash +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +rlJournalStart + rlPhaseStartSetup + rlRun "run=\$(mktemp -d)" 0 "Create run directory" + rlRun "pushd special" + rlPhaseEnd + + rlPhaseStartTest "Check characters are correctly escaped in tmt-report-result output" + rlRun -s "tmt run -v -i $run" 0 + + RESULT_FILE="$run/special-chars/execute/data/guest/default-0/0-7-special-characters-in-the-name-1/data/tmt-report-results.yaml" + rlRun "yq -ye '.' $RESULT_FILE" 0 "Check the YAML is valid" + + rlAssertGrep 'name: "/0\.\.7 \\"special\\": \\" characters: \*\$@|&>< in: the: name"' "$RESULT_FILE" + rlAssertGrep "result: \"pass\"" "$RESULT_FILE" + rlAssertGrep "end-time: \".*\"" "$RESULT_FILE" + rlAssertGrep "data-path: \"/.*\"" "$RESULT_FILE" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -r ${run}" 0 "Remove run directory" + rlPhaseEnd +rlJournalEnd diff --git a/tests/execute/result/special/.fmf/version b/tests/execute/result/special/.fmf/version new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/execute/result/special/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/tests/execute/result/special/special-chars.fmf b/tests/execute/result/special/special-chars.fmf new file mode 100644 index 0000000000..db11257e61 --- /dev/null +++ b/tests/execute/result/special/special-chars.fmf @@ -0,0 +1,10 @@ +execute: + how: tmt +discover: + how: shell + tests: + - name: '0..7 special: characters: *$@|&>< in: the: name' + result: restraint + test: "tmt-report-result '0..7 \"special\": \" characters: *$@|&>< in: the: name' PASS" +provision: + how: container diff --git a/tmt/steps/execute/scripts/tmt-report-result b/tmt/steps/execute/scripts/tmt-report-result index 2ad80c219e..4d0c199a27 100755 --- a/tmt/steps/execute/scripts/tmt-report-result +++ b/tmt/steps/execute/scripts/tmt-report-result @@ -10,14 +10,17 @@ die() { echo "$*" >&2; exit 2; } # complain to STDERR and exit with error needs_arg() { if [ -z "$OPTARG" ]; then die "No arg for --$OPT option"; fi; } write_report_file () { - echo " - name: ${TESTNAME}" >> "$REPORT_RESULT_OUTPUTFILE" - echo " result: ${TESTRESULT}" >> "$REPORT_RESULT_OUTPUTFILE" + echo " - name: \"${TESTNAME}\"" >> "$REPORT_RESULT_OUTPUTFILE" + echo " result: \"${TESTRESULT}\"" >> "$REPORT_RESULT_OUTPUTFILE" if [ -n "${outputFile}" ]; then + # FIXME: The UNIX filenames can contain double quotes in the filename + # (`$outputFile`). We should escape them as well as for TESTNAME. + # Otherwise, the resulting YAML file can be invalid. echo " log:" >> "$REPORT_RESULT_OUTPUTFILE" - echo " - ${outputFile}" >> "$REPORT_RESULT_OUTPUTFILE" + echo " - \"${outputFile}\"" >> "$REPORT_RESULT_OUTPUTFILE" fi echo " end-time: \"$(date --utc +%FT%T.%6N%:z)\"" >> "$REPORT_RESULT_OUTPUTFILE" - echo " data-path: ${TMT_TEST_DATA/$TMT_TEST_EXE}" >> "$REPORT_RESULT_OUTPUTFILE" + echo " data-path: \"${TMT_TEST_DATA/$TMT_TEST_EXE}\"" >> "$REPORT_RESULT_OUTPUTFILE" } copy_outputfile_to_data_dir () { @@ -85,7 +88,10 @@ if [ $# -lt 2 ] || [ $help == True ]; then echo "" exit 1 fi + TESTNAME=$1 +# If test name contains double quotes, escape them with a backslash +TESTNAME=${TESTNAME//\"/\\\"} # If last character is a ':' then delete it. [[ ${TESTNAME: -1} == ':' ]] && TESTNAME=${TESTNAME::-1} # If the first character isn't a '/' then add it.