summaryrefslogtreecommitdiffstatshomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/basics/string_format.py10
-rw-r--r--tests/cpydiff/core_fstring_concat.py2
-rw-r--r--tests/cpydiff/core_fstring_parser.py2
-rw-r--r--tests/cpydiff/core_fstring_repr.py2
-rw-r--r--tests/cpydiff/syntax_arg_unpacking.py2
-rw-r--r--tests/cpydiff/syntax_literal_underscore.py19
-rw-r--r--tests/cpydiff/syntax_spaces.py19
-rw-r--r--tests/cpydiff/types_str_formatsep.py19
-rw-r--r--tests/extmod/framebuf_blit.py68
-rw-r--r--tests/extmod/framebuf_blit.py.exp45
-rw-r--r--tests/extmod/json_loads.py24
-rw-r--r--tests/extmod/vfs_lfs_error.py46
-rw-r--r--tests/extmod/vfs_lfs_error.py.exp44
-rw-r--r--tests/float/math_constants.py27
-rw-r--r--tests/inlineasm/xtensa/asmargs.py44
-rw-r--r--tests/inlineasm/xtensa/asmargs.py.exp5
-rw-r--r--tests/inlineasm/xtensa/asmarith.py119
-rw-r--r--tests/inlineasm/xtensa/asmarith.py.exp40
-rw-r--r--tests/inlineasm/xtensa/asmbranch.py299
-rw-r--r--tests/inlineasm/xtensa/asmbranch.py.exp66
-rw-r--r--tests/inlineasm/xtensa/asmjump.py26
-rw-r--r--tests/inlineasm/xtensa/asmjump.py.exp2
-rw-r--r--tests/inlineasm/xtensa/asmloadstore.py98
-rw-r--r--tests/inlineasm/xtensa/asmloadstore.py.exp9
-rw-r--r--tests/inlineasm/xtensa/asmmisc.py25
-rw-r--r--tests/inlineasm/xtensa/asmmisc.py.exp3
-rw-r--r--tests/inlineasm/xtensa/asmshift.py137
-rw-r--r--tests/inlineasm/xtensa/asmshift.py.exp17
-rw-r--r--tests/micropython/viper_ptr16_load_boundary.py25
-rw-r--r--tests/micropython/viper_ptr16_load_boundary.py.exp12
-rw-r--r--tests/micropython/viper_ptr16_store_boundary.py41
-rw-r--r--tests/micropython/viper_ptr16_store_boundary.py.exp18
-rw-r--r--tests/micropython/viper_ptr32_load_boundary.py25
-rw-r--r--tests/micropython/viper_ptr32_load_boundary.py.exp12
-rw-r--r--tests/micropython/viper_ptr32_store_boundary.py35
-rw-r--r--tests/micropython/viper_ptr32_store_boundary.py.exp18
-rw-r--r--tests/micropython/viper_ptr8_load_boundary.py25
-rw-r--r--tests/micropython/viper_ptr8_load_boundary.py.exp12
-rw-r--r--tests/micropython/viper_ptr8_store_boundary.py30
-rw-r--r--tests/micropython/viper_ptr8_store_boundary.py.exp12
-rw-r--r--tests/misc/print_exception.py2
-rw-r--r--tests/multi_net/tcp_recv_peek.py46
-rw-r--r--tests/multi_net/udp_recv_dontwait.py59
-rw-r--r--tests/multi_net/udp_recv_dontwait.py.exp7
-rw-r--r--tests/multi_net/udp_recv_peek.py36
-rw-r--r--tests/ports/rp2/rp2_lightsleep_thread.py23
-rw-r--r--tests/ports/unix/extra_coverage.py.exp7
-rwxr-xr-xtests/run-natmodtests.py15
-rwxr-xr-xtests/run-tests.py128
49 files changed, 1700 insertions, 107 deletions
diff --git a/tests/basics/string_format.py b/tests/basics/string_format.py
index e8600f5836..11e7836a73 100644
--- a/tests/basics/string_format.py
+++ b/tests/basics/string_format.py
@@ -22,7 +22,17 @@ test("{:4o}", 123)
test("{:4x}", 123)
test("{:4X}", 123)
+test("{:4,d}", 1)
+test("{:4_d}", 1)
+test("{:4_o}", 1)
+test("{:4_b}", 1)
+test("{:4_x}", 1)
+
test("{:4,d}", 12345678)
+test("{:4_d}", 12345678)
+test("{:4_o}", 12345678)
+test("{:4_b}", 12345678)
+test("{:4_x}", 12345678)
test("{:#4b}", 10)
test("{:#4o}", 123)
diff --git a/tests/cpydiff/core_fstring_concat.py b/tests/cpydiff/core_fstring_concat.py
index 3daa13d753..2fbe1b961a 100644
--- a/tests/cpydiff/core_fstring_concat.py
+++ b/tests/cpydiff/core_fstring_concat.py
@@ -1,5 +1,5 @@
"""
-categories: Core
+categories: Core,f-strings
description: f-strings don't support concatenation with adjacent literals if the adjacent literals contain braces
cause: MicroPython is optimised for code space.
workaround: Use the + operator between literal strings when they are not both f-strings
diff --git a/tests/cpydiff/core_fstring_parser.py b/tests/cpydiff/core_fstring_parser.py
index 22bbc5866e..570b92434a 100644
--- a/tests/cpydiff/core_fstring_parser.py
+++ b/tests/cpydiff/core_fstring_parser.py
@@ -1,5 +1,5 @@
"""
-categories: Core
+categories: Core,f-strings
description: f-strings cannot support expressions that require parsing to resolve unbalanced nested braces and brackets
cause: MicroPython is optimised for code space.
workaround: Always use balanced braces and brackets in expressions inside f-strings
diff --git a/tests/cpydiff/core_fstring_repr.py b/tests/cpydiff/core_fstring_repr.py
index d37fb48db7..2589a34b7e 100644
--- a/tests/cpydiff/core_fstring_repr.py
+++ b/tests/cpydiff/core_fstring_repr.py
@@ -1,5 +1,5 @@
"""
-categories: Core
+categories: Core,f-strings
description: f-strings don't support !a conversions
cause: MicropPython does not implement ascii()
workaround: None
diff --git a/tests/cpydiff/syntax_arg_unpacking.py b/tests/cpydiff/syntax_arg_unpacking.py
index e54832ddb9..7133a8a282 100644
--- a/tests/cpydiff/syntax_arg_unpacking.py
+++ b/tests/cpydiff/syntax_arg_unpacking.py
@@ -1,5 +1,5 @@
"""
-categories: Syntax
+categories: Syntax,Unpacking
description: Argument unpacking does not work if the argument being unpacked is the nth or greater argument where n is the number of bits in an MP_SMALL_INT.
cause: The implementation uses an MP_SMALL_INT to flag args that need to be unpacked.
workaround: Use fewer arguments.
diff --git a/tests/cpydiff/syntax_literal_underscore.py b/tests/cpydiff/syntax_literal_underscore.py
new file mode 100644
index 0000000000..4b1406e9f3
--- /dev/null
+++ b/tests/cpydiff/syntax_literal_underscore.py
@@ -0,0 +1,19 @@
+"""
+categories: Syntax,Literals
+description: MicroPython accepts underscores in numeric literals where CPython doesn't
+cause: Different parser implementation
+
+MicroPython's tokenizer ignores underscores in numeric literals, while CPython
+rejects multiple consecutive underscores and underscores after the last digit.
+
+workaround: Remove the underscores not accepted by CPython.
+"""
+
+try:
+ print(eval("1__1"))
+except SyntaxError:
+ print("Should not work")
+try:
+ print(eval("1_"))
+except SyntaxError:
+ print("Should not work")
diff --git a/tests/cpydiff/syntax_spaces.py b/tests/cpydiff/syntax_spaces.py
index 03d25d5619..670cefdeac 100644
--- a/tests/cpydiff/syntax_spaces.py
+++ b/tests/cpydiff/syntax_spaces.py
@@ -1,8 +1,15 @@
"""
-categories: Syntax,Spaces
-description: uPy requires spaces between literal numbers and keywords, CPy doesn't
-cause: Unknown
-workaround: Unknown
+categories: Syntax,Literals
+description: MicroPython requires spaces between literal numbers and keywords or ".", CPython doesn't
+cause: Different parser implementation
+
+MicroPython's tokenizer treats a sequence like ``1and`` as a single token, while CPython treats it as two tokens.
+
+Since CPython 3.11, when the literal number is followed by a token, this syntax causes a ``SyntaxWarning`` for an "invalid literal". When a literal number is followed by a "." denoting attribute access, CPython does not warn.
+
+workaround: Add a space between the integer literal and the intended next token.
+
+This also fixes the ``SyntaxWarning`` in CPython.
"""
try:
@@ -17,3 +24,7 @@ try:
print(eval("1if 1else 0"))
except SyntaxError:
print("Should have worked")
+try:
+ print(eval("0x1.to_bytes(1)"))
+except SyntaxError:
+ print("Should have worked")
diff --git a/tests/cpydiff/types_str_formatsep.py b/tests/cpydiff/types_str_formatsep.py
new file mode 100644
index 0000000000..05d0b8d3d2
--- /dev/null
+++ b/tests/cpydiff/types_str_formatsep.py
@@ -0,0 +1,19 @@
+"""
+categories: Types,str
+description: MicroPython accepts the "," grouping option with any radix, unlike CPython
+cause: To reduce code size, MicroPython does not issue an error for this combination
+workaround: Do not use a format string like ``{:,b}`` if CPython compatibility is required.
+"""
+
+try:
+ print("{:,b}".format(99))
+except ValueError:
+ print("ValueError")
+try:
+ print("{:,x}".format(99))
+except ValueError:
+ print("ValueError")
+try:
+ print("{:,o}".format(99))
+except ValueError:
+ print("ValueError")
diff --git a/tests/extmod/framebuf_blit.py b/tests/extmod/framebuf_blit.py
new file mode 100644
index 0000000000..b1d98b330a
--- /dev/null
+++ b/tests/extmod/framebuf_blit.py
@@ -0,0 +1,68 @@
+# Test FrameBuffer.blit method.
+
+try:
+ import framebuf
+except ImportError:
+ print("SKIP")
+ raise SystemExit
+
+
+def printbuf():
+ print("--8<--")
+ for y in range(h):
+ for x in range(w):
+ print("%02x" % buf[(x + y * w)], end="")
+ print()
+ print("-->8--")
+
+
+w = 5
+h = 4
+buf = bytearray(w * h)
+fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8)
+
+fbuf2 = framebuf.FrameBuffer(bytearray(4), 2, 2, framebuf.GS8)
+fbuf2.fill(0xFF)
+
+# Blit another FrameBuffer, at various locations.
+for x, y in ((-1, -1), (0, 0), (1, 1), (4, 3)):
+ fbuf.fill(0)
+ fbuf.blit(fbuf2, x, y)
+ printbuf()
+
+# Blit a bytes object.
+fbuf.fill(0)
+image = (b"\x10\x11\x12\x13", 2, 2, framebuf.GS8)
+fbuf.blit(image, 1, 1)
+printbuf()
+
+# Blit a bytes object that has a stride.
+fbuf.fill(0)
+image = (b"\x20\x21\xff\x22\x23\xff", 2, 2, framebuf.GS8, 3)
+fbuf.blit(image, 1, 1)
+printbuf()
+
+# Blit a bytes object with a bytes palette.
+fbuf.fill(0)
+image = (b"\x00\x01\x01\x00", 2, 2, framebuf.GS8)
+palette = (b"\xa1\xa2", 2, 1, framebuf.GS8)
+fbuf.blit(image, 1, 1, -1, palette)
+printbuf()
+
+# Not enough elements in the tuple.
+try:
+ fbuf.blit((0, 0, 0), 0, 0)
+except ValueError:
+ print("ValueError")
+
+# Too many elements in the tuple.
+try:
+ fbuf.blit((0, 0, 0, 0, 0, 0), 0, 0)
+except ValueError:
+ print("ValueError")
+
+# Bytes too small.
+try:
+ fbuf.blit((b"", 1, 1, framebuf.GS8), 0, 0)
+except ValueError:
+ print("ValueError")
diff --git a/tests/extmod/framebuf_blit.py.exp b/tests/extmod/framebuf_blit.py.exp
new file mode 100644
index 0000000000..e340f1990c
--- /dev/null
+++ b/tests/extmod/framebuf_blit.py.exp
@@ -0,0 +1,45 @@
+--8<--
+ff00000000
+0000000000
+0000000000
+0000000000
+-->8--
+--8<--
+ffff000000
+ffff000000
+0000000000
+0000000000
+-->8--
+--8<--
+0000000000
+00ffff0000
+00ffff0000
+0000000000
+-->8--
+--8<--
+0000000000
+0000000000
+0000000000
+00000000ff
+-->8--
+--8<--
+0000000000
+0010110000
+0012130000
+0000000000
+-->8--
+--8<--
+0000000000
+0020210000
+0022230000
+0000000000
+-->8--
+--8<--
+0000000000
+00a1a20000
+00a2a10000
+0000000000
+-->8--
+ValueError
+ValueError
+ValueError
diff --git a/tests/extmod/json_loads.py b/tests/extmod/json_loads.py
index f9073c121e..095e67d740 100644
--- a/tests/extmod/json_loads.py
+++ b/tests/extmod/json_loads.py
@@ -71,3 +71,27 @@ try:
my_print(json.loads("[null] a"))
except ValueError:
print("ValueError")
+
+# incomplete object declaration
+try:
+ my_print(json.loads('{"a":0,'))
+except ValueError:
+ print("ValueError")
+
+# incomplete nested array declaration
+try:
+ my_print(json.loads('{"a":0, ['))
+except ValueError:
+ print("ValueError")
+
+# incomplete array declaration
+try:
+ my_print(json.loads('[0,'))
+except ValueError:
+ print("ValueError")
+
+# incomplete nested object declaration
+try:
+ my_print(json.loads('[0, {"a":0, '))
+except ValueError:
+ print("ValueError")
diff --git a/tests/extmod/vfs_lfs_error.py b/tests/extmod/vfs_lfs_error.py
index 2ac7629bfa..73cdf34373 100644
--- a/tests/extmod/vfs_lfs_error.py
+++ b/tests/extmod/vfs_lfs_error.py
@@ -1,7 +1,7 @@
# Test for VfsLittle using a RAM device, testing error handling
try:
- import vfs
+ import errno, vfs
vfs.VfsLfs1
vfs.VfsLfs2
@@ -41,14 +41,14 @@ def test(bdev, vfs_class):
# mkfs with too-small block device
try:
vfs_class.mkfs(RAMBlockDevice(1))
- except OSError:
- print("mkfs OSError")
+ except OSError as er:
+ print("mkfs OSError", er.errno > 0)
# mount with invalid filesystem
try:
vfs_class(bdev)
- except OSError:
- print("mount OSError")
+ except OSError as er:
+ print("mount OSError", er.errno > 0)
# set up for following tests
vfs_class.mkfs(bdev)
@@ -60,60 +60,60 @@ def test(bdev, vfs_class):
# ilistdir
try:
fs.ilistdir("noexist")
- except OSError:
- print("ilistdir OSError")
+ except OSError as er:
+ print("ilistdir OSError", er)
# remove
try:
fs.remove("noexist")
- except OSError:
- print("remove OSError")
+ except OSError as er:
+ print("remove OSError", er)
# rmdir
try:
fs.rmdir("noexist")
- except OSError:
- print("rmdir OSError")
+ except OSError as er:
+ print("rmdir OSError", er)
# rename
try:
fs.rename("noexist", "somethingelse")
- except OSError:
- print("rename OSError")
+ except OSError as er:
+ print("rename OSError", er)
# mkdir
try:
fs.mkdir("testdir")
- except OSError:
- print("mkdir OSError")
+ except OSError as er:
+ print("mkdir OSError", er)
# chdir to nonexistent
try:
fs.chdir("noexist")
- except OSError:
- print("chdir OSError")
+ except OSError as er:
+ print("chdir OSError", er)
print(fs.getcwd()) # check still at root
# chdir to file
try:
fs.chdir("testfile")
- except OSError:
- print("chdir OSError")
+ except OSError as er:
+ print("chdir OSError", er)
print(fs.getcwd()) # check still at root
# stat
try:
fs.stat("noexist")
- except OSError:
- print("stat OSError")
+ except OSError as er:
+ print("stat OSError", er)
# error during seek
with fs.open("testfile", "r") as f:
f.seek(1 << 30) # SEEK_SET
try:
f.seek(1 << 30, 1) # SEEK_CUR
- except OSError:
- print("seek OSError")
+ except OSError as er:
+ print("seek OSError", er)
bdev = RAMBlockDevice(30)
diff --git a/tests/extmod/vfs_lfs_error.py.exp b/tests/extmod/vfs_lfs_error.py.exp
index f4327f6962..440607ed84 100644
--- a/tests/extmod/vfs_lfs_error.py.exp
+++ b/tests/extmod/vfs_lfs_error.py.exp
@@ -1,28 +1,28 @@
test <class 'VfsLfs1'>
-mkfs OSError
-mount OSError
-ilistdir OSError
-remove OSError
-rmdir OSError
-rename OSError
-mkdir OSError
-chdir OSError
+mkfs OSError True
+mount OSError True
+ilistdir OSError [Errno 2] ENOENT
+remove OSError [Errno 2] ENOENT
+rmdir OSError [Errno 2] ENOENT
+rename OSError [Errno 2] ENOENT
+mkdir OSError [Errno 17] EEXIST
+chdir OSError [Errno 2] ENOENT
/
-chdir OSError
+chdir OSError [Errno 2] ENOENT
/
-stat OSError
-seek OSError
+stat OSError [Errno 2] ENOENT
+seek OSError [Errno 22] EINVAL
test <class 'VfsLfs2'>
-mkfs OSError
-mount OSError
-ilistdir OSError
-remove OSError
-rmdir OSError
-rename OSError
-mkdir OSError
-chdir OSError
+mkfs OSError True
+mount OSError True
+ilistdir OSError [Errno 2] ENOENT
+remove OSError [Errno 2] ENOENT
+rmdir OSError [Errno 2] ENOENT
+rename OSError [Errno 2] ENOENT
+mkdir OSError [Errno 17] EEXIST
+chdir OSError [Errno 2] ENOENT
/
-chdir OSError
+chdir OSError [Errno 2] ENOENT
/
-stat OSError
-seek OSError
+stat OSError [Errno 2] ENOENT
+seek OSError [Errno 22] EINVAL
diff --git a/tests/float/math_constants.py b/tests/float/math_constants.py
index 2e4c321052..21d822a01e 100644
--- a/tests/float/math_constants.py
+++ b/tests/float/math_constants.py
@@ -1,11 +1,30 @@
# Tests various constants of the math module.
+
+import sys
+
try:
- import math
- from math import exp, cos
+ from array import array
+ from math import e, pi
except ImportError:
print("SKIP")
raise SystemExit
-print(math.e == exp(1.0))
+# Hexadecimal representations of e and pi constants.
+e_truth_single = 0x402DF854
+pi_truth_single = 0x40490FDB
+e_truth_double = 0x4005BF0A8B145769
+pi_truth_double = 0x400921FB54442D18
+
+# Detect the floating-point precision of the system, to determine the exact values of
+# the constants (parsing the float from a decimal string can lead to inaccuracies).
+if float("1e300") == float("inf"):
+ # Single precision floats.
+ e_truth = array("f", e_truth_single.to_bytes(4, sys.byteorder))[0]
+ pi_truth = array("f", pi_truth_single.to_bytes(4, sys.byteorder))[0]
+else:
+ # Double precision floats.
+ e_truth = array("d", e_truth_double.to_bytes(8, sys.byteorder))[0]
+ pi_truth = array("d", pi_truth_double.to_bytes(8, sys.byteorder))[0]
-print(cos(math.pi))
+print("e:", e == e_truth or (e, e_truth, e - e_truth))
+print("pi:", pi == pi_truth or (pi, pi_truth, pi - pi_truth))
diff --git a/tests/inlineasm/xtensa/asmargs.py b/tests/inlineasm/xtensa/asmargs.py
new file mode 100644
index 0000000000..2bfccfcc69
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmargs.py
@@ -0,0 +1,44 @@
+# test passing arguments
+
+
+@micropython.asm_xtensa
+def arg0():
+ movi(a2, 1)
+
+
+print(arg0())
+
+
+@micropython.asm_xtensa
+def arg1(a2):
+ addi(a2, a2, 1)
+
+
+print(arg1(1))
+
+
+@micropython.asm_xtensa
+def arg2(a2, a3):
+ add(a2, a2, a3)
+
+
+print(arg2(1, 2))
+
+
+@micropython.asm_xtensa
+def arg3(a2, a3, a4):
+ add(a2, a2, a3)
+ add(a2, a2, a4)
+
+
+print(arg3(1, 2, 3))
+
+
+@micropython.asm_xtensa
+def arg4(a2, a3, a4, a5):
+ add(a2, a2, a3)
+ add(a2, a2, a4)
+ add(a2, a2, a5)
+
+
+print(arg4(1, 2, 3, 4))
diff --git a/tests/inlineasm/xtensa/asmargs.py.exp b/tests/inlineasm/xtensa/asmargs.py.exp
new file mode 100644
index 0000000000..e33a6964f4
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmargs.py.exp
@@ -0,0 +1,5 @@
+1
+2
+3
+6
+10
diff --git a/tests/inlineasm/xtensa/asmarith.py b/tests/inlineasm/xtensa/asmarith.py
new file mode 100644
index 0000000000..1c0934eb7a
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmarith.py
@@ -0,0 +1,119 @@
+@micropython.asm_xtensa
+def f1(a2):
+ abs_(a2, a2)
+
+
+for value in (10, -10, 0):
+ print(f1(value))
+
+
+ADDMI_TEMPLATE = """
+@micropython.asm_xtensa
+def f1(a2) -> int:
+ addmi(a2, a2, {})
+print(f1(0))
+"""
+
+for value in (-32768, -32767, 32512, 32513, 0):
+ try:
+ exec(ADDMI_TEMPLATE.format(value))
+ except SyntaxError as error:
+ print(error)
+
+
+@micropython.asm_xtensa
+def a2(a2, a3) -> int:
+ addx2(a2, a2, a3)
+
+
+@micropython.asm_xtensa
+def a4(a2, a3) -> int:
+ addx4(a2, a2, a3)
+
+
+@micropython.asm_xtensa
+def a8(a2, a3) -> int:
+ addx8(a2, a2, a3)
+
+
+@micropython.asm_xtensa
+def s2(a2, a3) -> int:
+ subx2(a2, a2, a3)
+
+
+@micropython.asm_xtensa
+def s4(a2, a3) -> int:
+ subx4(a2, a2, a3)
+
+
+@micropython.asm_xtensa
+def s8(a2, a3) -> int:
+ subx8(a2, a2, a3)
+
+
+for first, second in ((100, 100), (-100, 100), (-100, -100), (100, -100)):
+ print("a2", a2(first, second))
+ print("a4", a4(first, second))
+ print("a8", a8(first, second))
+ print("s2", s2(first, second))
+ print("s4", s4(first, second))
+ print("s8", s8(first, second))
+
+
+@micropython.asm_xtensa
+def f5(a2) -> int:
+ neg(a2, a2)
+
+
+for value in (0, -100, 100):
+ print(f5(value))
+
+
+@micropython.asm_xtensa
+def f6():
+ movi(a2, 0x100)
+ movi(a3, 1)
+ add(a2, a2, a3)
+ addi(a2, a2, 1)
+ addi(a2, a2, -2)
+ sub(a2, a2, a3)
+
+
+print(hex(f6()))
+
+
+@micropython.asm_xtensa
+def f7():
+ movi(a2, 0x10FF)
+ movi(a3, 1)
+ and_(a4, a2, a3)
+ or_(a4, a4, a3)
+ movi(a3, 0x200)
+ xor(a2, a4, a3)
+
+
+print(hex(f7()))
+
+
+@micropython.asm_xtensa
+def f8(a2, a3):
+ add_n(a2, a2, a3)
+
+
+print(f8(100, 200))
+
+
+@micropython.asm_xtensa
+def f9(a2):
+ addi_n(a2, a2, 1)
+
+
+print(f9(100))
+
+
+@micropython.asm_xtensa
+def f10(a2, a3) -> uint:
+ mull(a2, a2, a3)
+
+
+print(hex(f10(0xC0000000, 2)))
diff --git a/tests/inlineasm/xtensa/asmarith.py.exp b/tests/inlineasm/xtensa/asmarith.py.exp
new file mode 100644
index 0000000000..7aba46a27d
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmarith.py.exp
@@ -0,0 +1,40 @@
+10
+10
+0
+-32768
+-32767 is not a multiple of 256
+32512
+'addmi' integer 32513 isn't within range -32768..32512
+0
+a2 300
+a4 500
+a8 900
+s2 100
+s4 300
+s8 700
+a2 -100
+a4 -300
+a8 -700
+s2 -300
+s4 -500
+s8 -900
+a2 -300
+a4 -500
+a8 -900
+s2 -100
+s4 -300
+s8 -700
+a2 100
+a4 300
+a8 700
+s2 300
+s4 500
+s8 900
+0
+100
+-100
+0xff
+0x201
+300
+101
+0x80000000
diff --git a/tests/inlineasm/xtensa/asmbranch.py b/tests/inlineasm/xtensa/asmbranch.py
new file mode 100644
index 0000000000..22bcd5a7c7
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmbranch.py
@@ -0,0 +1,299 @@
+# test branch instructions
+
+
+@micropython.asm_xtensa
+def tball(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ ball(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tball(0xFFFFFFFF, 0xFFFFFFFF))
+print(tball(0xFFFEFFFF, 0xFFFFFFFF))
+print(tball(0x00000000, 0xFFFFFFFF))
+print(tball(0xFFFFFFFF, 0x01010101))
+
+
+@micropython.asm_xtensa
+def tbany(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bany(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbany(0xFFFFFFFF, 0xFFFFFFFF))
+print(tbany(0xFFFEFFFF, 0xFFFFFFFF))
+print(tbany(0x00000000, 0xFFFFFFFF))
+print(tbany(0xFFFFFFFF, 0x01010101))
+
+
+@micropython.asm_xtensa
+def tbbc(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bbc(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbbc(0xFFFFFFFF, 4))
+print(tbbc(0xFFFEFFFF, 16))
+print(tbbc(0x00000000, 1))
+
+
+BBCI_TEMPLATE = """
+@micropython.asm_xtensa
+def tbbci(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ bbci(a3, {}, end)
+ movi(a2, -1)
+ label(end)
+
+print(tbbci({}))
+"""
+
+
+for value, bit in ((0xFFFFFFFF, 4), (0xFFFEFFFF, 16), (0x00000000, 1)):
+ try:
+ exec(BBCI_TEMPLATE.format(bit, value))
+ except SyntaxError as error:
+ print(error)
+
+
+@micropython.asm_xtensa
+def tbbs(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bbs(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbbs(0x00000000, 4))
+print(tbbs(0x00010000, 16))
+print(tbbs(0xFFFFFFFF, 1))
+
+
+BBSI_TEMPLATE = """
+@micropython.asm_xtensa
+def tbbsi(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ bbsi(a3, {}, end)
+ movi(a2, -1)
+ label(end)
+
+print(tbbsi({}))
+"""
+
+
+for value, bit in ((0x00000000, 4), (0x00010000, 16), (0xFFFFFFFF, 1)):
+ try:
+ exec(BBSI_TEMPLATE.format(bit, value))
+ except SyntaxError as error:
+ print(error)
+
+
+@micropython.asm_xtensa
+def tbeq(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ beq(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbeq(0x00000000, 0x00000000))
+print(tbeq(0x00010000, 0x00000000))
+print(tbeq(0xFFFFFFFF, 0xFFFFFFFF))
+
+
+@micropython.asm_xtensa
+def tbeqz(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ beqz(a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbeqz(0))
+print(tbeqz(0x12345678))
+print(tbeqz(-1))
+
+
+@micropython.asm_xtensa
+def tbge(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bge(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbge(0x00000000, 0x00000000))
+print(tbge(0x00010000, 0x00000000))
+print(tbge(0xF0000000, 0xFFFFFFFF))
+
+
+@micropython.asm_xtensa
+def tbgeu(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bgeu(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbgeu(0x00000000, 0x00000000))
+print(tbgeu(0x00010000, 0x00000000))
+print(tbgeu(0xF0000000, 0xFFFFFFFF))
+print(tbgeu(0xFFFFFFFF, 0xF0000000))
+
+
+@micropython.asm_xtensa
+def tbgez(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ bgez(a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbgez(0))
+print(tbgez(0x12345678))
+print(tbgez(-1))
+
+
+@micropython.asm_xtensa
+def tblt(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ blt(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tblt(0x00000000, 0x00000000))
+print(tblt(0x00010000, 0x00000000))
+print(tblt(0xF0000000, 0xFFFFFFFF))
+
+
+@micropython.asm_xtensa
+def tbltu(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bltu(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbltu(0x00000000, 0x00000000))
+print(tbltu(0x00010000, 0x00000000))
+print(tbltu(0xF0000000, 0xFFFFFFFF))
+print(tbltu(0xFFFFFFFF, 0xF0000000))
+
+
+@micropython.asm_xtensa
+def tbltz(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ bltz(a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbltz(0))
+print(tbltz(0x12345678))
+print(tbltz(-1))
+
+
+@micropython.asm_xtensa
+def tbnall(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bnall(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbnall(0xFFFFFFFF, 0xFFFFFFFF))
+print(tbnall(0xFFFEFFFF, 0xFFFFFFFF))
+print(tbnall(0x00000000, 0xFFFFFFFF))
+print(tbnall(0xFFFFFFFF, 0x01010101))
+
+
+@micropython.asm_xtensa
+def tbne(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bne(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbne(0x00000000, 0x00000000))
+print(tbne(0x00010000, 0x00000000))
+print(tbne(0xFFFFFFFF, 0xFFFFFFFF))
+
+
+@micropython.asm_xtensa
+def tbnez(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ bnez(a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbnez(0))
+print(tbnez(0x12345678))
+print(tbnez(-1))
+
+
+@micropython.asm_xtensa
+def tbnone(a2, a3) -> int:
+ mov(a4, a2)
+ movi(a2, 0)
+ bnone(a4, a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbnone(0xFFFFFFFF, 0xFFFFFFFF))
+print(tbnone(0xFFFEFFFF, 0xFFFFFFFF))
+print(tbnone(0x00000000, 0xFFFFFFFF))
+print(tbnone(0x10101010, 0x01010101))
+
+
+@micropython.asm_xtensa
+def tbeqz_n(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ beqz_n(a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbeqz_n(0))
+print(tbeqz_n(0x12345678))
+print(tbeqz_n(-1))
+
+
+@micropython.asm_xtensa
+def tbnez_n(a2) -> int:
+ mov(a3, a2)
+ movi(a2, 0)
+ bnez(a3, end)
+ movi(a2, -1)
+ label(end)
+
+
+print(tbnez_n(0))
+print(tbnez_n(0x12345678))
+print(tbnez_n(-1))
diff --git a/tests/inlineasm/xtensa/asmbranch.py.exp b/tests/inlineasm/xtensa/asmbranch.py.exp
new file mode 100644
index 0000000000..319a4b435e
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmbranch.py.exp
@@ -0,0 +1,66 @@
+0
+-1
+-1
+0
+0
+0
+-1
+0
+-1
+0
+0
+-1
+0
+0
+-1
+0
+0
+-1
+0
+0
+0
+-1
+0
+0
+-1
+-1
+0
+0
+-1
+0
+0
+-1
+0
+0
+0
+-1
+-1
+-1
+0
+-1
+-1
+0
+-1
+-1
+-1
+0
+-1
+0
+0
+-1
+-1
+0
+-1
+-1
+0
+0
+-1
+-1
+0
+0
+0
+-1
+-1
+-1
+0
+0
diff --git a/tests/inlineasm/xtensa/asmjump.py b/tests/inlineasm/xtensa/asmjump.py
new file mode 100644
index 0000000000..f41c948231
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmjump.py
@@ -0,0 +1,26 @@
+@micropython.asm_xtensa
+def jump() -> int:
+ movi(a2, 0)
+ j(NEXT)
+ addi(a2, a2, 1)
+ j(DONE)
+ label(NEXT)
+ addi(a2, a2, 2)
+ label(DONE)
+
+
+print(jump())
+
+
+@micropython.asm_xtensa
+def jumpx() -> int:
+ call0(ENTRY)
+ label(ENTRY)
+ movi(a2, 0)
+ addi(a3, a0, 12)
+ jx(a3)
+ movi(a2, 1)
+ movi(a2, 2)
+
+
+print(jumpx())
diff --git a/tests/inlineasm/xtensa/asmjump.py.exp b/tests/inlineasm/xtensa/asmjump.py.exp
new file mode 100644
index 0000000000..51993f072d
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmjump.py.exp
@@ -0,0 +1,2 @@
+2
+2
diff --git a/tests/inlineasm/xtensa/asmloadstore.py b/tests/inlineasm/xtensa/asmloadstore.py
new file mode 100644
index 0000000000..b185e30520
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmloadstore.py
@@ -0,0 +1,98 @@
+import array
+
+# On the 8266 the generated code gets put into the IRAM segment, which is only
+# word-addressable. Therefore, to test byte and halfword load/store opcodes
+# some memory must be reserved in the DRAM segment.
+
+BYTE_DATA = array.array("B", (0x11, 0x22, 0x33, 0x44))
+WORD_DATA = array.array("h", (100, 200, -100, -200))
+DWORD_DATA = array.array("i", (100_000, -200_000, 300_000, -400_000))
+
+
+@micropython.asm_xtensa
+def tl32r() -> int:
+ nop()
+ j(CODE)
+ align(4)
+ label(DATA)
+ data(1, 1, 2, 3, 4, 5, 6, 7)
+ align(4)
+ label(CODE)
+ nop_n()
+ nop_n()
+ l32r(a2, DATA)
+
+
+print(hex(tl32r()))
+
+
+@micropython.asm_xtensa
+def tl32i() -> uint:
+ call0(ENTRY)
+ label(ENTRY)
+ l32i(a2, a0, 0)
+
+
+print(hex(tl32i()))
+
+
+@micropython.asm_xtensa
+def tl8ui(a2) -> uint:
+ mov(a3, a2)
+ l8ui(a2, a3, 1)
+
+
+print(hex(tl8ui(BYTE_DATA)))
+
+
+@micropython.asm_xtensa
+def tl16ui(a2) -> uint:
+ mov(a3, a2)
+ l16ui(a2, a3, 2)
+
+
+print(tl16ui(WORD_DATA))
+
+
+@micropython.asm_xtensa
+def tl16si(a2) -> int:
+ mov(a3, a2)
+ l16si(a2, a3, 6)
+
+
+print(tl16si(WORD_DATA))
+
+
+@micropython.asm_xtensa
+def ts8i(a2, a3):
+ s8i(a3, a2, 1)
+
+
+ts8i(BYTE_DATA, 0xFF)
+print(BYTE_DATA)
+
+
+@micropython.asm_xtensa
+def ts16i(a2, a3):
+ s16i(a3, a2, 2)
+
+
+ts16i(WORD_DATA, -123)
+print(WORD_DATA)
+
+
+@micropython.asm_xtensa
+def ts32i(a2, a3) -> uint:
+ s32i(a3, a2, 4)
+
+
+ts32i(DWORD_DATA, -123456)
+print(DWORD_DATA)
+
+
+@micropython.asm_xtensa
+def tl32i_n(a2) -> uint:
+ l32i_n(a2, a2, 8)
+
+
+print(tl32i_n(DWORD_DATA))
diff --git a/tests/inlineasm/xtensa/asmloadstore.py.exp b/tests/inlineasm/xtensa/asmloadstore.py.exp
new file mode 100644
index 0000000000..e6672df6f8
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmloadstore.py.exp
@@ -0,0 +1,9 @@
+0x4030201
+0xf8002022
+0x22
+200
+-200
+array('B', [17, 255, 51, 68])
+array('h', [100, -123, -100, -200])
+array('i', [100000, -123456, 300000, -400000])
+300000
diff --git a/tests/inlineasm/xtensa/asmmisc.py b/tests/inlineasm/xtensa/asmmisc.py
new file mode 100644
index 0000000000..271ab83662
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmmisc.py
@@ -0,0 +1,25 @@
+@micropython.asm_xtensa
+def tnop(a2, a3, a4, a5):
+ nop()
+
+
+out2 = tnop(0x100, 0x200, 0x300, 0x400)
+print(out2 == 0x100)
+
+
+@micropython.asm_xtensa
+def tnop_n(a2, a3, a4, a5):
+ nop_n()
+
+
+out2 = tnop_n(0x100, 0x200, 0x300, 0x400)
+print(out2 == 0x100)
+
+
+@micropython.asm_xtensa
+def tmov_n(a2, a3):
+ mov_n(a4, a3)
+ add(a2, a4, a3)
+
+
+print(tmov_n(0, 1))
diff --git a/tests/inlineasm/xtensa/asmmisc.py.exp b/tests/inlineasm/xtensa/asmmisc.py.exp
new file mode 100644
index 0000000000..eefaa35daf
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmmisc.py.exp
@@ -0,0 +1,3 @@
+True
+True
+2
diff --git a/tests/inlineasm/xtensa/asmshift.py b/tests/inlineasm/xtensa/asmshift.py
new file mode 100644
index 0000000000..271ca1ccd4
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmshift.py
@@ -0,0 +1,137 @@
+@micropython.asm_xtensa
+def lsl1(a2):
+ slli(a2, a2, 1)
+
+
+print(hex(lsl1(0x123)))
+
+
+@micropython.asm_xtensa
+def lsl23(a2):
+ slli(a2, a2, 23)
+
+
+print(hex(lsl23(1)))
+
+
+@micropython.asm_xtensa
+def lsr1(a2):
+ srli(a2, a2, 1)
+
+
+print(hex(lsr1(0x123)))
+
+
+@micropython.asm_xtensa
+def lsr15(a2):
+ srli(a2, a2, 15)
+
+
+print(hex(lsr15(0x80000000)))
+
+
+@micropython.asm_xtensa
+def asr1(a2):
+ srai(a2, a2, 1)
+
+
+print(hex(asr1(0x123)))
+
+
+@micropython.asm_xtensa
+def asr31(a2):
+ srai(a2, a2, 31)
+
+
+print(hex(asr31(0x80000000)))
+
+
+@micropython.asm_xtensa
+def lsl1r(a2):
+ movi(a3, 1)
+ ssl(a3)
+ sll(a2, a2)
+
+
+print(hex(lsl1r(0x123)))
+
+
+@micropython.asm_xtensa
+def lsr1r(a2):
+ movi(a3, 1)
+ ssr(a3)
+ srl(a2, a2)
+
+
+print(hex(lsr1r(0x123)))
+
+
+@micropython.asm_xtensa
+def asr1r(a2):
+ movi(a3, 1)
+ ssr(a3)
+ sra(a2, a2)
+
+
+print(hex(asr1r(0x123)))
+
+
+@micropython.asm_xtensa
+def sll9(a2):
+ ssai(9)
+ sll(a2, a2)
+
+
+print(hex(sll9(1)))
+
+
+@micropython.asm_xtensa
+def srlr(a2, a3):
+ ssa8l(a3)
+ srl(a2, a2)
+
+
+print(hex(srlr(0x12340000, 2)))
+
+
+@micropython.asm_xtensa
+def sllr(a2, a3):
+ ssa8b(a3)
+ sll(a2, a2)
+
+
+print(hex(sllr(0x1234, 2)))
+
+
+@micropython.asm_xtensa
+def srcr(a2, a3, a4):
+ ssr(a4)
+ src(a2, a2, a3)
+
+
+print(hex(srcr(0x00000001, 0x80000000, 2)))
+
+
+@micropython.asm_xtensa
+def srai24(a2):
+ srai(a2, a2, 24)
+
+
+print(hex(srai24(0x12345678)))
+
+
+@micropython.asm_xtensa
+def nsar(a2, a3):
+ nsa(a2, a3)
+
+
+print(nsar(0x12345678, 0))
+print(nsar(0x12345678, -1))
+
+
+@micropython.asm_xtensa
+def nsaur(a2, a3):
+ nsau(a2, a3)
+
+
+print(nsaur(0x12345678, 0))
diff --git a/tests/inlineasm/xtensa/asmshift.py.exp b/tests/inlineasm/xtensa/asmshift.py.exp
new file mode 100644
index 0000000000..3e2bb3b4ae
--- /dev/null
+++ b/tests/inlineasm/xtensa/asmshift.py.exp
@@ -0,0 +1,17 @@
+0x246
+0x800000
+0x91
+0x10000
+0x91
+-0x1
+0x246
+0x91
+0x91
+0x800000
+0x1234
+0x12340000
+0x60000000
+0x12
+31
+31
+32
diff --git a/tests/micropython/viper_ptr16_load_boundary.py b/tests/micropython/viper_ptr16_load_boundary.py
new file mode 100644
index 0000000000..ccaaa0909a
--- /dev/null
+++ b/tests/micropython/viper_ptr16_load_boundary.py
@@ -0,0 +1,25 @@
+# Test boundary conditions for various architectures
+
+GET_TEMPLATE = """
+@micropython.viper
+def get{off}(src: ptr16) -> int:
+ return src[{off}]
+print(b[{off} * 2:({off} + 1) * 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"
+
+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))
+ 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
new file mode 100644
index 0000000000..4b8c184c13
--- /dev/null
+++ b/tests/micropython/viper_ptr16_load_boundary.py.exp
@@ -0,0 +1,12 @@
+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')
diff --git a/tests/micropython/viper_ptr16_store_boundary.py b/tests/micropython/viper_ptr16_store_boundary.py
new file mode 100644
index 0000000000..e0a4f84557
--- /dev/null
+++ b/tests/micropython/viper_ptr16_store_boundary.py
@@ -0,0 +1,41 @@
+# Test boundary conditions for various architectures
+
+SET_TEMPLATE = """
+@micropython.viper
+def set{off}(dest: ptr16):
+ dest[{off}] = {val}
+set{off}(b)
+print(b[{off} * 2:({off} + 1) * 2])
+"""
+
+TEST_DATA = (
+ (15, (0x4241, 0x4443, 0x4645)),
+ (127, (0x4847, 0x4A49, 0x4C4B)),
+ (2047, (0x4E4D, 0x504F, 0x5251)),
+)
+
+
+@micropython.viper
+def set_index(dest: ptr16, i: int, val: int):
+ 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))
diff --git a/tests/micropython/viper_ptr16_store_boundary.py.exp b/tests/micropython/viper_ptr16_store_boundary.py.exp
new file mode 100644
index 0000000000..b56fe6695f
--- /dev/null
+++ b/tests/micropython/viper_ptr16_store_boundary.py.exp
@@ -0,0 +1,18 @@
+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')
diff --git a/tests/micropython/viper_ptr32_load_boundary.py b/tests/micropython/viper_ptr32_load_boundary.py
new file mode 100644
index 0000000000..6954bd46b2
--- /dev/null
+++ b/tests/micropython/viper_ptr32_load_boundary.py
@@ -0,0 +1,25 @@
+# Test boundary conditions for various architectures
+
+GET_TEMPLATE = """
+@micropython.viper
+def get{off}(src: ptr32) -> int:
+ return src[{off}]
+print(b[{off} * 4:({off} + 1) * 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"
+
+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))
+ 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
new file mode 100644
index 0000000000..a58e703f91
--- /dev/null
+++ b/tests/micropython/viper_ptr32_load_boundary.py.exp
@@ -0,0 +1,12 @@
+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')
diff --git a/tests/micropython/viper_ptr32_store_boundary.py b/tests/micropython/viper_ptr32_store_boundary.py
new file mode 100644
index 0000000000..243ff5cd9c
--- /dev/null
+++ b/tests/micropython/viper_ptr32_store_boundary.py
@@ -0,0 +1,35 @@
+# 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])
+"""
+
+
+@micropython.viper
+def set_index(dest: ptr32, 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) * 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))
diff --git a/tests/micropython/viper_ptr32_store_boundary.py.exp b/tests/micropython/viper_ptr32_store_boundary.py.exp
new file mode 100644
index 0000000000..89f09fbc7a
--- /dev/null
+++ b/tests/micropython/viper_ptr32_store_boundary.py.exp
@@ -0,0 +1,18 @@
+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'"#$%')
diff --git a/tests/micropython/viper_ptr8_load_boundary.py b/tests/micropython/viper_ptr8_load_boundary.py
new file mode 100644
index 0000000000..bcb17a1e1f
--- /dev/null
+++ b/tests/micropython/viper_ptr8_load_boundary.py
@@ -0,0 +1,25 @@
+# Test boundary conditions for various architectures
+
+GET_TEMPLATE = """
+@micropython.viper
+def get{off}(src: ptr8) -> int:
+ return src[{off}]
+print(get{off}(b))
+"""
+
+
+@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"
+
+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))
+ 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
new file mode 100644
index 0000000000..7cbd1ac78c
--- /dev/null
+++ b/tests/micropython/viper_ptr8_load_boundary.py.exp
@@ -0,0 +1,12 @@
+49 50 51
+49
+50
+51
+52 53 54
+52
+53
+54
+55 56 57
+55
+56
+57
diff --git a/tests/micropython/viper_ptr8_store_boundary.py b/tests/micropython/viper_ptr8_store_boundary.py
new file mode 100644
index 0000000000..ad51268454
--- /dev/null
+++ b/tests/micropython/viper_ptr8_store_boundary.py
@@ -0,0 +1,30 @@
+# 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}])
+"""
+
+
+@micropython.viper
+def set_index(dest: ptr8, i: int, val: int):
+ 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))
diff --git a/tests/micropython/viper_ptr8_store_boundary.py.exp b/tests/micropython/viper_ptr8_store_boundary.py.exp
new file mode 100644
index 0000000000..a35cb3ac9e
--- /dev/null
+++ b/tests/micropython/viper_ptr8_store_boundary.py.exp
@@ -0,0 +1,12 @@
+bytearray(b'123')
+bytearray(b'456')
+bytearray(b'789')
+65
+66
+67
+68
+69
+70
+71
+72
+73
diff --git a/tests/misc/print_exception.py b/tests/misc/print_exception.py
index 1d196d6ab1..92754733b5 100644
--- a/tests/misc/print_exception.py
+++ b/tests/misc/print_exception.py
@@ -1,3 +1,5 @@
+# Test sys.print_exception (MicroPython) / traceback.print_exception (CPython).
+
try:
import io
import sys
diff --git a/tests/multi_net/tcp_recv_peek.py b/tests/multi_net/tcp_recv_peek.py
new file mode 100644
index 0000000000..ff540dd3c3
--- /dev/null
+++ b/tests/multi_net/tcp_recv_peek.py
@@ -0,0 +1,46 @@
+# Test TCP recv with MSG_PEEK
+#
+# Note that bare metal LWIP only returns at most one packet's worth of TCP data
+# in any recv() call - including when peeking - so can't be too clever with
+# different recv() combinations
+import socket
+import random
+
+
+# Server
+def instance0():
+ PORT = random.randrange(10000, 50000)
+ multitest.globals(IP=multitest.get_network_ip(), PORT=PORT)
+ 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()
+ multitest.next()
+ s2, _ = s.accept()
+ print(s2.recv(8, socket.MSG_PEEK))
+ print(s2.recv(8))
+ s2.send(b"1234567890")
+ multitest.broadcast("0-sent")
+ multitest.wait("1-sent")
+ print(s2.recv(5, socket.MSG_PEEK))
+ print(s2.recv(5, socket.MSG_PEEK))
+ multitest.broadcast("0-recved")
+ multitest.wait("1-recved") # sync here necessary as MP sends RST if closing TCP early
+ s2.close()
+ s.close()
+
+
+# Client
+def instance1():
+ multitest.next()
+ s = socket.socket()
+ s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
+ s.send(b"abcdefgh")
+ multitest.broadcast("1-sent")
+ multitest.wait("0-sent")
+ s.send(b"klmnopqr")
+ print(s.recv(5, socket.MSG_PEEK))
+ print(s.recv(10))
+ multitest.broadcast("1-recved")
+ multitest.wait("0-recved")
+ s.close()
diff --git a/tests/multi_net/udp_recv_dontwait.py b/tests/multi_net/udp_recv_dontwait.py
new file mode 100644
index 0000000000..640f3f060e
--- /dev/null
+++ b/tests/multi_net/udp_recv_dontwait.py
@@ -0,0 +1,59 @@
+# Test UDP recv and recvfrom with MSG_DONTWAIT
+import random
+import socket
+
+try:
+ import errno, time
+except ImportError:
+ print("SKIP")
+ raise SystemExit
+
+
+# Server
+def instance0():
+ PORT = random.randrange(10000, 50000)
+ multitest.globals(IP=multitest.get_network_ip(), PORT=PORT)
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1])
+ multitest.next()
+ begin = time.ticks_ms()
+
+ # do some recvs before instance1 starts, when we know no packet is waiting
+ try:
+ print(s.recvfrom(8, socket.MSG_DONTWAIT))
+ except OSError as e:
+ print(e.errno == errno.EAGAIN)
+ try:
+ print(s.recv(8, socket.MSG_DONTWAIT))
+ except OSError as e:
+ print(e.errno == errno.EAGAIN)
+
+ # the above steps should not have taken any substantial time
+ elapsed = time.ticks_diff(time.ticks_ms(), begin)
+ print(True if elapsed < 50 else elapsed)
+
+ # Now instance1 will send us a UDP packet
+ multitest.broadcast("0-ready")
+ multitest.wait("1-sent")
+
+ for _ in range(10): # retry if necessary, to allow for network delay
+ time.sleep_ms(100)
+ try:
+ print(s.recv(8, socket.MSG_DONTWAIT))
+ break
+ except OSError as er:
+ if er.errno != errno.EAGAIN:
+ raise er
+ s.close()
+
+
+# Client
+def instance1():
+ multitest.next()
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
+ multitest.wait("0-ready")
+ print(s.send(b"abcdefgh"))
+ multitest.broadcast("1-sent")
+ s.close()
diff --git a/tests/multi_net/udp_recv_dontwait.py.exp b/tests/multi_net/udp_recv_dontwait.py.exp
new file mode 100644
index 0000000000..f61fd4bbe2
--- /dev/null
+++ b/tests/multi_net/udp_recv_dontwait.py.exp
@@ -0,0 +1,7 @@
+--- instance0 ---
+True
+True
+True
+b'abcdefgh'
+--- instance1 ---
+8
diff --git a/tests/multi_net/udp_recv_peek.py b/tests/multi_net/udp_recv_peek.py
new file mode 100644
index 0000000000..47897ce553
--- /dev/null
+++ b/tests/multi_net/udp_recv_peek.py
@@ -0,0 +1,36 @@
+# Test UDP recv and recvfrom with MSG_PEEK
+import random
+import socket
+import time
+
+
+# Server
+def instance0():
+ PORT = random.randrange(10000, 50000)
+ multitest.globals(IP=multitest.get_network_ip(), PORT=PORT)
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1])
+ multitest.next()
+ peek_bytes, peek_addr = s.recvfrom(8, socket.MSG_PEEK)
+ print(peek_bytes)
+ real_bytes, real_addr = s.recvfrom(8)
+ print(real_bytes)
+ print(peek_addr == real_addr) # source addr should be the same for each
+ res = s.sendto(b"1234567890", peek_addr)
+ print(res)
+ print(s.recv(5, socket.MSG_PEEK))
+ print(s.recv(5, socket.MSG_PEEK))
+ s.close()
+
+
+# Client
+def instance1():
+ multitest.next()
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
+ s.send(b"abcdefgh")
+ s.send(b"klmnopqr")
+ print(s.recv(5, socket.MSG_PEEK))
+ print(s.recv(10))
+ s.close()
diff --git a/tests/ports/rp2/rp2_lightsleep_thread.py b/tests/ports/rp2/rp2_lightsleep_thread.py
index 2aaa34bbe3..494ead4223 100644
--- a/tests/ports/rp2/rp2_lightsleep_thread.py
+++ b/tests/ports/rp2/rp2_lightsleep_thread.py
@@ -42,12 +42,25 @@ class LightSleepInThread(unittest.TestCase):
def test_cpu0_also_lightsleep(self):
_thread.start_new_thread(self.thread_entry, ())
- time.sleep(0.050) # account for any delay in starting the thread
+ time.sleep_ms(50) # account for any delay in starting the thread
self.thread_entry(False) # does the same lightsleep loop, doesn't set the done flag
- self.assertTrue(self.thread_done)
- # only one thread can actually be in lightsleep at a time to avoid races, so the total
- # runtime is doubled by doing it on both CPUs
- self.assertAlmostEqual(self.elapsed_ms(), IDEAL_RUNTIME * 2, delta=IDEAL_RUNTIME)
+ while not self.thread_done:
+ time.sleep_ms(10)
+ #
+ # Only one thread can actually be in lightsleep at a time to avoid
+ # races, but otherwise the behaviour when both threads call lightsleep()
+ # is unspecified.
+ #
+ # Currently, the other thread will return immediately if one is already
+ # in lightsleep. Therefore, runtime can be between IDEAL_RUNTIME and
+ # IDEAL_RUNTIME * 2 depending on how many times the calls to lightsleep() race
+ # each other.
+ #
+ # Note this test case is really only here to ensure that the rp2 hasn't
+ # hung or failed to sleep at all - not to verify any correct behaviour
+ # when there's a race to call lightsleep().
+ self.assertGreaterEqual(self.elapsed_ms(), IDEAL_RUNTIME - MAX_DELTA)
+ self.assertLessEqual(self.elapsed_ms(), IDEAL_RUNTIME * 2 + MAX_DELTA)
if __name__ == "__main__":
diff --git a/tests/ports/unix/extra_coverage.py.exp b/tests/ports/unix/extra_coverage.py.exp
index 5ff947e883..19b32f1c9d 100644
--- a/tests/ports/unix/extra_coverage.py.exp
+++ b/tests/ports/unix/extra_coverage.py.exp
@@ -122,6 +122,13 @@ unlocked
KeyboardInterrupt:
KeyboardInterrupt:
10
+loop
+scheduled function
+loop
+scheduled function
+loop
+scheduled function
+scheduled function
# ringbuf
99 0
98 1
diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py
index b858989daa..073e0b053e 100755
--- a/tests/run-natmodtests.py
+++ b/tests/run-natmodtests.py
@@ -73,6 +73,7 @@ class __FS:
return __File()
vfs.mount(__FS(), '/__remote')
sys.path.insert(0, '/__remote')
+{import_prelude}
sys.modules['{}'] = __import__('__injected')
"""
@@ -133,6 +134,13 @@ def detect_architecture(target):
def run_tests(target_truth, target, args, stats, resolved_arch):
+ global injected_import_hook_code
+
+ prelude = ""
+ if args.begin:
+ prelude = args.begin.read()
+ injected_import_hook_code = injected_import_hook_code.replace("{import_prelude}", prelude)
+
for test_file in args.files:
# Find supported test
test_file_basename = os.path.basename(test_file)
@@ -212,6 +220,13 @@ def main():
cmd_parser.add_argument(
"-a", "--arch", choices=AVAILABLE_ARCHS, help="override native architecture of the target"
)
+ cmd_parser.add_argument(
+ "-b",
+ "--begin",
+ type=argparse.FileType("rt"),
+ default=None,
+ help="prologue python file to execute before module import",
+ )
cmd_parser.add_argument("files", nargs="*", help="input test files")
args = cmd_parser.parse_args()
diff --git a/tests/run-tests.py b/tests/run-tests.py
index ac411a0be6..cb7a8b7705 100755
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -105,14 +105,11 @@ PC_PLATFORMS = ("darwin", "linux", "win32")
# These are tests that are difficult to detect that they should not be run on the given target.
platform_tests_to_skip = {
"esp8266": (
- "micropython/viper_args.py", # too large
- "micropython/viper_binop_arith.py", # too large
- "misc/rge_sm.py", # too large
+ "misc/rge_sm.py", # incorrect values due to object representation C
),
"minimal": (
"basics/class_inplace_op.py", # all special methods not supported
"basics/subclass_native_init.py", # native subclassing corner cases not support
- "misc/rge_sm.py", # too large
"micropython/opt_level.py", # don't assume line numbers are stored
),
"nrf": (
@@ -272,22 +269,17 @@ def detect_test_platform(pyb, args):
print()
-def prepare_script_for_target(args, *, script_filename=None, script_text=None, force_plain=False):
+def prepare_script_for_target(args, *, script_text=None, force_plain=False):
if force_plain or (not args.via_mpy and args.emit == "bytecode"):
- if script_filename is not None:
- with open(script_filename, "rb") as f:
- script_text = f.read()
+ # A plain test to run as-is, no processing needed.
+ pass
elif args.via_mpy:
tempname = tempfile.mktemp(dir="")
mpy_filename = tempname + ".mpy"
- if script_filename is None:
- script_filename = tempname + ".py"
- cleanup_script_filename = True
- with open(script_filename, "wb") as f:
- f.write(script_text)
- else:
- cleanup_script_filename = False
+ script_filename = tempname + ".py"
+ with open(script_filename, "wb") as f:
+ f.write(script_text)
try:
subprocess.check_output(
@@ -303,8 +295,7 @@ def prepare_script_for_target(args, *, script_filename=None, script_text=None, f
script_text = b"__buf=" + bytes(repr(f.read()), "ascii") + b"\n"
rm_f(mpy_filename)
- if cleanup_script_filename:
- rm_f(script_filename)
+ rm_f(script_filename)
script_text += bytes(injected_import_hook_code, "ascii")
else:
@@ -315,9 +306,21 @@ def prepare_script_for_target(args, *, script_filename=None, script_text=None, f
def run_script_on_remote_target(pyb, args, test_file, is_special):
- had_crash, script = prepare_script_for_target(
- args, script_filename=test_file, force_plain=is_special
- )
+ with open(test_file, "rb") as f:
+ script = f.read()
+
+ # If the test is not a special test, prepend it with a print to indicate that it started.
+ # If the print does not execute this means that the test did not even start, eg it was
+ # too large for the target.
+ prepend_start_test = not is_special
+ if prepend_start_test:
+ if script.startswith(b"#"):
+ script = b"print('START TEST')" + script
+ else:
+ script = b"print('START TEST')\n" + script
+
+ had_crash, script = prepare_script_for_target(args, script_text=script, force_plain=is_special)
+
if had_crash:
return True, script
@@ -328,9 +331,19 @@ def run_script_on_remote_target(pyb, args, test_file, is_special):
except pyboard.PyboardError as e:
had_crash = True
if not is_special and e.args[0] == "exception":
- output_mupy = e.args[1] + e.args[2] + b"CRASH"
+ if prepend_start_test and e.args[1] == b"" and b"MemoryError" in e.args[2]:
+ output_mupy = b"SKIP-TOO-LARGE\n"
+ else:
+ output_mupy = e.args[1] + e.args[2] + b"CRASH"
else:
output_mupy = bytes(e.args[0], "ascii") + b"\nCRASH"
+
+ if prepend_start_test:
+ if output_mupy.startswith(b"START TEST\r\n"):
+ output_mupy = output_mupy.removeprefix(b"START TEST\r\n")
+ else:
+ had_crash = True
+
return had_crash, output_mupy
@@ -474,7 +487,7 @@ def run_micropython(pyb, args, test_file, test_file_abspath, is_special=False):
output_mupy = output_mupy.replace(b"\r\n", b"\n")
# don't try to convert the output if we should skip this test
- if had_crash or output_mupy in (b"SKIP\n", b"CRASH"):
+ if had_crash or output_mupy in (b"SKIP\n", b"SKIP-TOO-LARGE\n", b"CRASH"):
return output_mupy
# skipped special tests will output "SKIP" surrounded by other interpreter debug output
@@ -605,9 +618,7 @@ class PyboardNodeRunner:
def run_tests(pyb, tests, args, result_dir, num_threads=1):
test_count = ThreadSafeCounter()
testcase_count = ThreadSafeCounter()
- passed_count = ThreadSafeCounter()
- failed_tests = ThreadSafeCounter([])
- skipped_tests = ThreadSafeCounter([])
+ test_results = ThreadSafeCounter([])
skip_tests = set()
skip_native = False
@@ -896,7 +907,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
if skip_it:
print("skip ", test_file)
- skipped_tests.append(test_name)
+ test_results.append((test_name, test_file, "skip", ""))
return
# Run the test on the MicroPython target.
@@ -911,7 +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)
- skipped_tests.append(test_name)
+ test_results.append((test_name, 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"))
return
# Look at the output of the test to see if unittest was used.
@@ -994,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)
- passed_count.increment()
+ test_results.append((test_name, test_file, "pass", ""))
rm_f(filename_expected)
rm_f(filename_mupy)
else:
@@ -1006,7 +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)
- failed_tests.append((test_name, test_file))
+ test_results.append((test_name, test_file, "fail", ""))
test_count.increment()
@@ -1035,17 +1050,41 @@ 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")
+ skipped_tests_too_large = list(
+ r for r in test_results if r[2] == "skip" and r[3] == "too large"
+ )
+ failed_tests = list(r for r in test_results if r[2] == "fail")
+
print(
"{} tests performed ({} individual testcases)".format(
test_count.value, testcase_count.value
)
)
- print("{} tests passed".format(passed_count.value))
+ print("{} tests passed".format(len(passed_tests)))
- skipped_tests = sorted(skipped_tests.value)
if len(skipped_tests) > 0:
- print("{} tests skipped: {}".format(len(skipped_tests), " ".join(skipped_tests)))
- failed_tests = sorted(failed_tests.value)
+ print(
+ "{} tests skipped: {}".format(
+ len(skipped_tests), " ".join(test[0] for test in skipped_tests)
+ )
+ )
+
+ if len(skipped_tests_too_large) > 0:
+ print(
+ "{} tests skipped because they are too large: {}".format(
+ len(skipped_tests_too_large), " ".join(test[0] for test in skipped_tests_too_large)
+ )
+ )
+
+ if len(failed_tests) > 0:
+ print(
+ "{} tests failed: {}".format(
+ len(failed_tests), " ".join(test[0] for test in failed_tests)
+ )
+ )
# Serialize regex added by append_filter.
def to_json(obj):
@@ -1055,21 +1094,20 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
with open(os.path.join(result_dir, RESULTS_FILE), "w") as f:
json.dump(
- {"args": vars(args), "failed_tests": [test[1] for test in failed_tests]},
+ {
+ # 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),
+ # A list of failed tests. This is deprecated, use the "results" above instead.
+ "failed_tests": [test[1] for test in failed_tests],
+ },
f,
default=to_json,
)
- if len(failed_tests) > 0:
- print(
- "{} tests failed: {}".format(
- len(failed_tests), " ".join(test[0] for test in failed_tests)
- )
- )
- return False
-
- # all tests succeeded
- return True
+ # Return True only if all tests succeeded.
+ return len(failed_tests) == 0
class append_filter(argparse.Action):
@@ -1238,7 +1276,7 @@ the last matching regex is used:
results_file = os.path.join(args.result_dir, RESULTS_FILE)
if os.path.exists(results_file):
with open(results_file, "r") as f:
- tests = json.load(f)["failed_tests"]
+ tests = list(test[0] for test in json.load(f)["results"] if test[1] == "fail")
else:
tests = []
elif len(args.files) == 0: