tests/run-tests.py: Add general newline normalization function.

Add a general normalize_newlines() function that handles newline variations
(\\r\\r\\n, \\r\\n) to \\n while preserving literal \\r characters that are
part of test content.

This provides a robust solution for cross-platform test compatibility,
particularly addressing PTY double-newline issues that can occur with some
terminal implementations.

The function is applied to all test output before comparison, eliminating
platform-specific newline issues.

Includes a unit test to verify the normalization behavior.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
This commit is contained in:
Andrew Leech
2025-05-26 19:31:30 +10:00
committed by Damien George
parent 7ac8fcf752
commit e067d96c8b
5 changed files with 42 additions and 1 deletions

1
.gitattributes vendored
View File

@@ -18,6 +18,7 @@
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text
tests/basics/string_crlf_conversion.py -text
tests/micropython/test_normalize_newlines.py.exp -text
ports/stm32/pybcdc.inf_template -text
ports/stm32/usbhost/** -text
ports/cc3200/hal/aes.c -text

View File

@@ -74,5 +74,6 @@ exclude = [
"tests/basics/*.py",
"tests/*/repl_*.py",
"tests/cmdline/cmd_compile_only_error.py",
"tests/micropython/test_normalize_newlines.py",
"tests/micropython/viper_args.py",
]

View File

@@ -0,0 +1,14 @@
# Test for normalize_newlines functionality
# This test verifies that test framework handles various newline combinations correctly
# Note: This is more of an integration test since normalize_newlines is in the test framework
# The actual testing happens when this test is run through run-tests.py
print("Testing newline handling")
print("Line 1\r\nLine 2") # Windows-style line ending - should be normalized
print("Line 3") # Normal line
print("Line 4") # Normal line
print("Line 5\nLine 6") # Unix-style line ending - already normalized
# Test that literal \r in strings is preserved
print(repr("test\rstring")) # Should show 'test\rstring' not 'test\nstring'

View File

@@ -0,0 +1,8 @@
Testing newline handling
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
'test\rstring'

View File

@@ -60,6 +60,23 @@ DIFF = os.getenv("MICROPY_DIFF", "diff -u")
# Set PYTHONIOENCODING so that CPython will use utf-8 on systems which set another encoding in the locale
os.environ["PYTHONIOENCODING"] = "utf-8"
def normalize_newlines(data):
"""Normalize newline variations to \\n.
Only normalizes actual line endings, not literal \\r characters in strings.
Handles \\r\\r\\n and \\r\\n cases to ensure consistent comparison
across different platforms and terminals.
"""
if isinstance(data, bytes):
# Handle PTY double-newline issue first
data = data.replace(b"\r\r\n", b"\n")
# Then handle standard Windows line endings
data = data.replace(b"\r\n", b"\n")
# Don't convert standalone \r as it might be literal content
return data
# Code to allow a target MicroPython to import an .mpy from RAM
# Note: the module is named `__injected_test` but it needs to have `__name__` set to
# `__main__` so that the test sees itself as the main module, eg so unittest works.
@@ -706,7 +723,7 @@ def run_micropython(pyb, args, test_file, test_file_abspath, is_special=False):
)
# canonical form for all ports/platforms is to use \n for end-of-line
output_mupy = output_mupy.replace(b"\r\n", b"\n")
output_mupy = normalize_newlines(output_mupy)
# don't try to convert the output if we should skip this test
if had_crash or output_mupy in (b"SKIP\n", b"SKIP-TOO-LARGE\n", b"CRASH"):