[llvm] 3b3cdcc - [lit] Remove ANSI control characters from xunit output

Alex Richardson via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 6 01:17:29 PDT 2020


Author: Alex Richardson
Date: 2020-08-06T09:16:52+01:00
New Revision: 3b3cdcc7a557a7dbd53e9e8cc311247d6df46c5c

URL: https://github.com/llvm/llvm-project/commit/3b3cdcc7a557a7dbd53e9e8cc311247d6df46c5c
DIFF: https://github.com/llvm/llvm-project/commit/3b3cdcc7a557a7dbd53e9e8cc311247d6df46c5c.diff

LOG: [lit] Remove ANSI control characters from xunit output

Failing test output sometimes contains control characters like \x1b (e.g.
if there was some -fcolor-diagnostics output) which are not allowed inside
XML files. This causes problems with CI systems: for example, the Jenkins
JUnit XML will throw an exception when ecountering those characters and
similar problems also occur with GitLab CI.

Reviewed By: yln, jdenny

Differential Revision: https://reviews.llvm.org/D84233

Added: 
    llvm/utils/lit/tests/Inputs/shtest-format/external_shell/fail_with_control_chars.txt
    llvm/utils/lit/tests/Inputs/shtest-format/external_shell/write-control-chars.py

Modified: 
    llvm/utils/lit/lit/reports.py
    llvm/utils/lit/tests/shtest-format.py

Removed: 
    


################################################################################
diff  --git a/llvm/utils/lit/lit/reports.py b/llvm/utils/lit/lit/reports.py
index b43f77911673..3d4aecf0c4d3 100755
--- a/llvm/utils/lit/lit/reports.py
+++ b/llvm/utils/lit/lit/reports.py
@@ -68,6 +68,20 @@ def write_results(self, tests, elapsed):
             file.write('\n')
 
 
+_invalid_xml_chars_dict = {c: None for c in range(32) if chr(c) not in ('\t', '\n', '\r')}
+
+
+def remove_invalid_xml_chars(s):
+    # According to the XML 1.0 spec, control characters other than
+    # \t,\r, and \n are not permitted anywhere in the document
+    # (https://www.w3.org/TR/xml/#charsets) and therefore this function
+    # removes them to produce a valid XML document.
+    #
+    # Note: In XML 1.1 only \0 is illegal (https://www.w3.org/TR/xml11/#charsets)
+    # but lit currently produces XML 1.0 output.
+    return s.translate(_invalid_xml_chars_dict)
+
+
 class XunitReport(object):
     def __init__(self, output_file):
         self.output_file = output_file
@@ -113,7 +127,15 @@ def _write_test(self, file, test, suite_name):
             # terminator we wrap it by creating a new CDATA block.
             output = test.result.output.replace(']]>', ']]]]><![CDATA[>')
             if isinstance(output, bytes):
-                output.decode("utf-8", 'ignore')
+                output = output.decode("utf-8", 'ignore')
+
+            # Failing test  output sometimes contains control characters like
+            # \x1b (e.g. if there was some -fcolor-diagnostics output) which are
+            # not allowed inside XML files.
+            # This causes problems with CI systems: for example, the Jenkins
+            # JUnit XML will throw an exception when ecountering those
+            # characters and similar problems also occur with GitLab CI.
+            output = remove_invalid_xml_chars(output)
             file.write(output)
             file.write(']]></failure>\n</testcase>\n')
         elif test.result.code in self.skipped_codes:

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-format/external_shell/fail_with_control_chars.txt b/llvm/utils/lit/tests/Inputs/shtest-format/external_shell/fail_with_control_chars.txt
new file mode 100644
index 000000000000..70d5b61d47cc
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-format/external_shell/fail_with_control_chars.txt
@@ -0,0 +1,5 @@
+# Run a command that fails and prints control characters on stdout.
+# This tests checks that the xunit output correctly escapes them in the XML.
+#
+# RUN: %{python} %S/write-control-chars.py
+

diff  --git a/llvm/utils/lit/tests/Inputs/shtest-format/external_shell/write-control-chars.py b/llvm/utils/lit/tests/Inputs/shtest-format/external_shell/write-control-chars.py
new file mode 100644
index 000000000000..34f08a03de0e
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-format/external_shell/write-control-chars.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+import sys
+
+print("a line with \x1b[2;30;41mcontrol characters\x1b[0m.")
+sys.exit(1)

diff  --git a/llvm/utils/lit/tests/shtest-format.py b/llvm/utils/lit/tests/shtest-format.py
index aa74a2caa8a2..5c483972f2d0 100644
--- a/llvm/utils/lit/tests/shtest-format.py
+++ b/llvm/utils/lit/tests/shtest-format.py
@@ -27,6 +27,13 @@
 # CHECK-NEXT: a line with bad encoding:
 # CHECK: --
 
+# CHECK: FAIL: shtest-format :: external_shell/fail_with_control_chars.txt
+# CHECK-NEXT: *** TEST 'shtest-format :: external_shell/fail_with_control_chars.txt' FAILED ***
+# CHECK: Command Output (stdout):
+# CHECK-NEXT: --
+# CHECK-NEXT: a line with {{.*}}control characters{{.*}}.
+# CHECK: --
+
 # CHECK: PASS: shtest-format :: external_shell/pass.txt
 
 # CHECK: FAIL: shtest-format :: fail.txt
@@ -68,9 +75,10 @@
 # CHECK-NEXT: true
 # CHECK-NEXT: --
 
-# CHECK: Failed Tests (3)
+# CHECK: Failed Tests (4)
 # CHECK: shtest-format :: external_shell/fail.txt
 # CHECK: shtest-format :: external_shell/fail_with_bad_encoding.txt
+# CHECK: shtest-format :: external_shell/fail_with_control_chars.txt
 # CHECK: shtest-format :: fail.txt
 
 # CHECK: Unexpectedly Passed Tests (1)
@@ -81,13 +89,13 @@
 # CHECK: Passed             : 6
 # CHECK: Expectedly Failed  : 4
 # CHECK: Unresolved         : 3
-# CHECK: Failed             : 3
+# CHECK: Failed             : 4
 # CHECK: Unexpectedly Passed: 1
 
 
 # XUNIT: <?xml version="1.0" encoding="UTF-8"?>
 # XUNIT-NEXT: <testsuites time="{{[0-9.]+}}">
-# XUNIT-NEXT: <testsuite name="shtest-format" tests="21" failures="7" skipped="4">
+# XUNIT-NEXT: <testsuite name="shtest-format" tests="22" failures="8" skipped="4">
 
 # XUNIT: <testcase classname="shtest-format.external_shell" name="fail.txt" time="{{[0-9]+\.[0-9]+}}">
 # XUNIT-NEXT: <failure{{[ ]*}}>
@@ -100,6 +108,14 @@
 # XUNIT: </failure>
 # XUNIT-NEXT: </testcase>
 
+# XUNIT: <testcase classname="shtest-format.external_shell" name="fail_with_control_chars.txt" time="{{[0-9]+\.[0-9]+}}">
+# XUNIT-NEXT: <failure><![CDATA[Script:
+# XUNIT: Command Output (stdout):
+# XUNIT-NEXT: --
+# XUNIT-NEXT: a line with [2;30;41mcontrol characters[0m.
+# XUNIT: </failure>
+# XUNIT-NEXT: </testcase>
+
 # XUNIT: <testcase classname="shtest-format.external_shell" name="pass.txt" time="{{[0-9]+\.[0-9]+}}"/>
 
 # XUNIT: <testcase classname="shtest-format.shtest-format" name="fail.txt" time="{{[0-9]+\.[0-9]+}}">


        


More information about the llvm-commits mailing list