diff options
| author | Damien George | 2020-07-29 01:01:48 +1000 |
|---|---|---|
| committer | Damien George | 2020-08-25 17:35:19 +1000 |
| commit | 2acc087880de39d7e17abc9344b8d2faba3478dd (patch) | |
| tree | e7a8e21a14bad32ef1b78b351c8d754962e18d1c /tests | |
| parent | ee50a6effebf315c38d4a129dc9f65ee722eb5b6 (diff) | |
extmod/vfs_lfs: Add mtime support to littlefs files.
This commit adds support for modification time of files on littlefs v2
filesystems, using file attributes. For some background see issue #6114.
Features/properties of this implementation:
- Only supported on littlefs2 (not littlefs1).
- Uses littlefs2's general file attributes to store the timestamp.
- The timestamp is 64-bits and stores nanoseconds since 1970/1/1 (if the
range to the year 2554 is not enough then additional bits can be added to
this timestamp by adding another file attribute).
- mtime is enabled by default but can be disabled in the constructor, eg:
uos.mount(uos.VfsLfs2(bdev, mtime=False), '/flash')
- It's fully backwards compatible, existing littlefs2 filesystems will work
without reformatting and timestamps will be added transparently to
existing files (once they are opened for writing).
- Files without timestamps will open correctly, and stat will just return 0
for their timestamp.
- mtime can be disabled or enabled each mount time and timestamps will only
be updated if mtime is enabled (otherwise they will be untouched).
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/extmod/vfs_lfs.py | 13 | ||||
| -rw-r--r-- | tests/extmod/vfs_lfs.py.exp | 16 | ||||
| -rw-r--r-- | tests/extmod/vfs_lfs_mtime.py | 98 | ||||
| -rw-r--r-- | tests/extmod/vfs_lfs_mtime.py.exp | 13 |
4 files changed, 128 insertions, 12 deletions
diff --git a/tests/extmod/vfs_lfs.py b/tests/extmod/vfs_lfs.py index 609d9f949..8e56400df 100644 --- a/tests/extmod/vfs_lfs.py +++ b/tests/extmod/vfs_lfs.py @@ -35,6 +35,11 @@ class RAMBlockDevice: return 0 +def print_stat(st, print_size=True): + # don't print times (just check that they have the correct type) + print(st[:6], st[6] if print_size else -1, type(st[7]), type(st[8]), type(st[9])) + + def test(bdev, vfs_class): print("test", vfs_class) @@ -69,10 +74,10 @@ def test(bdev, vfs_class): vfs.mkdir("testdir") # stat a file - print(vfs.stat("test")) + print_stat(vfs.stat("test")) # stat a dir (size seems to vary on LFS2 so don't print that) - print(vfs.stat("testdir")[:6]) + print_stat(vfs.stat("testdir"), False) # read with vfs.open("test", "r") as f: @@ -112,8 +117,8 @@ def test(bdev, vfs_class): # create file in directory to make sure paths are relative vfs.open("test2", "w").close() - print(vfs.stat("test2")) - print(vfs.stat("/testdir/test2")) + print_stat(vfs.stat("test2")) + print_stat(vfs.stat("/testdir/test2")) vfs.remove("test2") # chdir back to root and remove testdir diff --git a/tests/extmod/vfs_lfs.py.exp b/tests/extmod/vfs_lfs.py.exp index a70255774..a0450c84b 100644 --- a/tests/extmod/vfs_lfs.py.exp +++ b/tests/extmod/vfs_lfs.py.exp @@ -7,8 +7,8 @@ test <class 'VfsLfs1'> [('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) +(32768, 0, 0, 0, 0, 0) 8 <class 'int'> <class 'int'> <class 'int'> +(16384, 0, 0, 0, 0, 0) -1 <class 'int'> <class 'int'> <class 'int'> littlefs data length: 4096 write 0 @@ -22,8 +22,8 @@ write 3 [('test', 32768, 0, 8), ('testdir', 16384, 0, 0)] / /testdir -(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0) -(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0) +(32768, 0, 0, 0, 0, 0) 0 <class 'int'> <class 'int'> <class 'int'> +(32768, 0, 0, 0, 0, 0) 0 <class 'int'> <class 'int'> <class 'int'> / /testdir / @@ -44,8 +44,8 @@ test <class 'VfsLfs2'> [('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) +(32768, 0, 0, 0, 0, 0) 8 <class 'int'> <class 'int'> <class 'int'> +(16384, 0, 0, 0, 0, 0) -1 <class 'int'> <class 'int'> <class 'int'> littlefs data length: 4096 write 0 @@ -59,8 +59,8 @@ write 3 [('test', 32768, 0, 8), ('testdir', 16384, 0, 0)] / /testdir -(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0) -(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0) +(32768, 0, 0, 0, 0, 0) 0 <class 'int'> <class 'int'> <class 'int'> +(32768, 0, 0, 0, 0, 0) 0 <class 'int'> <class 'int'> <class 'int'> / /testdir / diff --git a/tests/extmod/vfs_lfs_mtime.py b/tests/extmod/vfs_lfs_mtime.py new file mode 100644 index 000000000..010807688 --- /dev/null +++ b/tests/extmod/vfs_lfs_mtime.py @@ -0,0 +1,98 @@ +# Test for VfsLfs using a RAM device, mtime feature + +try: + import utime, uos + + utime.sleep + 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) + + # Initial format of block device. + vfs_class.mkfs(bdev) + + # construction + print("mtime=True") + vfs = vfs_class(bdev, mtime=True) + + # Create an empty file, should have a timestamp. + vfs.open("test1", "wt").close() + + # Wait 1 second so mtime will increase by at least 1. + utime.sleep(1) + + # Create another empty file, should have a timestamp. + vfs.open("test2", "wt").close() + + # Stat the files and check that test1 is older than test2. + stat1 = vfs.stat("test1") + stat2 = vfs.stat("test2") + print(stat1[8] != 0, stat2[8] != 0) + print(stat1[8] < stat2[8]) + + # Wait 1 second so mtime will increase by at least 1. + utime.sleep(1) + + # Open test1 for reading and ensure mtime did not change. + vfs.open("test1", "rt").close() + print(vfs.stat("test1") == stat1) + + # Open test1 for writing and ensure mtime increased from the previous value. + vfs.open("test1", "wt").close() + stat1_old = stat1 + stat1 = vfs.stat("test1") + print(stat1_old[8] < stat1[8]) + + # Unmount. + vfs.umount() + + # Check that remounting with mtime=False can read the timestamps. + print("mtime=False") + vfs = vfs_class(bdev, mtime=False) + print(vfs.stat("test1") == stat1) + print(vfs.stat("test2") == stat2) + f = vfs.open("test1", "wt") + f.close() + print(vfs.stat("test1") == stat1) + vfs.umount() + + # Check that remounting with mtime=True still has the timestamps. + print("mtime=True") + vfs = vfs_class(bdev, mtime=True) + print(vfs.stat("test1") == stat1) + print(vfs.stat("test2") == stat2) + vfs.umount() + + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_mtime.py.exp b/tests/extmod/vfs_lfs_mtime.py.exp new file mode 100644 index 000000000..2e3d7491b --- /dev/null +++ b/tests/extmod/vfs_lfs_mtime.py.exp @@ -0,0 +1,13 @@ +test <class 'VfsLfs2'> +mtime=True +True True +True +True +True +mtime=False +True +True +True +mtime=True +True +True |
