mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +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_file_t file; | ||||||
|     __attribute__((unused)) lfs_dir_t dir; |     __attribute__((unused)) lfs_dir_t dir; | ||||||
|     __attribute__((unused)) struct lfs_info info; |     __attribute__((unused)) struct lfs_info info; | ||||||
|     __attribute__((unused)) uint8_t buffer[1024]; |  | ||||||
|     __attribute__((unused)) char path[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 = { |     __attribute__((unused)) const struct lfs_config cfg = { | ||||||
|         .context = LFS_DISK ? (void*)&filebd : (void*)&rambd, |         .context = LFS_DISK ? (void*)&filebd : (void*)&rambd, | ||||||
| @@ -124,9 +126,11 @@ class TestCase: | |||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         if hasattr(self, 'permno'): |         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: |         else: | ||||||
|             return '%s[%d]' % (self.suite.name, self.caseno) |             return '%s[%d]' % ( | ||||||
|  |                 self.suite.name, self.caseno) | ||||||
|  |  | ||||||
|     def permute(self, defines, permno=None, **_): |     def permute(self, defines, permno=None, **_): | ||||||
|         ncase = copy.copy(self) |         ncase = copy.copy(self) | ||||||
| @@ -211,7 +215,10 @@ class TestCase: | |||||||
|             if args.get('verbose', False): |             if args.get('verbose', False): | ||||||
|                 sys.stdout.write(line) |                 sys.stdout.write(line) | ||||||
|             # intercept asserts |             # 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: |             if m and assert_ is None: | ||||||
|                 try: |                 try: | ||||||
|                     with open(m.group(1)) as f: |                     with open(m.group(1)) as f: | ||||||
| @@ -221,7 +228,7 @@ class TestCase: | |||||||
|                         'path': m.group(1), |                         'path': m.group(1), | ||||||
|                         'line': line, |                         'line': line, | ||||||
|                         'lineno': lineno, |                         'lineno': lineno, | ||||||
|                         'message': m.group(4)} |                         'message': m.group(3)} | ||||||
|                 except: |                 except: | ||||||
|                     pass |                     pass | ||||||
|         proc.wait() |         proc.wait() | ||||||
| @@ -385,7 +392,7 @@ class TestSuite: | |||||||
|  |  | ||||||
|         self.defines = {} |         self.defines = {} | ||||||
|         for k, v in self.perms[0].defines.items(): |         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 |                 self.defines[k] = v | ||||||
|  |  | ||||||
|         return self.perms |         return self.perms | ||||||
| @@ -401,7 +408,7 @@ class TestSuite: | |||||||
|  |  | ||||||
|         f.write('\n') |         f.write('\n') | ||||||
|         f.write('int main(int argc, char **argv) {\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*' '+'int perm = (argc >= 3) ? atoi(argv[2]) : 0;\n') | ||||||
|         f.write(4*' '+'LFS_DISK = (argc >= 4) ? argv[3] : NULL;\n') |         f.write(4*' '+'LFS_DISK = (argc >= 4) ? argv[3] : NULL;\n') | ||||||
|         for perm in self.perms: |         for perm in self.perms: | ||||||
| @@ -544,6 +551,23 @@ def main(**args): | |||||||
|         stdout.append(line) |         stdout.append(line) | ||||||
|         if args.get('verbose', False): |         if args.get('verbose', False): | ||||||
|             sys.stdout.write(line) |             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() |     proc.wait() | ||||||
|  |  | ||||||
|     if proc.returncode != 0: |     if proc.returncode != 0: | ||||||
| @@ -587,12 +611,20 @@ def main(**args): | |||||||
|             if perm.result == PASS: |             if perm.result == PASS: | ||||||
|                 passed += 1 |                 passed += 1 | ||||||
|             else: |             else: | ||||||
|                 sys.stdout.write("--- %s ---\n" % perm) |                 #sys.stdout.write("--- %s ---\n" % perm) | ||||||
|                 if perm.result.assert_: |  | ||||||
|                     for line in perm.result.stdout[:-1]: |  | ||||||
|                         sys.stdout.write(line) |  | ||||||
|                 sys.stdout.write( |                 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( |                         "{message}\n{line}\n".format( | ||||||
|                             **perm.result.assert_)) |                             **perm.result.assert_)) | ||||||
|                 else: |                 else: | ||||||
|   | |||||||
| @@ -1,54 +1,179 @@ | |||||||
| [[case]] # format | [[case]] # root | ||||||
| code = """ | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |  | ||||||
| """ |  | ||||||
|  |  | ||||||
| [[case]] # mount/unmount |  | ||||||
| code = """ |  | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&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; |     lfs_unmount(&lfs) => 0; | ||||||
| """ | ''' | ||||||
|  |  | ||||||
| [[case]] # reentrant format | [[case]] # many directory creation | ||||||
| code = """ | code = ''' | ||||||
|     int err = lfs_mount(&lfs, &cfg); |     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) { |     if (err) { | ||||||
|         lfs_format(&lfs, &cfg) => 0; |         lfs_format(&lfs, &cfg) => 0; | ||||||
|         lfs_mount(&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++) { |     for (int i = 0; i < N; i++) { | ||||||
|         sprintf(path, "dir%03d", i); |         sprintf(path, "hi%03d", i); | ||||||
|         lfs_mkdir(&lfs, path) => 0; |         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_open(&lfs, &dir, "/") => 0; | ||||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|     assert(info.type == LFS_TYPE_DIR); |     assert(info.type == LFS_TYPE_DIR); | ||||||
| @@ -57,29 +182,23 @@ code = """ | |||||||
|     assert(info.type == LFS_TYPE_DIR); |     assert(info.type == LFS_TYPE_DIR); | ||||||
|     assert(strcmp(info.name, "..") == 0); |     assert(strcmp(info.name, "..") == 0); | ||||||
|     for (int i = 0; i < N; i++) { |     for (int i = 0; i < N; i++) { | ||||||
|         sprintf(path, "dir%03d", i); |         sprintf(path, "hi%03d", i); | ||||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; |         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|         assert(info.type == LFS_TYPE_DIR); |         assert(info.type == LFS_TYPE_DIR); | ||||||
|         assert(strcmp(info.name, path) == 0); |         assert(strcmp(info.name, path) == 0); | ||||||
|     } |     } | ||||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|     lfs_dir_close(&lfs, &dir) => 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++) { |     for (int i = 0; i < N; i++) { | ||||||
|         sprintf(path, "removeme%03d", i); |         char oldpath[128]; | ||||||
|         lfs_mkdir(&lfs, path) => 0; |         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_open(&lfs, &dir, "/") => 0; | ||||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|     assert(info.type == LFS_TYPE_DIR); |     assert(info.type == LFS_TYPE_DIR); | ||||||
| @@ -88,23 +207,19 @@ code = """ | |||||||
|     assert(info.type == LFS_TYPE_DIR); |     assert(info.type == LFS_TYPE_DIR); | ||||||
|     assert(strcmp(info.name, "..") == 0); |     assert(strcmp(info.name, "..") == 0); | ||||||
|     for (int i = 0; i < N; i++) { |     for (int i = 0; i < N; i++) { | ||||||
|         sprintf(path, "removeme%03d", i); |         sprintf(path, "hello%03d", i); | ||||||
|         lfs_dir_read(&lfs, &dir, &info) => 1; |         lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|         assert(info.type == LFS_TYPE_DIR); |         assert(info.type == LFS_TYPE_DIR); | ||||||
|         assert(strcmp(info.name, path) == 0); |         assert(strcmp(info.name, path) == 0); | ||||||
|     } |     } | ||||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs); |  | ||||||
|  |  | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |  | ||||||
|     for (int i = 0; i < N; i++) { |     for (int i = 0; i < N; i++) { | ||||||
|         sprintf(path, "removeme%03d", i); |         sprintf(path, "hello%03d", i); | ||||||
|         lfs_remove(&lfs, path) => 0; |         lfs_remove(&lfs, path) => 0; | ||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs); |  | ||||||
|  |  | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |  | ||||||
|     lfs_dir_open(&lfs, &dir, "/") => 0; |     lfs_dir_open(&lfs, &dir, "/") => 0; | ||||||
|     lfs_dir_read(&lfs, &dir, &info) => 1; |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|     assert(info.type == LFS_TYPE_DIR); |     assert(info.type == LFS_TYPE_DIR); | ||||||
| @@ -115,17 +230,19 @@ code = """ | |||||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| """ | ''' | ||||||
| define.N = 'range(3, 100, 11)' | define.N = [5, 25] | ||||||
|  | reentrant = true | ||||||
|  |  | ||||||
| [[case]] # file creation | [[case]] # file creation | ||||||
| code = """ | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|     for (int i = 0; i < N; i++) { |     for (int i = 0; i < N; i++) { | ||||||
|         sprintf(path, "file%03d", 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_file_close(&lfs, &file) => 0; | ||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| @@ -147,17 +264,18 @@ code = """ | |||||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs); |     lfs_unmount(&lfs); | ||||||
| """ | ''' | ||||||
| define.N = 'range(3, 100, 11)' | define.N = 'range(3, 100, 11)' | ||||||
|  |  | ||||||
| [[case]] # file removal | [[case]] # file removal | ||||||
| code = """ | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|     for (int i = 0; i < N; i++) { |     for (int i = 0; i < N; i++) { | ||||||
|         sprintf(path, "removeme%03d", 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_file_close(&lfs, &file) => 0; | ||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| @@ -198,23 +316,401 @@ code = """ | |||||||
|     lfs_dir_read(&lfs, &dir, &info) => 0; |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| """ | ''' | ||||||
| define.N = 'range(0, 100, 3)' | define.N = 'range(0, 100, 3)' | ||||||
|  |  | ||||||
| [[case]] # error cases | [[case]] # file rename | ||||||
| code = """ | 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_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|     lfs_mkdir(&lfs, "potato") => 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_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|     lfs_mount(&lfs, &cfg) => 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, "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, "tomato") => LFS_ERR_NOENT; | ||||||
|     lfs_dir_open(&lfs, &dir, "burito") => LFS_ERR_NOTDIR; |     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, "tomato", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|     lfs_file_open(&lfs, &file, "potato", LFS_O_RDONLY) => LFS_ERR_ISDIR; |     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; |     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