Files
micropython/tests/extmod/vfs_blockdev_invalid.py
Alessandro Gatti dbf59db5a1 tests/extmod/vfs_blockdev_invalid.py: Handle low memory conditions.
This commit modifies the "extmod/vfs_blockdev_invalid" test to better
behave on boards with low available memory.

Before these changes the test would fail on ESP8266 (at least), due to
low memory, but in a way that could not be easily solved as the error
occurred in the middle of the test.

The test has been rewritten to delay its output until the very end, so
if a low memory condition occurs and needs to stop execution then no
real output will show up before the skip marker.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2025-12-17 16:05:29 +11:00

116 lines
3.0 KiB
Python

# Tests where the block device returns invalid values
try:
import vfs
vfs.VfsFat
vfs.VfsLfs2
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
class RAMBlockDevice:
ERASE_BLOCK_SIZE = 512
def __init__(self, blocks):
self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE)
self.read_res = 0
self.write_res = 0
def readblocks(self, block, buf, off=0):
# print("readblocks", block, len(buf), off)
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
buf[i] = self.data[addr + i]
return self.read_res
def writeblocks(self, block, buf, off=None):
if off is None:
# erase, then write
off = 0
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
self.data[addr + i] = buf[i]
return self.write_res
def ioctl(self, op, arg):
if op == 4: # block count
return len(self.data) // self.ERASE_BLOCK_SIZE
if op == 5: # block size
return self.ERASE_BLOCK_SIZE
if op == 6: # erase block
return 0
try:
bdev = RAMBlockDevice(50)
except MemoryError:
print("SKIP-TOO-LARGE")
raise SystemExit
ERROR_EIO = (OSError, "[Errno 5] EIO")
ERROR_EINVAL = (OSError, "[Errno 22] EINVAL")
ERROR_TYPE = (TypeError, "can't convert str to int")
def test(vfs_class, test_data):
bdev.read_res = 0 # reset function results
bdev.write_res = 0
vfs_class.mkfs(bdev)
fs = vfs_class(bdev)
with fs.open("test", "w") as f:
f.write("a" * 64)
for res, error_open, error_read in test_data:
# This variant will fail on open
bdev.read_res = res
try:
with fs.open("test", "r") as f:
assert error_open is None
except Exception as e:
assert error_open is not None
assert (type(e), str(e)) == error_open
# This variant should succeed on open, may fail on read
# unless the filesystem cached the contents already
bdev.read_res = 0
try:
with fs.open("test", "r") as f:
bdev.read_res = res
assert f.read(1) == "a"
assert f.read() == "a" * 63
assert error_read is None
except Exception as e:
assert error_read is not None
assert (type(e), str(e)) == error_read
try:
test(
vfs.VfsLfs2,
(
(0, None, None),
(-5, ERROR_EIO, None),
(5, ERROR_EINVAL, None),
(33, ERROR_EINVAL, None),
("invalid", ERROR_TYPE, None),
),
)
test(
vfs.VfsFat,
(
(0, None, None),
(-5, ERROR_EIO, ERROR_EIO),
(5, ERROR_EIO, ERROR_EIO),
(33, ERROR_EIO, ERROR_EIO),
("invalid", ERROR_TYPE, ERROR_TYPE),
),
)
print("OK")
except MemoryError:
print("SKIP-TOO-LARGE")