summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Leech <andrew.leech@planetinnovation.com.au>2025-05-26 19:31:30 +1000
committerDamien George <damien@micropython.org>2025-11-22 00:06:59 +1100
commite067d96c8b71b3fe258583fd6cddb1094cb4efe5 (patch)
treed04978be6c7739c6987d6f40137191682a5b2baf
parent7ac8fcf752389e2af37b49994478bd9d93f48434 (diff)
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>
-rw-r--r--.gitattributes1
-rw-r--r--pyproject.toml1
-rw-r--r--tests/micropython/test_normalize_newlines.py14
-rw-r--r--tests/micropython/test_normalize_newlines.py.exp8
-rwxr-xr-xtests/run-tests.py19
5 files changed, 42 insertions, 1 deletions
diff --git a/.gitattributes b/.gitattributes
index 2d8496db5..c14a61b0d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -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
diff --git a/pyproject.toml b/pyproject.toml
index cdc79bb8a..f3693eae1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -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",
]
diff --git a/tests/micropython/test_normalize_newlines.py b/tests/micropython/test_normalize_newlines.py
new file mode 100644
index 000000000..f19aaa69a
--- /dev/null
+++ b/tests/micropython/test_normalize_newlines.py
@@ -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'
diff --git a/tests/micropython/test_normalize_newlines.py.exp b/tests/micropython/test_normalize_newlines.py.exp
new file mode 100644
index 000000000..c4395468c
--- /dev/null
+++ b/tests/micropython/test_normalize_newlines.py.exp
@@ -0,0 +1,8 @@
+Testing newline handling
+Line 1
+Line 2
+Line 3
+Line 4
+Line 5
+Line 6
+'test\rstring'
diff --git a/tests/run-tests.py b/tests/run-tests.py
index b4654c2e6..fba011fb5 100755
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -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"):