summaryrefslogtreecommitdiffstatshomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/basics/io_buffered_writer.py24
-rw-r--r--tests/basics/io_buffered_writer.py.exp5
-rw-r--r--tests/cmdline/repl_autocomplete_underscore.py33
-rw-r--r--tests/cmdline/repl_autocomplete_underscore.py.exp41
-rw-r--r--tests/cmdline/repl_paste.py90
-rw-r--r--tests/cmdline/repl_paste.py.exp133
-rw-r--r--tests/cpydiff/core_import_all.py10
-rw-r--r--tests/cpydiff/modules3/__init__.py1
-rw-r--r--tests/cpydiff/modules3/foo.py2
-rw-r--r--tests/cpydiff/types_complex_parser.py14
-rw-r--r--tests/extmod/platform_basic.py8
-rw-r--r--tests/extmod/random_extra_float.py8
-rw-r--r--tests/float/float_array.py8
-rw-r--r--tests/float/math_constants_extra.py3
-rw-r--r--tests/import/import_star.py59
-rw-r--r--tests/import/pkgstar_all_array/__init__.py49
-rw-r--r--tests/import/pkgstar_all_array/funcs.py2
-rw-r--r--tests/import/pkgstar_all_inval/__init__.py1
-rw-r--r--tests/import/pkgstar_all_miss/__init__.py8
-rw-r--r--tests/import/pkgstar_all_tuple/__init__.py22
-rw-r--r--tests/import/pkgstar_default/__init__.py20
-rw-r--r--tests/micropython/viper_ptr16_load_boundary.py32
-rw-r--r--tests/micropython/viper_ptr16_load_boundary.py.exp32
-rw-r--r--tests/micropython/viper_ptr16_store_boundary.py66
-rw-r--r--tests/micropython/viper_ptr16_store_boundary.py.exp38
-rw-r--r--tests/micropython/viper_ptr32_load_boundary.py32
-rw-r--r--tests/micropython/viper_ptr32_load_boundary.py.exp32
-rw-r--r--tests/micropython/viper_ptr32_store_boundary.py69
-rw-r--r--tests/micropython/viper_ptr32_store_boundary.py.exp38
-rw-r--r--tests/micropython/viper_ptr8_load_boundary.py31
-rw-r--r--tests/micropython/viper_ptr8_load_boundary.py.exp32
-rw-r--r--tests/micropython/viper_ptr8_store_boundary.py53
-rw-r--r--tests/micropython/viper_ptr8_store_boundary.py.exp32
-rw-r--r--tests/multi_net/tcp_accept_recv.py73
-rw-r--r--tests/ports/rp2/rp2_machine_timer.py20
-rw-r--r--tests/ports/rp2/rp2_machine_timer.py.exp16
-rw-r--r--tests/ports/unix/extra_coverage.py.exp25
-rwxr-xr-xtests/run-multitests.py32
-rwxr-xr-xtests/run-natmodtests.py37
-rwxr-xr-xtests/run-perfbench.py29
-rwxr-xr-xtests/run-tests.py69
41 files changed, 1045 insertions, 284 deletions
diff --git a/tests/basics/io_buffered_writer.py b/tests/basics/io_buffered_writer.py
index 5c065f158a..60cf2c837d 100644
--- a/tests/basics/io_buffered_writer.py
+++ b/tests/basics/io_buffered_writer.py
@@ -28,3 +28,27 @@ print(bts.getvalue())
# hashing a BufferedWriter
print(type(hash(buf)))
+
+# Test failing flush()
+class MyIO(io.IOBase):
+ def __init__(self):
+ self.count = 0
+
+ def write(self, buf):
+ self.count += 1
+ if self.count < 3:
+ return None
+ print("writing", buf)
+ return len(buf)
+
+
+buf = io.BufferedWriter(MyIO(), 8)
+
+buf.write(b"foobar")
+
+for _ in range(4):
+ try:
+ buf.flush()
+ print("flushed")
+ except OSError:
+ print("OSError")
diff --git a/tests/basics/io_buffered_writer.py.exp b/tests/basics/io_buffered_writer.py.exp
index 2209348f5a..d61eb148b4 100644
--- a/tests/basics/io_buffered_writer.py.exp
+++ b/tests/basics/io_buffered_writer.py.exp
@@ -4,3 +4,8 @@ b'foobarfoobar'
b'foobarfoobar'
b'foo'
<class 'int'>
+OSError
+OSError
+writing bytearray(b'foobar')
+flushed
+flushed
diff --git a/tests/cmdline/repl_autocomplete_underscore.py b/tests/cmdline/repl_autocomplete_underscore.py
new file mode 100644
index 0000000000..98bbb69920
--- /dev/null
+++ b/tests/cmdline/repl_autocomplete_underscore.py
@@ -0,0 +1,33 @@
+# Test REPL autocompletion filtering of underscore attributes
+
+# Start paste mode
+{\x05}
+class TestClass:
+ def __init__(self):
+ self.public_attr = 1
+ self._private_attr = 2
+ self.__very_private = 3
+
+ def public_method(self):
+ pass
+
+ def _private_method(self):
+ pass
+
+ @property
+ def public_property(self):
+ return 42
+
+ @property
+ def _private_property(self):
+ return 99
+
+{\x04}
+# Paste executed
+
+# Create an instance
+obj = TestClass()
+
+# Test tab completion on the instance
+# The tab character after `obj.` and 'a' below triggers the completions
+obj.{\x09}{\x09}a{\x09}
diff --git a/tests/cmdline/repl_autocomplete_underscore.py.exp b/tests/cmdline/repl_autocomplete_underscore.py.exp
new file mode 100644
index 0000000000..35617554f5
--- /dev/null
+++ b/tests/cmdline/repl_autocomplete_underscore.py.exp
@@ -0,0 +1,41 @@
+MicroPython \.\+ version
+Use Ctrl-D to exit, Ctrl-E for paste mode
+>>> # Test REPL autocompletion filtering of underscore attributes
+>>>
+>>> # Start paste mode
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== class TestClass:
+=== def __init__(self):
+=== self.public_attr = 1
+=== self._private_attr = 2
+=== self.__very_private = 3
+===
+=== def public_method(self):
+=== pass
+===
+=== def _private_method(self):
+=== pass
+===
+=== @property
+=== def public_property(self):
+=== return 42
+===
+=== @property
+=== def _private_property(self):
+=== return 99
+===
+===
+>>> # Paste executed
+>>>
+>>> # Create an instance
+>>> obj = TestClass()
+>>>
+>>> # Test tab completion on the instance
+>>> # The tab character after `obj.` and 'a' below triggers the completions
+>>> obj.public_
+public_attr public_method public_property
+>>> obj.public_attr
+1
+>>>
diff --git a/tests/cmdline/repl_paste.py b/tests/cmdline/repl_paste.py
new file mode 100644
index 0000000000..7cec450fce
--- /dev/null
+++ b/tests/cmdline/repl_paste.py
@@ -0,0 +1,90 @@
+# Test REPL paste mode functionality
+
+# Basic paste mode with a simple function
+{\x05}
+def hello():
+ print('Hello from paste mode!')
+hello()
+{\x04}
+
+# Paste mode with multiple indentation levels
+{\x05}
+def calculate(n):
+ if n > 0:
+ for i in range(n):
+ if i % 2 == 0:
+ print(f'Even: {i}')
+ else:
+ print(f'Odd: {i}')
+ else:
+ print('n must be positive')
+
+calculate(5)
+{\x04}
+
+# Paste mode with blank lines
+{\x05}
+def function_with_blanks():
+ print('First line')
+
+ print('After blank line')
+
+
+ print('After two blank lines')
+
+function_with_blanks()
+{\x04}
+
+# Paste mode with class definition and multiple methods
+{\x05}
+class TestClass:
+ def __init__(self, value):
+ self.value = value
+
+ def display(self):
+ print(f'Value is: {self.value}')
+
+ def double(self):
+ self.value *= 2
+ return self.value
+
+obj = TestClass(21)
+obj.display()
+print(f'Doubled: {obj.double()}')
+obj.display()
+{\x04}
+
+# Paste mode with exception handling
+{\x05}
+try:
+ x = 1 / 0
+except ZeroDivisionError:
+ print('Caught division by zero')
+finally:
+ print('Finally block executed')
+{\x04}
+
+# Cancel paste mode with Ctrl-C
+{\x05}
+print('This should not execute')
+{\x03}
+
+# Normal REPL still works after cancelled paste
+print('Back to normal REPL')
+
+# Paste mode with syntax error
+{\x05}
+def bad_syntax(:
+ print('Missing parameter')
+{\x04}
+
+# Paste mode with runtime error
+{\x05}
+def will_error():
+ undefined_variable
+
+will_error()
+{\x04}
+
+# Final test to show REPL is still functioning
+1 + 2 + 3
diff --git a/tests/cmdline/repl_paste.py.exp b/tests/cmdline/repl_paste.py.exp
new file mode 100644
index 0000000000..22d9bd5740
--- /dev/null
+++ b/tests/cmdline/repl_paste.py.exp
@@ -0,0 +1,133 @@
+MicroPython \.\+ version
+Use Ctrl-D to exit, Ctrl-E for paste mode
+>>> # Test REPL paste mode functionality
+>>>
+>>> # Basic paste mode with a simple function
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== def hello():
+=== print('Hello from paste mode!')
+=== hello()
+===
+Hello from paste mode!
+>>>
+>>> # Paste mode with multiple indentation levels
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== def calculate(n):
+=== if n > 0:
+=== for i in range(n):
+=== if i % 2 == 0:
+=== print(f'Even: {i}')
+=== else:
+=== print(f'Odd: {i}')
+=== else:
+=== print('n must be positive')
+===
+=== calculate(5)
+===
+Even: 0
+Odd: 1
+Even: 2
+Odd: 3
+Even: 4
+>>>
+>>> # Paste mode with blank lines
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== def function_with_blanks():
+=== print('First line')
+===
+=== print('After blank line')
+===
+===
+=== print('After two blank lines')
+===
+=== function_with_blanks()
+===
+First line
+After blank line
+After two blank lines
+>>>
+>>> # Paste mode with class definition and multiple methods
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== class TestClass:
+=== def __init__(self, value):
+=== self.value = value
+===
+=== def display(self):
+=== print(f'Value is: {self.value}')
+===
+=== def double(self):
+=== self.value *= 2
+=== return self.value
+===
+=== obj = TestClass(21)
+=== obj.display()
+=== print(f'Doubled: {obj.double()}')
+=== obj.display()
+===
+Value is: 21
+Doubled: 42
+Value is: 42
+>>>
+>>> # Paste mode with exception handling
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== try:
+=== x = 1 / 0
+=== except ZeroDivisionError:
+=== print('Caught division by zero')
+=== finally:
+=== print('Finally block executed')
+===
+Caught division by zero
+Finally block executed
+>>>
+>>> # Cancel paste mode with Ctrl-C
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== print('This should not execute')
+===
+>>>
+>>>
+>>> # Normal REPL still works after cancelled paste
+>>> print('Back to normal REPL')
+Back to normal REPL
+>>>
+>>> # Paste mode with syntax error
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== def bad_syntax(:
+=== print('Missing parameter')
+===
+Traceback (most recent call last):
+ File "<stdin>", line 2
+SyntaxError: invalid syntax
+>>>
+>>> # Paste mode with runtime error
+>>>
+paste mode; Ctrl-C to cancel, Ctrl-D to finish
+===
+=== def will_error():
+=== undefined_variable
+===
+=== will_error()
+===
+Traceback (most recent call last):
+ File "<stdin>", line 5, in <module>
+ File "<stdin>", line 3, in will_error
+NameError: name 'undefined_variable' isn't defined
+>>>
+>>> # Final test to show REPL is still functioning
+>>> 1 + 2 + 3
+6
+>>>
diff --git a/tests/cpydiff/core_import_all.py b/tests/cpydiff/core_import_all.py
deleted file mode 100644
index 0fbe9d4d4e..0000000000
--- a/tests/cpydiff/core_import_all.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""
-categories: Core,import
-description: __all__ is unsupported in __init__.py in MicroPython.
-cause: Not implemented.
-workaround: Manually import the sub-modules directly in __init__.py using ``from . import foo, bar``.
-"""
-
-from modules3 import *
-
-foo.hello()
diff --git a/tests/cpydiff/modules3/__init__.py b/tests/cpydiff/modules3/__init__.py
deleted file mode 100644
index 27a2bf2ad9..0000000000
--- a/tests/cpydiff/modules3/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__all__ = ["foo"]
diff --git a/tests/cpydiff/modules3/foo.py b/tests/cpydiff/modules3/foo.py
deleted file mode 100644
index dd9b9d4ddd..0000000000
--- a/tests/cpydiff/modules3/foo.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def hello():
- print("hello")
diff --git a/tests/cpydiff/types_complex_parser.py b/tests/cpydiff/types_complex_parser.py
new file mode 100644
index 0000000000..4a012987d9
--- /dev/null
+++ b/tests/cpydiff/types_complex_parser.py
@@ -0,0 +1,14 @@
+"""
+categories: Types,complex
+description: MicroPython's complex() accepts certain incorrect values that CPython rejects
+cause: MicroPython is highly optimized for memory usage.
+workaround: Do not use non-standard complex literals as argument to complex()
+
+MicroPython's ``complex()`` function accepts literals that contain a space and
+no sign between the real and imaginary parts, and interprets it as a plus.
+"""
+
+try:
+ print(complex("1 1j"))
+except ValueError:
+ print("ValueError")
diff --git a/tests/extmod/platform_basic.py b/tests/extmod/platform_basic.py
new file mode 100644
index 0000000000..eb6f2be13c
--- /dev/null
+++ b/tests/extmod/platform_basic.py
@@ -0,0 +1,8 @@
+try:
+ import platform
+except ImportError:
+ print("SKIP")
+ raise SystemExit
+
+print(type(platform.python_compiler()))
+print(type(platform.libc_ver()))
diff --git a/tests/extmod/random_extra_float.py b/tests/extmod/random_extra_float.py
index 3b37ed8dce..03973c5834 100644
--- a/tests/extmod/random_extra_float.py
+++ b/tests/extmod/random_extra_float.py
@@ -1,12 +1,8 @@
try:
import random
-except ImportError:
- print("SKIP")
- raise SystemExit
-try:
- random.randint
-except AttributeError:
+ random.random
+except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
diff --git a/tests/float/float_array.py b/tests/float/float_array.py
index 3d128da838..cfff3b220c 100644
--- a/tests/float/float_array.py
+++ b/tests/float/float_array.py
@@ -19,4 +19,10 @@ def test(a):
test(array("f"))
test(array("d"))
-print("{:.4f}".format(array("f", bytes(array("I", [0x3DCCCCCC])))[0]))
+# hand-crafted floats, including non-standard nan
+for float_hex in (0x3DCCCCCC, 0x7F800024, 0x7FC00004):
+ f = array("f", bytes(array("I", [float_hex])))[0]
+ if type(f) is float:
+ print("{:.4e}".format(f))
+ else:
+ print(f)
diff --git a/tests/float/math_constants_extra.py b/tests/float/math_constants_extra.py
index dea49aef5a..756cb45803 100644
--- a/tests/float/math_constants_extra.py
+++ b/tests/float/math_constants_extra.py
@@ -9,9 +9,12 @@ except (ImportError, AttributeError):
raise SystemExit
print(math.tau == 2.0 * math.pi)
+print(math.copysign(1.0, math.tau))
print(math.inf == float("inf"))
print(-math.inf == -float("inf"))
+print(math.copysign(1.0, math.inf))
print(isnan(math.nan))
print(isnan(-math.nan))
+print(math.copysign(1.0, math.nan))
diff --git a/tests/import/import_star.py b/tests/import/import_star.py
new file mode 100644
index 0000000000..0947f6a835
--- /dev/null
+++ b/tests/import/import_star.py
@@ -0,0 +1,59 @@
+# test `from package import *` conventions, including __all__ support
+#
+# This test requires MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES
+
+try:
+ next(iter([]), 42)
+except TypeError:
+ # 2-argument version of next() not supported
+ # we are probably not at MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES
+ print('SKIP')
+ raise SystemExit
+
+# 1. test default visibility
+from pkgstar_default import *
+
+print('visibleFun' in globals())
+print('VisibleClass' in globals())
+print('_hiddenFun' in globals())
+print('_HiddenClass' in globals())
+print(visibleFun())
+
+# 2. test explicit visibility as defined by __all__ (as an array)
+from pkgstar_all_array import *
+
+print('publicFun' in globals())
+print('PublicClass' in globals())
+print('unlistedFun' in globals())
+print('UnlistedClass' in globals())
+print('_privateFun' in globals())
+print('_PrivateClass' in globals())
+print(publicFun())
+# test dynamic import as used in asyncio
+print('dynamicFun' in globals())
+print(dynamicFun())
+
+# 3. test explicit visibility as defined by __all__ (as an tuple)
+from pkgstar_all_tuple import *
+
+print('publicFun2' in globals())
+print('PublicClass2' in globals())
+print('unlistedFun2' in globals())
+print('UnlistedClass2' in globals())
+print(publicFun2())
+
+# 4. test reporting of missing entries in __all__
+try:
+ from pkgstar_all_miss import *
+
+ print("missed detection of incorrect __all__ definition")
+except AttributeError as er:
+ print("AttributeError triggered for bad __all__ definition")
+
+# 5. test reporting of invalid __all__ definition
+try:
+ from pkgstar_all_inval import *
+
+ print("missed detection of incorrect __all__ definition")
+except TypeError as er:
+ print("TypeError triggered for bad __all__ definition")
diff --git a/tests/import/pkgstar_all_array/__init__.py b/tests/import/pkgstar_all_array/__init__.py
new file mode 100644
index 0000000000..4499a94d59
--- /dev/null
+++ b/tests/import/pkgstar_all_array/__init__.py
@@ -0,0 +1,49 @@
+__all__ = ['publicFun', 'PublicClass', 'dynamicFun']
+
+
+# Definitions below should always be imported by a star import
+def publicFun():
+ return 1
+
+
+class PublicClass:
+ def __init__(self):
+ self._val = 1
+
+
+# If __all__ support is enabled, definitions below
+# should not be imported by a star import
+def unlistedFun():
+ return 0
+
+
+class UnlistedClass:
+ def __init__(self):
+ self._val = 0
+
+
+# Definitions below should be not be imported by a star import
+# (they start with an underscore, and are not listed in __all__)
+def _privateFun():
+ return -1
+
+
+class _PrivateClass:
+ def __init__(self):
+ self._val = -1
+
+
+# Test lazy loaded function, as used by extmod/asyncio:
+# Works with a star import only if __all__ support is enabled
+_attrs = {
+ "dynamicFun": "funcs",
+}
+
+
+def __getattr__(attr):
+ mod = _attrs.get(attr, None)
+ if mod is None:
+ raise AttributeError(attr)
+ value = getattr(__import__(mod, globals(), locals(), True, 1), attr)
+ globals()[attr] = value
+ return value
diff --git a/tests/import/pkgstar_all_array/funcs.py b/tests/import/pkgstar_all_array/funcs.py
new file mode 100644
index 0000000000..7540d70f66
--- /dev/null
+++ b/tests/import/pkgstar_all_array/funcs.py
@@ -0,0 +1,2 @@
+def dynamicFun():
+ return 777
diff --git a/tests/import/pkgstar_all_inval/__init__.py b/tests/import/pkgstar_all_inval/__init__.py
new file mode 100644
index 0000000000..7022476c19
--- /dev/null
+++ b/tests/import/pkgstar_all_inval/__init__.py
@@ -0,0 +1 @@
+__all__ = 42
diff --git a/tests/import/pkgstar_all_miss/__init__.py b/tests/import/pkgstar_all_miss/__init__.py
new file mode 100644
index 0000000000..d960c7d0e2
--- /dev/null
+++ b/tests/import/pkgstar_all_miss/__init__.py
@@ -0,0 +1,8 @@
+__all__ = ('existingFun', 'missingFun')
+
+
+def existingFun():
+ return None
+
+
+# missingFun is not defined, should raise an error on import
diff --git a/tests/import/pkgstar_all_tuple/__init__.py b/tests/import/pkgstar_all_tuple/__init__.py
new file mode 100644
index 0000000000..a97715ed39
--- /dev/null
+++ b/tests/import/pkgstar_all_tuple/__init__.py
@@ -0,0 +1,22 @@
+__all__ = ('publicFun2', 'PublicClass2')
+
+
+# Definitions below should always be imported by a star import
+def publicFun2():
+ return 2
+
+
+class PublicClass2:
+ def __init__(self):
+ self._val = 2
+
+
+# If __all__ support is enabled, definitions below
+# should not be imported by a star import
+def unlistedFun2():
+ return 0
+
+
+class UnlistedClass2:
+ def __init__(self):
+ self._val = 0
diff --git a/tests/import/pkgstar_default/__init__.py b/tests/import/pkgstar_default/__init__.py
new file mode 100644
index 0000000000..4947e4ce7f
--- /dev/null
+++ b/tests/import/pkgstar_default/__init__.py
@@ -0,0 +1,20 @@
+# When __all__ is undefined, star import should only
+# show objects that do not start with an underscore
+
+
+def visibleFun():
+ return 42
+
+
+class VisibleClass:
+ def __init__(self):
+ self._val = 42
+
+
+def _hiddenFun():
+ return -1
+
+
+class _HiddenClass:
+ def __init__(self):
+ self._val = -1
diff --git a/tests/micropython/viper_ptr16_load_boundary.py b/tests/micropython/viper_ptr16_load_boundary.py
index ccaaa0909a..0d4c3105b6 100644
--- a/tests/micropython/viper_ptr16_load_boundary.py
+++ b/tests/micropython/viper_ptr16_load_boundary.py
@@ -2,24 +2,38 @@
GET_TEMPLATE = """
@micropython.viper
-def get{off}(src: ptr16) -> int:
- return src[{off}]
-print(b[{off} * 2:({off} + 1) * 2])
+def get{off}(src: ptr16) -> uint:
+ return uint(src[{off}])
+print(hex(get{off}(buffer)))
"""
+BIT_THRESHOLDS = (5, 8, 11, 12)
+SIZE = 2
+
+
@micropython.viper
def get_index(src: ptr16, i: int) -> int:
return src[i]
-b = bytearray(5000)
-b[28:38] = b"0123456789"
-b[252:262] = b"ABCDEFGHIJ"
-b[4092:4102] = b"KLMNOPQRST"
+def data(start, len):
+ output = bytearray(len)
+ for idx in range(len):
+ output[idx] = (start + idx) & 0xFF
+ return output
+
+
+buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024)
+val = 0
+for bit in BIT_THRESHOLDS:
+ print("---", bit)
+ pre, idx, post = ((1 << bit) - (2 * SIZE), (1 << bit) - (1 * SIZE), 1 << bit)
+ buffer[pre:post] = data(val, 3 * SIZE)
+ val = val + (3 * SIZE)
-for pre, idx, post in (15, 16, 17), (127, 128, 129), (2047, 2048, 2049):
- print(get_index(b, pre), get_index(b, idx), get_index(b, post))
+ pre, idx, post = pre // SIZE, idx // SIZE, post // SIZE
+ print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post)))
exec(GET_TEMPLATE.format(off=pre))
exec(GET_TEMPLATE.format(off=idx))
exec(GET_TEMPLATE.format(off=post))
diff --git a/tests/micropython/viper_ptr16_load_boundary.py.exp b/tests/micropython/viper_ptr16_load_boundary.py.exp
index 4b8c184c13..56f1d32290 100644
--- a/tests/micropython/viper_ptr16_load_boundary.py.exp
+++ b/tests/micropython/viper_ptr16_load_boundary.py.exp
@@ -1,12 +1,20 @@
-13106 13620 14134
-bytearray(b'23')
-bytearray(b'45')
-bytearray(b'67')
-17475 17989 18503
-bytearray(b'CD')
-bytearray(b'EF')
-bytearray(b'GH')
-20045 20559 21073
-bytearray(b'MN')
-bytearray(b'OP')
-bytearray(b'QR')
+--- 5
+0x100 0x302 0x504
+0x100
+0x302
+0x504
+--- 8
+0x706 0x908 0xb0a
+0x706
+0x908
+0xb0a
+--- 11
+0xd0c 0xf0e 0x1110
+0xd0c
+0xf0e
+0x1110
+--- 12
+0x1312 0x1514 0x1716
+0x1312
+0x1514
+0x1716
diff --git a/tests/micropython/viper_ptr16_store_boundary.py b/tests/micropython/viper_ptr16_store_boundary.py
index e0a4f84557..1694c61ac0 100644
--- a/tests/micropython/viper_ptr16_store_boundary.py
+++ b/tests/micropython/viper_ptr16_store_boundary.py
@@ -4,38 +4,50 @@ SET_TEMPLATE = """
@micropython.viper
def set{off}(dest: ptr16):
dest[{off}] = {val}
-set{off}(b)
-print(b[{off} * 2:({off} + 1) * 2])
+set{off}(buffer)
+print(hex(get_index(buffer, {off})))
"""
-TEST_DATA = (
- (15, (0x4241, 0x4443, 0x4645)),
- (127, (0x4847, 0x4A49, 0x4C4B)),
- (2047, (0x4E4D, 0x504F, 0x5251)),
-)
+BIT_THRESHOLDS = (5, 8, 11, 12)
+SIZE = 2
+MASK = (1 << (8 * SIZE)) - 1
@micropython.viper
-def set_index(dest: ptr16, i: int, val: int):
+def set_index(dest: ptr16, i: int, val: uint):
dest[i] = val
-@micropython.viper
-def set_index(dest: ptr16, i: int, val: int):
- dest[i] = val
-
-
-b = bytearray(5000)
-for start, vals in TEST_DATA:
- for i, v in enumerate(vals):
- set_index(b, start + i, v)
- print(b[(start + i) * 2 : (start + i + 1) * 2])
-
-
-for i in range(len(b)):
- b[i] = 0
-
-
-for start, vals in TEST_DATA:
- for i, v in enumerate(vals):
- exec(SET_TEMPLATE.format(off=start + i, val=v + 0x0101))
+def get_index(src, i):
+ return src[i * SIZE] + (src[(i * SIZE) + 1] << 8)
+
+
+buffer = bytearray(((1 << max(BIT_THRESHOLDS) + 1) // 1024) * 1024)
+next = 1
+val = 0
+for bit in BIT_THRESHOLDS:
+ print("---", bit)
+ pre, idx, post = (
+ (((1 << bit) - (2 * SIZE)) // SIZE),
+ (((1 << bit) - (1 * SIZE)) // SIZE),
+ ((1 << bit) // SIZE),
+ )
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, pre, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, idx, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, post, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post)))
+ exec(SET_TEMPLATE.format(off=pre, val=val & MASK))
+ val = (val << 8) + next
+ next += 1
+ exec(SET_TEMPLATE.format(off=idx, val=val & MASK))
+ val = (val << 8) + next
+ next += 1
+ exec(SET_TEMPLATE.format(off=post, val=val & MASK))
diff --git a/tests/micropython/viper_ptr16_store_boundary.py.exp b/tests/micropython/viper_ptr16_store_boundary.py.exp
index b56fe6695f..1c084da2d9 100644
--- a/tests/micropython/viper_ptr16_store_boundary.py.exp
+++ b/tests/micropython/viper_ptr16_store_boundary.py.exp
@@ -1,18 +1,20 @@
-bytearray(b'AB')
-bytearray(b'CD')
-bytearray(b'EF')
-bytearray(b'GH')
-bytearray(b'IJ')
-bytearray(b'KL')
-bytearray(b'MN')
-bytearray(b'OP')
-bytearray(b'QR')
-bytearray(b'BC')
-bytearray(b'DE')
-bytearray(b'FG')
-bytearray(b'HI')
-bytearray(b'JK')
-bytearray(b'LM')
-bytearray(b'NO')
-bytearray(b'PQ')
-bytearray(b'RS')
+--- 5
+0x1 0x102 0x203
+0x304
+0x405
+0x506
+--- 8
+0x607 0x708 0x809
+0x90a
+0xa0b
+0xb0c
+--- 11
+0xc0d 0xd0e 0xe0f
+0xf10
+0x1011
+0x1112
+--- 12
+0x1213 0x1314 0x1415
+0x1516
+0x1617
+0x1718
diff --git a/tests/micropython/viper_ptr32_load_boundary.py b/tests/micropython/viper_ptr32_load_boundary.py
index 6954bd46b2..971d1113c4 100644
--- a/tests/micropython/viper_ptr32_load_boundary.py
+++ b/tests/micropython/viper_ptr32_load_boundary.py
@@ -2,24 +2,38 @@
GET_TEMPLATE = """
@micropython.viper
-def get{off}(src: ptr32) -> int:
- return src[{off}]
-print(b[{off} * 4:({off} + 1) * 4])
+def get{off}(src: ptr32) -> uint:
+ return uint(src[{off}])
+print(hex(get{off}(buffer)))
"""
+BIT_THRESHOLDS = (5, 8, 11, 12)
+SIZE = 4
+
+
@micropython.viper
def get_index(src: ptr32, i: int) -> int:
return src[i]
-b = bytearray(5000)
-b[24:43] = b"0123456789ABCDEFGHIJ"
-b[248:268] = b"KLMNOPQRSTUVWXYZabcd"
-b[4088:4108] = b"efghijklmnopqrstuvwx"
+def data(start, len):
+ output = bytearray(len)
+ for idx in range(len):
+ output[idx] = (start + idx) & 0xFF
+ return output
+
+
+buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024)
+val = 0
+for bit in BIT_THRESHOLDS:
+ print("---", bit)
+ pre, idx, post = (((1 << bit) - (2 * SIZE)), ((1 << bit) - (1 * SIZE)), (1 << bit))
+ buffer[pre:post] = data(val, 3 * SIZE)
+ val = val + (3 * SIZE)
-for pre, idx, post in (7, 8, 9), (63, 64, 65), (1023, 1024, 1025):
- print(get_index(b, pre), get_index(b, idx), get_index(b, post))
+ pre, idx, post = pre // SIZE, idx // SIZE, post // SIZE
+ print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post)))
exec(GET_TEMPLATE.format(off=pre))
exec(GET_TEMPLATE.format(off=idx))
exec(GET_TEMPLATE.format(off=post))
diff --git a/tests/micropython/viper_ptr32_load_boundary.py.exp b/tests/micropython/viper_ptr32_load_boundary.py.exp
index a58e703f91..1e22a8b361 100644
--- a/tests/micropython/viper_ptr32_load_boundary.py.exp
+++ b/tests/micropython/viper_ptr32_load_boundary.py.exp
@@ -1,12 +1,20 @@
-926299444 1111570744 1178944579
-bytearray(b'4567')
-bytearray(b'89AB')
-bytearray(b'CDEF')
-1381060687 1448432723 1515804759
-bytearray(b'OPQR')
-bytearray(b'STUV')
-bytearray(b'WXYZ')
-1818978921 1886350957 1953722993
-bytearray(b'ijkl')
-bytearray(b'mnop')
-bytearray(b'qrst')
+--- 5
+0x3020100 0x7060504 0xb0a0908
+0x3020100
+0x7060504
+0xb0a0908
+--- 8
+0xf0e0d0c 0x13121110 0x17161514
+0xf0e0d0c
+0x13121110
+0x17161514
+--- 11
+0x1b1a1918 0x1f1e1d1c 0x23222120
+0x1b1a1918
+0x1f1e1d1c
+0x23222120
+--- 12
+0x27262524 0x2b2a2928 0x2f2e2d2c
+0x27262524
+0x2b2a2928
+0x2f2e2d2c
diff --git a/tests/micropython/viper_ptr32_store_boundary.py b/tests/micropython/viper_ptr32_store_boundary.py
index 243ff5cd9c..5109abb9dc 100644
--- a/tests/micropython/viper_ptr32_store_boundary.py
+++ b/tests/micropython/viper_ptr32_store_boundary.py
@@ -1,35 +1,58 @@
# Test boundary conditions for various architectures
-TEST_DATA = (
- (3, (0x04030201, 0x08070605, 0x0C0B0A09)),
- (63, (0x100F0E0D, 0x14131211, 0x18171615)),
- (1023, (0x1C1B1A19, 0x201F1E1D, 0x24232221)),
-)
-
SET_TEMPLATE = """
@micropython.viper
def set{off}(dest: ptr32):
- dest[{off}] = {val} & 0x3FFFFFFF
-set{off}(b)
-print(b[{off} * 4:({off} + 1) * 4])
+ dest[{off}] = {val}
+set{off}(buffer)
+print(hex(get_index(buffer, {off})))
"""
+BIT_THRESHOLDS = (5, 8, 11, 12)
+SIZE = 4
+MASK = (1 << (8 * SIZE)) - 1
+
@micropython.viper
-def set_index(dest: ptr32, i: int, val: int):
+def set_index(dest: ptr32, i: int, val: uint):
dest[i] = val
-b = bytearray(5000)
-for start, vals in TEST_DATA:
- for i, v in enumerate(vals):
- set_index(b, start + i, v)
- print(b[(start + i) * 4 : (start + i + 1) * 4])
-
-for i in range(len(b)):
- b[i] = 0
-
-
-for start, vals in TEST_DATA:
- for i, v in enumerate(vals):
- exec(SET_TEMPLATE.format(off=start + i, val=v + 0x01010101))
+def get_index(src, i):
+ return (
+ src[i * SIZE]
+ + (src[(i * SIZE) + 1] << 8)
+ + (src[(i * SIZE) + 2] << 16)
+ + (src[(i * SIZE) + 3] << 24)
+ )
+
+
+buffer = bytearray(((1 << max(BIT_THRESHOLDS) + 1) // 1024) * 1024)
+next = 1
+val = 0
+for bit in BIT_THRESHOLDS:
+ print("---", bit)
+ pre, idx, post = (
+ (((1 << bit) - (2 * SIZE)) // SIZE),
+ (((1 << bit) - (1 * SIZE)) // SIZE),
+ ((1 << bit) // SIZE),
+ )
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, pre, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, idx, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, post, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post)))
+ exec(SET_TEMPLATE.format(off=pre, val=val & MASK))
+ val = (val << 8) + next
+ next += 1
+ exec(SET_TEMPLATE.format(off=idx, val=val & MASK))
+ val = (val << 8) + next
+ next += 1
+ exec(SET_TEMPLATE.format(off=post, val=val & MASK))
diff --git a/tests/micropython/viper_ptr32_store_boundary.py.exp b/tests/micropython/viper_ptr32_store_boundary.py.exp
index 89f09fbc7a..67b114d335 100644
--- a/tests/micropython/viper_ptr32_store_boundary.py.exp
+++ b/tests/micropython/viper_ptr32_store_boundary.py.exp
@@ -1,18 +1,20 @@
-bytearray(b'\x01\x02\x03\x04')
-bytearray(b'\x05\x06\x07\x08')
-bytearray(b'\t\n\x0b\x0c')
-bytearray(b'\r\x0e\x0f\x10')
-bytearray(b'\x11\x12\x13\x14')
-bytearray(b'\x15\x16\x17\x18')
-bytearray(b'\x19\x1a\x1b\x1c')
-bytearray(b'\x1d\x1e\x1f ')
-bytearray(b'!"#$')
-bytearray(b'\x02\x03\x04\x05')
-bytearray(b'\x06\x07\x08\t')
-bytearray(b'\n\x0b\x0c\r')
-bytearray(b'\x0e\x0f\x10\x11')
-bytearray(b'\x12\x13\x14\x15')
-bytearray(b'\x16\x17\x18\x19')
-bytearray(b'\x1a\x1b\x1c\x1d')
-bytearray(b'\x1e\x1f !')
-bytearray(b'"#$%')
+--- 5
+0x1 0x102 0x10203
+0x1020304
+0x2030405
+0x3040506
+--- 8
+0x4050607 0x5060708 0x6070809
+0x708090a
+0x8090a0b
+0x90a0b0c
+--- 11
+0xa0b0c0d 0xb0c0d0e 0xc0d0e0f
+0xd0e0f10
+0xe0f1011
+0xf101112
+--- 12
+0x10111213 0x11121314 0x12131415
+0x13141516
+0x14151617
+0x15161718
diff --git a/tests/micropython/viper_ptr8_load_boundary.py b/tests/micropython/viper_ptr8_load_boundary.py
index bcb17a1e1f..57e06da570 100644
--- a/tests/micropython/viper_ptr8_load_boundary.py
+++ b/tests/micropython/viper_ptr8_load_boundary.py
@@ -2,24 +2,37 @@
GET_TEMPLATE = """
@micropython.viper
-def get{off}(src: ptr8) -> int:
- return src[{off}]
-print(get{off}(b))
+def get{off}(src: ptr8) -> uint:
+ return uint(src[{off}])
+print(hex(get{off}(buffer)))
"""
+BIT_THRESHOLDS = (5, 8, 11, 12)
+SIZE = 1
+
+
@micropython.viper
def get_index(src: ptr8, i: int) -> int:
return src[i]
-b = bytearray(5000)
-b[30:32] = b"123"
-b[254:256] = b"456"
-b[4094:4096] = b"789"
+def data(start, len):
+ output = bytearray(len)
+ for idx in range(len):
+ output[idx] = (start + idx) & 0xFF
+ return output
+
+
+buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024)
+val = 0
+for bit in BIT_THRESHOLDS:
+ print("---", bit)
+ pre, idx, post = (((1 << bit) - (2 * SIZE)), ((1 << bit) - (1 * SIZE)), (1 << bit))
+ buffer[pre:post] = data(val, 3 * SIZE)
+ val = val + (3 * SIZE)
-for pre, idx, post in (30, 31, 32), (254, 255, 256), (4094, 4095, 4096):
- print(get_index(b, pre), get_index(b, idx), get_index(b, post))
+ print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post)))
exec(GET_TEMPLATE.format(off=pre))
exec(GET_TEMPLATE.format(off=idx))
exec(GET_TEMPLATE.format(off=post))
diff --git a/tests/micropython/viper_ptr8_load_boundary.py.exp b/tests/micropython/viper_ptr8_load_boundary.py.exp
index 7cbd1ac78c..a0e423686b 100644
--- a/tests/micropython/viper_ptr8_load_boundary.py.exp
+++ b/tests/micropython/viper_ptr8_load_boundary.py.exp
@@ -1,12 +1,20 @@
-49 50 51
-49
-50
-51
-52 53 54
-52
-53
-54
-55 56 57
-55
-56
-57
+--- 5
+0x0 0x1 0x2
+0x0
+0x1
+0x2
+--- 8
+0x3 0x4 0x5
+0x3
+0x4
+0x5
+--- 11
+0x6 0x7 0x8
+0x6
+0x7
+0x8
+--- 12
+0x9 0xa 0xb
+0x9
+0xa
+0xb
diff --git a/tests/micropython/viper_ptr8_store_boundary.py b/tests/micropython/viper_ptr8_store_boundary.py
index ad51268454..e1fe6dcae3 100644
--- a/tests/micropython/viper_ptr8_store_boundary.py
+++ b/tests/micropython/viper_ptr8_store_boundary.py
@@ -1,30 +1,49 @@
# Test boundary conditions for various architectures
-TEST_DATA = ((49, 30, 3), (52, 254, 3), (55, 4094, 3))
-
SET_TEMPLATE = """
@micropython.viper
def set{off}(dest: ptr8):
dest[{off}] = {val}
-set{off}(b)
-print(b[{off}])
+set{off}(buffer)
+print(hex(get_index(buffer, {off})))
"""
+BIT_THRESHOLDS = (5, 8, 11, 12)
+SIZE = 1
+MASK = (1 << (8 * SIZE)) - 1
+
@micropython.viper
-def set_index(dest: ptr8, i: int, val: int):
+def set_index(dest: ptr8, i: int, val: uint):
dest[i] = val
-b = bytearray(5000)
-for val, start, count in TEST_DATA:
- for i in range(count):
- set_index(b, start + i, val + i)
- print(b[start : start + count])
-
-for i in range(len(b)):
- b[i] = 0
-
-for val, start, count in TEST_DATA:
- for i in range(count):
- exec(SET_TEMPLATE.format(off=start + i, val=val + i + 16))
+def get_index(src: ptr8, i: int):
+ return src[i]
+
+
+buffer = bytearray(((1 << max(BIT_THRESHOLDS) + 1) // 1024) * 1024)
+next = 1
+val = 0
+for bit in BIT_THRESHOLDS:
+ print("---", bit)
+ pre, idx, post = (((1 << bit) - (2 * SIZE)), ((1 << bit) - (1 * SIZE)), (1 << bit))
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, pre, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, idx, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ set_index(buffer, post, val & MASK)
+ val = (val << 8) + next
+ next += 1
+ print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post)))
+ exec(SET_TEMPLATE.format(off=pre, val=val & MASK))
+ val = (val << 8) + next
+ next += 1
+ exec(SET_TEMPLATE.format(off=idx, val=val & MASK))
+ val = (val << 8) + next
+ next += 1
+ exec(SET_TEMPLATE.format(off=post, val=val & MASK))
diff --git a/tests/micropython/viper_ptr8_store_boundary.py.exp b/tests/micropython/viper_ptr8_store_boundary.py.exp
index a35cb3ac9e..6b0f7ce13e 100644
--- a/tests/micropython/viper_ptr8_store_boundary.py.exp
+++ b/tests/micropython/viper_ptr8_store_boundary.py.exp
@@ -1,12 +1,20 @@
-bytearray(b'123')
-bytearray(b'456')
-bytearray(b'789')
-65
-66
-67
-68
-69
-70
-71
-72
-73
+--- 5
+0x1 0x2 0x3
+0x4
+0x5
+0x6
+--- 8
+0x7 0x8 0x9
+0xa
+0xb
+0xc
+--- 11
+0xd 0xe 0xf
+0x10
+0x11
+0x12
+--- 12
+0x13 0x14 0x15
+0x16
+0x17
+0x18
diff --git a/tests/multi_net/tcp_accept_recv.py b/tests/multi_net/tcp_accept_recv.py
index dee14e3b97..4108a6f8a3 100644
--- a/tests/multi_net/tcp_accept_recv.py
+++ b/tests/multi_net/tcp_accept_recv.py
@@ -1,30 +1,73 @@
-# Test recv on socket that just accepted a connection
+# Test recv on listening socket after accept(), with various listen() arguments
import socket
PORT = 8000
+# Test cases for listen() function
+LISTEN_ARGS = [None, 0, 1, 2] # None means no argument
+
# Server
def instance0():
multitest.globals(IP=multitest.get_network_ip())
- s = socket.socket()
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1])
- s.listen(1)
multitest.next()
- s.accept()
- try:
- print("recv", s.recv(10)) # should raise Errno 107 ENOTCONN
- except OSError as er:
- print(er.errno in (107, 128))
- s.close()
+
+ test_num = 0
+ for blocking_mode in [True, False]:
+ for listen_arg in LISTEN_ARGS:
+ test_num += 1
+ s = socket.socket()
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1])
+
+ # Call listen with or without argument based on test case
+ if listen_arg is None:
+ print(f"Test case {test_num}/8: listen() blocking={blocking_mode}")
+ s.listen()
+ else:
+ print(f"Test case {test_num}/8: listen({listen_arg}) blocking={blocking_mode}")
+ s.listen(listen_arg)
+
+ # Signal client that server is ready
+ multitest.broadcast(f"server_ready_{test_num}")
+
+ # Wait for client connection
+ c, _ = s.accept()
+
+ # Set blocking mode after accept
+ s.setblocking(blocking_mode)
+
+ try:
+ print("recv", s.recv(10)) # should raise Errno 107 ENOTCONN
+ except OSError as er:
+ # Verify the error code is either 107 (ENOTCONN) or 128 (ENOTCONN on Windows)
+ print(er.errno in (107, 128))
+
+ # Cleanup
+ c.close()
+ s.close()
+
+ # Signal client we're done with this test case
+ multitest.broadcast(f"server_done_{test_num}")
# Client
def instance1():
multitest.next()
- s = socket.socket()
- s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
- s.send(b"GET / HTTP/1.0\r\n\r\n")
- s.close()
+
+ test_num = 0
+ for blocking_mode in [True, False]:
+ for _ in LISTEN_ARGS:
+ test_num += 1
+ # Wait for server to be ready
+ multitest.wait(f"server_ready_{test_num}")
+
+ # Connect to server
+ s = socket.socket()
+ s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
+ s.send(b"GET / HTTP/1.0\r\n\r\n")
+ s.close()
+
+ # Wait for server to finish this test case
+ multitest.wait(f"server_done_{test_num}")
diff --git a/tests/ports/rp2/rp2_machine_timer.py b/tests/ports/rp2/rp2_machine_timer.py
new file mode 100644
index 0000000000..ac4efcf7f3
--- /dev/null
+++ b/tests/ports/rp2/rp2_machine_timer.py
@@ -0,0 +1,20 @@
+from machine import Timer
+from time import sleep_ms
+
+# Test the rp2-specific adjustable tick_hz and hard/soft IRQ handlers
+# for both one-shot and periodic timers.
+
+modes = {Timer.ONE_SHOT: "one-shot", Timer.PERIODIC: "periodic"}
+kinds = {False: "soft", True: "hard"}
+
+for mode in modes:
+ for hard in kinds:
+ for period in 2, 4:
+ timer = Timer(
+ mode=mode,
+ period=period,
+ hard=hard,
+ callback=lambda t: print("callback", modes[mode], kinds[hard], period),
+ )
+ sleep_ms(9)
+ timer.deinit()
diff --git a/tests/ports/rp2/rp2_machine_timer.py.exp b/tests/ports/rp2/rp2_machine_timer.py.exp
new file mode 100644
index 0000000000..b3dd93dfab
--- /dev/null
+++ b/tests/ports/rp2/rp2_machine_timer.py.exp
@@ -0,0 +1,16 @@
+callback one-shot soft 2
+callback one-shot soft 4
+callback one-shot hard 2
+callback one-shot hard 4
+callback periodic soft 2
+callback periodic soft 2
+callback periodic soft 2
+callback periodic soft 2
+callback periodic soft 4
+callback periodic soft 4
+callback periodic hard 2
+callback periodic hard 2
+callback periodic hard 2
+callback periodic hard 2
+callback periodic hard 4
+callback periodic hard 4
diff --git a/tests/ports/unix/extra_coverage.py.exp b/tests/ports/unix/extra_coverage.py.exp
index 19b32f1c9d..ac64edde69 100644
--- a/tests/ports/unix/extra_coverage.py.exp
+++ b/tests/ports/unix/extra_coverage.py.exp
@@ -14,6 +14,7 @@ false true
80000000
abc
%
+.a .
# GC
0
0
@@ -50,16 +51,16 @@ RuntimeError:
ame__
port
-builtins micropython _asyncio _thread
-array binascii btree cexample
-cmath collections cppexample cryptolib
-deflate errno example_package
-ffi framebuf gc hashlib
-heapq io json machine
-marshal math os platform
-random re select socket
-struct sys termios time
-tls uctypes vfs websocket
+builtins micropython array binascii
+btree cexample cmath collections
+cppexample cryptolib deflate errno
+example_package ffi framebuf
+gc hashlib heapq io
+json machine marshal math
+os platform random re
+select socket struct sys
+termios time tls uctypes
+vfs websocket
me
micropython machine marshal math
@@ -89,6 +90,10 @@ data
12345
6
-1
+0
+1
+0
+0.000000
# runtime utils
TypeError: unsupported type for __abs__: 'str'
TypeError: unsupported types for __divmod__: 'str', 'str'
diff --git a/tests/run-multitests.py b/tests/run-multitests.py
index 387eec7018..92bd64193d 100755
--- a/tests/run-multitests.py
+++ b/tests/run-multitests.py
@@ -15,6 +15,8 @@ import itertools
import subprocess
import tempfile
+run_tests_module = __import__("run-tests")
+
test_dir = os.path.abspath(os.path.dirname(__file__))
if os.path.abspath(sys.path[0]) == test_dir:
@@ -488,9 +490,7 @@ def print_diff(a, b):
def run_tests(test_files, instances_truth, instances_test):
- skipped_tests = []
- passed_tests = []
- failed_tests = []
+ test_results = []
for test_file, num_instances in test_files:
instances_str = "|".join(str(instances_test[i]) for i in range(num_instances))
@@ -526,13 +526,13 @@ def run_tests(test_files, instances_truth, instances_test):
# Print result of test
if skip:
print("skip")
- skipped_tests.append(test_file)
+ test_results.append((test_file, "skip", ""))
elif output_test == output_truth:
print("pass")
- passed_tests.append(test_file)
+ test_results.append((test_file, "pass", ""))
else:
print("FAIL")
- failed_tests.append(test_file)
+ test_results.append((test_file, "fail", ""))
if not cmd_args.show_output:
print("### TEST ###")
print(output_test, end="")
@@ -549,15 +549,7 @@ def run_tests(test_files, instances_truth, instances_test):
if cmd_args.show_output:
print()
- print("{} tests performed".format(len(skipped_tests) + len(passed_tests) + len(failed_tests)))
- print("{} tests passed".format(len(passed_tests)))
-
- if skipped_tests:
- print("{} tests skipped: {}".format(len(skipped_tests), " ".join(skipped_tests)))
- if failed_tests:
- print("{} tests failed: {}".format(len(failed_tests), " ".join(failed_tests)))
-
- return not failed_tests
+ return test_results
def main():
@@ -583,6 +575,12 @@ def main():
default=1,
help="repeat the test with this many permutations of the instance order",
)
+ cmd_parser.add_argument(
+ "-r",
+ "--result-dir",
+ default=run_tests_module.base_path("results"),
+ help="directory for test results",
+ )
cmd_parser.epilog = (
"Supported instance types:\r\n"
" -i pyb:<port> physical device (eg. pyboard) on provided repl port.\n"
@@ -623,13 +621,15 @@ def main():
for _ in range(max_instances - len(instances_test)):
instances_test.append(PyInstanceSubProcess([MICROPYTHON]))
+ os.makedirs(cmd_args.result_dir, exist_ok=True)
all_pass = True
try:
for i, instances_test_permutation in enumerate(itertools.permutations(instances_test)):
if i >= cmd_args.permutations:
break
- all_pass &= run_tests(test_files, instances_truth, instances_test_permutation)
+ test_results = run_tests(test_files, instances_truth, instances_test_permutation)
+ all_pass &= run_tests_module.create_test_report(cmd_args, test_results)
finally:
for i in instances_truth:
diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py
index 073e0b053e..f9d2074f6f 100755
--- a/tests/run-natmodtests.py
+++ b/tests/run-natmodtests.py
@@ -9,6 +9,8 @@ import subprocess
import sys
import argparse
+run_tests_module = __import__("run-tests")
+
sys.path.append("../tools")
import pyboard
@@ -133,7 +135,7 @@ def detect_architecture(target):
return platform, arch, None
-def run_tests(target_truth, target, args, stats, resolved_arch):
+def run_tests(target_truth, target, args, resolved_arch):
global injected_import_hook_code
prelude = ""
@@ -141,6 +143,7 @@ def run_tests(target_truth, target, args, stats, resolved_arch):
prelude = args.begin.read()
injected_import_hook_code = injected_import_hook_code.replace("{import_prelude}", prelude)
+ test_results = []
for test_file in args.files:
# Find supported test
test_file_basename = os.path.basename(test_file)
@@ -163,7 +166,8 @@ def run_tests(target_truth, target, args, stats, resolved_arch):
with open(NATMOD_EXAMPLE_DIR + test_mpy, "rb") as f:
test_script += b"__buf=" + bytes(repr(f.read()), "ascii") + b"\n"
except OSError:
- print("---- {} - mpy file not compiled".format(test_file))
+ test_results.append((test_file, "skip", "mpy file not compiled"))
+ print("skip {} - mpy file not compiled".format(test_file))
continue
test_script += bytes(injected_import_hook_code.format(test_module), "ascii")
test_script += test_file_data
@@ -195,17 +199,18 @@ def run_tests(target_truth, target, args, stats, resolved_arch):
result = "pass"
# Accumulate statistics
- stats["total"] += 1
if result == "pass":
- stats["pass"] += 1
+ test_results.append((test_file, "pass", ""))
elif result == "SKIP":
- stats["skip"] += 1
+ test_results.append((test_file, "skip", ""))
else:
- stats["fail"] += 1
+ test_results.append((test_file, "fail", ""))
# Print result
print("{:4} {}{}".format(result, test_file, extra))
+ return test_results
+
def main():
cmd_parser = argparse.ArgumentParser(
@@ -227,6 +232,12 @@ def main():
default=None,
help="prologue python file to execute before module import",
)
+ cmd_parser.add_argument(
+ "-r",
+ "--result-dir",
+ default=run_tests_module.base_path("results"),
+ help="directory for test results",
+ )
cmd_parser.add_argument("files", nargs="*", help="input test files")
args = cmd_parser.parse_args()
@@ -251,20 +262,14 @@ def main():
print("platform={} ".format(target_platform), end="")
print("arch={}".format(target_arch))
- stats = {"total": 0, "pass": 0, "fail": 0, "skip": 0}
- run_tests(target_truth, target, args, stats, target_arch)
+ os.makedirs(args.result_dir, exist_ok=True)
+ test_results = run_tests(target_truth, target, args, target_arch)
+ res = run_tests_module.create_test_report(args, test_results)
target.close()
target_truth.close()
- print("{} tests performed".format(stats["total"]))
- print("{} tests passed".format(stats["pass"]))
- if stats["fail"]:
- print("{} tests failed".format(stats["fail"]))
- if stats["skip"]:
- print("{} tests skipped".format(stats["skip"]))
-
- if stats["fail"]:
+ if not res:
sys.exit(1)
diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py
index 81d873c459..cac2fee58f 100755
--- a/tests/run-perfbench.py
+++ b/tests/run-perfbench.py
@@ -10,10 +10,12 @@ import sys
import argparse
from glob import glob
+run_tests_module = __import__("run-tests")
+
sys.path.append("../tools")
import pyboard
-prepare_script_for_target = __import__("run-tests").prepare_script_for_target
+prepare_script_for_target = run_tests_module.prepare_script_for_target
# Paths for host executables
if os.name == "nt":
@@ -90,9 +92,9 @@ def run_benchmark_on_target(target, script):
def run_benchmarks(args, target, param_n, param_m, n_average, test_list):
+ test_results = []
skip_complex = run_feature_test(target, "complex") != "complex"
skip_native = run_feature_test(target, "native_check") != "native"
- target_had_error = False
for test_file in sorted(test_list):
print(test_file + ": ", end="")
@@ -105,6 +107,7 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list):
and test_file.find("viper_") != -1
)
if skip:
+ test_results.append((test_file, "skip", ""))
print("SKIP")
continue
@@ -125,6 +128,7 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list):
if isinstance(target, pyboard.Pyboard) or args.via_mpy:
crash, test_script_target = prepare_script_for_target(args, script_text=test_script)
if crash:
+ test_results.append((test_file, "fail", "preparation"))
print("CRASH:", test_script_target)
continue
else:
@@ -162,10 +166,13 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list):
error = "FAIL truth"
if error is not None:
- if not error.startswith("SKIP"):
- target_had_error = True
+ if error.startswith("SKIP"):
+ test_results.append((test_file, "skip", error))
+ else:
+ test_results.append((test_file, "fail", error))
print(error)
else:
+ test_results.append((test_file, "pass", ""))
t_avg, t_sd = compute_stats(times)
s_avg, s_sd = compute_stats(scores)
print(
@@ -179,7 +186,7 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list):
sys.stdout.flush()
- return target_had_error
+ return test_results
def parse_output(filename):
@@ -265,6 +272,12 @@ def main():
cmd_parser.add_argument("--via-mpy", action="store_true", help="compile code to .mpy first")
cmd_parser.add_argument("--mpy-cross-flags", default="", help="flags to pass to mpy-cross")
cmd_parser.add_argument(
+ "-r",
+ "--result-dir",
+ default=run_tests_module.base_path("results"),
+ help="directory for test results",
+ )
+ cmd_parser.add_argument(
"N", nargs=1, help="N parameter (approximate target CPU frequency in MHz)"
)
cmd_parser.add_argument("M", nargs=1, help="M parameter (approximate target heap in kbytes)")
@@ -307,13 +320,15 @@ def main():
print("N={} M={} n_average={}".format(N, M, n_average))
- target_had_error = run_benchmarks(args, target, N, M, n_average, tests)
+ os.makedirs(args.result_dir, exist_ok=True)
+ test_results = run_benchmarks(args, target, N, M, n_average, tests)
+ res = run_tests_module.create_test_report(args, test_results)
if isinstance(target, pyboard.Pyboard):
target.exit_raw_repl()
target.close()
- if target_had_error:
+ if not res:
sys.exit(1)
diff --git a/tests/run-tests.py b/tests/run-tests.py
index da05e18e4f..e45122b10e 100755
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -95,6 +95,7 @@ class __FS:
return __File()
vfs.mount(__FS(), '/__vfstest')
os.chdir('/__vfstest')
+{import_prologue}
__import__('__injected_test')
"""
@@ -405,6 +406,10 @@ def run_micropython(pyb, args, test_file, test_file_abspath, is_special=False):
return rv
def send_get(what):
+ # Detect {\x00} pattern and convert to ctrl-key codes.
+ ctrl_code = lambda m: bytes([int(m.group(1))])
+ what = re.sub(rb'{\\x(\d\d)}', ctrl_code, what)
+
os.write(master, what)
return get()
@@ -616,7 +621,6 @@ class PyboardNodeRunner:
def run_tests(pyb, tests, args, result_dir, num_threads=1):
- test_count = ThreadSafeCounter()
testcase_count = ThreadSafeCounter()
test_results = ThreadSafeCounter([])
@@ -903,7 +907,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
if skip_it:
print("skip ", test_file)
- test_results.append((test_name, test_file, "skip", ""))
+ test_results.append((test_file, "skip", ""))
return
# Run the test on the MicroPython target.
@@ -918,11 +922,11 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
# start-up code (eg boot.py) when preparing to run the next test.
pyb.read_until(1, b"raw REPL; CTRL-B to exit\r\n")
print("skip ", test_file)
- test_results.append((test_name, test_file, "skip", ""))
+ test_results.append((test_file, "skip", ""))
return
elif output_mupy == b"SKIP-TOO-LARGE\n":
print("lrge ", test_file)
- test_results.append((test_name, test_file, "skip", "too large"))
+ test_results.append((test_file, "skip", "too large"))
return
# Look at the output of the test to see if unittest was used.
@@ -1005,7 +1009,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
# Print test summary, update counters, and save .exp/.out files if needed.
if test_passed:
print("pass ", test_file, extra_info)
- test_results.append((test_name, test_file, "pass", ""))
+ test_results.append((test_file, "pass", ""))
rm_f(filename_expected)
rm_f(filename_mupy)
else:
@@ -1017,9 +1021,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
rm_f(filename_expected) # in case left over from previous failed run
with open(filename_mupy, "wb") as f:
f.write(output_mupy)
- test_results.append((test_name, test_file, "fail", ""))
-
- test_count.increment()
+ test_results.append((test_file, "fail", ""))
# Print a note if this looks like it might have been a misfired unittest
if not uses_unittest and not test_passed:
@@ -1046,19 +1048,27 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
print(line)
sys.exit(1)
- test_results = test_results.value
- passed_tests = list(r for r in test_results if r[2] == "pass")
- skipped_tests = list(r for r in test_results if r[2] == "skip" and r[3] != "too large")
+ # Return test results.
+ return test_results.value, testcase_count.value
+
+
+# Print a summary of the results and save them to a JSON file.
+# Returns True if everything succeeded, False otherwise.
+def create_test_report(args, test_results, testcase_count=None):
+ passed_tests = list(r for r in test_results if r[1] == "pass")
+ skipped_tests = list(r for r in test_results if r[1] == "skip" and r[2] != "too large")
skipped_tests_too_large = list(
- r for r in test_results if r[2] == "skip" and r[3] == "too large"
+ r for r in test_results if r[1] == "skip" and r[2] == "too large"
)
- failed_tests = list(r for r in test_results if r[2] == "fail")
+ failed_tests = list(r for r in test_results if r[1] == "fail")
+
+ num_tests_performed = len(passed_tests) + len(failed_tests)
+
+ testcase_count_info = ""
+ if testcase_count is not None:
+ testcase_count_info = " ({} individual testcases)".format(testcase_count)
+ print("{} tests performed{}".format(num_tests_performed, testcase_count_info))
- print(
- "{} tests performed ({} individual testcases)".format(
- test_count.value, testcase_count.value
- )
- )
print("{} tests passed".format(len(passed_tests)))
if len(skipped_tests) > 0:
@@ -1088,15 +1098,15 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
return obj.pattern
return obj
- with open(os.path.join(result_dir, RESULTS_FILE), "w") as f:
+ with open(os.path.join(args.result_dir, RESULTS_FILE), "w") as f:
json.dump(
{
# The arguments passed on the command-line.
"args": vars(args),
# A list of all results of the form [(test, result, reason), ...].
- "results": list(test[1:] for test in test_results),
+ "results": list(test for test in test_results),
# A list of failed tests. This is deprecated, use the "results" above instead.
- "failed_tests": [test[1] for test in failed_tests],
+ "failed_tests": [test[0] for test in failed_tests],
},
f,
default=to_json,
@@ -1121,6 +1131,8 @@ class append_filter(argparse.Action):
def main():
+ global injected_import_hook_code
+
cmd_parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""Run and manage tests for MicroPython.
@@ -1230,8 +1242,20 @@ the last matching regex is used:
action="store_true",
help="re-run only the failed tests",
)
+ cmd_parser.add_argument(
+ "--begin",
+ metavar="PROLOGUE",
+ default=None,
+ help="prologue python file to execute before module import",
+ )
args = cmd_parser.parse_args()
+ prologue = ""
+ if args.begin:
+ with open(args.begin, "rt") as source:
+ prologue = source.read()
+ injected_import_hook_code = injected_import_hook_code.replace("{import_prologue}", prologue)
+
if args.print_failures:
for out in glob(os.path.join(args.result_dir, "*.out")):
testbase = out[:-4]
@@ -1350,7 +1374,8 @@ the last matching regex is used:
try:
os.makedirs(args.result_dir, exist_ok=True)
- res = run_tests(pyb, tests, args, args.result_dir, args.jobs)
+ test_results, testcase_count = run_tests(pyb, tests, args, args.result_dir, args.jobs)
+ res = create_test_report(args, test_results, testcase_count)
finally:
if pyb:
pyb.close()