summaryrefslogtreecommitdiff
path: root/mesonbuild/mtest.py
diff options
context:
space:
mode:
authorNazir Bilal Yavuz <byavuz81@gmail.com>2023-06-12 13:47:19 +0300
committerDylan Baker <dylan@pnwbakers.com>2023-07-13 09:38:55 -0700
commitbd3d2cf91894b1f91128011b2cf56a5bd2c326ae (patch)
tree1955faa13e2a9b97630b0dc4d540e7428c228710 /mesonbuild/mtest.py
parent61984bcfa3e4e758d18174d13aa0aaedbf406889 (diff)
downloadmeson-bd3d2cf91894b1f91128011b2cf56a5bd2c326ae.tar.gz
mtest: fix unencodable XML chars
Replace unencodable XML chars with their printable representation, so that, xmllint can parse test outputs without error. Closes #9894 Co-authored-by: Tristan Partin <tristan@partin.io>
Diffstat (limited to 'mesonbuild/mtest.py')
-rw-r--r--mesonbuild/mtest.py31
1 files changed, 29 insertions, 2 deletions
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 8975dcdff..eb56c42be 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -72,6 +72,26 @@ GNU_ERROR_RETURNCODE = 99
# Exit if 3 Ctrl-C's are received within one second
MAX_CTRLC = 3
+# Define unencodable xml characters' regex for replacing them with their
+# printable representation
+UNENCODABLE_XML_UNICHRS: T.List[T.Tuple[int, int]] = [
+ (0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84),
+ (0x86, 0x9F), (0xFDD0, 0xFDEF), (0xFFFE, 0xFFFF)]
+# Not narrow build
+if sys.maxunicode >= 0x10000:
+ UNENCODABLE_XML_UNICHRS.extend([
+ (0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF),
+ (0x3FFFE, 0x3FFFF), (0x4FFFE, 0x4FFFF),
+ (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF),
+ (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF),
+ (0x9FFFE, 0x9FFFF), (0xAFFFE, 0xAFFFF),
+ (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF),
+ (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF),
+ (0xFFFFE, 0xFFFFF), (0x10FFFE, 0x10FFFF)])
+UNENCODABLE_XML_CHR_RANGES = [fr'{chr(low)}-{chr(high)}' for (low, high) in UNENCODABLE_XML_UNICHRS]
+UNENCODABLE_XML_CHRS_RE = re.compile('([' + ''.join(UNENCODABLE_XML_CHR_RANGES) + '])')
+
+
def is_windows() -> bool:
platname = platform.system().lower()
return platname == 'windows'
@@ -1148,14 +1168,21 @@ class TestRunRust(TestRun):
TestRun.PROTOCOL_TO_CLASS[TestProtocol.RUST] = TestRunRust
+# Check unencodable characters in xml output and replace them with
+# their printable representation
+def replace_unencodable_xml_chars(original_str: str) -> str:
+ # [1:-1] is needed for removing `'` characters from both start and end
+ # of the string
+ replacement_lambda = lambda illegal_chr: repr(illegal_chr.group())[1:-1]
+ return UNENCODABLE_XML_CHRS_RE.sub(replacement_lambda, original_str)
def decode(stream: T.Union[None, bytes]) -> str:
if stream is None:
return ''
try:
- return stream.decode('utf-8')
+ return replace_unencodable_xml_chars(stream.decode('utf-8'))
except UnicodeDecodeError:
- return stream.decode('iso-8859-1', errors='ignore')
+ return replace_unencodable_xml_chars(stream.decode('iso-8859-1', errors='ignore'))
async def read_decode(reader: asyncio.StreamReader,
queue: T.Optional['asyncio.Queue[T.Optional[str]]'],