1# Test VfsFat class and its finaliser 2 3try: 4 import uerrno, uos 5 6 uos.VfsFat 7except (ImportError, AttributeError): 8 print("SKIP") 9 raise SystemExit 10 11 12class RAMBlockDevice: 13 def __init__(self, blocks, sec_size=512): 14 self.sec_size = sec_size 15 self.data = bytearray(blocks * self.sec_size) 16 17 def readblocks(self, n, buf): 18 for i in range(len(buf)): 19 buf[i] = self.data[n * self.sec_size + i] 20 21 def writeblocks(self, n, buf): 22 for i in range(len(buf)): 23 self.data[n * self.sec_size + i] = buf[i] 24 25 def ioctl(self, op, arg): 26 if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT 27 return len(self.data) // self.sec_size 28 if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE 29 return self.sec_size 30 31 32# Create block device, and skip test if not enough RAM 33try: 34 bdev = RAMBlockDevice(50) 35except MemoryError: 36 print("SKIP") 37 raise SystemExit 38 39# Format block device and create VFS object 40uos.VfsFat.mkfs(bdev) 41vfs = uos.VfsFat(bdev) 42 43# Here we test that opening a file with the heap locked fails correctly. This 44# is a special case because file objects use a finaliser and allocating with a 45# finaliser is a different path to normal allocation. It would be better to 46# test this in the core tests but there are no core objects that use finaliser. 47import micropython 48 49micropython.heap_lock() 50try: 51 vfs.open("x", "r") 52except MemoryError: 53 print("MemoryError") 54micropython.heap_unlock() 55 56# Here we test that the finaliser is actually called during a garbage collection. 57import gc 58 59N = 4 60for i in range(N): 61 n = "x%d" % i 62 f = vfs.open(n, "w") 63 f.write(n) 64 f = None # release f without closing 65 [0, 1, 2, 3] # use up Python stack so f is really gone 66gc.collect() # should finalise all N files by closing them 67for i in range(N): 68 with vfs.open("x%d" % i, "r") as f: 69 print(f.read()) 70