mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 00:32:38 +01:00 
			
		
		
		
	Migrated test_files, test_dirs, test_format suites to new framework
Also some tweaks to test_.py to capture Makefile warnings and print test locations a bit better.
This commit is contained in:
		| @@ -62,8 +62,10 @@ PROLOGUE = """ | ||||
|     __attribute__((unused)) lfs_file_t file; | ||||
|     __attribute__((unused)) lfs_dir_t dir; | ||||
|     __attribute__((unused)) struct lfs_info info; | ||||
|     __attribute__((unused)) uint8_t buffer[1024]; | ||||
|     __attribute__((unused)) char path[1024]; | ||||
|     __attribute__((unused)) uint8_t buffer[1024]; | ||||
|     __attribute__((unused)) lfs_size_t size; | ||||
|     __attribute__((unused)) int err; | ||||
|      | ||||
|     __attribute__((unused)) const struct lfs_config cfg = { | ||||
|         .context = LFS_DISK ? (void*)&filebd : (void*)&rambd, | ||||
| @@ -124,9 +126,11 @@ class TestCase: | ||||
|  | ||||
|     def __str__(self): | ||||
|         if hasattr(self, 'permno'): | ||||
|             return '%s[%d,%d]' % (self.suite.name, self.caseno, self.permno) | ||||
|             return '%s[%d,%d]' % ( | ||||
|                 self.suite.name, self.caseno, self.permno) | ||||
|         else: | ||||
|             return '%s[%d]' % (self.suite.name, self.caseno) | ||||
|             return '%s[%d]' % ( | ||||
|                 self.suite.name, self.caseno) | ||||
|  | ||||
|     def permute(self, defines, permno=None, **_): | ||||
|         ncase = copy.copy(self) | ||||
| @@ -211,7 +215,10 @@ class TestCase: | ||||
|             if args.get('verbose', False): | ||||
|                 sys.stdout.write(line) | ||||
|             # intercept asserts | ||||
|             m = re.match('^([^:]+):([0-9]+):(assert): (.*)$', line) | ||||
|             m = re.match( | ||||
|                 '^{0}([^:]+):(\d+):(?:\d+:)?{0}{1}:{0}(.*)$' | ||||
|                 .format('(?:\033\[[\d;]*.| )*', 'assert'), | ||||
|                 line) | ||||
|             if m and assert_ is None: | ||||
|                 try: | ||||
|                     with open(m.group(1)) as f: | ||||
| @@ -221,7 +228,7 @@ class TestCase: | ||||
|                         'path': m.group(1), | ||||
|                         'line': line, | ||||
|                         'lineno': lineno, | ||||
|                         'message': m.group(4)} | ||||
|                         'message': m.group(3)} | ||||
|                 except: | ||||
|                     pass | ||||
|         proc.wait() | ||||
| @@ -385,7 +392,7 @@ class TestSuite: | ||||
|  | ||||
|         self.defines = {} | ||||
|         for k, v in self.perms[0].defines.items(): | ||||
|             if all(perm.defines[k] == v for perm in self.perms): | ||||
|             if all(perm.defines.get(k, None) == v for perm in self.perms): | ||||
|                 self.defines[k] = v | ||||
|  | ||||
|         return self.perms | ||||
| @@ -401,7 +408,7 @@ class TestSuite: | ||||
|  | ||||
|         f.write('\n') | ||||
|         f.write('int main(int argc, char **argv) {\n') | ||||
|         f.write(4*' '+'int case_ = (argc >= 3) ? atoi(argv[1]) : 0;\n') | ||||
|         f.write(4*' '+'int case_ = (argc >= 2) ? atoi(argv[1]) : 0;\n') | ||||
|         f.write(4*' '+'int perm = (argc >= 3) ? atoi(argv[2]) : 0;\n') | ||||
|         f.write(4*' '+'LFS_DISK = (argc >= 4) ? argv[3] : NULL;\n') | ||||
|         for perm in self.perms: | ||||
| @@ -544,6 +551,23 @@ def main(**args): | ||||
|         stdout.append(line) | ||||
|         if args.get('verbose', False): | ||||
|             sys.stdout.write(line) | ||||
|         # intercept warnings | ||||
|         m = re.match( | ||||
|             '^{0}([^:]+):(\d+):(?:\d+:)?{0}{1}:{0}(.*)$' | ||||
|             .format('(?:\033\[[\d;]*.| )*', 'warning'), | ||||
|             line) | ||||
|         if m and not args.get('verbose', False): | ||||
|             try: | ||||
|                 with open(m.group(1)) as f: | ||||
|                     lineno = int(m.group(2)) | ||||
|                     line = next(it.islice(f, lineno-1, None)).strip('\n') | ||||
|                 sys.stdout.write( | ||||
|                     "\033[01m{path}:{lineno}:\033[01;35mwarning:\033[m " | ||||
|                     "{message}\n{line}\n\n".format( | ||||
|                         path=m.group(1), line=line, lineno=lineno, | ||||
|                         message=m.group(3))) | ||||
|             except: | ||||
|                 pass | ||||
|     proc.wait() | ||||
|  | ||||
|     if proc.returncode != 0: | ||||
| @@ -587,12 +611,20 @@ def main(**args): | ||||
|             if perm.result == PASS: | ||||
|                 passed += 1 | ||||
|             else: | ||||
|                 sys.stdout.write("--- %s ---\n" % perm) | ||||
|                 if perm.result.assert_: | ||||
|                     for line in perm.result.stdout[:-1]: | ||||
|                         sys.stdout.write(line) | ||||
|                 #sys.stdout.write("--- %s ---\n" % perm) | ||||
|                 sys.stdout.write( | ||||
|                         "\033[97m{path}:{lineno}:\033[91massert:\033[0m " | ||||
|                     "\033[01m{path}:{lineno}:\033[01;31mfailure:\033[m " | ||||
|                     "{perm} failed with {returncode}\n".format( | ||||
|                         perm=perm, path=perm.suite.path, lineno=perm.lineno-2, | ||||
|                         returncode=perm.result.returncode or 0)) | ||||
|                 if perm.result.stdout: | ||||
|                     for line in (perm.result.stdout | ||||
|                             if not perm.result.assert_ | ||||
|                             else perm.result.stdout[:-1]): | ||||
|                         sys.stdout.write(line) | ||||
|                 if perm.result.assert_: | ||||
|                     sys.stdout.write( | ||||
|                         "\033[01m{path}:{lineno}:\033[01;31massert:\033[m " | ||||
|                         "{message}\n{line}\n".format( | ||||
|                             **perm.result.assert_)) | ||||
|                 else: | ||||
|   | ||||
| @@ -1,54 +1,179 @@ | ||||
| [[case]] # format | ||||
| code = """ | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
| """ | ||||
|  | ||||
| [[case]] # mount/unmount | ||||
| code = """ | ||||
| [[case]] # root | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| """ | ||||
| ''' | ||||
|  | ||||
| [[case]] # reentrant format | ||||
| code = """ | ||||
|     int err = lfs_mount(&lfs, &cfg); | ||||
| [[case]] # many directory creation | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "dir%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "dir%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.N = 'range(0, 100, 3)' | ||||
|  | ||||
| [[case]] # many directory removal | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_remove(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.N = 'range(3, 100, 11)' | ||||
|  | ||||
| [[case]] # many directory rename | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "test%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "test%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         char oldpath[128]; | ||||
|         char newpath[128]; | ||||
|         sprintf(oldpath, "test%03d", i); | ||||
|         sprintf(newpath, "tedd%03d", i); | ||||
|         lfs_rename(&lfs, oldpath, newpath) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "tedd%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
| ''' | ||||
| define.N = 'range(3, 100, 11)' | ||||
|  | ||||
| [[case]] # reentrant many directory creation/rename/removal | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| """ | ||||
| reentrant = true | ||||
|  | ||||
| [[case]] # root | ||||
| code = """ | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| """ | ||||
|  | ||||
| [[case]] # directory creation | ||||
| code = """ | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "dir%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|         sprintf(path, "hi%03d", i); | ||||
|         err = lfs_mkdir(&lfs, path); | ||||
|         assert(err == 0 || err == LFS_ERR_EXIST); | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "hello%03d", i); | ||||
|         err = lfs_remove(&lfs, path); | ||||
|         assert(err == 0 || err == LFS_ERR_NOENT); | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -57,29 +182,23 @@ code = """ | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "dir%03d", i); | ||||
|         sprintf(path, "hi%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| """ | ||||
| define.N = 'range(0, 100, 3)' | ||||
|  | ||||
| [[case]] # directory removal | ||||
| code = """ | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|         char oldpath[128]; | ||||
|         char newpath[128]; | ||||
|         sprintf(oldpath, "hi%03d", i); | ||||
|         sprintf(newpath, "hello%03d", i); | ||||
|         // YES this can overwrite an existing newpath | ||||
|         lfs_rename(&lfs, oldpath, newpath) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -88,23 +207,19 @@ code = """ | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         sprintf(path, "hello%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         sprintf(path, "hello%03d", i); | ||||
|         lfs_remove(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
| @@ -115,17 +230,19 @@ code = """ | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| """ | ||||
| define.N = 'range(3, 100, 11)' | ||||
| ''' | ||||
| define.N = [5, 25] | ||||
| reentrant = true | ||||
|  | ||||
| [[case]] # file creation | ||||
| code = """ | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "file%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| @@ -147,17 +264,18 @@ code = """ | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
| """ | ||||
| ''' | ||||
| define.N = 'range(3, 100, 11)' | ||||
|  | ||||
| [[case]] # file removal | ||||
| code = """ | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "removeme%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| @@ -198,23 +316,401 @@ code = """ | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| """ | ||||
| ''' | ||||
| define.N = 'range(0, 100, 3)' | ||||
|  | ||||
| [[case]] # error cases | ||||
| code = """ | ||||
| [[case]] # file rename | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "test%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "test%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_REG); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         char oldpath[128]; | ||||
|         char newpath[128]; | ||||
|         sprintf(oldpath, "test%03d", i); | ||||
|         sprintf(newpath, "tedd%03d", i); | ||||
|         lfs_rename(&lfs, oldpath, newpath) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "tedd%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_REG); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
| ''' | ||||
| define.N = 'range(0, 100, 3)' | ||||
|  | ||||
| [[case]] # reentrant file creation/rename/removal | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "hi%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "hello%03d", i); | ||||
|         err = lfs_remove(&lfs, path); | ||||
|         assert(err == 0 || err == LFS_ERR_NOENT); | ||||
|     } | ||||
|  | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "hi%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_REG); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         char oldpath[128]; | ||||
|         char newpath[128]; | ||||
|         sprintf(oldpath, "hi%03d", i); | ||||
|         sprintf(newpath, "hello%03d", i); | ||||
|         // YES this can overwrite an existing newpath | ||||
|         lfs_rename(&lfs, oldpath, newpath) => 0; | ||||
|     } | ||||
|  | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "hello%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_REG); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "hello%03d", i); | ||||
|         lfs_remove(&lfs, path) => 0; | ||||
|     } | ||||
|  | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.N = [5, 25] | ||||
| reentrant = true | ||||
|  | ||||
| [[case]] # nested directories | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "potato") => 0; | ||||
|     lfs_file_open(&lfs, &file, "burito", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|     lfs_file_open(&lfs, &file, "burito", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "potato/baked") => 0; | ||||
|     lfs_mkdir(&lfs, "potato/sweet") => 0; | ||||
|     lfs_mkdir(&lfs, "potato/fried") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "potato") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "baked") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "fried") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "sweet") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // try removing? | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "potato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // try renaming? | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "potato", "coldpotato") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_rename(&lfs, "coldpotato", "warmpotato") => 0; | ||||
|     lfs_rename(&lfs, "warmpotato", "hotpotato") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "potato") => LFS_ERR_NOENT; | ||||
|     lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT; | ||||
|     lfs_remove(&lfs, "warmpotato") => LFS_ERR_NOENT; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // try cross-directory renaming | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "coldpotato") => 0; | ||||
|     lfs_rename(&lfs, "hotpotato/baked", "coldpotato/baked") => 0; | ||||
|     lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_rename(&lfs, "hotpotato/fried", "coldpotato/fried") => 0; | ||||
|     lfs_rename(&lfs, "coldpotato", "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_rename(&lfs, "hotpotato/sweet", "coldpotato/sweet") => 0; | ||||
|     lfs_rename(&lfs, "coldpotato", "hotpotato") => 0; | ||||
|     lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOENT; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "hotpotato") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "baked") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "fried") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "sweet") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|      | ||||
|     // final remove | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "hotpotato/baked") => 0; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "hotpotato/fried") => 0; | ||||
|     lfs_remove(&lfs, "hotpotato") => LFS_ERR_NOTEMPTY; | ||||
|     lfs_remove(&lfs, "hotpotato/sweet") => 0; | ||||
|     lfs_remove(&lfs, "hotpotato") => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     info.type => LFS_TYPE_DIR; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(strcmp(info.name, "burito") == 0); | ||||
|     info.type => LFS_TYPE_REG; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # recursive remove | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "prickly-pear") => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "prickly-pear/cactus%03d", i); | ||||
|         lfs_mkdir(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_dir_open(&lfs, &dir, "prickly-pear") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "cactus%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs); | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY; | ||||
|  | ||||
|     lfs_dir_open(&lfs, &dir, "prickly-pear") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "cactus%03d", i); | ||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|         assert(info.type == LFS_TYPE_DIR); | ||||
|         assert(strcmp(info.name, path) == 0); | ||||
|         sprintf(path, "prickly-pear/%s", info.name); | ||||
|         lfs_remove(&lfs, path) => 0; | ||||
|     } | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|  | ||||
|     lfs_remove(&lfs, "prickly-pear") => 0; | ||||
|     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.N = [10, 100] | ||||
|  | ||||
| [[case]] # other error cases | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "potato") => 0; | ||||
|     lfs_file_open(&lfs, &file, "burito", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|  | ||||
|     lfs_mkdir(&lfs, "potato") => LFS_ERR_EXIST; | ||||
|     lfs_mkdir(&lfs, "burito") => LFS_ERR_EXIST; | ||||
|     lfs_file_open(&lfs, &file, "burito", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; | ||||
|     lfs_file_open(&lfs, &file, "potato", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; | ||||
|     lfs_dir_open(&lfs, &dir, "tomato") => LFS_ERR_NOENT; | ||||
|     lfs_dir_open(&lfs, &dir, "burito") => LFS_ERR_NOTDIR; | ||||
|     lfs_file_open(&lfs, &file, "tomato", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||
|     lfs_file_open(&lfs, &file, "potato", LFS_O_RDONLY) => LFS_ERR_ISDIR; | ||||
|     lfs_file_open(&lfs, &file, "tomato", LFS_O_WRONLY) => LFS_ERR_NOENT; | ||||
|     lfs_file_open(&lfs, &file, "potato", LFS_O_WRONLY) => LFS_ERR_ISDIR; | ||||
|     lfs_file_open(&lfs, &file, "potato", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; | ||||
|  | ||||
|     lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; | ||||
|     lfs_file_open(&lfs, &file, "/", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; | ||||
|     lfs_file_open(&lfs, &file, "/", LFS_O_RDONLY) => LFS_ERR_ISDIR; | ||||
|     lfs_file_open(&lfs, &file, "/", LFS_O_WRONLY) => LFS_ERR_ISDIR; | ||||
|     lfs_file_open(&lfs, &file, "/", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; | ||||
|  | ||||
|     // check that errors did not corrupt directory | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_REG); | ||||
|     assert(strcmp(info.name, "burito") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "potato") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| """ | ||||
|  | ||||
|     // or on disk | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, ".") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "..") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_REG); | ||||
|     assert(strcmp(info.name, "burito") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||
|     assert(info.type == LFS_TYPE_DIR); | ||||
|     assert(strcmp(info.name, "potato") == 0); | ||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||
|     lfs_dir_close(&lfs, &dir) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|   | ||||
							
								
								
									
										486
									
								
								tests_/test_files.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								tests_/test_files.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,486 @@ | ||||
|  | ||||
| [[case]] # simple file test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     size = strlen("Hello World!")+1; | ||||
|     strcpy((char*)buffer, "Hello World!"); | ||||
|     lfs_file_write(&lfs, &file, buffer, size) => size; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_read(&lfs, &file, buffer, size) => size; | ||||
|     assert(strcmp((char*)buffer, "Hello World!") == 0); | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # larger files | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.SIZE = [32, 8192, 262144, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 33, 1, 1023] | ||||
|  | ||||
| [[case]] # rewriting files | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // rewrite | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY) => 0; | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => lfs_max(SIZE1, SIZE2); | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     if (SIZE1 > SIZE2) { | ||||
|         srand(1); | ||||
|         for (lfs_size_t b = 0; b < SIZE2; b++) { | ||||
|             rand(); | ||||
|         } | ||||
|         for (lfs_size_t i = SIZE2; i < SIZE1; i += CHUNKSIZE) { | ||||
|             lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|             lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|             for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|                 assert(buffer[b] == (rand() & 0xff)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 1, 1025] | ||||
|  | ||||
| [[case]] # appending files | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // append | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_APPEND) => 0; | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1 + SIZE2; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 1, 1025] | ||||
|  | ||||
| [[case]] # truncating files | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|  | ||||
|     // write | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE1; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // truncate | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_TRUNC) => 0; | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE2; | ||||
|     srand(2); | ||||
|     for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||
| define.CHUNKSIZE = [31, 16, 1, 1025] | ||||
|  | ||||
| [[case]] # reentrant file writing | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); | ||||
|     assert(err == LFS_ERR_NOENT || err == 0); | ||||
|     if (err == 0) { | ||||
|         // can only be 0 (new file) or full size | ||||
|         size = lfs_file_size(&lfs, &file); | ||||
|         assert(size == 0 || size == SIZE); | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|  | ||||
|     // write | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.SIZE = [32, 0, 7, 2049] | ||||
| define.CHUNKSIZE = [31, 16, 65] | ||||
| reentrant = true | ||||
|  | ||||
| [[case]] # reentrant file writing with syncs | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); | ||||
|     assert(err == LFS_ERR_NOENT || err == 0); | ||||
|     if (err == 0) { | ||||
|         // with syncs we could be any size, but it at least must be valid data | ||||
|         size = lfs_file_size(&lfs, &file); | ||||
|         assert(size <= SIZE); | ||||
|         srand(1); | ||||
|         for (lfs_size_t i = 0; i < size; i += CHUNKSIZE) { | ||||
|             lfs_size_t chunk = lfs_min(CHUNKSIZE, size-i); | ||||
|             lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|             for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|                 assert(buffer[b] == (rand() & 0xff)); | ||||
|             } | ||||
|         } | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|  | ||||
|     // write | ||||
|     lfs_file_open(&lfs, &file, "avacado", | ||||
|         LFS_O_WRONLY | LFS_O_CREAT | MODE) => 0; | ||||
|     size = lfs_file_size(&lfs, &file); | ||||
|     assert(size <= SIZE); | ||||
|     srand(1); | ||||
|     lfs_size_t skip = (MODE == LFS_O_APPEND) ? size : 0; | ||||
|     for (lfs_size_t b = 0; b < skip; b++) { | ||||
|         rand(); | ||||
|     } | ||||
|     for (lfs_size_t i = skip; i < SIZE; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             buffer[b] = rand() & 0xff; | ||||
|         } | ||||
|         lfs_file_write(&lfs, &file, buffer, chunk) => chunk; | ||||
|         lfs_file_sync(&lfs, &file) => 0; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|  | ||||
|     // read | ||||
|     lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; | ||||
|     lfs_file_size(&lfs, &file) => SIZE; | ||||
|     srand(1); | ||||
|     for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { | ||||
|         lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); | ||||
|         lfs_file_read(&lfs, &file, buffer, chunk) => chunk; | ||||
|         for (lfs_size_t b = 0; b < chunk; b++) { | ||||
|             assert(buffer[b] == (rand() & 0xff)); | ||||
|         } | ||||
|     } | ||||
|     lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define = [ | ||||
|     # append (O(n)) | ||||
|     {MODE='LFS_O_APPEND',   SIZE=[32, 0, 7, 2049],  CHUNKSIZE=[31, 16, 65]}, | ||||
|     # truncate (O(n^2)) | ||||
|     {MODE='LFS_O_TRUNC',    SIZE=[32, 0, 7, 200],   CHUNKSIZE=[31, 16, 65]}, | ||||
|     # rewrite (O(n^2)) | ||||
|     {MODE=0,                SIZE=[32, 0, 7, 200],   CHUNKSIZE=[31, 16, 65]}, | ||||
| ] | ||||
| reentrant = true | ||||
|  | ||||
| [[case]] # many files | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     // create N files of 7 bytes | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "file_%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|         char wbuffer[1024]; | ||||
|         size = 7; | ||||
|         snprintf(wbuffer, size, "Hi %03d", i); | ||||
|         lfs_file_write(&lfs, &file, wbuffer, size) => size; | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|  | ||||
|         char rbuffer[1024]; | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
|         lfs_file_read(&lfs, &file, rbuffer, size) => size; | ||||
|         assert(strcmp(rbuffer, wbuffer) == 0); | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.N = 300 | ||||
|  | ||||
| [[case]] # many files with power cycle | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     // create N files of 7 bytes | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "file_%03d", i); | ||||
|         lfs_file_open(&lfs, &file, path, | ||||
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; | ||||
|         char wbuffer[1024]; | ||||
|         size = 7; | ||||
|         snprintf(wbuffer, size, "Hi %03d", i); | ||||
|         lfs_file_write(&lfs, &file, wbuffer, size) => size; | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|         char rbuffer[1024]; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
|         lfs_file_read(&lfs, &file, rbuffer, size) => size; | ||||
|         assert(strcmp(rbuffer, wbuffer) == 0); | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.N = 300 | ||||
|  | ||||
| [[case]] # many files with power loss | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     // create N files of 7 bytes | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sprintf(path, "file_%03d", i); | ||||
|         err = lfs_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT); | ||||
|         char wbuffer[1024]; | ||||
|         size = 7; | ||||
|         snprintf(wbuffer, size, "Hi %03d", i); | ||||
|         if ((lfs_size_t)lfs_file_size(&lfs, &file) != size) { | ||||
|             lfs_file_write(&lfs, &file, wbuffer, size) => size; | ||||
|         } | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|  | ||||
|         char rbuffer[1024]; | ||||
|         lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; | ||||
|         lfs_file_read(&lfs, &file, rbuffer, size) => size; | ||||
|         assert(strcmp(rbuffer, wbuffer) == 0); | ||||
|         lfs_file_close(&lfs, &file) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.N = 300 | ||||
| reentrant = true | ||||
							
								
								
									
										105
									
								
								tests_/test_format.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								tests_/test_format.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| [[case]] # simple formatting test | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # mount/unmount | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # reentrant format | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| reentrant = true | ||||
|  | ||||
| [[case]] # invalid mount | ||||
| code = ''' | ||||
|     lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; | ||||
| ''' | ||||
|  | ||||
| # TODO invalid superblock? (corrupt 1, 0) | ||||
|  | ||||
| [[case]] # expanding superblock | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         lfs_mkdir(&lfs, "dummy") => 0; | ||||
|         lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|         assert(strcmp(info.name, "dummy") == 0); | ||||
|         lfs_remove(&lfs, "dummy") => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // one last check after power-cycle | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_mkdir(&lfs, "dummy") => 0; | ||||
|     lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|     assert(strcmp(info.name, "dummy") == 0); | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.BLOCK_CYCLES = [32, 33, 1] | ||||
| define.N = [10, 100, 1000] | ||||
|  | ||||
| [[case]] # expanding superblock with power cycle | ||||
| code = ''' | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|         // remove lingering dummy? | ||||
|         err = lfs_remove(&lfs, "dummy"); | ||||
|         assert(err == 0 || (err == LFS_ERR_NOENT && i == 0)); | ||||
|          | ||||
|         lfs_mkdir(&lfs, "dummy") => 0; | ||||
|         lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|         assert(strcmp(info.name, "dummy") == 0); | ||||
|         lfs_unmount(&lfs) => 0; | ||||
|     } | ||||
|  | ||||
|     // one last check after power-cycle | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|     assert(strcmp(info.name, "dummy") == 0); | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.BLOCK_CYCLES = [32, 33, 1] | ||||
| define.N = [10, 100, 1000] | ||||
|  | ||||
| [[case]] # reentrant expanding superblock | ||||
| code = ''' | ||||
|     err = lfs_mount(&lfs, &cfg); | ||||
|     if (err) { | ||||
|         lfs_format(&lfs, &cfg) => 0; | ||||
|         lfs_mount(&lfs, &cfg) => 0; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         // remove lingering dummy? | ||||
|         err = lfs_remove(&lfs, "dummy"); | ||||
|         assert(err == 0 || (err == LFS_ERR_NOENT && i == 0)); | ||||
|          | ||||
|         lfs_mkdir(&lfs, "dummy") => 0; | ||||
|         lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|         assert(strcmp(info.name, "dummy") == 0); | ||||
|     } | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // one last check after power-cycle | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_stat(&lfs, "dummy", &info) => 0; | ||||
|     assert(strcmp(info.name, "dummy") == 0); | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
| define.BLOCK_CYCLES = [2, 1] | ||||
| define.N = 24 | ||||
| reentrant = true | ||||
		Reference in New Issue
	
	Block a user