mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Migrated the first of the tests with internal knowledge
Both test_move and test_orphan needed internal knowledge which comes with the addition of the "in" attribute. This was in the plan for the test-revamp from the beginning as it really opens up the ability to write more unit-style-tests using internal knowledge of how littlefs works. More unit-style-tests should help _fix_ bugs by limiting the scope of the test and where the bug could be hiding. The "in" attribute effectively runs tests _inside_ the .c file specified, giving the test access to all static members without needed to change their visibility.
This commit is contained in:
		
							
								
								
									
										200
									
								
								scripts/test_.py
									
									
									
									
									
								
							
							
						
						
									
										200
									
								
								scripts/test_.py
									
									
									
									
									
								
							| @@ -5,18 +5,20 @@ | |||||||
| # | # | ||||||
|  |  | ||||||
| # TODO | # TODO | ||||||
| # - nargs > 1? | # x nargs > 1? | ||||||
| # x show perm config on failure | # x show perm config on failure | ||||||
| # x filtering | # x filtering | ||||||
| # n show perm config on verbose? | # n show perm config on verbose? | ||||||
| # - better lineno tracking for cases? | # x better lineno tracking for cases? | ||||||
| # n non-int perms? | # n non-int perms? | ||||||
| # - different path format? | # x different path format? | ||||||
| # - suite.prologue, suite.epilogue | # - suite.prologue, suite.epilogue | ||||||
| # - in | # x in | ||||||
| # x change BLOCK_CYCLES to -1 by default | # x change BLOCK_CYCLES to -1 by default | ||||||
| # x change persist behaviour | # x change persist behaviour | ||||||
| # x config chaining correct | # x config chaining correct | ||||||
|  | # - why can't gdb see my defines? | ||||||
|  | # - say no to internal? | ||||||
|  |  | ||||||
| import toml | import toml | ||||||
| import glob | import glob | ||||||
| @@ -34,17 +36,14 @@ import shlex | |||||||
| TESTDIR = 'tests_' | TESTDIR = 'tests_' | ||||||
| RULES = """ | RULES = """ | ||||||
| define FLATTEN | define FLATTEN | ||||||
| %$(subst /,.,$(target:.c=.tc)): $(target) | tests_/%$(subst /,.,$(target)): $(target) | ||||||
|     cat <(echo '#line 1 "$$<"') $$< > $$@ |     ./scripts/explode_asserts.py $$< -o $$@ | ||||||
| endef | endef | ||||||
| $(foreach target,$(SRC),$(eval $(FLATTEN))) | $(foreach target,$(SRC),$(eval $(FLATTEN))) | ||||||
|  |  | ||||||
| -include tests_/*.d | -include tests_/*.d | ||||||
|  |  | ||||||
| .SECONDARY: | .SECONDARY: | ||||||
| %.c: %.tc |  | ||||||
|     ./scripts/explode_asserts.py $< -o $@ |  | ||||||
|  |  | ||||||
| %.test: override CFLAGS += -fdiagnostics-color=always | %.test: override CFLAGS += -fdiagnostics-color=always | ||||||
| %.test: override CFLAGS += -ggdb | %.test: override CFLAGS += -ggdb | ||||||
| %.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f) | %.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f) | ||||||
| @@ -56,7 +55,6 @@ GLOBALS = """ | |||||||
| #include "filebd/lfs_filebd.h" | #include "filebd/lfs_filebd.h" | ||||||
| #include "rambd/lfs_rambd.h" | #include "rambd/lfs_rambd.h" | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| const char *LFS_DISK = NULL; |  | ||||||
| """ | """ | ||||||
| DEFINES = { | DEFINES = { | ||||||
|     "LFS_READ_SIZE": 16, |     "LFS_READ_SIZE": 16, | ||||||
| @@ -70,6 +68,8 @@ DEFINES = { | |||||||
| } | } | ||||||
| PROLOGUE = """ | PROLOGUE = """ | ||||||
|     // prologue |     // prologue | ||||||
|  |     extern const char *LFS_DISK; | ||||||
|  |  | ||||||
|     __attribute__((unused)) lfs_t lfs; |     __attribute__((unused)) lfs_t lfs; | ||||||
|     __attribute__((unused)) lfs_filebd_t filebd; |     __attribute__((unused)) lfs_filebd_t filebd; | ||||||
|     __attribute__((unused)) lfs_rambd_t rambd; |     __attribute__((unused)) lfs_rambd_t rambd; | ||||||
| @@ -129,28 +129,31 @@ class TestFailure(Exception): | |||||||
|         self.assert_ = assert_ |         self.assert_ = assert_ | ||||||
|  |  | ||||||
| class TestCase: | class TestCase: | ||||||
|     def __init__(self, config, suite=None, caseno=None, lineno=None, **_): |     def __init__(self, config, filter=filter, | ||||||
|  |             suite=None, caseno=None, lineno=None, **_): | ||||||
|  |         self.filter = filter | ||||||
|         self.suite = suite |         self.suite = suite | ||||||
|         self.caseno = caseno |         self.caseno = caseno | ||||||
|         self.lineno = lineno |         self.lineno = lineno | ||||||
|  |  | ||||||
|         self.code = config['code'] |         self.code = config['code'] | ||||||
|  |         self.code_lineno = config['code_lineno'] | ||||||
|         self.defines = config.get('define', {}) |         self.defines = config.get('define', {}) | ||||||
|         self.if_ = config.get('if', None) |         self.if_ = config.get('if', None) | ||||||
|         self.leaky = config.get('leaky', False) |         self.in_ = config.get('in', None) | ||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         if hasattr(self, 'permno'): |         if hasattr(self, 'permno'): | ||||||
|             if any(k not in self.case.defines for k in self.defines): |             if any(k not in self.case.defines for k in self.defines): | ||||||
|                 return '%s[%d,%d] (%s)' % ( |                 return '%s#%d#%d (%s)' % ( | ||||||
|                     self.suite.name, self.caseno, self.permno, ', '.join( |                     self.suite.name, self.caseno, self.permno, ', '.join( | ||||||
|                         '%s=%s' % (k, v) for k, v in self.defines.items() |                         '%s=%s' % (k, v) for k, v in self.defines.items() | ||||||
|                         if k not in self.case.defines)) |                         if k not in self.case.defines)) | ||||||
|             else: |             else: | ||||||
|                 return '%s[%d,%d]' % ( |                 return '%s#%d#%d' % ( | ||||||
|                     self.suite.name, self.caseno, self.permno) |                     self.suite.name, self.caseno, self.permno) | ||||||
|         else: |         else: | ||||||
|             return '%s[%d]' % ( |             return '%s#%d' % ( | ||||||
|                 self.suite.name, self.caseno) |                 self.suite.name, self.caseno) | ||||||
|  |  | ||||||
|     def permute(self, defines, permno=None, **_): |     def permute(self, defines, permno=None, **_): | ||||||
| @@ -163,17 +166,10 @@ class TestCase: | |||||||
|  |  | ||||||
|     def build(self, f, **_): |     def build(self, f, **_): | ||||||
|         # prologue |         # prologue | ||||||
|         f.write('void test_case%d(' % self.caseno) |         f.write('void test_case%d(%s) {\n' % (self.caseno, ','.join( | ||||||
|         first = True |             '\n'+8*' '+'__attribute__((unused)) intmax_t %s' % k | ||||||
|         for k, v in sorted(self.perms[0].defines.items()): |             for k in sorted(self.perms[0].defines) | ||||||
|             if k not in self.defines: |             if k not in self.defines))) | ||||||
|                 if not first: |  | ||||||
|                     f.write(',') |  | ||||||
|                 else: |  | ||||||
|                     first = False |  | ||||||
|                 f.write('\n') |  | ||||||
|                 f.write(8*' '+'__attribute__((unused)) intmax_t %s' % k) |  | ||||||
|         f.write(') {\n') |  | ||||||
|  |  | ||||||
|         for k, v in sorted(self.defines.items()): |         for k, v in sorted(self.defines.items()): | ||||||
|             if k not in self.suite.defines: |             if k not in self.suite.defines: | ||||||
| @@ -182,7 +178,7 @@ class TestCase: | |||||||
|         f.write(PROLOGUE) |         f.write(PROLOGUE) | ||||||
|         f.write('\n') |         f.write('\n') | ||||||
|         f.write(4*' '+'// test case %d\n' % self.caseno) |         f.write(4*' '+'// test case %d\n' % self.caseno) | ||||||
|         f.write(4*' '+'#line %d "%s"\n' % (self.lineno, self.suite.path)) |         f.write(4*' '+'#line %d "%s"\n' % (self.code_lineno, self.suite.path)) | ||||||
|  |  | ||||||
|         # test case goes here |         # test case goes here | ||||||
|         f.write(self.code) |         f.write(self.code) | ||||||
| @@ -198,7 +194,15 @@ class TestCase: | |||||||
|         f.write('}\n') |         f.write('}\n') | ||||||
|  |  | ||||||
|     def shouldtest(self, **args): |     def shouldtest(self, **args): | ||||||
|         if self.if_ is not None: |         if (self.filter is not None and | ||||||
|  |                 len(self.filter) >= 1 and | ||||||
|  |                 self.filter[0] != self.caseno): | ||||||
|  |             return False | ||||||
|  |         elif (self.filter is not None and | ||||||
|  |                 len(self.filter) >= 2 and | ||||||
|  |                 self.filter[1] != self.permno): | ||||||
|  |             return False | ||||||
|  |         elif self.if_ is not None: | ||||||
|             return eval(self.if_, None, self.defines.copy()) |             return eval(self.if_, None, self.defines.copy()) | ||||||
|         else: |         else: | ||||||
|             return True |             return True | ||||||
| @@ -227,7 +231,7 @@ class TestCase: | |||||||
|                     ncmd.extend(['-ex', 'up']) |                     ncmd.extend(['-ex', 'up']) | ||||||
|             elif gdb == 'start': |             elif gdb == 'start': | ||||||
|                 ncmd.extend([ |                 ncmd.extend([ | ||||||
|                     '-ex', 'b %s:%d' % (self.suite.path, self.lineno), |                     '-ex', 'b %s:%d' % (self.suite.path, self.code_lineno), | ||||||
|                     '-ex', 'r']) |                     '-ex', 'r']) | ||||||
|             ncmd.extend(['--args'] + cmd) |             ncmd.extend(['--args'] + cmd) | ||||||
|  |  | ||||||
| @@ -309,7 +313,7 @@ class ReentrantTestCase(TestCase): | |||||||
|         for cycles in it.count(1): |         for cycles in it.count(1): | ||||||
|             # exact cycle we should drop into debugger? |             # exact cycle we should drop into debugger? | ||||||
|             if gdb and failure and failure.cycleno == cycles: |             if gdb and failure and failure.cycleno == cycles: | ||||||
|                 return super().test(exec=exec, persist=True, |                 return super().test(exec=exec, persist='noerase', | ||||||
|                     gdb=gdb, failure=failure, **args) |                     gdb=gdb, failure=failure, **args) | ||||||
|  |  | ||||||
|             # run tests, but kill the program after prog/erase has |             # run tests, but kill the program after prog/erase has | ||||||
| @@ -337,11 +341,12 @@ class ReentrantTestCase(TestCase): | |||||||
|                     raise |                     raise | ||||||
|  |  | ||||||
| class TestSuite: | class TestSuite: | ||||||
|     def __init__(self, path, TestCase=TestCase, **args): |     def __init__(self, path, filter=None, TestCase=TestCase, **args): | ||||||
|         self.name = os.path.basename(path) |         self.name = os.path.basename(path) | ||||||
|         if self.name.endswith('.toml'): |         if self.name.endswith('.toml'): | ||||||
|             self.name = self.name[:-len('.toml')] |             self.name = self.name[:-len('.toml')] | ||||||
|         self.path = path |         self.path = path | ||||||
|  |         self.filter = filter | ||||||
|         self.TestCase = TestCase |         self.TestCase = TestCase | ||||||
|  |  | ||||||
|         with open(path) as f: |         with open(path) as f: | ||||||
| @@ -351,9 +356,12 @@ class TestSuite: | |||||||
|             # find line numbers |             # find line numbers | ||||||
|             f.seek(0) |             f.seek(0) | ||||||
|             linenos = [] |             linenos = [] | ||||||
|  |             code_linenos = [] | ||||||
|             for i, line in enumerate(f): |             for i, line in enumerate(f): | ||||||
|                 if re.match(r'^\s*code\s*=\s*(\'\'\'|""")', line): |                 if re.match(r'\[\[\s*case\s*\]\]', line): | ||||||
|                     linenos.append(i + 2) |                     linenos.append(i+1) | ||||||
|  |                 if re.match(r'code\s*=\s*(\'\'\'|""")', line): | ||||||
|  |                     code_linenos.append(i+2) | ||||||
|  |  | ||||||
|         # grab global config |         # grab global config | ||||||
|         self.defines = config.get('define', {}) |         self.defines = config.get('define', {}) | ||||||
| @@ -361,12 +369,15 @@ class TestSuite: | |||||||
|         # create initial test cases |         # create initial test cases | ||||||
|         self.cases = [] |         self.cases = [] | ||||||
|         for i, (case, lineno) in enumerate(zip(config['case'], linenos)): |         for i, (case, lineno) in enumerate(zip(config['case'], linenos)): | ||||||
|  |             # code lineno? | ||||||
|  |             if 'code' in case: | ||||||
|  |                 case['code_lineno'] = code_linenos.pop(0) | ||||||
|             # give our case's config a copy of our "global" config |             # give our case's config a copy of our "global" config | ||||||
|             for k, v in config.items(): |             for k, v in config.items(): | ||||||
|                 if k not in case: |                 if k not in case: | ||||||
|                     case[k] = v |                     case[k] = v | ||||||
|             # initialize test case |             # initialize test case | ||||||
|             self.cases.append(self.TestCase(case, |             self.cases.append(self.TestCase(case, filter=filter, | ||||||
|                 suite=self, caseno=i, lineno=lineno, **args)) |                 suite=self, caseno=i, lineno=lineno, **args)) | ||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
| @@ -438,40 +449,52 @@ class TestSuite: | |||||||
|         return self.perms |         return self.perms | ||||||
|  |  | ||||||
|     def build(self, **args): |     def build(self, **args): | ||||||
|         # build test.c |         # build test files | ||||||
|         f = io.StringIO() |         tf = open(self.path + '.test.c.t', 'w') | ||||||
|         f.write(GLOBALS) |         tf.write(GLOBALS) | ||||||
|  |         tfs = {None: tf} | ||||||
|  |  | ||||||
|         for case in self.cases: |         for case in self.cases: | ||||||
|             f.write('\n') |             if case.in_ not in tfs: | ||||||
|             case.build(f, **args) |                 tfs[case.in_] = open(self.path+'.'+ | ||||||
|  |                     case.in_.replace('/', '.')+'.t', 'w') | ||||||
|  |                 tfs[case.in_].write('#line 1 "%s"\n' % case.in_) | ||||||
|  |                 with open(case.in_) as f: | ||||||
|  |                     for line in f: | ||||||
|  |                         tfs[case.in_].write(line) | ||||||
|  |                 tfs[case.in_].write('\n') | ||||||
|  |                 tfs[case.in_].write(GLOBALS) | ||||||
|  |  | ||||||
|         f.write('\n') |             tfs[case.in_].write('\n') | ||||||
|         f.write('int main(int argc, char **argv) {\n') |             case.build(tfs[case.in_], **args) | ||||||
|         f.write(4*' '+'int case_ = (argc >= 2) ? atoi(argv[1]) : 0;\n') |  | ||||||
|         f.write(4*' '+'int perm = (argc >= 3) ? atoi(argv[2]) : 0;\n') |         tf.write('\n') | ||||||
|         f.write(4*' '+'LFS_DISK = (argc >= 4) ? argv[3] : NULL;\n') |         tf.write('const char *LFS_DISK = NULL;\n') | ||||||
|  |         tf.write('int main(int argc, char **argv) {\n') | ||||||
|  |         tf.write(4*' '+'int case_ = (argc >= 2) ? atoi(argv[1]) : 0;\n') | ||||||
|  |         tf.write(4*' '+'int perm = (argc >= 3) ? atoi(argv[2]) : 0;\n') | ||||||
|  |         tf.write(4*' '+'LFS_DISK = (argc >= 4) ? argv[3] : NULL;\n') | ||||||
|         for perm in self.perms: |         for perm in self.perms: | ||||||
|             f.write(4*' '+'if (argc < 3 || ' |             # test declaration | ||||||
|                 '(case_ == %d && perm == %d)) { ' % ( |             tf.write(4*' '+'extern void test_case%d(%s);\n' % ( | ||||||
|                     perm.caseno, perm.permno)) |                 perm.caseno, ', '.join( | ||||||
|             f.write('test_case%d(' % perm.caseno) |                     'intmax_t %s' % k for k in sorted(perm.defines) | ||||||
|             first = True |                     if k not in perm.case.defines))) | ||||||
|             for k, v in sorted(perm.defines.items()): |             # test call | ||||||
|                 if k not in perm.case.defines: |             tf.write(4*' '+ | ||||||
|                     if not first: |                 'if (argc < 3 || (case_ == %d && perm == %d)) {' | ||||||
|                         f.write(', ') |                 ' test_case%d(%s); ' | ||||||
|                     else: |                 '}\n' % (perm.caseno, perm.permno, perm.caseno, ', '.join( | ||||||
|                         first = False |                     str(v) for k, v in sorted(perm.defines.items()) | ||||||
|                     f.write(str(v)) |                     if k not in perm.case.defines))) | ||||||
|             f.write('); }\n') |         tf.write('}\n') | ||||||
|         f.write('}\n') |  | ||||||
|  |  | ||||||
|         # add test-related rules |         for tf in tfs.values(): | ||||||
|         rules = RULES.replace(4*' ', '\t') |             tf.close() | ||||||
|  |  | ||||||
|  |         # write makefiles | ||||||
|         with open(self.path + '.mk', 'w') as mk: |         with open(self.path + '.mk', 'w') as mk: | ||||||
|             mk.write(rules) |             mk.write(RULES.replace(4*' ', '\t')) | ||||||
|             mk.write('\n') |             mk.write('\n') | ||||||
|  |  | ||||||
|             # add truely global defines globally |             # add truely global defines globally | ||||||
| @@ -479,12 +502,18 @@ class TestSuite: | |||||||
|                 mk.write('%s: override CFLAGS += -D%s=%r\n' % ( |                 mk.write('%s: override CFLAGS += -D%s=%r\n' % ( | ||||||
|                     self.path+'.test', k, v)) |                     self.path+'.test', k, v)) | ||||||
|  |  | ||||||
|             # write test.c in base64 so make can decide when to rebuild |             for path in tfs: | ||||||
|             mk.write('%s: %s\n' % (self.path+'.test.tc', self.path)) |                 if path is None: | ||||||
|             mk.write('\t@base64 -d <<< ') |                     mk.write('%s: %s | %s\n' % ( | ||||||
|             mk.write(base64.b64encode( |                         self.path+'.test.c', | ||||||
|                 f.getvalue().encode('utf8')).decode('utf8')) |                         self.path, | ||||||
|             mk.write(' > $@\n') |                         self.path+'.test.c.t')) | ||||||
|  |                 else: | ||||||
|  |                     mk.write('%s: %s %s | %s\n' % ( | ||||||
|  |                         self.path+'.'+path.replace('/', '.'), | ||||||
|  |                         self.path, path, | ||||||
|  |                         self.path+'.'+path.replace('/', '.')+'.t')) | ||||||
|  |                 mk.write('\t./scripts/explode_asserts.py $| -o $@\n') | ||||||
|  |  | ||||||
|         self.makefile = self.path + '.mk' |         self.makefile = self.path + '.mk' | ||||||
|         self.target = self.path + '.test' |         self.target = self.path + '.test' | ||||||
| @@ -524,17 +553,11 @@ class TestSuite: | |||||||
|             sys.stdout.write('\n') |             sys.stdout.write('\n') | ||||||
|  |  | ||||||
| def main(**args): | def main(**args): | ||||||
|     testpath = args['testpath'] |     suites = [] | ||||||
|  |     for testpath in args['testpaths']: | ||||||
|     # optional brackets for specific test |         # optionally specified test case/perm | ||||||
|     m = re.search(r'\[(\d+)(?:,(\d+))?\]$', testpath) |         testpath, *filter = testpath.split('#') | ||||||
|     if m: |         filter = [int(f) for f in filter] | ||||||
|         caseno = int(m.group(1)) |  | ||||||
|         permno = int(m.group(2)) if m.group(2) is not None else None |  | ||||||
|         testpath = testpath[:m.start()] |  | ||||||
|     else: |  | ||||||
|         caseno = None |  | ||||||
|         permno = None |  | ||||||
|  |  | ||||||
|         # figure out the suite's toml file |         # figure out the suite's toml file | ||||||
|         if os.path.isdir(testpath): |         if os.path.isdir(testpath): | ||||||
| @@ -547,14 +570,16 @@ def main(**args): | |||||||
|             testpath = TESTDIR + '/' + testpath + '.toml' |             testpath = TESTDIR + '/' + testpath + '.toml' | ||||||
|  |  | ||||||
|         # find tests |         # find tests | ||||||
|     suites = [] |  | ||||||
|         for path in glob.glob(testpath): |         for path in glob.glob(testpath): | ||||||
|             if args.get('valgrind', False): |             if args.get('valgrind', False): | ||||||
|             suites.append(TestSuite(path, TestCase=ValgrindTestCase, **args)) |                 TestCase_ = ValgrindTestCase | ||||||
|             elif args.get('reentrant', False): |             elif args.get('reentrant', False): | ||||||
|             suites.append(TestSuite(path, TestCase=ReentrantTestCase, **args)) |                 TestCase_ = ReentrantTestCase | ||||||
|             else: |             else: | ||||||
|             suites.append(TestSuite(path, **args)) |                 TestCase_ = TestCase | ||||||
|  |  | ||||||
|  |             suites.append(TestSuite(path, | ||||||
|  |                 filter=filter, TestCase=TestCase_, **args)) | ||||||
|  |  | ||||||
|     # sort for reproducability |     # sort for reproducability | ||||||
|     suites = sorted(suites) |     suites = sorted(suites) | ||||||
| @@ -632,7 +657,7 @@ def main(**args): | |||||||
|     print('====== testing ======') |     print('====== testing ======') | ||||||
|     try: |     try: | ||||||
|         for suite in suites: |         for suite in suites: | ||||||
|             suite.test(caseno, permno, **args) |             suite.test(**args) | ||||||
|     except TestFailure: |     except TestFailure: | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
| @@ -647,11 +672,10 @@ 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( |                 sys.stdout.write( | ||||||
|                     "\033[01m{path}:{lineno}:\033[01;31mfailure:\033[m " |                     "\033[01m{path}:{lineno}:\033[01;31mfailure:\033[m " | ||||||
|                     "{perm} failed with {returncode}\n".format( |                     "{perm} failed with {returncode}\n".format( | ||||||
|                         perm=perm, path=perm.suite.path, lineno=perm.lineno-2, |                         perm=perm, path=perm.suite.path, lineno=perm.lineno, | ||||||
|                         returncode=perm.result.returncode or 0)) |                         returncode=perm.result.returncode or 0)) | ||||||
|                 if perm.result.stdout: |                 if perm.result.stdout: | ||||||
|                     for line in (perm.result.stdout |                     for line in (perm.result.stdout | ||||||
| @@ -681,15 +705,15 @@ def main(**args): | |||||||
|             failure.case.test(failure=failure, **args) |             failure.case.test(failure=failure, **args) | ||||||
|             sys.exit(0) |             sys.exit(0) | ||||||
|  |  | ||||||
|  |  | ||||||
|     print('tests passed: %d' % passed) |     print('tests passed: %d' % passed) | ||||||
|     print('tests failed: %d' % failed) |     print('tests failed: %d' % failed) | ||||||
|  |     return 1 if failed > 0 else 0 | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     import argparse |     import argparse | ||||||
|     parser = argparse.ArgumentParser( |     parser = argparse.ArgumentParser( | ||||||
|         description="Run parameterized tests in various configurations.") |         description="Run parameterized tests in various configurations.") | ||||||
|     parser.add_argument('testpath', nargs='?', default=TESTDIR, |     parser.add_argument('testpaths', nargs='*', default=[TESTDIR], | ||||||
|         help="Description of test(s) to run. By default, this is all tests \ |         help="Description of test(s) to run. By default, this is all tests \ | ||||||
|             found in the \"{0}\" directory. Here, you can specify a different \ |             found in the \"{0}\" directory. Here, you can specify a different \ | ||||||
|             directory of tests, a specific file, a suite by name, and even a \ |             directory of tests, a specific file, a suite by name, and even a \ | ||||||
| @@ -713,4 +737,4 @@ if __name__ == "__main__": | |||||||
|         help="Run reentrant tests with simulated power-loss.") |         help="Run reentrant tests with simulated power-loss.") | ||||||
|     parser.add_argument('-e', '--exec', default=[], type=lambda e: e.split(' '), |     parser.add_argument('-e', '--exec', default=[], type=lambda e: e.split(' '), | ||||||
|         help="Run tests with another executable prefixed on the command line.") |         help="Run tests with another executable prefixed on the command line.") | ||||||
|     main(**vars(parser.parse_args())) |     sys.exit(main(**vars(parser.parse_args()))) | ||||||
|   | |||||||
| @@ -2,6 +2,8 @@ | |||||||
| # note for these to work there are many constraints on the device geometry | # note for these to work there are many constraints on the device geometry | ||||||
|  |  | ||||||
| [[case]] # parallel allocation test | [[case]] # parallel allocation test | ||||||
|  | define.FILES = 3 | ||||||
|  | define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' | ||||||
| code = ''' | code = ''' | ||||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; |     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||||
|     lfs_file_t files[FILES]; |     lfs_file_t files[FILES]; | ||||||
| @@ -41,10 +43,10 @@ code = ''' | |||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.FILES = 3 |  | ||||||
| define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' |  | ||||||
|  |  | ||||||
| [[case]] # serial allocation test | [[case]] # serial allocation test | ||||||
|  | define.FILES = 3 | ||||||
|  | define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' | ||||||
| code = ''' | code = ''' | ||||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; |     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||||
|  |  | ||||||
| @@ -80,10 +82,11 @@ code = ''' | |||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.FILES = 3 |  | ||||||
| define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' |  | ||||||
|  |  | ||||||
| [[case]] # parallel allocation reuse test | [[case]] # parallel allocation reuse test | ||||||
|  | define.FILES = 3 | ||||||
|  | define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' | ||||||
|  | define.CYCLES = [1, 10] | ||||||
| code = ''' | code = ''' | ||||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; |     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||||
|     lfs_file_t files[FILES]; |     lfs_file_t files[FILES]; | ||||||
| @@ -134,11 +137,11 @@ code = ''' | |||||||
|         lfs_unmount(&lfs) => 0; |         lfs_unmount(&lfs) => 0; | ||||||
|     } |     } | ||||||
| ''' | ''' | ||||||
|  |  | ||||||
|  | [[case]] # serial allocation reuse test | ||||||
| define.FILES = 3 | define.FILES = 3 | ||||||
| define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' | define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' | ||||||
| define.CYCLES = [1, 10] | define.CYCLES = [1, 10] | ||||||
|  |  | ||||||
| [[case]] # serial allocation reuse test |  | ||||||
| code = ''' | code = ''' | ||||||
|     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; |     const char *names[FILES] = {"bacon", "eggs", "pancakes"}; | ||||||
|  |  | ||||||
| @@ -185,9 +188,6 @@ code = ''' | |||||||
|         lfs_unmount(&lfs) => 0; |         lfs_unmount(&lfs) => 0; | ||||||
|     } |     } | ||||||
| ''' | ''' | ||||||
| define.FILES = 3 |  | ||||||
| define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / FILES)' |  | ||||||
| define.CYCLES = [1, 10] |  | ||||||
|  |  | ||||||
| [[case]] # exhaustion test | [[case]] # exhaustion test | ||||||
| code = ''' | code = ''' | ||||||
| @@ -226,6 +226,7 @@ code = ''' | |||||||
| ''' | ''' | ||||||
|  |  | ||||||
| [[case]] # exhaustion wraparound test | [[case]] # exhaustion wraparound test | ||||||
|  | define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / 3)' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -271,7 +272,6 @@ code = ''' | |||||||
|     lfs_remove(&lfs, "exhaustion") => 0; |     lfs_remove(&lfs, "exhaustion") => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.SIZE = '(((LFS_BLOCK_SIZE-8)*(LFS_BLOCK_COUNT-4)) / 3)' |  | ||||||
|  |  | ||||||
| [[case]] # dir exhaustion test | [[case]] # dir exhaustion test | ||||||
| code = ''' | code = ''' | ||||||
| @@ -327,6 +327,9 @@ code = ''' | |||||||
| # should be removed and replaced with generalized tests. | # should be removed and replaced with generalized tests. | ||||||
|  |  | ||||||
| [[case]] # chained dir exhaustion test | [[case]] # chained dir exhaustion test | ||||||
|  | define.LFS_BLOCK_SIZE = 512 | ||||||
|  | define.LFS_BLOCK_COUNT = 1024 | ||||||
|  | if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -393,11 +396,11 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
|  |  | ||||||
|  | [[case]] # split dir test | ||||||
| define.LFS_BLOCK_SIZE = 512 | define.LFS_BLOCK_SIZE = 512 | ||||||
| define.LFS_BLOCK_COUNT = 1024 | define.LFS_BLOCK_COUNT = 1024 | ||||||
| if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' | if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' | ||||||
|  |  | ||||||
| [[case]] # split dir test |  | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -438,11 +441,11 @@ code = ''' | |||||||
|  |  | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
|  |  | ||||||
|  | [[case]] # outdated lookahead test | ||||||
| define.LFS_BLOCK_SIZE = 512 | define.LFS_BLOCK_SIZE = 512 | ||||||
| define.LFS_BLOCK_COUNT = 1024 | define.LFS_BLOCK_COUNT = 1024 | ||||||
| if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' | if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' | ||||||
|  |  | ||||||
| [[case]] # outdated lookahead test |  | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -501,11 +504,11 @@ code = ''' | |||||||
|     } |     } | ||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
| ''' | ''' | ||||||
|  |  | ||||||
|  | [[case]] # outdated lookahead and split dir test | ||||||
| define.LFS_BLOCK_SIZE = 512 | define.LFS_BLOCK_SIZE = 512 | ||||||
| define.LFS_BLOCK_COUNT = 1024 | define.LFS_BLOCK_COUNT = 1024 | ||||||
| if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' | if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' | ||||||
|  |  | ||||||
| [[case]] # outdated lookahead and split dir test |  | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -561,6 +564,3 @@ code = ''' | |||||||
|  |  | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.LFS_BLOCK_SIZE = 512 |  | ||||||
| define.LFS_BLOCK_COUNT = 1024 |  | ||||||
| if = 'LFS_BLOCK_SIZE == 512 and LFS_BLOCK_COUNT == 1024' |  | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ code = ''' | |||||||
| ''' | ''' | ||||||
|  |  | ||||||
| [[case]] # many directory creation | [[case]] # many directory creation | ||||||
|  | define.N = 'range(0, 100, 3)' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -43,9 +44,9 @@ code = ''' | |||||||
|     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)' |  | ||||||
|  |  | ||||||
| [[case]] # many directory removal | [[case]] # many directory removal | ||||||
|  | define.N = 'range(3, 100, 11)' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -93,9 +94,9 @@ code = ''' | |||||||
|     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)' |  | ||||||
|  |  | ||||||
| [[case]] # many directory rename | [[case]] # many directory rename | ||||||
|  | define.N = 'range(3, 100, 11)' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -152,9 +153,10 @@ code = ''' | |||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs); |     lfs_unmount(&lfs); | ||||||
| ''' | ''' | ||||||
| define.N = 'range(3, 100, 11)' |  | ||||||
|  |  | ||||||
| [[case]] # reentrant many directory creation/rename/removal | [[case]] # reentrant many directory creation/rename/removal | ||||||
|  | define.N = [5, 25] | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -231,10 +233,9 @@ code = ''' | |||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.N = [5, 25] |  | ||||||
| reentrant = true |  | ||||||
|  |  | ||||||
| [[case]] # file creation | [[case]] # file creation | ||||||
|  | define.N = 'range(3, 100, 11)' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -265,9 +266,9 @@ code = ''' | |||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs); |     lfs_unmount(&lfs); | ||||||
| ''' | ''' | ||||||
| define.N = 'range(3, 100, 11)' |  | ||||||
|  |  | ||||||
| [[case]] # file removal | [[case]] # file removal | ||||||
|  | define.N = 'range(0, 100, 3)' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -317,9 +318,9 @@ code = ''' | |||||||
|     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)' |  | ||||||
|  |  | ||||||
| [[case]] # file rename | [[case]] # file rename | ||||||
|  | define.N = 'range(0, 100, 3)' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -378,9 +379,10 @@ code = ''' | |||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs); |     lfs_unmount(&lfs); | ||||||
| ''' | ''' | ||||||
| define.N = 'range(0, 100, 3)' |  | ||||||
|  |  | ||||||
| [[case]] # reentrant file creation/rename/removal | [[case]] # reentrant file creation/rename/removal | ||||||
|  | define.N = [5, 25] | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -457,8 +459,6 @@ code = ''' | |||||||
|     lfs_dir_close(&lfs, &dir) => 0; |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.N = [5, 25] |  | ||||||
| reentrant = true |  | ||||||
|  |  | ||||||
| [[case]] # nested directories | [[case]] # nested directories | ||||||
| code = ''' | code = ''' | ||||||
| @@ -585,6 +585,7 @@ code = ''' | |||||||
| ''' | ''' | ||||||
|  |  | ||||||
| [[case]] # recursive remove | [[case]] # recursive remove | ||||||
|  | define.N = [10, 100] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -639,7 +640,6 @@ code = ''' | |||||||
|     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; |     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOENT; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.N = [10, 100] |  | ||||||
|  |  | ||||||
| [[case]] # other error cases | [[case]] # other error cases | ||||||
| code = ''' | code = ''' | ||||||
| @@ -716,6 +716,7 @@ code = ''' | |||||||
| ''' | ''' | ||||||
|  |  | ||||||
| [[case]] # directory seek | [[case]] # directory seek | ||||||
|  | define.COUNT = [4, 128, 132] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -774,9 +775,9 @@ code = ''' | |||||||
|         lfs_unmount(&lfs) => 0; |         lfs_unmount(&lfs) => 0; | ||||||
|     } |     } | ||||||
| ''' | ''' | ||||||
| define.COUNT = [4, 128, 132] |  | ||||||
|  |  | ||||||
| [[case]] # root seek | [[case]] # root seek | ||||||
|  | define.COUNT = [4, 128, 132] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -834,5 +835,4 @@ code = ''' | |||||||
|         lfs_unmount(&lfs) => 0; |         lfs_unmount(&lfs) => 0; | ||||||
|     } |     } | ||||||
| ''' | ''' | ||||||
| define.COUNT = [4, 128, 132] |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,6 +20,8 @@ code = ''' | |||||||
| ''' | ''' | ||||||
|  |  | ||||||
| [[case]] # larger files | [[case]] # larger files | ||||||
|  | define.SIZE = [32, 8192, 262144, 0, 7, 8193] | ||||||
|  | define.CHUNKSIZE = [31, 16, 33, 1, 1023] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -54,10 +56,11 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.SIZE = [32, 8192, 262144, 0, 7, 8193] |  | ||||||
| define.CHUNKSIZE = [31, 16, 33, 1, 1023] |  | ||||||
|  |  | ||||||
| [[case]] # rewriting files | [[case]] # rewriting files | ||||||
|  | define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||||
|  | define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||||
|  | define.CHUNKSIZE = [31, 16, 1, 1025] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -135,11 +138,11 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
|  |  | ||||||
|  | [[case]] # appending files | ||||||
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||||
| define.CHUNKSIZE = [31, 16, 1, 1025] | define.CHUNKSIZE = [31, 16, 1, 1025] | ||||||
|  |  | ||||||
| [[case]] # appending files |  | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -212,11 +215,11 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
|  |  | ||||||
|  | [[case]] # truncating files | ||||||
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] | ||||||
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] | ||||||
| define.CHUNKSIZE = [31, 16, 1, 1025] | define.CHUNKSIZE = [31, 16, 1, 1025] | ||||||
|  |  | ||||||
| [[case]] # truncating files |  | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |  | ||||||
| @@ -281,11 +284,11 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 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 | [[case]] # reentrant file writing | ||||||
|  | define.SIZE = [32, 0, 7, 2049] | ||||||
|  | define.CHUNKSIZE = [31, 16, 65] | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -329,11 +332,17 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.SIZE = [32, 0, 7, 2049] |  | ||||||
| define.CHUNKSIZE = [31, 16, 65] |  | ||||||
| reentrant = true |  | ||||||
|  |  | ||||||
| [[case]] # reentrant file writing with syncs | [[case]] # reentrant file writing with syncs | ||||||
|  | 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 | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -393,17 +402,9 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 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 | [[case]] # many files | ||||||
|  | define.N = 300 | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     // create N files of 7 bytes |     // create N files of 7 bytes | ||||||
| @@ -426,9 +427,9 @@ code = ''' | |||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.N = 300 |  | ||||||
|  |  | ||||||
| [[case]] # many files with power cycle | [[case]] # many files with power cycle | ||||||
|  | define.N = 300 | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     // create N files of 7 bytes |     // create N files of 7 bytes | ||||||
| @@ -453,9 +454,10 @@ code = ''' | |||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.N = 300 |  | ||||||
|  |  | ||||||
| [[case]] # many files with power loss | [[case]] # many files with power loss | ||||||
|  | define.N = 300 | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -482,5 +484,3 @@ code = ''' | |||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.N = 300 |  | ||||||
| reentrant = true |  | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ code = ''' | |||||||
| ''' | ''' | ||||||
|  |  | ||||||
| [[case]] # reentrant format | [[case]] # reentrant format | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -19,7 +20,6 @@ code = ''' | |||||||
|     } |     } | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| reentrant = true |  | ||||||
|  |  | ||||||
| [[case]] # invalid mount | [[case]] # invalid mount | ||||||
| code = ''' | code = ''' | ||||||
| @@ -29,6 +29,8 @@ code = ''' | |||||||
| # TODO invalid superblock? (corrupt 1, 0) | # TODO invalid superblock? (corrupt 1, 0) | ||||||
|  |  | ||||||
| [[case]] # expanding superblock | [[case]] # expanding superblock | ||||||
|  | define.BLOCK_CYCLES = [32, 33, 1] | ||||||
|  | define.N = [10, 100, 1000] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -47,10 +49,10 @@ code = ''' | |||||||
|     assert(strcmp(info.name, "dummy") == 0); |     assert(strcmp(info.name, "dummy") == 0); | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.BLOCK_CYCLES = [32, 33, 1] |  | ||||||
| define.N = [10, 100, 1000] |  | ||||||
|  |  | ||||||
| [[case]] # expanding superblock with power cycle | [[case]] # expanding superblock with power cycle | ||||||
|  | define.BLOCK_CYCLES = [32, 33, 1] | ||||||
|  | define.N = [10, 100, 1000] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     for (int i = 0; i < N; i++) { |     for (int i = 0; i < N; i++) { | ||||||
| @@ -71,10 +73,11 @@ code = ''' | |||||||
|     assert(strcmp(info.name, "dummy") == 0); |     assert(strcmp(info.name, "dummy") == 0); | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.BLOCK_CYCLES = [32, 33, 1] |  | ||||||
| define.N = [10, 100, 1000] |  | ||||||
|  |  | ||||||
| [[case]] # reentrant expanding superblock | [[case]] # reentrant expanding superblock | ||||||
|  | define.BLOCK_CYCLES = [2, 1] | ||||||
|  | define.N = 24 | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -100,6 +103,3 @@ code = ''' | |||||||
|     assert(strcmp(info.name, "dummy") == 0); |     assert(strcmp(info.name, "dummy") == 0); | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.BLOCK_CYCLES = [2, 1] |  | ||||||
| define.N = 24 |  | ||||||
| reentrant = true |  | ||||||
|   | |||||||
| @@ -1,5 +1,16 @@ | |||||||
|  |  | ||||||
| [[case]] # interspersed file test | [[case]] # interspersed file test | ||||||
|  | # TODO FILES=26 found bug | ||||||
|  | #define.SIZE = [10, 100] | ||||||
|  | #define.FILES = [4, 10, 26]  | ||||||
|  | define = [ | ||||||
|  |     {SIZE=10, FILES=4}, | ||||||
|  |     {SIZE=10, FILES=10}, | ||||||
|  |     #{SIZE=10, FILES=26}, | ||||||
|  |     {SIZE=100, FILES=4}, | ||||||
|  |     {SIZE=100, FILES=10}, | ||||||
|  |     #{SIZE=100, FILES=26}, | ||||||
|  | ] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_file_t files[FILES]; |     lfs_file_t files[FILES]; | ||||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; |     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||||
| @@ -56,19 +67,10 @@ code = ''' | |||||||
|      |      | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| # TODO FILES=26 found bug |  | ||||||
| #define.SIZE = [10, 100] |  | ||||||
| #define.FILES = [4, 10, 26]  |  | ||||||
| define = [ |  | ||||||
|     {SIZE=10, FILES=4}, |  | ||||||
|     {SIZE=10, FILES=10}, |  | ||||||
|     #{SIZE=10, FILES=26}, |  | ||||||
|     {SIZE=100, FILES=4}, |  | ||||||
|     {SIZE=100, FILES=10}, |  | ||||||
|     #{SIZE=100, FILES=26}, |  | ||||||
| ] |  | ||||||
|  |  | ||||||
| [[case]] # interspersed remove file test | [[case]] # interspersed remove file test | ||||||
|  | define.SIZE = [10, 100] | ||||||
|  | define.FILES = [4, 10, 26] | ||||||
| code = ''' | code = ''' | ||||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; |     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
| @@ -118,10 +120,9 @@ code = ''' | |||||||
|      |      | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.SIZE = [10, 100] |  | ||||||
| define.FILES = [4, 10, 26] |  | ||||||
|  |  | ||||||
| [[case]] # remove inconveniently test | [[case]] # remove inconveniently test | ||||||
|  | define.SIZE = [10, 100] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -179,9 +180,20 @@ code = ''' | |||||||
|      |      | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.SIZE = [10, 100] |  | ||||||
|  |  | ||||||
| [[case]] # reentrant interspersed file test | [[case]] # reentrant interspersed file test | ||||||
|  | # TODO FILES=26 found bug | ||||||
|  | #define.SIZE = [10, 100] | ||||||
|  | #define.FILES = [4, 10, 26]  | ||||||
|  | define = [ | ||||||
|  |     {SIZE=10, FILES=4}, | ||||||
|  |     {SIZE=10, FILES=10}, | ||||||
|  |     #{SIZE=10, FILES=26}, | ||||||
|  |     {SIZE=100, FILES=4}, | ||||||
|  |     #{SIZE=100, FILES=10}, | ||||||
|  |     #{SIZE=100, FILES=26}, | ||||||
|  | ] | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_file_t files[FILES]; |     lfs_file_t files[FILES]; | ||||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; |     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||||
| @@ -248,15 +260,3 @@ code = ''' | |||||||
|      |      | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| # TODO FILES=26 found bug |  | ||||||
| #define.SIZE = [10, 100] |  | ||||||
| #define.FILES = [4, 10, 26]  |  | ||||||
| define = [ |  | ||||||
|     {SIZE=10, FILES=4}, |  | ||||||
|     {SIZE=10, FILES=10}, |  | ||||||
|     #{SIZE=10, FILES=26}, |  | ||||||
|     {SIZE=100, FILES=4}, |  | ||||||
|     #{SIZE=100, FILES=10}, |  | ||||||
|     #{SIZE=100, FILES=26}, |  | ||||||
| ] |  | ||||||
| reentrant = true |  | ||||||
|   | |||||||
							
								
								
									
										957
									
								
								tests_/test_move.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										957
									
								
								tests_/test_move.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,957 @@ | |||||||
|  | [[case]] # move file | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||||
|  |     lfs_file_write(&lfs, &file, "hola\n", 5) => 5; | ||||||
|  |     lfs_file_write(&lfs, &file, "bonjour\n", 8) => 8; | ||||||
|  |     lfs_file_write(&lfs, &file, "ohayo\n", 6) => 6; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hello") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_REG); | ||||||
|  |     assert(info.size == 5+8+6); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 5) => 5; | ||||||
|  |     memcmp(buffer, "hola\n", 5) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 8) => 8; | ||||||
|  |     memcmp(buffer, "bonjour\n", 8) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 6) => 6; | ||||||
|  |     memcmp(buffer, "ohayo\n", 6) => 0; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "d/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move file corrupt source | ||||||
|  | in = "lfs.c" | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||||
|  |     lfs_file_write(&lfs, &file, "hola\n", 5) => 5; | ||||||
|  |     lfs_file_write(&lfs, &file, "bonjour\n", 8) => 8; | ||||||
|  |     lfs_file_write(&lfs, &file, "ohayo\n", 6) => 6; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the source | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_block_t block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     int off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hello") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_REG); | ||||||
|  |     assert(info.size == 5+8+6); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 5) => 5; | ||||||
|  |     memcmp(buffer, "hola\n", 5) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 8) => 8; | ||||||
|  |     memcmp(buffer, "bonjour\n", 8) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 6) => 6; | ||||||
|  |     memcmp(buffer, "ohayo\n", 6) => 0; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "d/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move file corrupt source and dest | ||||||
|  | in = "lfs.c" | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||||
|  |     lfs_file_write(&lfs, &file, "hola\n", 5) => 5; | ||||||
|  |     lfs_file_write(&lfs, &file, "bonjour\n", 8) => 8; | ||||||
|  |     lfs_file_write(&lfs, &file, "ohayo\n", 6) => 6; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the source | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_block_t block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     int off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the destination | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hello") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_REG); | ||||||
|  |     assert(info.size == 5+8+6); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 5) => 5; | ||||||
|  |     memcmp(buffer, "hola\n", 5) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 8) => 8; | ||||||
|  |     memcmp(buffer, "bonjour\n", 8) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 6) => 6; | ||||||
|  |     memcmp(buffer, "ohayo\n", 6) => 0; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "d/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move file after corrupt | ||||||
|  | in = "lfs.c" | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||||
|  |     lfs_file_write(&lfs, &file, "hola\n", 5) => 5; | ||||||
|  |     lfs_file_write(&lfs, &file, "bonjour\n", 8) => 8; | ||||||
|  |     lfs_file_write(&lfs, &file, "ohayo\n", 6) => 6; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the source | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_block_t block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     int off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the destination | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     // continue move | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hello", "c/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hello") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_REG); | ||||||
|  |     assert(info.size == 5+8+6); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 5) => 5; | ||||||
|  |     memcmp(buffer, "hola\n", 5) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 8) => 8; | ||||||
|  |     memcmp(buffer, "bonjour\n", 8) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 6) => 6; | ||||||
|  |     memcmp(buffer, "ohayo\n", 6) => 0; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "d/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # simple reentrant move file | ||||||
|  | reentrant = true | ||||||
|  | code = ''' | ||||||
|  |     err = lfs_mount(&lfs, &cfg); | ||||||
|  |     if (err) { | ||||||
|  |         lfs_format(&lfs, &cfg) => 0; | ||||||
|  |         lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     } | ||||||
|  |     err = lfs_mkdir(&lfs, "a"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     err = lfs_mkdir(&lfs, "b"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     err = lfs_mkdir(&lfs, "c"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     err = lfs_mkdir(&lfs, "d"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|  |         lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |         // there should never exist _2_ hello files | ||||||
|  |         int count = 0; | ||||||
|  |         if (lfs_stat(&lfs, "a/hello", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hello") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_REG); | ||||||
|  |             assert(info.size == 5+8+6 || info.size == 0); | ||||||
|  |             count += 1; | ||||||
|  |         } | ||||||
|  |         if (lfs_stat(&lfs, "b/hello", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hello") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_REG); | ||||||
|  |             assert(info.size == 5+8+6); | ||||||
|  |             count += 1;  | ||||||
|  |         } | ||||||
|  |         if (lfs_stat(&lfs, "c/hello", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hello") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_REG); | ||||||
|  |             assert(info.size == 5+8+6); | ||||||
|  |             count += 1; | ||||||
|  |         } | ||||||
|  |         if (lfs_stat(&lfs, "d/hello", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hello") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_REG); | ||||||
|  |             assert(info.size == 5+8+6); | ||||||
|  |             count += 1; | ||||||
|  |         } | ||||||
|  |         assert(count <= 1); | ||||||
|  |         lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |         lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |         if (lfs_stat(&lfs, "a/hello", &info) == 0 && info.size > 0) { | ||||||
|  |             lfs_rename(&lfs, "a/hello", "b/hello") => 0; | ||||||
|  |         } else if (lfs_stat(&lfs, "b/hello", &info) == 0) { | ||||||
|  |             lfs_rename(&lfs, "b/hello", "c/hello") => 0; | ||||||
|  |         } else if (lfs_stat(&lfs, "c/hello", &info) == 0) { | ||||||
|  |             lfs_rename(&lfs, "c/hello", "d/hello") => 0; | ||||||
|  |         } else if (lfs_stat(&lfs, "d/hello", &info) == 0) { | ||||||
|  |             // success | ||||||
|  |             break; | ||||||
|  |         } else { | ||||||
|  |             // create file | ||||||
|  |             lfs_file_open(&lfs, &file, "a/hello", | ||||||
|  |                     LFS_O_WRONLY | LFS_O_CREAT) => 0; | ||||||
|  |             lfs_file_write(&lfs, &file, "hola\n", 5) => 5; | ||||||
|  |             lfs_file_write(&lfs, &file, "bonjour\n", 8) => 8; | ||||||
|  |             lfs_file_write(&lfs, &file, "ohayo\n", 6) => 6; | ||||||
|  |             lfs_file_close(&lfs, &file) => 0; | ||||||
|  |         } | ||||||
|  |         lfs_unmount(&lfs) => 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "d") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hello") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_REG); | ||||||
|  |     assert(info.size == 5+8+6); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "d/hello", LFS_O_RDONLY) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 5) => 5; | ||||||
|  |     memcmp(buffer, "hola\n", 5) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 8) => 8; | ||||||
|  |     memcmp(buffer, "bonjour\n", 8) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 6) => 6; | ||||||
|  |     memcmp(buffer, "ohayo\n", 6) => 0; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move dir | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/hola") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/bonjour") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hi") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "b/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c/hi") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "bonjour") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hola") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "ohayo") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "d/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move dir corrupt source | ||||||
|  | in = "lfs.c" | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/hola") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/bonjour") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the source | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_block_t block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     int off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hi") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "b/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c/hi") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "bonjour") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hola") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "ohayo") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "d/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move dir corrupt source and dest | ||||||
|  | in = "lfs.c" | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/hola") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/bonjour") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the source | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_block_t block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     int off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the destination | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hi") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a/hi") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "bonjour") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hola") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "ohayo") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "b/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "d/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move dir after corrupt | ||||||
|  | in = "lfs.c" | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/hola") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/bonjour") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a/hi/ohayo") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the source | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_block_t block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     int off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the destination | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     // continue move | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hi", "c/hi") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hi") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "b/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c/hi") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "bonjour") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hola") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "ohayo") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "d/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # simple reentrant move dir | ||||||
|  | reentrant = true | ||||||
|  | code = ''' | ||||||
|  |     err = lfs_mount(&lfs, &cfg); | ||||||
|  |     if (err) { | ||||||
|  |         lfs_format(&lfs, &cfg) => 0; | ||||||
|  |         lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     } | ||||||
|  |     err = lfs_mkdir(&lfs, "a"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     err = lfs_mkdir(&lfs, "b"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     err = lfs_mkdir(&lfs, "c"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     err = lfs_mkdir(&lfs, "d"); | ||||||
|  |     assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|  |         lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |         // there should never exist _2_ hi directories | ||||||
|  |         int count = 0; | ||||||
|  |         if (lfs_stat(&lfs, "a/hi", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hi") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_DIR); | ||||||
|  |             count += 1; | ||||||
|  |         } | ||||||
|  |         if (lfs_stat(&lfs, "b/hi", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hi") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_DIR); | ||||||
|  |             count += 1;  | ||||||
|  |         } | ||||||
|  |         if (lfs_stat(&lfs, "c/hi", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hi") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_DIR); | ||||||
|  |             count += 1; | ||||||
|  |         } | ||||||
|  |         if (lfs_stat(&lfs, "d/hi", &info) == 0) { | ||||||
|  |             assert(strcmp(info.name, "hi") == 0); | ||||||
|  |             assert(info.type == LFS_TYPE_DIR); | ||||||
|  |             count += 1; | ||||||
|  |         } | ||||||
|  |         assert(count <= 1); | ||||||
|  |         lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |         lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |         if (lfs_stat(&lfs, "a/hi", &info) == 0) { | ||||||
|  |             lfs_rename(&lfs, "a/hi", "b/hi") => 0; | ||||||
|  |         } else if (lfs_stat(&lfs, "b/hi", &info) == 0) { | ||||||
|  |             lfs_rename(&lfs, "b/hi", "c/hi") => 0; | ||||||
|  |         } else if (lfs_stat(&lfs, "c/hi", &info) == 0) { | ||||||
|  |             lfs_rename(&lfs, "c/hi", "d/hi") => 0; | ||||||
|  |         } else if (lfs_stat(&lfs, "d/hi", &info) == 0) { | ||||||
|  |             break; // success | ||||||
|  |         } else { | ||||||
|  |             // create dir and rename for atomicity | ||||||
|  |             err = lfs_mkdir(&lfs, "temp"); | ||||||
|  |             assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |             err = lfs_mkdir(&lfs, "temp/hola"); | ||||||
|  |             assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |             err = lfs_mkdir(&lfs, "temp/bonjour"); | ||||||
|  |             assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |             err = lfs_mkdir(&lfs, "temp/ohayo"); | ||||||
|  |             assert(!err || err == LFS_ERR_EXIST); | ||||||
|  |             lfs_rename(&lfs, "temp", "a/hi") => 0; | ||||||
|  |         } | ||||||
|  |         lfs_unmount(&lfs) => 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "d") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hi") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_open(&lfs, &dir, "a/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "b/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "c/hi") => LFS_ERR_NOENT; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "d/hi") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, ".") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "..") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "bonjour") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "hola") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 1; | ||||||
|  |     assert(strcmp(info.name, "ohayo") == 0); | ||||||
|  |     assert(info.type == LFS_TYPE_DIR); | ||||||
|  |     lfs_dir_read(&lfs, &dir, &info) => 0; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
|  |  | ||||||
|  | [[case]] # move state stealing | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "a") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "b") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "c") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "d") => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||||
|  |     lfs_file_write(&lfs, &file, "hola\n", 5) => 5; | ||||||
|  |     lfs_file_write(&lfs, &file, "bonjour\n", 8) => 8; | ||||||
|  |     lfs_file_write(&lfs, &file, "ohayo\n", 6) => 6; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "a/hello", "b/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "b/hello", "c/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_rename(&lfs, "c/hello", "d/hello") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "d/hello", LFS_O_RDONLY) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 5) => 5; | ||||||
|  |     memcmp(buffer, "hola\n", 5) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 8) => 8; | ||||||
|  |     memcmp(buffer, "bonjour\n", 8) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 6) => 6; | ||||||
|  |     memcmp(buffer, "ohayo\n", 6) => 0; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_remove(&lfs, "b") => 0; | ||||||
|  |     lfs_remove(&lfs, "c") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_stat(&lfs, "a", &info) => 0; | ||||||
|  |     lfs_stat(&lfs, "b", &info) => LFS_ERR_NOENT; | ||||||
|  |     lfs_stat(&lfs, "c", &info) => LFS_ERR_NOENT; | ||||||
|  |     lfs_stat(&lfs, "d", &info) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file, "a/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "b/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "c/hello", LFS_O_RDONLY) => LFS_ERR_NOENT; | ||||||
|  |     lfs_file_open(&lfs, &file, "d/hello", LFS_O_RDONLY) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 5) => 5; | ||||||
|  |     memcmp(buffer, "hola\n", 5) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 8) => 8; | ||||||
|  |     memcmp(buffer, "bonjour\n", 8) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file, buffer, 6) => 6; | ||||||
|  |     memcmp(buffer, "ohayo\n", 6) => 0; | ||||||
|  |     lfs_file_close(&lfs, &file) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
							
								
								
									
										56
									
								
								tests_/test_orphan.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								tests_/test_orphan.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | [[case]] # orphan test | ||||||
|  | in = "lfs.c" | ||||||
|  | code = ''' | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "parent") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "parent/orphan") => 0; | ||||||
|  |     lfs_mkdir(&lfs, "parent/child") => 0; | ||||||
|  |     lfs_remove(&lfs, "parent/orphan") => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     // corrupt the child's most recent commit, this should be the update | ||||||
|  |     // to the linked-list entry, which should orphan the orphan. Note this | ||||||
|  |     // makes a lot of assumptions about the remove operation. | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir, "parent/child") => 0; | ||||||
|  |     lfs_block_t block = dir.m.pair[0]; | ||||||
|  |     lfs_dir_close(&lfs, &dir) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |     uint8_t bbuffer[LFS_BLOCK_SIZE]; | ||||||
|  |     cfg.read(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     int off = LFS_BLOCK_SIZE-1; | ||||||
|  |     while (off >= 0 && bbuffer[off] == LFS_ERASE_VALUE) { | ||||||
|  |         off -= 1; | ||||||
|  |     } | ||||||
|  |     memset(&bbuffer[off-3], LFS_BLOCK_SIZE, 3); | ||||||
|  |     cfg.erase(&cfg, block) => 0; | ||||||
|  |     cfg.prog(&cfg, block, 0, bbuffer, LFS_BLOCK_SIZE) => 0; | ||||||
|  |     cfg.sync(&cfg) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; | ||||||
|  |     lfs_stat(&lfs, "parent/child", &info) => 0; | ||||||
|  |     lfs_fs_size(&lfs) => 8; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; | ||||||
|  |     lfs_stat(&lfs, "parent/child", &info) => 0; | ||||||
|  |     lfs_fs_size(&lfs) => 8; | ||||||
|  |     // this mkdir should both create a dir and deorphan, so size | ||||||
|  |     // should be unchanged | ||||||
|  |     lfs_mkdir(&lfs, "parent/otherchild") => 0; | ||||||
|  |     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; | ||||||
|  |     lfs_stat(&lfs, "parent/child", &info) => 0; | ||||||
|  |     lfs_stat(&lfs, "parent/otherchild", &info) => 0; | ||||||
|  |     lfs_fs_size(&lfs) => 8; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  |  | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; | ||||||
|  |     lfs_stat(&lfs, "parent/child", &info) => 0; | ||||||
|  |     lfs_stat(&lfs, "parent/otherchild", &info) => 0; | ||||||
|  |     lfs_fs_size(&lfs) => 8; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | ''' | ||||||
| @@ -1,5 +1,13 @@ | |||||||
|  |  | ||||||
| [[case]] # simple file seek | [[case]] # simple file seek | ||||||
|  | define = [ | ||||||
|  |     {COUNT=132, SKIP=4}, | ||||||
|  |     {COUNT=132, SKIP=128}, | ||||||
|  |     {COUNT=200, SKIP=10}, | ||||||
|  |     {COUNT=200, SKIP=100}, | ||||||
|  |     {COUNT=4,   SKIP=1}, | ||||||
|  |     {COUNT=4,   SKIP=2}, | ||||||
|  | ] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -59,6 +67,8 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
|  |  | ||||||
|  | [[case]] # simple file seek and write | ||||||
| define = [ | define = [ | ||||||
|     {COUNT=132, SKIP=4}, |     {COUNT=132, SKIP=4}, | ||||||
|     {COUNT=132, SKIP=128}, |     {COUNT=132, SKIP=128}, | ||||||
| @@ -67,8 +77,6 @@ define = [ | |||||||
|     {COUNT=4,   SKIP=1}, |     {COUNT=4,   SKIP=1}, | ||||||
|     {COUNT=4,   SKIP=2}, |     {COUNT=4,   SKIP=2}, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[case]] # simple file seek and write |  | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -120,16 +128,10 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define = [ |  | ||||||
|     {COUNT=132, SKIP=4}, |  | ||||||
|     {COUNT=132, SKIP=128}, |  | ||||||
|     {COUNT=200, SKIP=10}, |  | ||||||
|     {COUNT=200, SKIP=100}, |  | ||||||
|     {COUNT=4,   SKIP=1}, |  | ||||||
|     {COUNT=4,   SKIP=2}, |  | ||||||
| ] |  | ||||||
|  |  | ||||||
| [[case]] # boundary seek and writes | [[case]] # boundary seek and writes | ||||||
|  | define.COUNT = 132 | ||||||
|  | define.OFFSETS = '"{512, 1020, 513, 1021, 511, 1019, 1441}"' | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -180,10 +182,16 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.COUNT = 132 |  | ||||||
| define.OFFSETS = '"{512, 1020, 513, 1021, 511, 1019, 1441}"' |  | ||||||
|  |  | ||||||
| [[case]] # out of bounds seek | [[case]] # out of bounds seek | ||||||
|  | define = [ | ||||||
|  |     {COUNT=132, SKIP=4}, | ||||||
|  |     {COUNT=132, SKIP=128}, | ||||||
|  |     {COUNT=200, SKIP=10}, | ||||||
|  |     {COUNT=200, SKIP=100}, | ||||||
|  |     {COUNT=4,   SKIP=2}, | ||||||
|  |     {COUNT=4,   SKIP=3}, | ||||||
|  | ] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -229,16 +237,9 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define = [ |  | ||||||
|     {COUNT=132, SKIP=4}, |  | ||||||
|     {COUNT=132, SKIP=128}, |  | ||||||
|     {COUNT=200, SKIP=10}, |  | ||||||
|     {COUNT=200, SKIP=100}, |  | ||||||
|     {COUNT=4,   SKIP=2}, |  | ||||||
|     {COUNT=4,   SKIP=3}, |  | ||||||
| ] |  | ||||||
|  |  | ||||||
| [[case]] # inline write and seek | [[case]] # inline write and seek | ||||||
|  | define.SIZE = [2, 4, 128, 132] | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -303,9 +304,11 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.SIZE = [2, 4, 128, 132] |  | ||||||
|  |  | ||||||
| [[case]] # file seek and write with power-loss | [[case]] # file seek and write with power-loss | ||||||
|  | # must be power-of-2 for quadratic probing to be exhaustive | ||||||
|  | define.COUNT = [4, 64, 128] | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -375,6 +378,3 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| # must be power-of-2 for quadratic probing to be exhaustive |  | ||||||
| define.COUNT = [4, 64, 128] |  | ||||||
| reentrant = true |  | ||||||
|   | |||||||
| @@ -1,4 +1,6 @@ | |||||||
| [[case]] # simple truncate | [[case]] # simple truncate | ||||||
|  | define.MEDIUMSIZE = [32, 2048] | ||||||
|  | define.LARGESIZE = 8192 | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -39,10 +41,10 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.MEDIUMSIZE = [32, 2048] |  | ||||||
| define.LARGESIZE = 8192 |  | ||||||
|  |  | ||||||
| [[case]] # truncate and read | [[case]] # truncate and read | ||||||
|  | define.MEDIUMSIZE = [32, 2048] | ||||||
|  | define.LARGESIZE = 8192 | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -90,8 +92,6 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.MEDIUMSIZE = [32, 2048] |  | ||||||
| define.LARGESIZE = 8192 |  | ||||||
|  |  | ||||||
| [[case]] # write, truncate, and read | [[case]] # write, truncate, and read | ||||||
| code = ''' | code = ''' | ||||||
| @@ -146,6 +146,8 @@ code = ''' | |||||||
| ''' | ''' | ||||||
|  |  | ||||||
| [[case]] # truncate and write | [[case]] # truncate and write | ||||||
|  | define.MEDIUMSIZE = [32, 2048] | ||||||
|  | define.LARGESIZE = 8192 | ||||||
| code = ''' | code = ''' | ||||||
|     lfs_format(&lfs, &cfg) => 0; |     lfs_format(&lfs, &cfg) => 0; | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -193,10 +195,12 @@ code = ''' | |||||||
|     lfs_file_close(&lfs, &file) => 0; |     lfs_file_close(&lfs, &file) => 0; | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.MEDIUMSIZE = [32, 2048] |  | ||||||
| define.LARGESIZE = 8192 |  | ||||||
|  |  | ||||||
| [[case]] # truncate write under powerloss | [[case]] # truncate write under powerloss | ||||||
|  | define.SMALLSIZE = [4, 512] | ||||||
|  | define.MEDIUMSIZE = [32, 1024] | ||||||
|  | define.LARGESIZE = 2048 | ||||||
|  | reentrant = true | ||||||
| code = ''' | code = ''' | ||||||
|     err = lfs_mount(&lfs, &cfg); |     err = lfs_mount(&lfs, &cfg); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -257,12 +261,12 @@ code = ''' | |||||||
|  |  | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.SMALLSIZE = [4, 512] |  | ||||||
| define.MEDIUMSIZE = [32, 1024] |  | ||||||
| define.LARGESIZE = 2048 |  | ||||||
| reentrant = true |  | ||||||
|  |  | ||||||
| [[case]] # more aggressive general truncation tests | [[case]] # more aggressive general truncation tests | ||||||
|  | define.CONFIG = 'range(6)' | ||||||
|  | define.SMALLSIZE = 32 | ||||||
|  | define.MEDIUMSIZE = 2048 | ||||||
|  | define.LARGESIZE = 8192 | ||||||
| code = ''' | code = ''' | ||||||
|     #define COUNT 5 |     #define COUNT 5 | ||||||
|     const struct { |     const struct { | ||||||
| @@ -388,8 +392,3 @@ code = ''' | |||||||
|  |  | ||||||
|     lfs_unmount(&lfs) => 0; |     lfs_unmount(&lfs) => 0; | ||||||
| ''' | ''' | ||||||
| define.CONFIG = 'range(6)' |  | ||||||
| define.SMALLSIZE = 32 |  | ||||||
| define.MEDIUMSIZE = 2048 |  | ||||||
| define.LARGESIZE = 8192 |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user