tests/extmod: Add littlefs tests.

This commit is contained in:
Damien George 2019-10-18 17:25:48 +11:00
parent 62d5659cdd
commit 73fddb84e5
10 changed files with 639 additions and 0 deletions

107
tests/extmod/vfs_lfs.py Normal file
View File

@ -0,0 +1,107 @@
# Test for VfsLittle using a RAM device
try:
import uos
uos.VfsLfs1
uos.VfsLfs2
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
class RAMBlockDevice:
ERASE_BLOCK_SIZE = 1024
def __init__(self, blocks):
self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE)
def readblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
buf[i] = self.data[addr + i]
def writeblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
self.data[addr + i] = buf[i]
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
def test(bdev, vfs_class):
print('test', vfs_class)
# mkfs
vfs_class.mkfs(bdev)
# construction
vfs = vfs_class(bdev)
# statvfs
print(vfs.statvfs('/'))
# open, write close
f = vfs.open('test', 'w')
f.write('littlefs')
f.close()
# statvfs after creating a file
print(vfs.statvfs('/'))
# ilistdir
print(list(vfs.ilistdir()))
print(list(vfs.ilistdir('/')))
print(list(vfs.ilistdir(b'/')))
# mkdir, rmdir
vfs.mkdir('testdir')
print(list(vfs.ilistdir()))
print(list(vfs.ilistdir('testdir')))
vfs.rmdir('testdir')
print(list(vfs.ilistdir()))
vfs.mkdir('testdir')
# stat a file
print(vfs.stat('test'))
# stat a dir (size seems to vary on LFS2 so don't print that)
print(vfs.stat('testdir')[:6])
# read
with vfs.open('test', 'r') as f:
print(f.read())
# create large file
with vfs.open('testbig', 'w') as f:
data = 'large012' * 32 * 16
print('data length:', len(data))
for i in range(4):
print('write', i)
f.write(data)
# stat after creating large file
print(vfs.statvfs('/'))
# rename
vfs.rename('testbig', 'testbig2')
print(list(vfs.ilistdir()))
# remove
vfs.remove('testbig2')
print(list(vfs.ilistdir()))
# getcwd, chdir
print(vfs.getcwd())
vfs.chdir('/testdir')
print(vfs.getcwd())
vfs.chdir('/')
print(vfs.getcwd())
vfs.rmdir('testdir')
bdev = RAMBlockDevice(30)
test(bdev, uos.VfsLfs1)
test(bdev, uos.VfsLfs2)

View File

@ -0,0 +1,46 @@
test <class 'VfsLfs1'>
(1024, 1024, 30, 26, 26, 0, 0, 0, 0, 255)
(1024, 1024, 30, 25, 25, 0, 0, 0, 0, 255)
[('test', 32768, 0, 8)]
[('test', 32768, 0, 8)]
[(b'test', 32768, 0, 8)]
[('test', 32768, 0, 8), ('testdir', 16384, 0, 0)]
[]
[('test', 32768, 0, 8)]
(32768, 0, 0, 0, 0, 0, 8, 0, 0, 0)
(16384, 0, 0, 0, 0, 0)
littlefs
data length: 4096
write 0
write 1
write 2
write 3
(1024, 1024, 30, 6, 6, 0, 0, 0, 0, 255)
[('test', 32768, 0, 8), ('testdir', 16384, 0, 0), ('testbig2', 32768, 0, 16384)]
[('test', 32768, 0, 8), ('testdir', 16384, 0, 0)]
/
/testdir
/
test <class 'VfsLfs2'>
(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255)
(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255)
[('test', 32768, 0, 8)]
[('test', 32768, 0, 8)]
[(b'test', 32768, 0, 8)]
[('testdir', 16384, 0, 0), ('test', 32768, 0, 8)]
[]
[('test', 32768, 0, 8)]
(32768, 0, 0, 0, 0, 0, 8, 0, 0, 0)
(16384, 0, 0, 0, 0, 0)
littlefs
data length: 4096
write 0
write 1
write 2
write 3
(1024, 1024, 30, 9, 9, 0, 0, 0, 0, 255)
[('testbig2', 32768, 0, 16384), ('testdir', 16384, 0, 0), ('test', 32768, 0, 8)]
[('testdir', 16384, 0, 0), ('test', 32768, 0, 8)]
/
/testdir
/

View File

@ -0,0 +1,106 @@
# Test for VfsLittle using a RAM device, testing error handling from corrupt block device
try:
import uos
uos.VfsLfs1
uos.VfsLfs2
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
class RAMBlockDevice:
ERASE_BLOCK_SIZE = 1024
def __init__(self, blocks):
self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE)
self.ret = 0
def readblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
buf[i] = self.data[addr + i]
return self.ret
def writeblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
self.data[addr + i] = buf[i]
return self.ret
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
def corrupt(bdev, block):
addr = block * bdev.ERASE_BLOCK_SIZE
for i in range(bdev.ERASE_BLOCK_SIZE):
bdev.data[addr + i] = i & 0xff
def create_vfs(bdev, vfs_class):
bdev.ret = 0
vfs_class.mkfs(bdev)
vfs = vfs_class(bdev)
with vfs.open('f', 'w') as f:
for i in range(100):
f.write('test')
return vfs
def test(bdev, vfs_class):
print('test', vfs_class)
# statvfs
vfs = create_vfs(bdev, vfs_class)
corrupt(bdev, 0)
corrupt(bdev, 1)
try:
print(vfs.statvfs(''))
except OSError:
print('statvfs OSError')
# error during read
vfs = create_vfs(bdev, vfs_class)
f = vfs.open('f', 'r')
bdev.ret = -5 # EIO
try:
f.read(10)
except OSError:
print('read OSError')
# error during write
vfs = create_vfs(bdev, vfs_class)
f = vfs.open('f', 'a')
bdev.ret = -5 # EIO
try:
f.write('test')
except OSError:
print('write OSError')
# error during close
vfs = create_vfs(bdev, vfs_class)
f = vfs.open('f', 'w')
f.write('test')
bdev.ret = -5 # EIO
try:
f.close()
except OSError:
print('close OSError')
# error during flush
vfs = create_vfs(bdev, vfs_class)
f = vfs.open('f', 'w')
f.write('test')
bdev.ret = -5 # EIO
try:
f.flush()
except OSError:
print('flush OSError')
bdev.ret = 0
f.close()
bdev = RAMBlockDevice(30)
test(bdev, uos.VfsLfs1)
test(bdev, uos.VfsLfs2)

View File

@ -0,0 +1,12 @@
test <class 'VfsLfs1'>
statvfs OSError
read OSError
write OSError
close OSError
flush OSError
test <class 'VfsLfs2'>
statvfs OSError
read OSError
write OSError
close OSError
flush OSError

View File

@ -0,0 +1,116 @@
# Test for VfsLittle using a RAM device, testing error handling
try:
import uos
uos.VfsLfs1
uos.VfsLfs2
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
class RAMBlockDevice:
ERASE_BLOCK_SIZE = 1024
def __init__(self, blocks):
self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE)
def readblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
buf[i] = self.data[addr + i]
def writeblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
self.data[addr + i] = buf[i]
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
def test(bdev, vfs_class):
print('test', vfs_class)
# mkfs with too-small block device
try:
vfs_class.mkfs(RAMBlockDevice(1))
except OSError:
print('mkfs OSError')
# mount with invalid filesystem
try:
vfs_class(bdev)
except OSError:
print('mount OSError')
# set up for following tests
vfs_class.mkfs(bdev)
vfs = vfs_class(bdev)
with vfs.open('testfile', 'w') as f:
f.write('test')
vfs.mkdir('testdir')
# ilistdir
try:
vfs.ilistdir('noexist')
except OSError:
print('ilistdir OSError')
# remove
try:
vfs.remove('noexist')
except OSError:
print('remove OSError')
# rmdir
try:
vfs.rmdir('noexist')
except OSError:
print('rmdir OSError')
# rename
try:
vfs.rename('noexist', 'somethingelse')
except OSError:
print('rename OSError')
# mkdir
try:
vfs.mkdir('testdir')
except OSError:
print('mkdir OSError')
# chdir to nonexistent
try:
vfs.chdir('noexist')
except OSError:
print('chdir OSError')
print(vfs.getcwd()) # check still at root
# chdir to file
try:
vfs.chdir('testfile')
except OSError:
print('chdir OSError')
print(vfs.getcwd()) # check still at root
# stat
try:
vfs.stat('noexist')
except OSError:
print('stat OSError')
# error during seek
with vfs.open('testfile', 'r') as f:
try:
f.seek(1 << 31)
except OSError:
print('seek OSError')
bdev = RAMBlockDevice(30)
test(bdev, uos.VfsLfs1)
test(bdev, uos.VfsLfs2)

View File

@ -0,0 +1,28 @@
test <class 'VfsLfs1'>
mkfs OSError
mount OSError
ilistdir OSError
remove OSError
rmdir OSError
rename OSError
mkdir OSError
chdir OSError
/
chdir OSError
/
stat OSError
seek OSError
test <class 'VfsLfs2'>
mkfs OSError
mount OSError
ilistdir OSError
remove OSError
rmdir OSError
rename OSError
mkdir OSError
chdir OSError
/
chdir OSError
/
stat OSError
seek OSError

View File

@ -0,0 +1,117 @@
# Test for VfsLittle using a RAM device, file IO
try:
import uos
uos.VfsLfs1
uos.VfsLfs2
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
class RAMBlockDevice:
ERASE_BLOCK_SIZE = 1024
def __init__(self, blocks):
self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE)
def readblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
buf[i] = self.data[addr + i]
def writeblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
self.data[addr + i] = buf[i]
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
def test(bdev, vfs_class):
print('test', vfs_class)
# mkfs
vfs_class.mkfs(bdev)
# construction
vfs = vfs_class(bdev)
# create text, print, write, close
f = vfs.open('test.txt', 'wt')
print(f)
f.write('littlefs')
f.close()
# close already-closed file
f.close()
# create binary, print, write, flush, close
f = vfs.open('test.bin', 'wb')
print(f)
f.write('littlefs')
f.flush()
f.close()
# create for append
f = vfs.open('test.bin', 'ab')
f.write('more')
f.close()
# create exclusive
f = vfs.open('test2.bin', 'xb')
f.close()
# create exclusive with error
try:
vfs.open('test2.bin', 'x')
except OSError:
print('open OSError')
# read default
with vfs.open('test.txt', '') as f:
print(f.read())
# read text
with vfs.open('test.txt', 'rt') as f:
print(f.read())
# read binary
with vfs.open('test.bin', 'rb') as f:
print(f.read())
# create read and write
with vfs.open('test.bin', 'r+b') as f:
print(f.read(8))
f.write('MORE')
with vfs.open('test.bin', 'rb') as f:
print(f.read())
# seek and tell
f = vfs.open('test.txt', 'r')
print(f.tell())
f.seek(3, 0)
print(f.tell())
f.close()
# open nonexistent
try:
vfs.open('noexist', 'r')
except OSError:
print('open OSError')
# open multiple files at the same time
f1 = vfs.open('test.txt', '')
f2 = vfs.open('test.bin', 'b')
print(f1.read())
print(f2.read())
f1.close()
f2.close()
bdev = RAMBlockDevice(30)
test(bdev, uos.VfsLfs1)
test(bdev, uos.VfsLfs2)

View File

@ -0,0 +1,28 @@
test <class 'VfsLfs1'>
<io.TextIOWrapper>
<io.FileIO>
open OSError
littlefs
littlefs
b'littlefsmore'
b'littlefs'
b'littlefsMORE'
0
3
open OSError
littlefs
b'littlefsMORE'
test <class 'VfsLfs2'>
<io.TextIOWrapper>
<io.FileIO>
open OSError
littlefs
littlefs
b'littlefsmore'
b'littlefs'
b'littlefsMORE'
0
3
open OSError
littlefs
b'littlefsMORE'

View File

@ -0,0 +1,73 @@
# Test for VfsLittle using a RAM device, with mount/umount
try:
import uos
uos.VfsLfs1
uos.VfsLfs2
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
class RAMBlockDevice:
ERASE_BLOCK_SIZE = 1024
def __init__(self, blocks):
self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE)
def readblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
buf[i] = self.data[addr + i]
def writeblocks(self, block, buf, off):
addr = block * self.ERASE_BLOCK_SIZE + off
for i in range(len(buf)):
self.data[addr + i] = buf[i]
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
def test(bdev, vfs_class):
print('test', vfs_class)
# mkfs
vfs_class.mkfs(bdev)
# construction
vfs = vfs_class(bdev)
# mount
uos.mount(vfs, '/lfs')
# import
with open('/lfs/lfsmod.py', 'w') as f:
f.write('print("hello from lfs")\n')
import lfsmod
# import package
uos.mkdir('/lfs/lfspkg')
with open('/lfs/lfspkg/__init__.py', 'w') as f:
f.write('print("package")\n')
import lfspkg
# umount
uos.umount('/lfs')
# clear imported modules
sys.modules.clear()
bdev = RAMBlockDevice(30)
# initialise path
import sys
sys.path.clear()
sys.path.append('/lfs')
# run tests
test(bdev, uos.VfsLfs1)
test(bdev, uos.VfsLfs2)

View File

@ -0,0 +1,6 @@
test <class 'VfsLfs1'>
hello from lfs
package
test <class 'VfsLfs2'>
hello from lfs
package