summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Gatti <a.gatti@frob.it>2025-09-25 01:10:50 +0200
committerAlessandro Gatti <a.gatti@frob.it>2025-10-24 19:13:15 +0200
commita080585ffdc628ab14d70a1489e31ede485e9a88 (patch)
treee3acfcb8f1aa6eff8646fadc19b9f35f38e77740
parent849c67bcdc9f848a674554f3e03ef850a8f70692 (diff)
tests/ports/qemu: Add arch flags MPY import checks test.
This commit introduces a test file (along with its necessary data) to test MPY files pass/reject cases, due to either mismatching architecture flag requirements or unneeded "no-flags" values set. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
-rw-r--r--tests/ports/qemu/mpy_arch_flags_test.py128
-rw-r--r--tests/ports/qemu/mpy_arch_flags_test.py.exp1
2 files changed, 129 insertions, 0 deletions
diff --git a/tests/ports/qemu/mpy_arch_flags_test.py b/tests/ports/qemu/mpy_arch_flags_test.py
new file mode 100644
index 000000000..c07d92d53
--- /dev/null
+++ b/tests/ports/qemu/mpy_arch_flags_test.py
@@ -0,0 +1,128 @@
+try:
+ import sys, io, vfs
+
+ sys.implementation._mpy
+ io.IOBase
+except (ImportError, AttributeError):
+ print("SKIP")
+ raise SystemExit
+
+sys_implementation_mpy = sys.implementation._mpy
+arch = (sys_implementation_mpy >> 10) & 0x0F
+
+# RV32-only for now.
+if arch != 11:
+ print("SKIP")
+ raise SystemExit
+
+
+class UserFile(io.IOBase):
+ def __init__(self, data):
+ self.data = memoryview(data)
+ self.pos = 0
+
+ def readinto(self, buf):
+ n = min(len(buf), len(self.data) - self.pos)
+ buf[:n] = self.data[self.pos : self.pos + n]
+ self.pos += n
+ return n
+
+ def ioctl(self, req, arg):
+ if req == 4: # MP_STREAM_CLOSE
+ return 0
+ return -1
+
+
+class UserFS:
+ def __init__(self, files):
+ self.files = files
+
+ def mount(self, readonly, mksfs):
+ pass
+
+ def umount(self):
+ pass
+
+ def stat(self, path):
+ if path in self.files:
+ return (32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ raise OSError
+
+ def open(self, path, mode):
+ return UserFile(self.files[path])
+
+
+def mp_encode_uint(val):
+ encoded = [val & 0x7F]
+ val >>= 7
+ while val != 0:
+ encoded.insert(0, 0x80 | (val & 0x7F))
+ val >>= 7
+ return bytes(encoded)
+
+
+def add_flags(module, flags):
+ output = bytearray()
+ output.extend(module[:4])
+ output[2] |= 0x40
+ output.extend(mp_encode_uint(flags))
+ output.extend(module[4:])
+ return output
+
+
+arch_flags = sys_implementation_mpy >> 16
+can_test_partial_flags = arch_flags not in [1 << i for i in range(16)]
+
+# To recreate this string run:
+# echo "hello=1" | mpy-cross -s module.py - | python -c 'import sys; print(sys.stdin.buffer.read())'
+MPY_FILE_BASE = b"M\x06\x00\x1f\x03\x00\x12module.py\x00\x0f\nhello\x00@\x00\x02\x01\x81\x16\x02Qc"
+
+user_files = {
+ "/matching_flags.mpy": add_flags(MPY_FILE_BASE, arch_flags),
+ "/invalid_flags.mpy": add_flags(MPY_FILE_BASE, (~arch_flags & 0xFFFF)),
+ "/explicit_no_flags.mpy": add_flags(MPY_FILE_BASE, 0),
+}
+if can_test_partial_flags:
+ user_files["/partial_flags_more.mpy"] = add_flags(
+ MPY_FILE_BASE, (arch_flags | (arch_flags << 1)) & 0xFFFF
+ )
+ user_files["/partial_flags_less.mpy"] = add_flags(
+ MPY_FILE_BASE, (arch_flags >> 1) & arch_flags
+ )
+
+vfs.mount(UserFS(user_files), "/userfs")
+sys.path.append("/userfs")
+
+import matching_flags
+
+if not hasattr(matching_flags, "hello"):
+ print("Improper matching_flags import")
+
+import explicit_no_flags
+
+if not hasattr(explicit_no_flags, "hello"):
+ print("Improper explicit_no_flags import")
+
+try:
+ import invalid_flags
+
+ print("Unexpected invalid_flags import")
+except ValueError as e:
+ if str(e) != "incompatible .mpy file":
+ print("Unexpected invalid_flags import error:", str(e))
+
+if can_test_partial_flags:
+ import partial_flags_less
+
+ if not hasattr(partial_flags_less, "hello"):
+ print("Improper partial_flags_less import")
+
+ try:
+ import partial_flags_more
+
+ print("Unexpected partial_flags_more import")
+ except ValueError as e:
+ if str(e) != "incompatible .mpy file":
+ print("Unexpected partial_flags_more import error:", str(e))
+
+print("OK")
diff --git a/tests/ports/qemu/mpy_arch_flags_test.py.exp b/tests/ports/qemu/mpy_arch_flags_test.py.exp
new file mode 100644
index 000000000..d86bac9de
--- /dev/null
+++ b/tests/ports/qemu/mpy_arch_flags_test.py.exp
@@ -0,0 +1 @@
+OK