From aab6aa0ed939303d7788e21bb547eb0a386636fb Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 26 Jan 2020 21:37:49 -0600 Subject: [PATCH] Cleaned up test script and directory naming - Removed old tests and test scripts - Reorganize the block devices to live under one directory - Plugged new test framework into Makefile renamed: - scripts/test_.py -> scripts/test.py - tests_ -> tests - {file,ram,test}bd/* -> bd/* It took a surprising amount of effort to make the Makefile behave since it turns out the "test_%" rule could override "tests/test_%.toml.test" which is generated as part of test.py. --- Makefile | 46 +- {filebd => bd}/lfs_filebd.c | 2 +- {filebd => bd}/lfs_filebd.h | 0 {rambd => bd}/lfs_rambd.c | 2 +- {rambd => bd}/lfs_rambd.h | 0 {testbd => bd}/lfs_testbd.c | 2 +- {testbd => bd}/lfs_testbd.h | 4 +- scripts/corrupt.py | 44 -- scripts/debug.py | 112 ---- scripts/results.py | 28 - scripts/template.fmt | 96 --- scripts/test.py | 787 +++++++++++++++++++++-- scripts/test_.py | 744 --------------------- tests/test_alloc.sh | 494 -------------- {tests_ => tests}/test_alloc.toml | 0 tests/test_attrs.sh | 294 --------- {tests_ => tests}/test_attrs.toml | 0 {tests_ => tests}/test_badblocks.toml | 0 tests/test_corrupt.sh | 120 ---- tests/test_dirs.sh | 489 -------------- {tests_ => tests}/test_dirs.toml | 0 tests/test_entries.sh | 251 -------- {tests_ => tests}/test_entries.toml | 0 {tests_ => tests}/test_exhaustion.toml | 0 tests/test_files.sh | 221 ------- {tests_ => tests}/test_files.toml | 0 tests/test_format.sh | 51 -- {tests_ => tests}/test_format.toml | 0 tests/test_interspersed.sh | 190 ------ {tests_ => tests}/test_interspersed.toml | 0 tests/test_move.sh | 333 ---------- {tests_ => tests}/test_move.toml | 0 tests/test_orphan.sh | 46 -- {tests_ => tests}/test_orphans.toml | 0 tests/test_paths.sh | 202 ------ {tests_ => tests}/test_paths.toml | 0 tests/test_relocations.sh | 139 ---- {tests_ => tests}/test_relocations.toml | 0 tests/test_seek.sh | 505 --------------- {tests_ => tests}/test_seek.toml | 0 tests/test_truncate.sh | 355 ---------- {tests_ => tests}/test_truncate.toml | 0 42 files changed, 741 insertions(+), 4816 deletions(-) rename {filebd => bd}/lfs_filebd.c (99%) rename {filebd => bd}/lfs_filebd.h (100%) rename {rambd => bd}/lfs_rambd.c (99%) rename {rambd => bd}/lfs_rambd.h (100%) rename {testbd => bd}/lfs_testbd.c (99%) rename {testbd => bd}/lfs_testbd.h (98%) delete mode 100755 scripts/corrupt.py delete mode 100755 scripts/debug.py delete mode 100755 scripts/results.py delete mode 100644 scripts/template.fmt delete mode 100755 scripts/test_.py delete mode 100755 tests/test_alloc.sh rename {tests_ => tests}/test_alloc.toml (100%) delete mode 100755 tests/test_attrs.sh rename {tests_ => tests}/test_attrs.toml (100%) rename {tests_ => tests}/test_badblocks.toml (100%) delete mode 100755 tests/test_corrupt.sh delete mode 100755 tests/test_dirs.sh rename {tests_ => tests}/test_dirs.toml (100%) delete mode 100755 tests/test_entries.sh rename {tests_ => tests}/test_entries.toml (100%) rename {tests_ => tests}/test_exhaustion.toml (100%) delete mode 100755 tests/test_files.sh rename {tests_ => tests}/test_files.toml (100%) delete mode 100755 tests/test_format.sh rename {tests_ => tests}/test_format.toml (100%) delete mode 100755 tests/test_interspersed.sh rename {tests_ => tests}/test_interspersed.toml (100%) delete mode 100755 tests/test_move.sh rename {tests_ => tests}/test_move.toml (100%) delete mode 100755 tests/test_orphan.sh rename {tests_ => tests}/test_orphans.toml (100%) delete mode 100755 tests/test_paths.sh rename {tests_ => tests}/test_paths.toml (100%) delete mode 100755 tests/test_relocations.sh rename {tests_ => tests}/test_relocations.toml (100%) delete mode 100755 tests/test_seek.sh rename {tests_ => tests}/test_seek.toml (100%) delete mode 100755 tests/test_truncate.sh rename {tests_ => tests}/test_truncate.toml (100%) diff --git a/Makefile b/Makefile index 67e1c9e..40245b8 100644 --- a/Makefile +++ b/Makefile @@ -7,15 +7,11 @@ CC ?= gcc AR ?= ar SIZE ?= size -SRC += $(wildcard *.c rambd/*.c filebd/*.c testbd/*.c) +SRC += $(wildcard *.c bd/*.c) OBJ := $(SRC:.c=.o) DEP := $(SRC:.c=.d) ASM := $(SRC:.c=.s) -TEST := $(patsubst tests/%.sh,%,$(wildcard tests/test_*)) - -SHELL = /bin/bash -o pipefail - ifdef DEBUG override CFLAGS += -O0 -g3 else @@ -33,6 +29,10 @@ override CFLAGS += -Wextra -Wshadow -Wjump-misses-init -Wundef # Remove missing-field-initializers because of GCC bug override CFLAGS += -Wno-missing-field-initializers +ifdef VERBOSE +override TFLAGS += -v +endif + all: $(TARGET) @@ -41,38 +41,14 @@ asm: $(ASM) size: $(OBJ) $(SIZE) -t $^ -.SUFFIXES: -test: \ - test_format \ - test_dirs \ - test_files \ - test_seek \ - test_truncate \ - test_entries \ - test_interspersed \ - test_alloc \ - test_paths \ - test_attrs \ - test_move \ - test_orphan \ - test_relocations \ - test_corrupt - @rm test.c -test_%: tests/test_%.sh -ifdef QUIET - @./$< | sed -nu '/^[-=]/p' -else - ./$< -endif - -test_: - ./scripts/test_.py $(TFLAGS) +test: + ./scripts/test.py $(TFLAGS) +.SECONDEXPANSION: +test%: tests/test$$(firstword $$(subst \#, ,%)).toml + ./scripts/test.py $(TFLAGS) $@ -include $(DEP) -%?: - @echo '$($*)' - lfs: $(OBJ) $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ @@ -90,4 +66,4 @@ clean: rm -f $(OBJ) rm -f $(DEP) rm -f $(ASM) - rm -f tests_/test_*.toml.* + rm -f tests/*.toml.* diff --git a/filebd/lfs_filebd.c b/bd/lfs_filebd.c similarity index 99% rename from filebd/lfs_filebd.c rename to bd/lfs_filebd.c index a897a02..01ba701 100644 --- a/filebd/lfs_filebd.c +++ b/bd/lfs_filebd.c @@ -4,7 +4,7 @@ * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ -#include "filebd/lfs_filebd.h" +#include "bd/lfs_filebd.h" #include #include diff --git a/filebd/lfs_filebd.h b/bd/lfs_filebd.h similarity index 100% rename from filebd/lfs_filebd.h rename to bd/lfs_filebd.h diff --git a/rambd/lfs_rambd.c b/bd/lfs_rambd.c similarity index 99% rename from rambd/lfs_rambd.c rename to bd/lfs_rambd.c index ce06556..c7c507c 100644 --- a/rambd/lfs_rambd.c +++ b/bd/lfs_rambd.c @@ -4,7 +4,7 @@ * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ -#include "rambd/lfs_rambd.h" +#include "bd/lfs_rambd.h" int lfs_rambd_createcfg(const struct lfs_config *cfg, const struct lfs_rambd_config *bdcfg) { diff --git a/rambd/lfs_rambd.h b/bd/lfs_rambd.h similarity index 100% rename from rambd/lfs_rambd.h rename to bd/lfs_rambd.h diff --git a/testbd/lfs_testbd.c b/bd/lfs_testbd.c similarity index 99% rename from testbd/lfs_testbd.c rename to bd/lfs_testbd.c index 0fae6bf..62cba01 100644 --- a/testbd/lfs_testbd.c +++ b/bd/lfs_testbd.c @@ -5,7 +5,7 @@ * Copyright (c) 2017, Arm Limited. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ -#include "testbd/lfs_testbd.h" +#include "bd/lfs_testbd.h" #include diff --git a/testbd/lfs_testbd.h b/bd/lfs_testbd.h similarity index 98% rename from testbd/lfs_testbd.h rename to bd/lfs_testbd.h index 9235457..78580d4 100644 --- a/testbd/lfs_testbd.h +++ b/bd/lfs_testbd.h @@ -10,8 +10,8 @@ #include "lfs.h" #include "lfs_util.h" -#include "rambd/lfs_rambd.h" -#include "filebd/lfs_filebd.h" +#include "bd/lfs_rambd.h" +#include "bd/lfs_filebd.h" #ifdef __cplusplus extern "C" diff --git a/scripts/corrupt.py b/scripts/corrupt.py deleted file mode 100755 index c452c42..0000000 --- a/scripts/corrupt.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python2 - -import struct -import sys -import os -import argparse - -def corrupt(block): - with open(block, 'r+b') as file: - # skip rev - file.read(4) - - # go to last commit - tag = 0xffffffff - while True: - try: - ntag, = struct.unpack('>I', file.read(4)) - except struct.error: - break - - tag ^= ntag - size = (tag & 0x3ff) if (tag & 0x3ff) != 0x3ff else 0 - file.seek(size, os.SEEK_CUR) - - # lob off last 3 bytes - file.seek(-(size + 3), os.SEEK_CUR) - file.truncate() - -def main(args): - if args.n or not args.blocks: - with open('blocks/.history', 'rb') as file: - for i in range(int(args.n or 1)): - last, = struct.unpack('I', data) - except struct.error: - break - - tag ^= ntag - off += 4 - - type = (tag & 0x7ff00000) >> 20 - id = (tag & 0x000ffc00) >> 10 - size = (tag & 0x000003ff) >> 0 - iscrc = (type & 0x700) == 0x500 - - data = file.read(size if size != 0x3ff else 0) - if iscrc: - crc = binascii.crc32(data[:4], crc) - else: - crc = binascii.crc32(data, crc) - - print '%04x: %08x %-15s %3s %4s %-23s %-8s' % ( - off, tag, - typeof(type) + (' bad!' if iscrc and ~crc else ''), - hex(id)[2:] if id != 0x3ff else '.', - size if size != 0x3ff else 'x', - ' '.join('%02x' % ord(c) for c in data[:8]), - ''.join(c if c >= ' ' and c <= '~' else '.' for c in data[:8])) - - off += size if size != 0x3ff else 0 - if iscrc: - crc = 0 - tag ^= (type & 1) << 31 - - return 0 - -if __name__ == "__main__": - import sys - sys.exit(main(*sys.argv[1:])) diff --git a/scripts/results.py b/scripts/results.py deleted file mode 100755 index 0e5cfc6..0000000 --- a/scripts/results.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python2 - -import struct -import sys -import time -import os -import re - -def main(): - with open('blocks/.config') as file: - read_size, prog_size, block_size, block_count = ( - struct.unpack(' -#include -#include - - -// test stuff -static void test_assert(const char *file, unsigned line, - const char *s, uintmax_t v, uintmax_t e) {{ - if (v != e) {{ - fprintf(stderr, "\033[97m%s:%u: \033[91m" - "assert failed with %jd, expected %jd\033[0m\n" - " %s\n\n", file, line, v, e, s); - exit(-2); - }} -}} - -#define test_assert(v, e) \ - test_assert(__FILE__, __LINE__, #v " => " #e, v, e) - -// implicit variable for asserts -uintmax_t test; - -// utility functions for traversals -static int __attribute__((used)) test_count(void *p, lfs_block_t b) {{ - (void)b; - unsigned *u = (unsigned*)p; - *u += 1; - return 0; -}} - -// lfs declarations -lfs_t lfs; -lfs_emubd_t bd; -// other declarations for convenience -lfs_file_t file; -lfs_dir_t dir; -struct lfs_info info; -uint8_t buffer[1024]; -char path[1024]; - -// test configuration options -#ifndef LFS_READ_SIZE -#define LFS_READ_SIZE 16 -#endif - -#ifndef LFS_PROG_SIZE -#define LFS_PROG_SIZE LFS_READ_SIZE -#endif - -#ifndef LFS_BLOCK_SIZE -#define LFS_BLOCK_SIZE 512 -#endif - -#ifndef LFS_BLOCK_COUNT -#define LFS_BLOCK_COUNT 1024 -#endif - -#ifndef LFS_BLOCK_CYCLES -#define LFS_BLOCK_CYCLES 1024 -#endif - -#ifndef LFS_CACHE_SIZE -#define LFS_CACHE_SIZE (64 % LFS_PROG_SIZE == 0 ? 64 : LFS_PROG_SIZE) -#endif - -#ifndef LFS_LOOKAHEAD_SIZE -#define LFS_LOOKAHEAD_SIZE 16 -#endif - -const struct lfs_config cfg = {{ - .context = &bd, - .read = &lfs_emubd_read, - .prog = &lfs_emubd_prog, - .erase = &lfs_emubd_erase, - .sync = &lfs_emubd_sync, - - .read_size = LFS_READ_SIZE, - .prog_size = LFS_PROG_SIZE, - .block_size = LFS_BLOCK_SIZE, - .block_count = LFS_BLOCK_COUNT, - .block_cycles = LFS_BLOCK_CYCLES, - .cache_size = LFS_CACHE_SIZE, - .lookahead_size = LFS_LOOKAHEAD_SIZE, -}}; - - -// Entry point -int main(void) {{ - lfs_emubd_create(&cfg, "blocks"); - -{tests} - lfs_emubd_destroy(&cfg); -}} diff --git a/scripts/test.py b/scripts/test.py index 3135c65..02801f8 100755 --- a/scripts/test.py +++ b/scripts/test.py @@ -1,81 +1,744 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 +# This script manages littlefs tests, which are configured with +# .toml files stored in the tests directory. +# + +import toml +import glob import re -import sys -import subprocess import os +import io +import itertools as it +import collections.abc as abc +import subprocess as sp +import base64 +import sys +import copy +import shlex +import pty +import errno +import signal +TESTDIR = 'tests' +RULES = """ +define FLATTEN +tests/%$(subst /,.,$(target)): $(target) + ./scripts/explode_asserts.py $$< -o $$@ +endef +$(foreach target,$(SRC),$(eval $(FLATTEN))) -def generate(test): - with open("scripts/template.fmt") as file: - template = file.read() +-include tests/*.d - haslines = 'TEST_LINE' in os.environ and 'TEST_FILE' in os.environ +.SECONDARY: +%.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f) + $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ +""" +GLOBALS = """ +//////////////// AUTOGENERATED TEST //////////////// +#include "lfs.h" +#include "bd/lfs_testbd.h" +#include +extern const char *lfs_testbd_path; +extern uint32_t lfs_testbd_cycles; +""" +DEFINES = { + 'LFS_READ_SIZE': 16, + 'LFS_PROG_SIZE': 'LFS_READ_SIZE', + 'LFS_BLOCK_SIZE': 512, + 'LFS_BLOCK_COUNT': 1024, + 'LFS_BLOCK_CYCLES': -1, + 'LFS_CACHE_SIZE': '(64 % LFS_PROG_SIZE == 0 ? 64 : LFS_PROG_SIZE)', + 'LFS_LOOKAHEAD_SIZE': 16, + 'LFS_ERASE_VALUE': 0xff, + 'LFS_ERASE_CYCLES': 0, + 'LFS_BADBLOCK_BEHAVIOR': 'LFS_TESTBD_BADBLOCK_NOPROG', +} +PROLOGUE = """ + // prologue + __attribute__((unused)) lfs_t lfs; + __attribute__((unused)) lfs_testbd_t bd; + __attribute__((unused)) lfs_file_t file; + __attribute__((unused)) lfs_dir_t dir; + __attribute__((unused)) struct lfs_info info; + __attribute__((unused)) char path[1024]; + __attribute__((unused)) uint8_t buffer[1024]; + __attribute__((unused)) lfs_size_t size; + __attribute__((unused)) int err; + + __attribute__((unused)) const struct lfs_config cfg = { + .context = &bd, + .read = lfs_testbd_read, + .prog = lfs_testbd_prog, + .erase = lfs_testbd_erase, + .sync = lfs_testbd_sync, + .read_size = LFS_READ_SIZE, + .prog_size = LFS_PROG_SIZE, + .block_size = LFS_BLOCK_SIZE, + .block_count = LFS_BLOCK_COUNT, + .block_cycles = LFS_BLOCK_CYCLES, + .cache_size = LFS_CACHE_SIZE, + .lookahead_size = LFS_LOOKAHEAD_SIZE, + }; - lines = [] - for offset, line in enumerate( - re.split('(?<=(?:.;| [{}]))\n', test.read())): - match = re.match('((?: *\n)*)( *)(.*)=>(.*);', - line, re.DOTALL | re.MULTILINE) - if match: - preface, tab, test, expect = match.groups() - lines.extend(['']*preface.count('\n')) - lines.append(tab+'test_assert({test}, {expect});'.format( - test=test.strip(), expect=expect.strip())) + __attribute__((unused)) const struct lfs_testbd_config bdcfg = { + .erase_value = LFS_ERASE_VALUE, + .erase_cycles = LFS_ERASE_CYCLES, + .badblock_behavior = LFS_BADBLOCK_BEHAVIOR, + .power_cycles = lfs_testbd_cycles, + }; + + lfs_testbd_createcfg(&cfg, lfs_testbd_path, &bdcfg) => 0; +""" +EPILOGUE = """ + // epilogue + lfs_testbd_destroy(&cfg) => 0; +""" +PASS = '\033[32m✓\033[0m' +FAIL = '\033[31m✗\033[0m' + +class TestFailure(Exception): + def __init__(self, case, returncode=None, stdout=None, assert_=None): + self.case = case + self.returncode = returncode + self.stdout = stdout + self.assert_ = assert_ + +class TestCase: + def __init__(self, config, filter=filter, + suite=None, caseno=None, lineno=None, **_): + self.config = config + self.filter = filter + self.suite = suite + self.caseno = caseno + self.lineno = lineno + + self.code = config['code'] + self.code_lineno = config['code_lineno'] + self.defines = config.get('define', {}) + self.if_ = config.get('if', None) + self.in_ = config.get('in', None) + + def __str__(self): + if hasattr(self, 'permno'): + if any(k not in self.case.defines for k in self.defines): + return '%s#%d#%d (%s)' % ( + self.suite.name, self.caseno, self.permno, ', '.join( + '%s=%s' % (k, v) for k, v in self.defines.items() + if k not in self.case.defines)) + else: + return '%s#%d#%d' % ( + self.suite.name, self.caseno, self.permno) else: - lines.append(line) + return '%s#%d' % ( + self.suite.name, self.caseno) - # Create test file - with open('test.c', 'w') as file: - if 'TEST_LINE' in os.environ and 'TEST_FILE' in os.environ: - lines.insert(0, '#line %d "%s"' % ( - int(os.environ['TEST_LINE']) + 1, - os.environ['TEST_FILE'])) - lines.append('#line %d "test.c"' % ( - template[:template.find('{tests}')].count('\n') - + len(lines) + 2)) + def permute(self, class_=None, defines={}, permno=None, **_): + ncase = (class_ or type(self))(self.config) + for k, v in self.__dict__.items(): + setattr(ncase, k, v) + ncase.case = self + ncase.perms = [ncase] + ncase.permno = permno + ncase.defines = defines + return ncase - file.write(template.format(tests='\n'.join(lines))) + def build(self, f, **_): + # prologue + for k, v in sorted(self.defines.items()): + if k not in self.suite.defines: + f.write('#define %s %s\n' % (k, v)) - # Remove build artifacts to force rebuild + f.write('void test_case%d(%s) {' % (self.caseno, ','.join( + '\n'+8*' '+'__attribute__((unused)) intmax_t %s' % k + for k in sorted(self.perms[0].defines) + if k not in self.defines))) + + f.write(PROLOGUE) + f.write('\n') + f.write(4*' '+'// test case %d\n' % self.caseno) + f.write(4*' '+'#line %d "%s"\n' % (self.code_lineno, self.suite.path)) + + # test case goes here + f.write(self.code) + + # epilogue + f.write(EPILOGUE) + f.write('}\n') + + for k, v in sorted(self.defines.items()): + if k not in self.suite.defines: + f.write('#undef %s\n' % k) + + def shouldtest(self, **args): + 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 args.get('no_internal', False) and self.in_ is not None: + return False + elif self.if_ is not None: + return eval(self.if_, None, self.defines.copy()) + else: + return True + + def test(self, exec=[], persist=False, cycles=None, + gdb=False, failure=None, **args): + # build command + cmd = exec + ['./%s.test' % self.suite.path, + repr(self.caseno), repr(self.permno)] + + # persist disk or keep in RAM for speed? + if persist: + if persist != 'noerase': + try: + os.remove(self.suite.path + '.disk') + if args.get('verbose', False): + print('rm', self.suite.path + '.disk') + except FileNotFoundError: + pass + + cmd.append(self.suite.path + '.disk') + + # simulate power-loss after n cycles? + if cycles: + cmd.append(str(cycles)) + + # failed? drop into debugger? + if gdb and failure: + ncmd = ['gdb'] + if gdb == 'assert': + ncmd.extend(['-ex', 'r']) + if failure.assert_: + ncmd.extend(['-ex', 'up 2']) + elif gdb == 'start': + ncmd.extend([ + '-ex', 'b %s:%d' % (self.suite.path, self.code_lineno), + '-ex', 'r']) + ncmd.extend(['--args'] + cmd) + + if args.get('verbose', False): + print(' '.join(shlex.quote(c) for c in ncmd)) + signal.signal(signal.SIGINT, signal.SIG_IGN) + sys.exit(sp.call(ncmd)) + + # run test case! + mpty, spty = pty.openpty() + if args.get('verbose', False): + print(' '.join(shlex.quote(c) for c in cmd)) + proc = sp.Popen(cmd, stdout=spty, stderr=spty) + os.close(spty) + mpty = os.fdopen(mpty, 'r', 1) + stdout = [] + assert_ = None + while True: + try: + line = mpty.readline() + except OSError as e: + if e.errno == errno.EIO: + break + raise + stdout.append(line) + if args.get('verbose', False): + sys.stdout.write(line) + # intercept asserts + m = re.match( + '^{0}([^:]+):(\d+):(?:\d+:)?{0}{1}:{0}(.*)$' + .format('(?:\033\[[\d;]*.| )*', 'assert'), + line) + if m and assert_ is None: + try: + with open(m.group(1)) as f: + lineno = int(m.group(2)) + line = next(it.islice(f, lineno-1, None)).strip('\n') + assert_ = { + 'path': m.group(1), + 'line': line, + 'lineno': lineno, + 'message': m.group(3)} + except: + pass + proc.wait() + + # did we pass? + if proc.returncode != 0: + raise TestFailure(self, proc.returncode, stdout, assert_) + else: + return PASS + +class ValgrindTestCase(TestCase): + def __init__(self, config, **args): + self.leaky = config.get('leaky', False) + super().__init__(config, **args) + + def shouldtest(self, **args): + return not self.leaky and super().shouldtest(**args) + + def test(self, exec=[], **args): + exec = exec + [ + 'valgrind', + '--leak-check=full', + '--error-exitcode=4', + '-q'] + return super().test(exec=exec, **args) + +class ReentrantTestCase(TestCase): + def __init__(self, config, **args): + self.reentrant = config.get('reentrant', False) + super().__init__(config, **args) + + def shouldtest(self, **args): + return self.reentrant and super().shouldtest(**args) + + def test(self, exec=[], persist=False, gdb=False, failure=None, **args): + for cycles in it.count(1): + # clear disk first? + if cycles == 1 and persist != 'noerase': + persist = 'erase' + else: + persist = 'noerase' + + # exact cycle we should drop into debugger? + if gdb and failure and failure.cycleno == cycles: + return super().test(gdb=gdb, persist=persist, cycles=cycles, + failure=failure, **args) + + # run tests, but kill the program after prog/erase has + # been hit n cycles. We exit with a special return code if the + # program has not finished, since this isn't a test failure. + try: + return super().test(persist=persist, cycles=cycles, **args) + except TestFailure as nfailure: + if nfailure.returncode == 33: + continue + else: + nfailure.cycleno = cycles + raise + +class TestSuite: + def __init__(self, path, classes=[TestCase], defines={}, + filter=None, **args): + self.name = os.path.basename(path) + if self.name.endswith('.toml'): + self.name = self.name[:-len('.toml')] + self.path = path + self.classes = classes + self.defines = defines.copy() + self.filter = filter + + with open(path) as f: + # load tests + config = toml.load(f) + + # find line numbers + f.seek(0) + linenos = [] + code_linenos = [] + for i, line in enumerate(f): + if re.match(r'\[\[\s*case\s*\]\]', line): + linenos.append(i+1) + if re.match(r'code\s*=\s*(\'\'\'|""")', line): + code_linenos.append(i+2) + + code_linenos.reverse() + + # grab global config + for k, v in config.get('define', {}).items(): + if k not in self.defines: + self.defines[k] = v + self.code = config.get('code', None) + if self.code is not None: + self.code_lineno = code_linenos.pop() + + # create initial test cases + self.cases = [] + for i, (case, lineno) in enumerate(zip(config['case'], linenos)): + # code lineno? + if 'code' in case: + case['code_lineno'] = code_linenos.pop() + # give our case's config a copy of our "global" config + for k, v in config.items(): + if k not in case: + case[k] = v + # initialize test case + self.cases.append(TestCase(case, filter=filter, + suite=self, caseno=i+1, lineno=lineno, **args)) + + def __str__(self): + return self.name + + def __lt__(self, other): + return self.name < other.name + + def permute(self, **args): + for case in self.cases: + # lets find all parameterized definitions, in one of [args.D, + # suite.defines, case.defines, DEFINES]. Note that each of these + # can be either a dict of defines, or a list of dicts, expressing + # an initial set of permutations. + pending = [{}] + for inits in [self.defines, case.defines, DEFINES]: + if not isinstance(inits, list): + inits = [inits] + + npending = [] + for init, pinit in it.product(inits, pending): + ninit = pinit.copy() + for k, v in init.items(): + if k not in ninit: + try: + ninit[k] = eval(v) + except: + ninit[k] = v + npending.append(ninit) + + pending = npending + + # expand permutations + pending = list(reversed(pending)) + expanded = [] + while pending: + perm = pending.pop() + for k, v in sorted(perm.items()): + if not isinstance(v, str) and isinstance(v, abc.Iterable): + for nv in reversed(v): + nperm = perm.copy() + nperm[k] = nv + pending.append(nperm) + break + else: + expanded.append(perm) + + # generate permutations + case.perms = [] + for i, (class_, defines) in enumerate( + it.product(self.classes, expanded)): + case.perms.append(case.permute( + class_, defines, permno=i+1, **args)) + + # also track non-unique defines + case.defines = {} + for k, v in case.perms[0].defines.items(): + if all(perm.defines[k] == v for perm in case.perms): + case.defines[k] = v + + # track all perms and non-unique defines + self.perms = [] + for case in self.cases: + self.perms.extend(case.perms) + + self.defines = {} + for k, v in self.perms[0].defines.items(): + if all(perm.defines.get(k, None) == v for perm in self.perms): + self.defines[k] = v + + return self.perms + + def build(self, **args): + # build test files + tf = open(self.path + '.test.c.t', 'w') + tf.write(GLOBALS) + if self.code is not None: + tf.write('#line %d "%s"\n' % (self.code_lineno, self.path)) + tf.write(self.code) + + tfs = {None: tf} + for case in self.cases: + if case.in_ not in tfs: + 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) + + tfs[case.in_].write('\n') + case.build(tfs[case.in_], **args) + + tf.write('\n') + tf.write('const char *lfs_testbd_path;\n') + tf.write('uint32_t lfs_testbd_cycles;\n') + tf.write('int main(int argc, char **argv) {\n') + tf.write(4*' '+'int case_ = (argc > 1) ? atoi(argv[1]) : 0;\n') + tf.write(4*' '+'int perm = (argc > 2) ? atoi(argv[2]) : 0;\n') + tf.write(4*' '+'lfs_testbd_path = (argc > 3) ? argv[3] : NULL;\n') + tf.write(4*' '+'lfs_testbd_cycles = (argc > 4) ? atoi(argv[4]) : 0;\n') + for perm in self.perms: + # test declaration + tf.write(4*' '+'extern void test_case%d(%s);\n' % ( + perm.caseno, ', '.join( + 'intmax_t %s' % k for k in sorted(perm.defines) + if k not in perm.case.defines))) + # test call + tf.write(4*' '+ + 'if (argc < 3 || (case_ == %d && perm == %d)) {' + ' test_case%d(%s); ' + '}\n' % (perm.caseno, perm.permno, perm.caseno, ', '.join( + str(v) for k, v in sorted(perm.defines.items()) + if k not in perm.case.defines))) + tf.write('}\n') + + for tf in tfs.values(): + tf.close() + + # write makefiles + with open(self.path + '.mk', 'w') as mk: + mk.write(RULES.replace(4*' ', '\t')) + mk.write('\n') + + # add truely global defines globally + for k, v in sorted(self.defines.items()): + mk.write('%s: override CFLAGS += -D%s=%r\n' % ( + self.path+'.test', k, v)) + + for path in tfs: + if path is None: + mk.write('%s: %s | %s\n' % ( + self.path+'.test.c', + self.path, + 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.target = self.path + '.test' + return self.makefile, self.target + + def test(self, **args): + # run test suite! + if not args.get('verbose', True): + sys.stdout.write(self.name + ' ') + sys.stdout.flush() + for perm in self.perms: + if not perm.shouldtest(**args): + continue + + try: + result = perm.test(**args) + except TestFailure as failure: + perm.result = failure + if not args.get('verbose', True): + sys.stdout.write(FAIL) + sys.stdout.flush() + if not args.get('keep_going', False): + if not args.get('verbose', True): + sys.stdout.write('\n') + raise + else: + perm.result = PASS + if not args.get('verbose', True): + sys.stdout.write(PASS) + sys.stdout.flush() + + if not args.get('verbose', True): + sys.stdout.write('\n') + +def main(**args): + # figure out explicit defines + defines = {} + for define in args['D']: + k, v, *_ = define.split('=', 2) + [''] + defines[k] = v + + # and what class of TestCase to run + classes = [] + if args.get('normal', False): + classes.append(TestCase) + if args.get('reentrant', False): + classes.append(ReentrantTestCase) + if args.get('valgrind', False): + classes.append(ValgrindTestCase) + if not classes: + classes = [TestCase] + + suites = [] + for testpath in args['testpaths']: + # optionally specified test case/perm + testpath, *filter = testpath.split('#') + filter = [int(f) for f in filter] + + # figure out the suite's toml file + if os.path.isdir(testpath): + testpath = testpath + '/test_*.toml' + elif os.path.isfile(testpath): + testpath = testpath + elif testpath.endswith('.toml'): + testpath = TESTDIR + '/' + testpath + else: + testpath = TESTDIR + '/' + testpath + '.toml' + + # find tests + for path in glob.glob(testpath): + suites.append(TestSuite(path, classes, defines, filter, **args)) + + # sort for reproducability + suites = sorted(suites) + + # generate permutations + for suite in suites: + suite.permute(**args) + + # build tests in parallel + print('====== building ======') + makefiles = [] + targets = [] + for suite in suites: + makefile, target = suite.build(**args) + makefiles.append(makefile) + targets.append(target) + + cmd = (['make', '-f', 'Makefile'] + + list(it.chain.from_iterable(['-f', m] for m in makefiles)) + + [target for target in targets]) + mpty, spty = pty.openpty() + if args.get('verbose', False): + print(' '.join(shlex.quote(c) for c in cmd)) + proc = sp.Popen(cmd, stdout=spty, stderr=spty) + os.close(spty) + mpty = os.fdopen(mpty, 'r', 1) + stdout = [] + while True: + try: + line = mpty.readline() + except OSError as e: + if e.errno == errno.EIO: + break + raise + stdout.append(line) + if args.get('verbose', False): + sys.stdout.write(line) + # intercept warnings + m = re.match( + '^{0}([^:]+):(\d+):(?:\d+:)?{0}{1}:{0}(.*)$' + .format('(?:\033\[[\d;]*.| )*', 'warning'), + line) + if m and not args.get('verbose', False): + try: + with open(m.group(1)) as f: + lineno = int(m.group(2)) + line = next(it.islice(f, lineno-1, None)).strip('\n') + sys.stdout.write( + "\033[01m{path}:{lineno}:\033[01;35mwarning:\033[m " + "{message}\n{line}\n\n".format( + path=m.group(1), line=line, lineno=lineno, + message=m.group(3))) + except: + pass + proc.wait() + + if proc.returncode != 0: + if not args.get('verbose', False): + for line in stdout: + sys.stdout.write(line) + sys.exit(-3) + + print('built %d test suites, %d test cases, %d permutations' % ( + len(suites), + sum(len(suite.cases) for suite in suites), + sum(len(suite.perms) for suite in suites))) + + filtered = 0 + for suite in suites: + for perm in suite.perms: + filtered += perm.shouldtest(**args) + if filtered != sum(len(suite.perms) for suite in suites): + print('filtered down to %d permutations' % filtered) + + print('====== testing ======') try: - os.remove('test.o') - os.remove('lfs') - except OSError: + for suite in suites: + suite.test(**args) + except TestFailure: pass -def compile(): - subprocess.check_call([ - os.environ.get('MAKE', 'make'), - '--no-print-directory', '-s']) + print('====== results ======') + passed = 0 + failed = 0 + for suite in suites: + for perm in suite.perms: + if not hasattr(perm, 'result'): + continue -def execute(): - if 'EXEC' in os.environ: - subprocess.check_call([os.environ['EXEC'], "./lfs"]) - else: - subprocess.check_call(["./lfs"]) + if perm.result == PASS: + passed += 1 + else: + sys.stdout.write( + "\033[01m{path}:{lineno}:\033[01;31mfailure:\033[m " + "{perm} failed with {returncode}\n".format( + perm=perm, path=perm.suite.path, lineno=perm.lineno, + returncode=perm.result.returncode or 0)) + if perm.result.stdout: + for line in (perm.result.stdout + if not perm.result.assert_ + else perm.result.stdout[:-1]): + sys.stdout.write(line) + if perm.result.assert_: + sys.stdout.write( + "\033[01m{path}:{lineno}:\033[01;31massert:\033[m " + "{message}\n{line}\n".format( + **perm.result.assert_)) + else: + for line in perm.result.stdout: + sys.stdout.write(line) + sys.stdout.write('\n') + failed += 1 -def main(test=None): - try: - if test and not test.startswith('-'): - with open(test) as file: - generate(file) - else: - generate(sys.stdin) + if args.get('gdb', False): + failure = None + for suite in suites: + for perm in suite.perms: + if getattr(perm, 'result', PASS) != PASS: + failure = perm.result + if failure is not None: + print('======= gdb ======') + # drop into gdb + failure.case.test(failure=failure, **args) + sys.exit(0) - compile() - - if test == '-s': - sys.exit(1) - - execute() - - except subprocess.CalledProcessError: - # Python stack trace is counterproductive, just exit - sys.exit(2) - except KeyboardInterrupt: - # Python stack trace is counterproductive, just exit - sys.exit(3) + print('tests passed: %d' % passed) + print('tests failed: %d' % failed) + return 1 if failed > 0 else 0 if __name__ == "__main__": - main(*sys.argv[1:]) + import argparse + parser = argparse.ArgumentParser( + description="Run parameterized tests in various configurations.") + parser.add_argument('testpaths', nargs='*', default=[TESTDIR], + help="Description of test(s) to run. By default, this is all tests \ + found in the \"{0}\" directory. Here, you can specify a different \ + directory of tests, a specific file, a suite by name, and even a \ + specific test case by adding brackets. For example \ + \"test_dirs[0]\" or \"{0}/test_dirs.toml[0]\".".format(TESTDIR)) + parser.add_argument('-D', action='append', default=[], + help="Overriding parameter definitions.") + parser.add_argument('-v', '--verbose', action='store_true', + help="Output everything that is happening.") + parser.add_argument('-k', '--keep-going', action='store_true', + help="Run all tests instead of stopping on first error. Useful for CI.") + parser.add_argument('-p', '--persist', choices=['erase', 'noerase'], + nargs='?', const='erase', + help="Store disk image in a file.") + parser.add_argument('-g', '--gdb', choices=['init', 'start', 'assert'], + nargs='?', const='assert', + help="Drop into gdb on test failure.") + parser.add_argument('--no-internal', action='store_true', + help="Don't run tests that require internal knowledge.") + parser.add_argument('-n', '--normal', action='store_true', + help="Run tests normally.") + parser.add_argument('-r', '--reentrant', action='store_true', + help="Run reentrant tests with simulated power-loss.") + parser.add_argument('-V', '--valgrind', action='store_true', + help="Run non-leaky tests under valgrind to check for memory leaks.") + parser.add_argument('-e', '--exec', default=[], type=lambda e: e.split(' '), + help="Run tests with another executable prefixed on the command line.") + sys.exit(main(**vars(parser.parse_args()))) diff --git a/scripts/test_.py b/scripts/test_.py deleted file mode 100755 index 4593b40..0000000 --- a/scripts/test_.py +++ /dev/null @@ -1,744 +0,0 @@ -#!/usr/bin/env python3 - -# This script manages littlefs tests, which are configured with -# .toml files stored in the tests directory. -# - -import toml -import glob -import re -import os -import io -import itertools as it -import collections.abc as abc -import subprocess as sp -import base64 -import sys -import copy -import shlex -import pty -import errno -import signal - -TESTDIR = 'tests_' -RULES = """ -define FLATTEN -tests_/%$(subst /,.,$(target)): $(target) - ./scripts/explode_asserts.py $$< -o $$@ -endef -$(foreach target,$(SRC),$(eval $(FLATTEN))) - --include tests_/*.d - -.SECONDARY: -%.test: %.test.o $(foreach f,$(subst /,.,$(SRC:.c=.o)),%.$f) - $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ -""" -GLOBALS = """ -//////////////// AUTOGENERATED TEST //////////////// -#include "lfs.h" -#include "testbd/lfs_testbd.h" -#include -extern const char *lfs_testbd_path; -extern uint32_t lfs_testbd_cycles; -""" -DEFINES = { - 'LFS_READ_SIZE': 16, - 'LFS_PROG_SIZE': 'LFS_READ_SIZE', - 'LFS_BLOCK_SIZE': 512, - 'LFS_BLOCK_COUNT': 1024, - 'LFS_BLOCK_CYCLES': -1, - 'LFS_CACHE_SIZE': '(64 % LFS_PROG_SIZE == 0 ? 64 : LFS_PROG_SIZE)', - 'LFS_LOOKAHEAD_SIZE': 16, - 'LFS_ERASE_VALUE': 0xff, - 'LFS_ERASE_CYCLES': 0, - 'LFS_BADBLOCK_BEHAVIOR': 'LFS_TESTBD_BADBLOCK_NOPROG', -} -PROLOGUE = """ - // prologue - __attribute__((unused)) lfs_t lfs; - __attribute__((unused)) lfs_testbd_t bd; - __attribute__((unused)) lfs_file_t file; - __attribute__((unused)) lfs_dir_t dir; - __attribute__((unused)) struct lfs_info info; - __attribute__((unused)) char path[1024]; - __attribute__((unused)) uint8_t buffer[1024]; - __attribute__((unused)) lfs_size_t size; - __attribute__((unused)) int err; - - __attribute__((unused)) const struct lfs_config cfg = { - .context = &bd, - .read = lfs_testbd_read, - .prog = lfs_testbd_prog, - .erase = lfs_testbd_erase, - .sync = lfs_testbd_sync, - .read_size = LFS_READ_SIZE, - .prog_size = LFS_PROG_SIZE, - .block_size = LFS_BLOCK_SIZE, - .block_count = LFS_BLOCK_COUNT, - .block_cycles = LFS_BLOCK_CYCLES, - .cache_size = LFS_CACHE_SIZE, - .lookahead_size = LFS_LOOKAHEAD_SIZE, - }; - - __attribute__((unused)) const struct lfs_testbd_config bdcfg = { - .erase_value = LFS_ERASE_VALUE, - .erase_cycles = LFS_ERASE_CYCLES, - .badblock_behavior = LFS_BADBLOCK_BEHAVIOR, - .power_cycles = lfs_testbd_cycles, - }; - - lfs_testbd_createcfg(&cfg, lfs_testbd_path, &bdcfg) => 0; -""" -EPILOGUE = """ - // epilogue - lfs_testbd_destroy(&cfg) => 0; -""" -PASS = '\033[32m✓\033[0m' -FAIL = '\033[31m✗\033[0m' - -class TestFailure(Exception): - def __init__(self, case, returncode=None, stdout=None, assert_=None): - self.case = case - self.returncode = returncode - self.stdout = stdout - self.assert_ = assert_ - -class TestCase: - def __init__(self, config, filter=filter, - suite=None, caseno=None, lineno=None, **_): - self.config = config - self.filter = filter - self.suite = suite - self.caseno = caseno - self.lineno = lineno - - self.code = config['code'] - self.code_lineno = config['code_lineno'] - self.defines = config.get('define', {}) - self.if_ = config.get('if', None) - self.in_ = config.get('in', None) - - def __str__(self): - if hasattr(self, 'permno'): - if any(k not in self.case.defines for k in self.defines): - return '%s#%d#%d (%s)' % ( - self.suite.name, self.caseno, self.permno, ', '.join( - '%s=%s' % (k, v) for k, v in self.defines.items() - if k not in self.case.defines)) - else: - return '%s#%d#%d' % ( - self.suite.name, self.caseno, self.permno) - else: - return '%s#%d' % ( - self.suite.name, self.caseno) - - def permute(self, class_=None, defines={}, permno=None, **_): - ncase = (class_ or type(self))(self.config) - for k, v in self.__dict__.items(): - setattr(ncase, k, v) - ncase.case = self - ncase.perms = [ncase] - ncase.permno = permno - ncase.defines = defines - return ncase - - def build(self, f, **_): - # prologue - for k, v in sorted(self.defines.items()): - if k not in self.suite.defines: - f.write('#define %s %s\n' % (k, v)) - - f.write('void test_case%d(%s) {' % (self.caseno, ','.join( - '\n'+8*' '+'__attribute__((unused)) intmax_t %s' % k - for k in sorted(self.perms[0].defines) - if k not in self.defines))) - - f.write(PROLOGUE) - f.write('\n') - f.write(4*' '+'// test case %d\n' % self.caseno) - f.write(4*' '+'#line %d "%s"\n' % (self.code_lineno, self.suite.path)) - - # test case goes here - f.write(self.code) - - # epilogue - f.write(EPILOGUE) - f.write('}\n') - - for k, v in sorted(self.defines.items()): - if k not in self.suite.defines: - f.write('#undef %s\n' % k) - - def shouldtest(self, **args): - 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 args.get('no_internal', False) and self.in_ is not None: - return False - elif self.if_ is not None: - return eval(self.if_, None, self.defines.copy()) - else: - return True - - def test(self, exec=[], persist=False, cycles=None, - gdb=False, failure=None, **args): - # build command - cmd = exec + ['./%s.test' % self.suite.path, - repr(self.caseno), repr(self.permno)] - - # persist disk or keep in RAM for speed? - if persist: - if persist != 'noerase': - try: - os.remove(self.suite.path + '.disk') - if args.get('verbose', False): - print('rm', self.suite.path + '.disk') - except FileNotFoundError: - pass - - cmd.append(self.suite.path + '.disk') - - # simulate power-loss after n cycles? - if cycles: - cmd.append(str(cycles)) - - # failed? drop into debugger? - if gdb and failure: - ncmd = ['gdb'] - if gdb == 'assert': - ncmd.extend(['-ex', 'r']) - if failure.assert_: - ncmd.extend(['-ex', 'up 2']) - elif gdb == 'start': - ncmd.extend([ - '-ex', 'b %s:%d' % (self.suite.path, self.code_lineno), - '-ex', 'r']) - ncmd.extend(['--args'] + cmd) - - if args.get('verbose', False): - print(' '.join(shlex.quote(c) for c in ncmd)) - signal.signal(signal.SIGINT, signal.SIG_IGN) - sys.exit(sp.call(ncmd)) - - # run test case! - mpty, spty = pty.openpty() - if args.get('verbose', False): - print(' '.join(shlex.quote(c) for c in cmd)) - proc = sp.Popen(cmd, stdout=spty, stderr=spty) - os.close(spty) - mpty = os.fdopen(mpty, 'r', 1) - stdout = [] - assert_ = None - while True: - try: - line = mpty.readline() - except OSError as e: - if e.errno == errno.EIO: - break - raise - stdout.append(line) - if args.get('verbose', False): - sys.stdout.write(line) - # intercept asserts - m = re.match( - '^{0}([^:]+):(\d+):(?:\d+:)?{0}{1}:{0}(.*)$' - .format('(?:\033\[[\d;]*.| )*', 'assert'), - line) - if m and assert_ is None: - try: - with open(m.group(1)) as f: - lineno = int(m.group(2)) - line = next(it.islice(f, lineno-1, None)).strip('\n') - assert_ = { - 'path': m.group(1), - 'line': line, - 'lineno': lineno, - 'message': m.group(3)} - except: - pass - proc.wait() - - # did we pass? - if proc.returncode != 0: - raise TestFailure(self, proc.returncode, stdout, assert_) - else: - return PASS - -class ValgrindTestCase(TestCase): - def __init__(self, config, **args): - self.leaky = config.get('leaky', False) - super().__init__(config, **args) - - def shouldtest(self, **args): - return not self.leaky and super().shouldtest(**args) - - def test(self, exec=[], **args): - exec = exec + [ - 'valgrind', - '--leak-check=full', - '--error-exitcode=4', - '-q'] - return super().test(exec=exec, **args) - -class ReentrantTestCase(TestCase): - def __init__(self, config, **args): - self.reentrant = config.get('reentrant', False) - super().__init__(config, **args) - - def shouldtest(self, **args): - return self.reentrant and super().shouldtest(**args) - - def test(self, exec=[], persist=False, gdb=False, failure=None, **args): - for cycles in it.count(1): - # clear disk first? - if cycles == 1 and persist != 'noerase': - persist = 'erase' - else: - persist = 'noerase' - - # exact cycle we should drop into debugger? - if gdb and failure and failure.cycleno == cycles: - return super().test(gdb=gdb, persist=persist, cycles=cycles, - failure=failure, **args) - - # run tests, but kill the program after prog/erase has - # been hit n cycles. We exit with a special return code if the - # program has not finished, since this isn't a test failure. - try: - return super().test(persist=persist, cycles=cycles, **args) - except TestFailure as nfailure: - if nfailure.returncode == 33: - continue - else: - nfailure.cycleno = cycles - raise - -class TestSuite: - def __init__(self, path, classes=[TestCase], defines={}, - filter=None, **args): - self.name = os.path.basename(path) - if self.name.endswith('.toml'): - self.name = self.name[:-len('.toml')] - self.path = path - self.classes = classes - self.defines = defines.copy() - self.filter = filter - - with open(path) as f: - # load tests - config = toml.load(f) - - # find line numbers - f.seek(0) - linenos = [] - code_linenos = [] - for i, line in enumerate(f): - if re.match(r'\[\[\s*case\s*\]\]', line): - linenos.append(i+1) - if re.match(r'code\s*=\s*(\'\'\'|""")', line): - code_linenos.append(i+2) - - code_linenos.reverse() - - # grab global config - for k, v in config.get('define', {}).items(): - if k not in self.defines: - self.defines[k] = v - self.code = config.get('code', None) - if self.code is not None: - self.code_lineno = code_linenos.pop() - - # create initial test cases - self.cases = [] - for i, (case, lineno) in enumerate(zip(config['case'], linenos)): - # code lineno? - if 'code' in case: - case['code_lineno'] = code_linenos.pop() - # give our case's config a copy of our "global" config - for k, v in config.items(): - if k not in case: - case[k] = v - # initialize test case - self.cases.append(TestCase(case, filter=filter, - suite=self, caseno=i+1, lineno=lineno, **args)) - - def __str__(self): - return self.name - - def __lt__(self, other): - return self.name < other.name - - def permute(self, **args): - for case in self.cases: - # lets find all parameterized definitions, in one of [args.D, - # suite.defines, case.defines, DEFINES]. Note that each of these - # can be either a dict of defines, or a list of dicts, expressing - # an initial set of permutations. - pending = [{}] - for inits in [self.defines, case.defines, DEFINES]: - if not isinstance(inits, list): - inits = [inits] - - npending = [] - for init, pinit in it.product(inits, pending): - ninit = pinit.copy() - for k, v in init.items(): - if k not in ninit: - try: - ninit[k] = eval(v) - except: - ninit[k] = v - npending.append(ninit) - - pending = npending - - # expand permutations - pending = list(reversed(pending)) - expanded = [] - while pending: - perm = pending.pop() - for k, v in sorted(perm.items()): - if not isinstance(v, str) and isinstance(v, abc.Iterable): - for nv in reversed(v): - nperm = perm.copy() - nperm[k] = nv - pending.append(nperm) - break - else: - expanded.append(perm) - - # generate permutations - case.perms = [] - for i, (class_, defines) in enumerate( - it.product(self.classes, expanded)): - case.perms.append(case.permute( - class_, defines, permno=i+1, **args)) - - # also track non-unique defines - case.defines = {} - for k, v in case.perms[0].defines.items(): - if all(perm.defines[k] == v for perm in case.perms): - case.defines[k] = v - - # track all perms and non-unique defines - self.perms = [] - for case in self.cases: - self.perms.extend(case.perms) - - self.defines = {} - for k, v in self.perms[0].defines.items(): - if all(perm.defines.get(k, None) == v for perm in self.perms): - self.defines[k] = v - - return self.perms - - def build(self, **args): - # build test files - tf = open(self.path + '.test.c.t', 'w') - tf.write(GLOBALS) - if self.code is not None: - tf.write('#line %d "%s"\n' % (self.code_lineno, self.path)) - tf.write(self.code) - - tfs = {None: tf} - for case in self.cases: - if case.in_ not in tfs: - 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) - - tfs[case.in_].write('\n') - case.build(tfs[case.in_], **args) - - tf.write('\n') - tf.write('const char *lfs_testbd_path;\n') - tf.write('uint32_t lfs_testbd_cycles;\n') - tf.write('int main(int argc, char **argv) {\n') - tf.write(4*' '+'int case_ = (argc > 1) ? atoi(argv[1]) : 0;\n') - tf.write(4*' '+'int perm = (argc > 2) ? atoi(argv[2]) : 0;\n') - tf.write(4*' '+'lfs_testbd_path = (argc > 3) ? argv[3] : NULL;\n') - tf.write(4*' '+'lfs_testbd_cycles = (argc > 4) ? atoi(argv[4]) : 0;\n') - for perm in self.perms: - # test declaration - tf.write(4*' '+'extern void test_case%d(%s);\n' % ( - perm.caseno, ', '.join( - 'intmax_t %s' % k for k in sorted(perm.defines) - if k not in perm.case.defines))) - # test call - tf.write(4*' '+ - 'if (argc < 3 || (case_ == %d && perm == %d)) {' - ' test_case%d(%s); ' - '}\n' % (perm.caseno, perm.permno, perm.caseno, ', '.join( - str(v) for k, v in sorted(perm.defines.items()) - if k not in perm.case.defines))) - tf.write('}\n') - - for tf in tfs.values(): - tf.close() - - # write makefiles - with open(self.path + '.mk', 'w') as mk: - mk.write(RULES.replace(4*' ', '\t')) - mk.write('\n') - - # add truely global defines globally - for k, v in sorted(self.defines.items()): - mk.write('%s: override CFLAGS += -D%s=%r\n' % ( - self.path+'.test', k, v)) - - for path in tfs: - if path is None: - mk.write('%s: %s | %s\n' % ( - self.path+'.test.c', - self.path, - 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.target = self.path + '.test' - return self.makefile, self.target - - def test(self, **args): - # run test suite! - if not args.get('verbose', True): - sys.stdout.write(self.name + ' ') - sys.stdout.flush() - for perm in self.perms: - if not perm.shouldtest(**args): - continue - - try: - result = perm.test(**args) - except TestFailure as failure: - perm.result = failure - if not args.get('verbose', True): - sys.stdout.write(FAIL) - sys.stdout.flush() - if not args.get('keep_going', False): - if not args.get('verbose', True): - sys.stdout.write('\n') - raise - else: - perm.result = PASS - if not args.get('verbose', True): - sys.stdout.write(PASS) - sys.stdout.flush() - - if not args.get('verbose', True): - sys.stdout.write('\n') - -def main(**args): - # figure out explicit defines - defines = {} - for define in args['D']: - k, v, *_ = define.split('=', 2) + [''] - defines[k] = v - - # and what class of TestCase to run - classes = [] - if args.get('normal', False): - classes.append(TestCase) - if args.get('reentrant', False): - classes.append(ReentrantTestCase) - if args.get('valgrind', False): - classes.append(ValgrindTestCase) - if not classes: - classes = [TestCase] - - suites = [] - for testpath in args['testpaths']: - # optionally specified test case/perm - testpath, *filter = testpath.split('#') - filter = [int(f) for f in filter] - - # figure out the suite's toml file - if os.path.isdir(testpath): - testpath = testpath + '/test_*.toml' - elif os.path.isfile(testpath): - testpath = testpath - elif testpath.endswith('.toml'): - testpath = TESTDIR + '/' + testpath - else: - testpath = TESTDIR + '/' + testpath + '.toml' - - # find tests - for path in glob.glob(testpath): - suites.append(TestSuite(path, classes, defines, filter, **args)) - - # sort for reproducability - suites = sorted(suites) - - # generate permutations - for suite in suites: - suite.permute(**args) - - # build tests in parallel - print('====== building ======') - makefiles = [] - targets = [] - for suite in suites: - makefile, target = suite.build(**args) - makefiles.append(makefile) - targets.append(target) - - cmd = (['make', '-f', 'Makefile'] + - list(it.chain.from_iterable(['-f', m] for m in makefiles)) + - [target for target in targets]) - mpty, spty = pty.openpty() - if args.get('verbose', False): - print(' '.join(shlex.quote(c) for c in cmd)) - proc = sp.Popen(cmd, stdout=spty, stderr=spty) - os.close(spty) - mpty = os.fdopen(mpty, 'r', 1) - stdout = [] - while True: - try: - line = mpty.readline() - except OSError as e: - if e.errno == errno.EIO: - break - raise - stdout.append(line) - if args.get('verbose', False): - sys.stdout.write(line) - # intercept warnings - m = re.match( - '^{0}([^:]+):(\d+):(?:\d+:)?{0}{1}:{0}(.*)$' - .format('(?:\033\[[\d;]*.| )*', 'warning'), - line) - if m and not args.get('verbose', False): - try: - with open(m.group(1)) as f: - lineno = int(m.group(2)) - line = next(it.islice(f, lineno-1, None)).strip('\n') - sys.stdout.write( - "\033[01m{path}:{lineno}:\033[01;35mwarning:\033[m " - "{message}\n{line}\n\n".format( - path=m.group(1), line=line, lineno=lineno, - message=m.group(3))) - except: - pass - proc.wait() - - if proc.returncode != 0: - if not args.get('verbose', False): - for line in stdout: - sys.stdout.write(line) - sys.exit(-3) - - print('built %d test suites, %d test cases, %d permutations' % ( - len(suites), - sum(len(suite.cases) for suite in suites), - sum(len(suite.perms) for suite in suites))) - - filtered = 0 - for suite in suites: - for perm in suite.perms: - filtered += perm.shouldtest(**args) - if filtered != sum(len(suite.perms) for suite in suites): - print('filtered down to %d permutations' % filtered) - - print('====== testing ======') - try: - for suite in suites: - suite.test(**args) - except TestFailure: - pass - - print('====== results ======') - passed = 0 - failed = 0 - for suite in suites: - for perm in suite.perms: - if not hasattr(perm, 'result'): - continue - - if perm.result == PASS: - passed += 1 - else: - sys.stdout.write( - "\033[01m{path}:{lineno}:\033[01;31mfailure:\033[m " - "{perm} failed with {returncode}\n".format( - perm=perm, path=perm.suite.path, lineno=perm.lineno, - returncode=perm.result.returncode or 0)) - if perm.result.stdout: - for line in (perm.result.stdout - if not perm.result.assert_ - else perm.result.stdout[:-1]): - sys.stdout.write(line) - if perm.result.assert_: - sys.stdout.write( - "\033[01m{path}:{lineno}:\033[01;31massert:\033[m " - "{message}\n{line}\n".format( - **perm.result.assert_)) - else: - for line in perm.result.stdout: - sys.stdout.write(line) - sys.stdout.write('\n') - failed += 1 - - if args.get('gdb', False): - failure = None - for suite in suites: - for perm in suite.perms: - if getattr(perm, 'result', PASS) != PASS: - failure = perm.result - if failure is not None: - print('======= gdb ======') - # drop into gdb - failure.case.test(failure=failure, **args) - sys.exit(0) - - print('tests passed: %d' % passed) - print('tests failed: %d' % failed) - return 1 if failed > 0 else 0 - -if __name__ == "__main__": - import argparse - parser = argparse.ArgumentParser( - description="Run parameterized tests in various configurations.") - parser.add_argument('testpaths', nargs='*', default=[TESTDIR], - help="Description of test(s) to run. By default, this is all tests \ - found in the \"{0}\" directory. Here, you can specify a different \ - directory of tests, a specific file, a suite by name, and even a \ - specific test case by adding brackets. For example \ - \"test_dirs[0]\" or \"{0}/test_dirs.toml[0]\".".format(TESTDIR)) - parser.add_argument('-D', action='append', default=[], - help="Overriding parameter definitions.") - parser.add_argument('-v', '--verbose', action='store_true', - help="Output everything that is happening.") - parser.add_argument('-k', '--keep-going', action='store_true', - help="Run all tests instead of stopping on first error. Useful for CI.") - parser.add_argument('-p', '--persist', choices=['erase', 'noerase'], - nargs='?', const='erase', - help="Store disk image in a file.") - parser.add_argument('-g', '--gdb', choices=['init', 'start', 'assert'], - nargs='?', const='assert', - help="Drop into gdb on test failure.") - parser.add_argument('--no-internal', action='store_true', - help="Don't run tests that require internal knowledge.") - parser.add_argument('-n', '--normal', action='store_true', - help="Run tests normally.") - parser.add_argument('-r', '--reentrant', action='store_true', - help="Run reentrant tests with simulated power-loss.") - parser.add_argument('-V', '--valgrind', action='store_true', - help="Run non-leaky tests under valgrind to check for memory leaks.") - parser.add_argument('-e', '--exec', default=[], type=lambda e: e.split(' '), - help="Run tests with another executable prefixed on the command line.") - sys.exit(main(**vars(parser.parse_args()))) diff --git a/tests/test_alloc.sh b/tests/test_alloc.sh deleted file mode 100755 index 0669850..0000000 --- a/tests/test_alloc.sh +++ /dev/null @@ -1,494 +0,0 @@ -#!/bin/bash -set -euE -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Allocator tests ===" -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -SIZE=15000 - -lfs_mkdir() { -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "$1") => 0; - lfs_unmount(&lfs) => 0; -TEST -} - -lfs_remove() { -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "$1/eggs") => 0; - lfs_remove(&lfs, "$1/bacon") => 0; - lfs_remove(&lfs, "$1/pancakes") => 0; - lfs_remove(&lfs, "$1") => 0; - lfs_unmount(&lfs) => 0; -TEST -} - -lfs_alloc_singleproc() { -scripts/test.py << TEST - const char *names[] = {"bacon", "eggs", "pancakes"}; - lfs_file_t files[sizeof(names)/sizeof(names[0])]; - lfs_mount(&lfs, &cfg) => 0; - for (unsigned n = 0; n < sizeof(names)/sizeof(names[0]); n++) { - sprintf(path, "$1/%s", names[n]); - lfs_file_open(&lfs, &files[n], path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; - } - for (unsigned n = 0; n < sizeof(names)/sizeof(names[0]); n++) { - lfs_size_t size = strlen(names[n]); - for (int i = 0; i < $SIZE; i++) { - lfs_file_write(&lfs, &files[n], names[n], size) => size; - } - } - for (unsigned n = 0; n < sizeof(names)/sizeof(names[0]); n++) { - lfs_file_close(&lfs, &files[n]) => 0; - } - lfs_unmount(&lfs) => 0; -TEST -} - -lfs_alloc_multiproc() { -for name in bacon eggs pancakes -do -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "$1/$name", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; - lfs_size_t size = strlen("$name"); - memcpy(buffer, "$name", size); - for (int i = 0; i < $SIZE; i++) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -done -} - -lfs_verify() { -for name in bacon eggs pancakes -do -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "$1/$name", LFS_O_RDONLY) => 0; - lfs_size_t size = strlen("$name"); - for (int i = 0; i < $SIZE; i++) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "$name", size) => 0; - } - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -done -} - -echo "--- Single-process allocation test ---" -lfs_mkdir singleproc -lfs_alloc_singleproc singleproc -lfs_verify singleproc - -echo "--- Multi-process allocation test ---" -lfs_mkdir multiproc -lfs_alloc_multiproc multiproc -lfs_verify multiproc -lfs_verify singleproc - -echo "--- Single-process reuse test ---" -lfs_remove singleproc -lfs_mkdir singleprocreuse -lfs_alloc_singleproc singleprocreuse -lfs_verify singleprocreuse -lfs_verify multiproc - -echo "--- Multi-process reuse test ---" -lfs_remove multiproc -lfs_mkdir multiprocreuse -lfs_alloc_singleproc multiprocreuse -lfs_verify multiprocreuse -lfs_verify singleprocreuse - -echo "--- Cleanup ---" -lfs_remove multiprocreuse -lfs_remove singleprocreuse - -echo "--- Exhaustion test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - lfs_size_t size = strlen("exhaustion"); - memcpy(buffer, "exhaustion", size); - lfs_file_write(&lfs, &file, buffer, size) => size; - lfs_file_sync(&lfs, &file) => 0; - - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - lfs_ssize_t res; - while (true) { - res = lfs_file_write(&lfs, &file, buffer, size); - if (res < 0) { - break; - } - - res => size; - } - res => LFS_ERR_NOSPC; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); - lfs_size_t size = strlen("exhaustion"); - lfs_file_size(&lfs, &file) => size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "exhaustion", size) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Exhaustion wraparound test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "exhaustion") => 0; - - lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT); - lfs_size_t size = strlen("buffering"); - memcpy(buffer, "buffering", size); - for (int i = 0; i < $SIZE; i++) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - lfs_remove(&lfs, "padding") => 0; - - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - size = strlen("exhaustion"); - memcpy(buffer, "exhaustion", size); - lfs_file_write(&lfs, &file, buffer, size) => size; - lfs_file_sync(&lfs, &file) => 0; - - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - lfs_ssize_t res; - while (true) { - res = lfs_file_write(&lfs, &file, buffer, size); - if (res < 0) { - break; - } - - res => size; - } - res => LFS_ERR_NOSPC; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); - lfs_size_t size = strlen("exhaustion"); - lfs_file_size(&lfs, &file) => size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "exhaustion", size) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_remove(&lfs, "exhaustion") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Dir exhaustion test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - - // find out max file size - lfs_mkdir(&lfs, "exhaustiondir") => 0; - lfs_size_t size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - int count = 0; - int err; - while (true) { - err = lfs_file_write(&lfs, &file, buffer, size); - if (err < 0) { - break; - } - - count += 1; - } - err => LFS_ERR_NOSPC; - lfs_file_close(&lfs, &file) => 0; - - lfs_remove(&lfs, "exhaustion") => 0; - lfs_remove(&lfs, "exhaustiondir") => 0; - - // see if dir fits with max file size - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - for (int i = 0; i < count; i++) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - lfs_mkdir(&lfs, "exhaustiondir") => 0; - lfs_remove(&lfs, "exhaustiondir") => 0; - lfs_remove(&lfs, "exhaustion") => 0; - - // see if dir fits with > max file size - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - for (int i = 0; i < count+1; i++) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - lfs_mkdir(&lfs, "exhaustiondir") => LFS_ERR_NOSPC; - - lfs_remove(&lfs, "exhaustion") => 0; - lfs_unmount(&lfs) => 0; -TEST - -## Below, these tests depend _very_ heavily on the geometry of the -## block device being tested, they should be removed and replaced -## by generalized tests. For now we'll just skip if the geometry -## is customized. - -if [[ ! $MAKEFLAGS =~ "LFS_BLOCK_CYCLES" ]] -then - -echo "--- Chained dir exhaustion test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - - // find out max file size - lfs_mkdir(&lfs, "exhaustiondir") => 0; - for (int i = 0; i < 10; i++) { - sprintf(path, "dirwithanexhaustivelylongnameforpadding%d", i); - lfs_mkdir(&lfs, path) => 0; - } - lfs_size_t size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - int count = 0; - int err; - while (true) { - err = lfs_file_write(&lfs, &file, buffer, size); - if (err < 0) { - break; - } - - count += 1; - } - err => LFS_ERR_NOSPC; - lfs_file_close(&lfs, &file) => 0; - - lfs_remove(&lfs, "exhaustion") => 0; - lfs_remove(&lfs, "exhaustiondir") => 0; - for (int i = 0; i < 10; i++) { - sprintf(path, "dirwithanexhaustivelylongnameforpadding%d", i); - lfs_remove(&lfs, path) => 0; - } - - // see that chained dir fails - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - for (int i = 0; i < count+1; i++) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_sync(&lfs, &file) => 0; - - for (int i = 0; i < 10; i++) { - sprintf(path, "dirwithanexhaustivelylongnameforpadding%d", i); - lfs_mkdir(&lfs, path) => 0; - } - - lfs_mkdir(&lfs, "exhaustiondir") => LFS_ERR_NOSPC; - - // shorten file to try a second chained dir - while (true) { - err = lfs_mkdir(&lfs, "exhaustiondir"); - if (err != LFS_ERR_NOSPC) { - break; - } - - lfs_ssize_t filesize = lfs_file_size(&lfs, &file); - filesize > 0 => true; - - lfs_file_truncate(&lfs, &file, filesize - size) => 0; - lfs_file_sync(&lfs, &file) => 0; - } - err => 0; - - lfs_mkdir(&lfs, "exhaustiondir2") => LFS_ERR_NOSPC; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Split dir test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - - // create one block hole for half a directory - lfs_file_open(&lfs, &file, "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0; - for (lfs_size_t i = 0; i < cfg.block_size; i += 2) { - memcpy(&buffer[i], "hi", 2); - } - lfs_file_write(&lfs, &file, buffer, cfg.block_size) => cfg.block_size; - lfs_file_close(&lfs, &file) => 0; - - lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); - lfs_size_t size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < (cfg.block_count-4)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - // remount to force reset of lookahead - lfs_unmount(&lfs) => 0; - lfs_mount(&lfs, &cfg) => 0; - - // open hole - lfs_remove(&lfs, "bump") => 0; - - lfs_mkdir(&lfs, "splitdir") => 0; - lfs_file_open(&lfs, &file, "splitdir/bump", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - for (lfs_size_t i = 0; i < cfg.block_size; i += 2) { - memcpy(&buffer[i], "hi", 2); - } - lfs_file_write(&lfs, &file, buffer, 2*cfg.block_size) => LFS_ERR_NOSPC; - lfs_file_close(&lfs, &file) => 0; - - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Outdated lookahead test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - lfs_mount(&lfs, &cfg) => 0; - - // fill completely with two files - lfs_file_open(&lfs, &file, "exhaustion1", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_size_t size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < ((cfg.block_count-2)/2)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - lfs_file_open(&lfs, &file, "exhaustion2", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < ((cfg.block_count-2+1)/2)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - // remount to force reset of lookahead - lfs_unmount(&lfs) => 0; - lfs_mount(&lfs, &cfg) => 0; - - // rewrite one file - lfs_file_open(&lfs, &file, "exhaustion1", - LFS_O_WRONLY | LFS_O_TRUNC) => 0; - lfs_file_sync(&lfs, &file) => 0; - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < ((cfg.block_count-2)/2)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - // rewrite second file, this requires lookahead does not - // use old population - lfs_file_open(&lfs, &file, "exhaustion2", - LFS_O_WRONLY | LFS_O_TRUNC) => 0; - lfs_file_sync(&lfs, &file) => 0; - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < ((cfg.block_count-2+1)/2)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; -TEST - -echo "--- Outdated lookahead and split dir test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - lfs_mount(&lfs, &cfg) => 0; - - // fill completely with two files - lfs_file_open(&lfs, &file, "exhaustion1", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_size_t size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < ((cfg.block_count-2)/2)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - lfs_file_open(&lfs, &file, "exhaustion2", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < ((cfg.block_count-2+1)/2)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - // remount to force reset of lookahead - lfs_unmount(&lfs) => 0; - lfs_mount(&lfs, &cfg) => 0; - - // rewrite one file with a hole of one block - lfs_file_open(&lfs, &file, "exhaustion1", - LFS_O_WRONLY | LFS_O_TRUNC) => 0; - lfs_file_sync(&lfs, &file) => 0; - size = strlen("blahblahblahblah"); - memcpy(buffer, "blahblahblahblah", size); - for (lfs_size_t i = 0; - i < ((cfg.block_count-2)/2 - 1)*(cfg.block_size-8); - i += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_close(&lfs, &file) => 0; - - // try to allocate a directory, should fail! - lfs_mkdir(&lfs, "split") => LFS_ERR_NOSPC; - - // file should not fail - lfs_file_open(&lfs, &file, "notasplit", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_write(&lfs, &file, "hi", 2) => 2; - lfs_file_close(&lfs, &file) => 0; - - lfs_unmount(&lfs) => 0; -TEST - -fi - -scripts/results.py diff --git a/tests_/test_alloc.toml b/tests/test_alloc.toml similarity index 100% rename from tests_/test_alloc.toml rename to tests/test_alloc.toml diff --git a/tests/test_attrs.sh b/tests/test_attrs.sh deleted file mode 100755 index 612cae1..0000000 --- a/tests/test_attrs.sh +++ /dev/null @@ -1,294 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Attr tests ===" -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "hello") => 0; - lfs_file_open(&lfs, &file, "hello/hello", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_write(&lfs, &file, "hello", strlen("hello")) - => strlen("hello"); - lfs_file_close(&lfs, &file); - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Set/get attribute ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(buffer, 0, sizeof(buffer)); - lfs_setattr(&lfs, "hello", 'A', "aaaa", 4) => 0; - lfs_setattr(&lfs, "hello", 'B', "bbbbbb", 6) => 0; - lfs_setattr(&lfs, "hello", 'C', "ccccc", 5) => 0; - lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6; - lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "bbbbbb", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "hello", 'B', "", 0) => 0; - lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 0; - lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_removeattr(&lfs, "hello", 'B') => 0; - lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => LFS_ERR_NOATTR; - lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "hello", 'B', "dddddd", 6) => 0; - lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6; - lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "dddddd", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "hello", 'B', "eee", 3) => 0; - lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 3; - lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "eee\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "hello", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC; - lfs_setattr(&lfs, "hello", 'B', "fffffffff", 9) => 0; - lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 9; - lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; - - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(buffer, 0, sizeof(buffer)); - lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "hello", 'B', buffer+4, 9) => 9; - lfs_getattr(&lfs, "hello", 'C', buffer+13, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "fffffffff", 9) => 0; - memcmp(buffer+13, "ccccc", 5) => 0; - - lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0; - lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello"); - memcmp(buffer, "hello", strlen("hello")) => 0; - lfs_file_close(&lfs, &file); - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Set/get root attribute ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(buffer, 0, sizeof(buffer)); - lfs_setattr(&lfs, "/", 'A', "aaaa", 4) => 0; - lfs_setattr(&lfs, "/", 'B', "bbbbbb", 6) => 0; - lfs_setattr(&lfs, "/", 'C', "ccccc", 5) => 0; - lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6; - lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "bbbbbb", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "/", 'B', "", 0) => 0; - lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 0; - lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_removeattr(&lfs, "/", 'B') => 0; - lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => LFS_ERR_NOATTR; - lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "/", 'B', "dddddd", 6) => 0; - lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6; - lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "dddddd", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "/", 'B', "eee", 3) => 0; - lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 3; - lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "eee\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - lfs_setattr(&lfs, "/", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC; - lfs_setattr(&lfs, "/", 'B', "fffffffff", 9) => 0; - lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 9; - lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(buffer, 0, sizeof(buffer)); - lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; - lfs_getattr(&lfs, "/", 'B', buffer+4, 9) => 9; - lfs_getattr(&lfs, "/", 'C', buffer+13, 5) => 5; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "fffffffff", 9) => 0; - memcmp(buffer+13, "ccccc", 5) => 0; - - lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0; - lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello"); - memcmp(buffer, "hello", strlen("hello")) => 0; - lfs_file_close(&lfs, &file); - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Set/get file attribute ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(buffer, 0, sizeof(buffer)); - struct lfs_attr attrs1[] = { - {'A', buffer, 4}, - {'B', buffer+4, 6}, - {'C', buffer+10, 5}, - }; - struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3}; - - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; - memcpy(buffer, "aaaa", 4); - memcpy(buffer+4, "bbbbbb", 6); - memcpy(buffer+10, "ccccc", 5); - lfs_file_close(&lfs, &file) => 0; - memset(buffer, 0, 15); - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; - lfs_file_close(&lfs, &file) => 0; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "bbbbbb", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - attrs1[1].size = 0; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; - lfs_file_close(&lfs, &file) => 0; - memset(buffer, 0, 15); - attrs1[1].size = 6; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; - lfs_file_close(&lfs, &file) => 0; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - attrs1[1].size = 6; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; - memcpy(buffer+4, "dddddd", 6); - lfs_file_close(&lfs, &file) => 0; - memset(buffer, 0, 15); - attrs1[1].size = 6; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; - lfs_file_close(&lfs, &file) => 0; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "dddddd", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - attrs1[1].size = 3; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; - memcpy(buffer+4, "eee", 3); - lfs_file_close(&lfs, &file) => 0; - memset(buffer, 0, 15); - attrs1[1].size = 6; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; - lfs_file_close(&lfs, &file) => 0; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "eee\0\0\0", 6) => 0; - memcmp(buffer+10, "ccccc", 5) => 0; - - attrs1[0].size = LFS_ATTR_MAX+1; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) - => LFS_ERR_NOSPC; - - struct lfs_attr attrs2[] = { - {'A', buffer, 4}, - {'B', buffer+4, 9}, - {'C', buffer+13, 5}, - }; - struct lfs_file_config cfg2 = {.attrs=attrs2, .attr_count=3}; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDWR, &cfg2) => 0; - memcpy(buffer+4, "fffffffff", 9); - lfs_file_close(&lfs, &file) => 0; - attrs1[0].size = 4; - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; - lfs_file_close(&lfs, &file) => 0; - - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(buffer, 0, sizeof(buffer)); - struct lfs_attr attrs2[] = { - {'A', buffer, 4}, - {'B', buffer+4, 9}, - {'C', buffer+13, 5}, - }; - struct lfs_file_config cfg2 = {.attrs=attrs2, .attr_count=3}; - - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg2) => 0; - lfs_file_close(&lfs, &file) => 0; - memcmp(buffer, "aaaa", 4) => 0; - memcmp(buffer+4, "fffffffff", 9) => 0; - memcmp(buffer+13, "ccccc", 5) => 0; - - lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0; - lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello"); - memcmp(buffer, "hello", strlen("hello")) => 0; - lfs_file_close(&lfs, &file); - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Deferred file attributes ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(buffer, 0, sizeof(buffer)); - struct lfs_attr attrs1[] = { - {'B', "gggg", 4}, - {'C', "", 0}, - {'D', "hhhh", 4}, - }; - struct lfs_file_config cfg1 = {.attrs=attrs1, .attr_count=3}; - - lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; - - lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 9; - lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 5; - lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => LFS_ERR_NOATTR; - memcmp(buffer, "fffffffff", 9) => 0; - memcmp(buffer+9, "ccccc\0\0\0\0", 9) => 0; - memcmp(buffer+18, "\0\0\0\0\0\0\0\0\0", 9) => 0; - - lfs_file_sync(&lfs, &file) => 0; - lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 4; - lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 0; - lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => 4; - memcmp(buffer, "gggg\0\0\0\0\0", 9) => 0; - memcmp(buffer+9, "\0\0\0\0\0\0\0\0\0", 9) => 0; - memcmp(buffer+18, "hhhh\0\0\0\0\0", 9) => 0; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_attrs.toml b/tests/test_attrs.toml similarity index 100% rename from tests_/test_attrs.toml rename to tests/test_attrs.toml diff --git a/tests_/test_badblocks.toml b/tests/test_badblocks.toml similarity index 100% rename from tests_/test_badblocks.toml rename to tests/test_badblocks.toml diff --git a/tests/test_corrupt.sh b/tests/test_corrupt.sh deleted file mode 100755 index 3001522..0000000 --- a/tests/test_corrupt.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Corrupt tests ===" - -NAMEMULT=64 -FILEMULT=1 - -lfs_mktree() { -scripts/test.py ${1:-} << TEST - lfs_format(&lfs, &cfg) => 0; - - lfs_mount(&lfs, &cfg) => 0; - for (int i = 1; i < 10; i++) { - for (int j = 0; j < $NAMEMULT; j++) { - buffer[j] = '0'+i; - } - buffer[$NAMEMULT] = '\0'; - lfs_mkdir(&lfs, (char*)buffer) => 0; - - buffer[$NAMEMULT] = '/'; - for (int j = 0; j < $NAMEMULT; j++) { - buffer[j+$NAMEMULT+1] = '0'+i; - } - buffer[2*$NAMEMULT+1] = '\0'; - lfs_file_open(&lfs, &file, (char*)buffer, - LFS_O_WRONLY | LFS_O_CREAT) => 0; - - lfs_size_t size = $NAMEMULT; - for (int j = 0; j < i*$FILEMULT; j++) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - - lfs_file_close(&lfs, &file) => 0; - } - lfs_unmount(&lfs) => 0; -TEST -} - -lfs_chktree() { -scripts/test.py ${1:-} << TEST - lfs_mount(&lfs, &cfg) => 0; - for (int i = 1; i < 10; i++) { - for (int j = 0; j < $NAMEMULT; j++) { - buffer[j] = '0'+i; - } - buffer[$NAMEMULT] = '\0'; - lfs_stat(&lfs, (char*)buffer, &info) => 0; - info.type => LFS_TYPE_DIR; - - buffer[$NAMEMULT] = '/'; - for (int j = 0; j < $NAMEMULT; j++) { - buffer[j+$NAMEMULT+1] = '0'+i; - } - buffer[2*$NAMEMULT+1] = '\0'; - lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0; - - lfs_size_t size = $NAMEMULT; - for (int j = 0; j < i*$FILEMULT; j++) { - uint8_t rbuffer[1024]; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(buffer, rbuffer, size) => 0; - } - - lfs_file_close(&lfs, &file) => 0; - } - lfs_unmount(&lfs) => 0; -TEST -} - -echo "--- Sanity check ---" -rm -rf blocks -lfs_mktree -lfs_chktree -BLOCKS="$(ls blocks | grep -vw '[01]')" - -echo "--- Block corruption ---" -for b in $BLOCKS -do - rm -rf blocks - mkdir blocks - ln -s /dev/zero blocks/$b - lfs_mktree - lfs_chktree -done - -echo "--- Block persistance ---" -for b in $BLOCKS -do - rm -rf blocks - mkdir blocks - lfs_mktree - chmod a-w blocks/$b || true - lfs_mktree - lfs_chktree -done - -echo "--- Big region corruption ---" -rm -rf blocks -mkdir blocks -for i in {2..512} -do - ln -s /dev/zero blocks/$(printf '%x' $i) -done -lfs_mktree -lfs_chktree - -echo "--- Alternating corruption ---" -rm -rf blocks -mkdir blocks -for i in {2..1024..2} -do - ln -s /dev/zero blocks/$(printf '%x' $i) -done -lfs_mktree -lfs_chktree - -scripts/results.py diff --git a/tests/test_dirs.sh b/tests/test_dirs.sh deleted file mode 100755 index 0125bfd..0000000 --- a/tests/test_dirs.sh +++ /dev/null @@ -1,489 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Directory tests ===" - -LARGESIZE=128 - -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -echo "--- Root directory ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Directory creation ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "potato") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- File creation ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "burito", LFS_O_CREAT | LFS_O_WRONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Directory iteration ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "burito") => 0; - info.type => LFS_TYPE_REG; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "potato") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Directory failures ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "potato") => LFS_ERR_EXIST; - lfs_dir_open(&lfs, &dir, "tomato") => LFS_ERR_NOENT; - lfs_dir_open(&lfs, &dir, "burito") => LFS_ERR_NOTDIR; - lfs_file_open(&lfs, &file, "tomato", LFS_O_RDONLY) => LFS_ERR_NOENT; - lfs_file_open(&lfs, &file, "potato", LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Nested directories ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "potato/baked") => 0; - lfs_mkdir(&lfs, "potato/sweet") => 0; - lfs_mkdir(&lfs, "potato/fried") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "potato") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "baked") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "fried") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "sweet") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Multi-block directory ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "cactus") => 0; - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "cactus/test%03d", i); - lfs_mkdir(&lfs, path) => 0; - } - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "cactus") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "test%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - info.type => LFS_TYPE_DIR; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Directory remove ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "potato") => LFS_ERR_NOTEMPTY; - lfs_remove(&lfs, "potato/sweet") => 0; - lfs_remove(&lfs, "potato/baked") => 0; - lfs_remove(&lfs, "potato/fried") => 0; - - lfs_dir_open(&lfs, &dir, "potato") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - lfs_remove(&lfs, "potato") => 0; - - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "burito") => 0; - info.type => LFS_TYPE_REG; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "cactus") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "burito") => 0; - info.type => LFS_TYPE_REG; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "cactus") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Directory rename ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "coldpotato") => 0; - lfs_mkdir(&lfs, "coldpotato/baked") => 0; - lfs_mkdir(&lfs, "coldpotato/sweet") => 0; - lfs_mkdir(&lfs, "coldpotato/fried") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "coldpotato", "hotpotato") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "hotpotato") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "baked") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "fried") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "sweet") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "warmpotato") => 0; - lfs_mkdir(&lfs, "warmpotato/mushy") => 0; - lfs_rename(&lfs, "hotpotato", "warmpotato") => LFS_ERR_NOTEMPTY; - - lfs_remove(&lfs, "warmpotato/mushy") => 0; - lfs_rename(&lfs, "hotpotato", "warmpotato") => 0; - - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "warmpotato") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "baked") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "fried") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "sweet") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "coldpotato") => 0; - lfs_rename(&lfs, "warmpotato/baked", "coldpotato/baked") => 0; - lfs_rename(&lfs, "warmpotato/sweet", "coldpotato/sweet") => 0; - lfs_rename(&lfs, "warmpotato/fried", "coldpotato/fried") => 0; - lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY; - lfs_remove(&lfs, "warmpotato") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "coldpotato") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "baked") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "fried") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "sweet") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Recursive remove ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "coldpotato") => LFS_ERR_NOTEMPTY; - - lfs_dir_open(&lfs, &dir, "coldpotato") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - - while (true) { - int err = lfs_dir_read(&lfs, &dir, &info); - err >= 0 => 1; - if (err == 0) { - break; - } - - strcpy(path, "coldpotato/"); - strcat(path, info.name); - lfs_remove(&lfs, path) => 0; - } - - lfs_remove(&lfs, "coldpotato") => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "burito") => 0; - info.type => LFS_TYPE_REG; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "cactus") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Multi-block rename ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - for (int i = 0; i < $LARGESIZE; i++) { - char oldpath[1024]; - char newpath[1024]; - sprintf(oldpath, "cactus/test%03d", i); - sprintf(newpath, "cactus/tedd%03d", i); - lfs_rename(&lfs, oldpath, newpath) => 0; - } - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "cactus") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "tedd%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - info.type => LFS_TYPE_DIR; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Multi-block remove ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "cactus") => LFS_ERR_NOTEMPTY; - - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "cactus/tedd%03d", i); - lfs_remove(&lfs, path) => 0; - } - - lfs_remove(&lfs, "cactus") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "burito") => 0; - info.type => LFS_TYPE_REG; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Multi-block directory with files ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "prickly-pear") => 0; - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "prickly-pear/test%03d", i); - lfs_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_size_t size = 6; - memcpy(buffer, "Hello", size); - lfs_file_write(&lfs, &file, buffer, size) => size; - lfs_file_close(&lfs, &file) => 0; - } - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "prickly-pear") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "test%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - info.type => LFS_TYPE_REG; - info.size => 6; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Multi-block rename with files ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - for (int i = 0; i < $LARGESIZE; i++) { - char oldpath[1024]; - char newpath[1024]; - sprintf(oldpath, "prickly-pear/test%03d", i); - sprintf(newpath, "prickly-pear/tedd%03d", i); - lfs_rename(&lfs, oldpath, newpath) => 0; - } - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "prickly-pear") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "tedd%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - info.type => LFS_TYPE_REG; - info.size => 6; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Multi-block remove with files ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY; - - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "prickly-pear/tedd%03d", i); - lfs_remove(&lfs, path) => 0; - } - - lfs_remove(&lfs, "prickly-pear") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "burito") => 0; - info.type => LFS_TYPE_REG; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_dirs.toml b/tests/test_dirs.toml similarity index 100% rename from tests_/test_dirs.toml rename to tests/test_dirs.toml diff --git a/tests/test_entries.sh b/tests/test_entries.sh deleted file mode 100755 index 5075faf..0000000 --- a/tests/test_entries.sh +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Entry tests ===" - -# Note: These tests are intended for 512 byte inline size at different -# inline sizes they should still pass, but won't be testing anything - -rm -rf blocks -function read_file { -cat << TEST - - size = $2; - lfs_file_open(&lfs, &file, "$1", LFS_O_RDONLY) => 0; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(rbuffer, wbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; -TEST -} - -function write_file { -cat << TEST - - size = $2; - lfs_file_open(&lfs, &file, "$1", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; - memset(wbuffer, 'c', size); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_close(&lfs, &file) => 0; -TEST -} - -echo "--- Entry grow test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - lfs_size_t size; - - lfs_mount(&lfs, &cfg) => 0; - $(write_file "hi0" 20) - $(write_file "hi1" 20) - $(write_file "hi2" 20) - $(write_file "hi3" 20) - - $(read_file "hi1" 20) - $(write_file "hi1" 200) - - $(read_file "hi0" 20) - $(read_file "hi1" 200) - $(read_file "hi2" 20) - $(read_file "hi3" 20) - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Entry shrink test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - lfs_size_t size; - - lfs_mount(&lfs, &cfg) => 0; - $(write_file "hi0" 20) - $(write_file "hi1" 200) - $(write_file "hi2" 20) - $(write_file "hi3" 20) - - $(read_file "hi1" 200) - $(write_file "hi1" 20) - - $(read_file "hi0" 20) - $(read_file "hi1" 20) - $(read_file "hi2" 20) - $(read_file "hi3" 20) - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Entry spill test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - lfs_size_t size; - - lfs_mount(&lfs, &cfg) => 0; - $(write_file "hi0" 200) - $(write_file "hi1" 200) - $(write_file "hi2" 200) - $(write_file "hi3" 200) - - $(read_file "hi0" 200) - $(read_file "hi1" 200) - $(read_file "hi2" 200) - $(read_file "hi3" 200) - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Entry push spill test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - lfs_size_t size; - - lfs_mount(&lfs, &cfg) => 0; - $(write_file "hi0" 200) - $(write_file "hi1" 20) - $(write_file "hi2" 200) - $(write_file "hi3" 200) - - $(read_file "hi1" 20) - $(write_file "hi1" 200) - - $(read_file "hi0" 200) - $(read_file "hi1" 200) - $(read_file "hi2" 200) - $(read_file "hi3" 200) - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Entry push spill two test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - lfs_size_t size; - - lfs_mount(&lfs, &cfg) => 0; - $(write_file "hi0" 200) - $(write_file "hi1" 20) - $(write_file "hi2" 200) - $(write_file "hi3" 200) - $(write_file "hi4" 200) - - $(read_file "hi1" 20) - $(write_file "hi1" 200) - - $(read_file "hi0" 200) - $(read_file "hi1" 200) - $(read_file "hi2" 200) - $(read_file "hi3" 200) - $(read_file "hi4" 200) - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Entry drop test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - lfs_size_t size; - - lfs_mount(&lfs, &cfg) => 0; - $(write_file "hi0" 200) - $(write_file "hi1" 200) - $(write_file "hi2" 200) - $(write_file "hi3" 200) - - lfs_remove(&lfs, "hi1") => 0; - lfs_stat(&lfs, "hi1", &info) => LFS_ERR_NOENT; - $(read_file "hi0" 200) - $(read_file "hi2" 200) - $(read_file "hi3" 200) - - lfs_remove(&lfs, "hi2") => 0; - lfs_stat(&lfs, "hi2", &info) => LFS_ERR_NOENT; - $(read_file "hi0" 200) - $(read_file "hi3" 200) - - lfs_remove(&lfs, "hi3") => 0; - lfs_stat(&lfs, "hi3", &info) => LFS_ERR_NOENT; - $(read_file "hi0" 200) - - lfs_remove(&lfs, "hi0") => 0; - lfs_stat(&lfs, "hi0", &info) => LFS_ERR_NOENT; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Create too big ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - lfs_mount(&lfs, &cfg) => 0; - memset(path, 'm', 200); - path[200] = '\0'; - - lfs_size_t size = 400; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; - uint8_t wbuffer[1024]; - memset(wbuffer, 'c', size); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_close(&lfs, &file) => 0; - - size = 400; - lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; - uint8_t rbuffer[1024]; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(rbuffer, wbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Resize too big ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - lfs_mount(&lfs, &cfg) => 0; - memset(path, 'm', 200); - path[200] = '\0'; - - lfs_size_t size = 40; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; - uint8_t wbuffer[1024]; - memset(wbuffer, 'c', size); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_close(&lfs, &file) => 0; - - size = 40; - lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; - uint8_t rbuffer[1024]; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(rbuffer, wbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; - - size = 400; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; - memset(wbuffer, 'c', size); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_close(&lfs, &file) => 0; - - size = 400; - lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(rbuffer, wbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_entries.toml b/tests/test_entries.toml similarity index 100% rename from tests_/test_entries.toml rename to tests/test_entries.toml diff --git a/tests_/test_exhaustion.toml b/tests/test_exhaustion.toml similarity index 100% rename from tests_/test_exhaustion.toml rename to tests/test_exhaustion.toml diff --git a/tests/test_files.sh b/tests/test_files.sh deleted file mode 100755 index f6535f6..0000000 --- a/tests/test_files.sh +++ /dev/null @@ -1,221 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== File tests ===" - -SMALLSIZE=32 -MEDIUMSIZE=8192 -LARGESIZE=262144 - -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -echo "--- Simple file test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_size_t size = strlen("Hello World!\n"); - uint8_t wbuffer[1024]; - memcpy(wbuffer, "Hello World!\n", size); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_close(&lfs, &file) => 0; - - lfs_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; - size = strlen("Hello World!\n"); - uint8_t rbuffer[1024]; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(rbuffer, wbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -w_test() { -scripts/test.py ${4:-} << TEST - lfs_size_t size = $1; - lfs_size_t chunk = 31; - srand(0); - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "$2", - ${3:-LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC}) => 0; - for (lfs_size_t i = 0; i < size; i += chunk) { - chunk = (chunk < size - i) ? chunk : size - i; - for (lfs_size_t b = 0; b < chunk; b++) { - buffer[b] = rand() & 0xff; - } - lfs_file_write(&lfs, &file, buffer, chunk) => chunk; - } - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -} - -r_test() { -scripts/test.py << TEST - lfs_size_t size = $1; - lfs_size_t chunk = 29; - srand(0); - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "$2", &info) => 0; - info.type => LFS_TYPE_REG; - info.size => size; - lfs_file_open(&lfs, &file, "$2", ${3:-LFS_O_RDONLY}) => 0; - for (lfs_size_t i = 0; i < size; i += chunk) { - chunk = (chunk < size - i) ? chunk : size - i; - lfs_file_read(&lfs, &file, buffer, chunk) => chunk; - for (lfs_size_t b = 0; b < chunk && i+b < size; b++) { - buffer[b] => rand() & 0xff; - } - } - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -} - -echo "--- Small file test ---" -w_test $SMALLSIZE smallavacado -r_test $SMALLSIZE smallavacado - -echo "--- Medium file test ---" -w_test $MEDIUMSIZE mediumavacado -r_test $MEDIUMSIZE mediumavacado - -echo "--- Large file test ---" -w_test $LARGESIZE largeavacado -r_test $LARGESIZE largeavacado - -echo "--- Zero file test ---" -w_test 0 noavacado -r_test 0 noavacado - -echo "--- Truncate small test ---" -w_test $SMALLSIZE mediumavacado -r_test $SMALLSIZE mediumavacado -w_test $MEDIUMSIZE mediumavacado -r_test $MEDIUMSIZE mediumavacado - -echo "--- Truncate zero test ---" -w_test $SMALLSIZE noavacado -r_test $SMALLSIZE noavacado -w_test 0 noavacado -r_test 0 noavacado - -echo "--- Non-overlap check ---" -r_test $SMALLSIZE smallavacado -r_test $MEDIUMSIZE mediumavacado -r_test $LARGESIZE largeavacado -r_test 0 noavacado - -echo "--- Dir check ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hello") => 0; - info.type => LFS_TYPE_REG; - info.size => strlen("Hello World!\n"); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "largeavacado") => 0; - info.type => LFS_TYPE_REG; - info.size => $LARGESIZE; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "mediumavacado") => 0; - info.type => LFS_TYPE_REG; - info.size => $MEDIUMSIZE; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "noavacado") => 0; - info.type => LFS_TYPE_REG; - info.size => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "smallavacado") => 0; - info.type => LFS_TYPE_REG; - info.size => $SMALLSIZE; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Many files test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST -scripts/test.py << TEST - // Create 300 files of 7 bytes - lfs_mount(&lfs, &cfg) => 0; - for (unsigned i = 0; i < 300; i++) { - sprintf(path, "file_%03d", i); - lfs_file_open(&lfs, &file, path, - LFS_O_RDWR | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfs_size_t size = 7; - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - snprintf((char*)wbuffer, size, "Hi %03d", i); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_rewind(&lfs, &file) => 0; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(wbuffer, rbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; - } - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Many files with flush test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST -scripts/test.py << TEST - // Create 300 files of 7 bytes - lfs_mount(&lfs, &cfg) => 0; - for (unsigned i = 0; i < 300; i++) { - sprintf(path, "file_%03d", i); - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfs_size_t size = 7; - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - snprintf((char*)wbuffer, size, "Hi %03d", i); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_close(&lfs, &file) => 0; - - lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(wbuffer, rbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; - } - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Many files with power cycle test ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST -scripts/test.py << TEST - // Create 300 files of 7 bytes - lfs_mount(&lfs, &cfg) => 0; - for (unsigned i = 0; i < 300; i++) { - sprintf(path, "file_%03d", i); - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfs_size_t size = 7; - uint8_t wbuffer[1024]; - uint8_t rbuffer[1024]; - snprintf((char*)wbuffer, size, "Hi %03d", i); - lfs_file_write(&lfs, &file, wbuffer, size) => size; - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; - - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; - lfs_file_read(&lfs, &file, rbuffer, size) => size; - memcmp(wbuffer, rbuffer, size) => 0; - lfs_file_close(&lfs, &file) => 0; - } - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_files.toml b/tests/test_files.toml similarity index 100% rename from tests_/test_files.toml rename to tests/test_files.toml diff --git a/tests/test_format.sh b/tests/test_format.sh deleted file mode 100755 index f0972bd..0000000 --- a/tests/test_format.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Formatting tests ===" -rm -rf blocks - -echo "--- Basic formatting ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -echo "--- Basic mounting ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - - lfs_mount(&lfs, &cfg) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Invalid superblocks ---" -ln -f -s /dev/zero blocks/0 -ln -f -s /dev/zero blocks/1 -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => LFS_ERR_NOSPC; -TEST -rm blocks/0 blocks/1 - -echo "--- Invalid mount ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT; -TEST - -echo "--- Expanding superblock ---" -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - lfs_mount(&lfs, &cfg) => 0; - for (int i = 0; i < 100; i++) { - lfs_mkdir(&lfs, "dummy") => 0; - lfs_remove(&lfs, "dummy") => 0; - } - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "dummy") => 0; - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_format.toml b/tests/test_format.toml similarity index 100% rename from tests_/test_format.toml rename to tests/test_format.toml diff --git a/tests/test_interspersed.sh b/tests/test_interspersed.sh deleted file mode 100755 index 84c5dd8..0000000 --- a/tests/test_interspersed.sh +++ /dev/null @@ -1,190 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Interspersed tests ===" -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -echo "--- Interspersed file test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_t files[4]; - lfs_file_open(&lfs, &files[0], "a", LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_open(&lfs, &files[1], "b", LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_open(&lfs, &files[2], "c", LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_open(&lfs, &files[3], "d", LFS_O_WRONLY | LFS_O_CREAT) => 0; - - for (int i = 0; i < 10; i++) { - lfs_file_write(&lfs, &files[0], (const void*)"a", 1) => 1; - lfs_file_write(&lfs, &files[1], (const void*)"b", 1) => 1; - lfs_file_write(&lfs, &files[2], (const void*)"c", 1) => 1; - lfs_file_write(&lfs, &files[3], (const void*)"d", 1) => 1; - } - - lfs_file_close(&lfs, &files[0]); - lfs_file_close(&lfs, &files[1]); - lfs_file_close(&lfs, &files[2]); - lfs_file_close(&lfs, &files[3]); - - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "a") => 0; - info.type => LFS_TYPE_REG; - info.size => 10; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "b") => 0; - info.type => LFS_TYPE_REG; - info.size => 10; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "c") => 0; - info.type => LFS_TYPE_REG; - info.size => 10; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "d") => 0; - info.type => LFS_TYPE_REG; - info.size => 10; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - lfs_file_open(&lfs, &files[0], "a", LFS_O_RDONLY) => 0; - lfs_file_open(&lfs, &files[1], "b", LFS_O_RDONLY) => 0; - lfs_file_open(&lfs, &files[2], "c", LFS_O_RDONLY) => 0; - lfs_file_open(&lfs, &files[3], "d", LFS_O_RDONLY) => 0; - - for (int i = 0; i < 10; i++) { - lfs_file_read(&lfs, &files[0], buffer, 1) => 1; - buffer[0] => 'a'; - lfs_file_read(&lfs, &files[1], buffer, 1) => 1; - buffer[0] => 'b'; - lfs_file_read(&lfs, &files[2], buffer, 1) => 1; - buffer[0] => 'c'; - lfs_file_read(&lfs, &files[3], buffer, 1) => 1; - buffer[0] => 'd'; - } - - lfs_file_close(&lfs, &files[0]); - lfs_file_close(&lfs, &files[1]); - lfs_file_close(&lfs, &files[2]); - lfs_file_close(&lfs, &files[3]); - - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Interspersed remove file test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_t files[4]; - lfs_file_open(&lfs, &files[0], "e", LFS_O_WRONLY | LFS_O_CREAT) => 0; - - for (int i = 0; i < 5; i++) { - lfs_file_write(&lfs, &files[0], (const void*)"e", 1) => 1; - } - - lfs_remove(&lfs, "a") => 0; - lfs_remove(&lfs, "b") => 0; - lfs_remove(&lfs, "c") => 0; - lfs_remove(&lfs, "d") => 0; - - for (int i = 0; i < 5; i++) { - lfs_file_write(&lfs, &files[0], (const void*)"e", 1) => 1; - } - - lfs_file_close(&lfs, &files[0]); - - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "e") => 0; - info.type => LFS_TYPE_REG; - info.size => 10; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - lfs_file_open(&lfs, &files[0], "e", LFS_O_RDONLY) => 0; - - for (int i = 0; i < 10; i++) { - lfs_file_read(&lfs, &files[0], buffer, 1) => 1; - buffer[0] => 'e'; - } - - lfs_file_close(&lfs, &files[0]); - - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Remove inconveniently test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_t files[4]; - lfs_file_open(&lfs, &files[0], "e", LFS_O_WRONLY | LFS_O_TRUNC) => 0; - lfs_file_open(&lfs, &files[1], "f", LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_open(&lfs, &files[2], "g", LFS_O_WRONLY | LFS_O_CREAT) => 0; - - for (int i = 0; i < 5; i++) { - lfs_file_write(&lfs, &files[0], (const void*)"e", 1) => 1; - lfs_file_write(&lfs, &files[1], (const void*)"f", 1) => 1; - lfs_file_write(&lfs, &files[2], (const void*)"g", 1) => 1; - } - - lfs_remove(&lfs, "f") => 0; - - for (int i = 0; i < 5; i++) { - lfs_file_write(&lfs, &files[0], (const void*)"e", 1) => 1; - lfs_file_write(&lfs, &files[1], (const void*)"f", 1) => 1; - lfs_file_write(&lfs, &files[2], (const void*)"g", 1) => 1; - } - - lfs_file_close(&lfs, &files[0]); - lfs_file_close(&lfs, &files[1]); - lfs_file_close(&lfs, &files[2]); - - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - info.type => LFS_TYPE_DIR; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "e") => 0; - info.type => LFS_TYPE_REG; - info.size => 10; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "g") => 0; - info.type => LFS_TYPE_REG; - info.size => 10; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - lfs_file_open(&lfs, &files[0], "e", LFS_O_RDONLY) => 0; - lfs_file_open(&lfs, &files[1], "g", LFS_O_RDONLY) => 0; - - for (int i = 0; i < 10; i++) { - lfs_file_read(&lfs, &files[0], buffer, 1) => 1; - buffer[0] => 'e'; - lfs_file_read(&lfs, &files[1], buffer, 1) => 1; - buffer[0] => 'g'; - } - - lfs_file_close(&lfs, &files[0]); - lfs_file_close(&lfs, &files[1]); - - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_interspersed.toml b/tests/test_interspersed.toml similarity index 100% rename from tests_/test_interspersed.toml rename to tests/test_interspersed.toml diff --git a/tests/test_move.sh b/tests/test_move.sh deleted file mode 100755 index f52ef22..0000000 --- a/tests/test_move.sh +++ /dev/null @@ -1,333 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Move tests ===" -rm -rf blocks -scripts/test.py << TEST - 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_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; -TEST - -echo "--- Move file ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "a/hello", "b/hello") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "a") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hi") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "b") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hello") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move file corrupt source ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "b/hello", "c/hello") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/corrupt.py -n 1 -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "b") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - 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; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hello") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move file corrupt source and dest ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "c/hello", "d/hello") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/corrupt.py -n 2 -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "c") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hello") => 0; - 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; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move file after corrupt ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "c/hello", "d/hello") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "c") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - 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; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hello") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move dir ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "a/hi", "b/hi") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "a") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "b") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hi") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move dir corrupt source ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "b/hi", "c/hi") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/corrupt.py -n 1 -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "b") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - 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; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hi") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move dir corrupt source and dest ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "c/hi", "d/hi") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/corrupt.py -n 2 -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "c") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hi") => 0; - 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; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hello") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move dir after corrupt ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_rename(&lfs, "c/hi", "d/hi") => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "c") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - 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; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hello") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hi") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Move check ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 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; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "bonjour") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hola") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "ohayo") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - lfs_dir_open(&lfs, &dir, "a/hello") => LFS_ERR_NOENT; - lfs_dir_open(&lfs, &dir, "b/hello") => LFS_ERR_NOENT; - lfs_dir_open(&lfs, &dir, "c/hello") => 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; -TEST - -echo "--- Move state stealing ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - - lfs_remove(&lfs, "b") => 0; - lfs_remove(&lfs, "c") => 0; - - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - - lfs_dir_open(&lfs, &dir, "a/hi") => LFS_ERR_NOENT; - lfs_dir_open(&lfs, &dir, "b") => LFS_ERR_NOENT; - lfs_dir_open(&lfs, &dir, "c") => LFS_ERR_NOENT; - - lfs_dir_open(&lfs, &dir, "d/hi") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "bonjour") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "hola") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "ohayo") => 0; - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - lfs_dir_open(&lfs, &dir, "a/hello") => LFS_ERR_NOENT; - lfs_dir_open(&lfs, &dir, "b") => LFS_ERR_NOENT; - lfs_dir_open(&lfs, &dir, "c") => 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; -TEST - - -scripts/results.py diff --git a/tests_/test_move.toml b/tests/test_move.toml similarity index 100% rename from tests_/test_move.toml rename to tests/test_move.toml diff --git a/tests/test_orphan.sh b/tests/test_orphan.sh deleted file mode 100755 index b0a8493..0000000 --- a/tests/test_orphan.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Orphan tests ===" -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -echo "--- Orphan test ---" -scripts/test.py << TEST - 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; -TEST -# corrupt most recent commit, this should be the update to the previous -# linked-list entry and should orphan the child -scripts/corrupt.py -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - - lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; - lfs_ssize_t before = lfs_fs_size(&lfs); - before => 8; - - lfs_unmount(&lfs) => 0; - lfs_mount(&lfs, &cfg) => 0; - - lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; - lfs_ssize_t orphaned = lfs_fs_size(&lfs); - orphaned => 8; - - lfs_mkdir(&lfs, "parent/otherchild") => 0; - - lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; - lfs_ssize_t deorphaned = lfs_fs_size(&lfs); - deorphaned => 8; - - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_orphans.toml b/tests/test_orphans.toml similarity index 100% rename from tests_/test_orphans.toml rename to tests/test_orphans.toml diff --git a/tests/test_paths.sh b/tests/test_paths.sh deleted file mode 100755 index cfdcd98..0000000 --- a/tests/test_paths.sh +++ /dev/null @@ -1,202 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Path tests ===" -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "tea") => 0; - lfs_mkdir(&lfs, "coffee") => 0; - lfs_mkdir(&lfs, "soda") => 0; - lfs_mkdir(&lfs, "tea/hottea") => 0; - lfs_mkdir(&lfs, "tea/warmtea") => 0; - lfs_mkdir(&lfs, "tea/coldtea") => 0; - lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; - lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; - lfs_mkdir(&lfs, "coffee/coldcoffee") => 0; - lfs_mkdir(&lfs, "soda/hotsoda") => 0; - lfs_mkdir(&lfs, "soda/warmsoda") => 0; - lfs_mkdir(&lfs, "soda/coldsoda") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Root path tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "/tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - - lfs_mkdir(&lfs, "/milk1") => 0; - lfs_stat(&lfs, "/milk1", &info) => 0; - strcmp(info.name, "milk1") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Redundant slash path tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "/tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "//tea//hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "///tea///hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - - lfs_mkdir(&lfs, "///milk2") => 0; - lfs_stat(&lfs, "///milk2", &info) => 0; - strcmp(info.name, "milk2") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Dot path tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "./tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "/./tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "/././tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "/./tea/./hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - - lfs_mkdir(&lfs, "/./milk3") => 0; - lfs_stat(&lfs, "/./milk3", &info) => 0; - strcmp(info.name, "milk3") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Dot dot path tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "coffee/../tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "tea/coldtea/../hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "coffee/coldcoffee/../../tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "coffee/../soda/../tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - - lfs_mkdir(&lfs, "coffee/../milk4") => 0; - lfs_stat(&lfs, "coffee/../milk4", &info) => 0; - strcmp(info.name, "milk4") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Trailing dot path tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "tea/hottea/", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "tea/hottea/.", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "tea/hottea/./.", &info) => 0; - strcmp(info.name, "hottea") => 0; - lfs_stat(&lfs, "tea/hottea/..", &info) => 0; - strcmp(info.name, "tea") => 0; - lfs_stat(&lfs, "tea/hottea/../.", &info) => 0; - strcmp(info.name, "tea") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Root dot dot path tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - - lfs_mkdir(&lfs, "coffee/../../../../../../milk5") => 0; - lfs_stat(&lfs, "coffee/../../../../../../milk5", &info) => 0; - strcmp(info.name, "milk5") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Root tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "/", &info) => 0; - info.type => LFS_TYPE_DIR; - strcmp(info.name, "/") => 0; - - lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; - lfs_file_open(&lfs, &file, "/", LFS_O_WRONLY | LFS_O_CREAT) - => LFS_ERR_ISDIR; - - // more corner cases - lfs_remove(&lfs, "") => LFS_ERR_INVAL; - lfs_remove(&lfs, ".") => LFS_ERR_INVAL; - lfs_remove(&lfs, "..") => LFS_ERR_INVAL; - lfs_remove(&lfs, "/") => LFS_ERR_INVAL; - lfs_remove(&lfs, "//") => LFS_ERR_INVAL; - lfs_remove(&lfs, "./") => LFS_ERR_INVAL; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Sketchy path tests ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "dirt/ground") => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "dirt/ground/earth") => LFS_ERR_NOENT; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Superblock conflict test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "littlefs") => 0; - lfs_remove(&lfs, "littlefs") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Max path test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(path, 'w', LFS_NAME_MAX+1); - path[LFS_NAME_MAX+2] = '\0'; - lfs_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG; - - memcpy(path, "coffee/", strlen("coffee/")); - memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX+1); - path[strlen("coffee/")+LFS_NAME_MAX+2] = '\0'; - lfs_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Really big path test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - memset(path, 'w', LFS_NAME_MAX); - path[LFS_NAME_MAX] = '\0'; - lfs_mkdir(&lfs, path) => 0; - lfs_remove(&lfs, path) => 0; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_remove(&lfs, path) => 0; - - memcpy(path, "coffee/", strlen("coffee/")); - memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX); - path[strlen("coffee/")+LFS_NAME_MAX] = '\0'; - lfs_mkdir(&lfs, path) => 0; - lfs_remove(&lfs, path) => 0; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_remove(&lfs, path) => 0; - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_paths.toml b/tests/test_paths.toml similarity index 100% rename from tests_/test_paths.toml rename to tests/test_paths.toml diff --git a/tests/test_relocations.sh b/tests/test_relocations.sh deleted file mode 100755 index 5244e5e..0000000 --- a/tests/test_relocations.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -ITERATIONS=20 -COUNT=10 - -echo "=== Relocation tests ===" -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - // fill up filesystem so only ~16 blocks are left - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; - memset(buffer, 0, 512); - while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { - lfs_file_write(&lfs, &file, buffer, 512) => 512; - } - lfs_file_close(&lfs, &file) => 0; - // make a child dir to use in bounded space - lfs_mkdir(&lfs, "child") => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Dangling split dir test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - for (int j = 0; j < $ITERATIONS; j++) { - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); - lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - } - - lfs_dir_open(&lfs, &dir, "child") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "test%03d_loooooooooooooooooong_name", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - if (j == $ITERATIONS-1) { - break; - } - - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); - lfs_remove(&lfs, path) => 0; - } - } - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "child") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "test%03d_loooooooooooooooooong_name", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); - lfs_remove(&lfs, path) => 0; - } - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Outdated head test ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - for (int j = 0; j < $ITERATIONS; j++) { - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); - lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - } - - lfs_dir_open(&lfs, &dir, "child") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "test%03d_loooooooooooooooooong_name", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - info.size => 0; - - sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); - lfs_file_open(&lfs, &file, path, LFS_O_WRONLY) => 0; - lfs_file_write(&lfs, &file, "hi", 2) => 2; - lfs_file_close(&lfs, &file) => 0; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - - lfs_dir_rewind(&lfs, &dir) => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "test%03d_loooooooooooooooooong_name", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - info.size => 2; - - sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); - lfs_file_open(&lfs, &file, path, LFS_O_WRONLY) => 0; - lfs_file_write(&lfs, &file, "hi", 2) => 2; - lfs_file_close(&lfs, &file) => 0; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - - lfs_dir_rewind(&lfs, &dir) => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - lfs_dir_read(&lfs, &dir, &info) => 1; - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "test%03d_loooooooooooooooooong_name", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - info.size => 2; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - for (int i = 0; i < $COUNT; i++) { - sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); - lfs_remove(&lfs, path) => 0; - } - } - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_relocations.toml b/tests/test_relocations.toml similarity index 100% rename from tests_/test_relocations.toml rename to tests/test_relocations.toml diff --git a/tests/test_seek.sh b/tests/test_seek.sh deleted file mode 100755 index e136aa0..0000000 --- a/tests/test_seek.sh +++ /dev/null @@ -1,505 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Seek tests ===" - -SMALLSIZE=4 -MEDIUMSIZE=128 -LARGESIZE=132 - -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; - lfs_mount(&lfs, &cfg) => 0; - lfs_mkdir(&lfs, "hello") => 0; - for (int i = 0; i < $LARGESIZE; i++) { - sprintf(path, "hello/kitty%03d", i); - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; - - lfs_size_t size = strlen("kittycatcat"); - memcpy(buffer, "kittycatcat", size); - for (int j = 0; j < $LARGESIZE; j++) { - lfs_file_write(&lfs, &file, buffer, size); - } - - lfs_file_close(&lfs, &file) => 0; - } - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Simple dir seek ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "hello") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - - lfs_soff_t pos; - int i; - for (i = 0; i < $SMALLSIZE; i++) { - sprintf(path, "kitty%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - pos = lfs_dir_tell(&lfs, &dir); - } - pos >= 0 => 1; - - lfs_dir_seek(&lfs, &dir, pos) => 0; - sprintf(path, "kitty%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - - lfs_dir_rewind(&lfs, &dir) => 0; - sprintf(path, "kitty%03d", 0); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - - lfs_dir_seek(&lfs, &dir, pos) => 0; - sprintf(path, "kitty%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Large dir seek ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_dir_open(&lfs, &dir, "hello") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - - lfs_soff_t pos; - int i; - for (i = 0; i < $MEDIUMSIZE; i++) { - sprintf(path, "kitty%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - pos = lfs_dir_tell(&lfs, &dir); - } - pos >= 0 => 1; - - lfs_dir_seek(&lfs, &dir, pos) => 0; - sprintf(path, "kitty%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - - lfs_dir_rewind(&lfs, &dir) => 0; - sprintf(path, "kitty%03d", 0); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, ".") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, "..") => 0; - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - - lfs_dir_seek(&lfs, &dir, pos) => 0; - sprintf(path, "kitty%03d", i); - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(info.name, path) => 0; - - lfs_dir_close(&lfs, &dir) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Simple file seek ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello/kitty042", LFS_O_RDONLY) => 0; - - lfs_soff_t pos; - lfs_size_t size = strlen("kittycatcat"); - for (int i = 0; i < $SMALLSIZE; i++) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - pos = lfs_file_tell(&lfs, &file); - } - pos >= 0 => 1; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_rewind(&lfs, &file) => 0; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, size, LFS_SEEK_CUR) => 3*size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, -size, LFS_SEEK_CUR) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, -size, LFS_SEEK_END) >= 0 => 1; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - size = lfs_file_size(&lfs, &file); - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Large file seek ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello/kitty042", LFS_O_RDONLY) => 0; - - lfs_soff_t pos; - lfs_size_t size = strlen("kittycatcat"); - for (int i = 0; i < $MEDIUMSIZE; i++) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - pos = lfs_file_tell(&lfs, &file); - } - pos >= 0 => 1; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_rewind(&lfs, &file) => 0; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, size, LFS_SEEK_CUR) => 3*size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, -size, LFS_SEEK_CUR) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, -size, LFS_SEEK_END) >= 0 => 1; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - size = lfs_file_size(&lfs, &file); - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Simple file seek and write ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello/kitty042", LFS_O_RDWR) => 0; - - lfs_soff_t pos; - lfs_size_t size = strlen("kittycatcat"); - for (int i = 0; i < $SMALLSIZE; i++) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - pos = lfs_file_tell(&lfs, &file); - } - pos >= 0 => 1; - - memcpy(buffer, "doggodogdog", size); - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_write(&lfs, &file, buffer, size) => size; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "doggodogdog", size) => 0; - - lfs_file_rewind(&lfs, &file) => 0; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "doggodogdog", size) => 0; - - lfs_file_seek(&lfs, &file, -size, LFS_SEEK_END) >= 0 => 1; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - size = lfs_file_size(&lfs, &file); - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Large file seek and write ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello/kitty042", LFS_O_RDWR) => 0; - - lfs_soff_t pos; - lfs_size_t size = strlen("kittycatcat"); - for (int i = 0; i < $MEDIUMSIZE; i++) { - lfs_file_read(&lfs, &file, buffer, size) => size; - if (i != $SMALLSIZE) { - memcmp(buffer, "kittycatcat", size) => 0; - } - pos = lfs_file_tell(&lfs, &file); - } - pos >= 0 => 1; - - memcpy(buffer, "doggodogdog", size); - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_write(&lfs, &file, buffer, size) => size; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "doggodogdog", size) => 0; - - lfs_file_rewind(&lfs, &file) => 0; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "doggodogdog", size) => 0; - - lfs_file_seek(&lfs, &file, -size, LFS_SEEK_END) >= 0 => 1; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - size = lfs_file_size(&lfs, &file); - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Boundary seek and write ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello/kitty042", LFS_O_RDWR) => 0; - - lfs_size_t size = strlen("hedgehoghog"); - const lfs_soff_t offsets[] = {512, 1020, 513, 1021, 511, 1019}; - - for (unsigned i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) { - lfs_soff_t off = offsets[i]; - memcpy(buffer, "hedgehoghog", size); - lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off; - lfs_file_write(&lfs, &file, buffer, size) => size; - lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "hedgehoghog", size) => 0; - - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "kittycatcat", size) => 0; - - lfs_file_sync(&lfs, &file) => 0; - } - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Out-of-bounds seek ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello/kitty042", LFS_O_RDWR) => 0; - - lfs_size_t size = strlen("kittycatcat"); - lfs_file_size(&lfs, &file) => $LARGESIZE*size; - lfs_file_seek(&lfs, &file, ($LARGESIZE+$SMALLSIZE)*size, - LFS_SEEK_SET) => ($LARGESIZE+$SMALLSIZE)*size; - lfs_file_read(&lfs, &file, buffer, size) => 0; - - memcpy(buffer, "porcupineee", size); - lfs_file_write(&lfs, &file, buffer, size) => size; - - lfs_file_seek(&lfs, &file, ($LARGESIZE+$SMALLSIZE)*size, - LFS_SEEK_SET) => ($LARGESIZE+$SMALLSIZE)*size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "porcupineee", size) => 0; - - lfs_file_seek(&lfs, &file, $LARGESIZE*size, - LFS_SEEK_SET) => $LARGESIZE*size; - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "\0\0\0\0\0\0\0\0\0\0\0", size) => 0; - - lfs_file_seek(&lfs, &file, -(($LARGESIZE+$SMALLSIZE)*size), - LFS_SEEK_CUR) => LFS_ERR_INVAL; - lfs_file_tell(&lfs, &file) => ($LARGESIZE+1)*size; - - lfs_file_seek(&lfs, &file, -(($LARGESIZE+2*$SMALLSIZE)*size), - LFS_SEEK_END) => LFS_ERR_INVAL; - lfs_file_tell(&lfs, &file) => ($LARGESIZE+1)*size; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Inline write and seek ---" -for SIZE in $SMALLSIZE $MEDIUMSIZE $LARGESIZE -do -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "hello/tinykitty$SIZE", - LFS_O_RDWR | LFS_O_CREAT) => 0; - int j = 0; - int k = 0; - - memcpy(buffer, "abcdefghijklmnopqrstuvwxyz", 26); - for (unsigned i = 0; i < $SIZE; i++) { - lfs_file_write(&lfs, &file, &buffer[j++ % 26], 1) => 1; - lfs_file_tell(&lfs, &file) => i+1; - lfs_file_size(&lfs, &file) => i+1; - } - - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0; - lfs_file_tell(&lfs, &file) => 0; - lfs_file_size(&lfs, &file) => $SIZE; - for (unsigned i = 0; i < $SIZE; i++) { - uint8_t c; - lfs_file_read(&lfs, &file, &c, 1) => 1; - c => buffer[k++ % 26]; - } - - lfs_file_sync(&lfs, &file) => 0; - lfs_file_tell(&lfs, &file) => $SIZE; - lfs_file_size(&lfs, &file) => $SIZE; - - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0; - for (unsigned i = 0; i < $SIZE; i++) { - lfs_file_write(&lfs, &file, &buffer[j++ % 26], 1) => 1; - lfs_file_tell(&lfs, &file) => i+1; - lfs_file_size(&lfs, &file) => $SIZE; - lfs_file_sync(&lfs, &file) => 0; - lfs_file_tell(&lfs, &file) => i+1; - lfs_file_size(&lfs, &file) => $SIZE; - if (i < $SIZE-2) { - uint8_t c[3]; - lfs_file_seek(&lfs, &file, -1, LFS_SEEK_CUR) => i; - lfs_file_read(&lfs, &file, &c, 3) => 3; - lfs_file_tell(&lfs, &file) => i+3; - lfs_file_size(&lfs, &file) => $SIZE; - lfs_file_seek(&lfs, &file, i+1, LFS_SEEK_SET) => i+1; - lfs_file_tell(&lfs, &file) => i+1; - lfs_file_size(&lfs, &file) => $SIZE; - } - } - - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0; - lfs_file_tell(&lfs, &file) => 0; - lfs_file_size(&lfs, &file) => $SIZE; - for (unsigned i = 0; i < $SIZE; i++) { - uint8_t c; - lfs_file_read(&lfs, &file, &c, 1) => 1; - c => buffer[k++ % 26]; - } - - lfs_file_sync(&lfs, &file) => 0; - lfs_file_tell(&lfs, &file) => $SIZE; - lfs_file_size(&lfs, &file) => $SIZE; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -done - -echo "--- Root seek test ---" -./scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - for (int i = 3; i < $MEDIUMSIZE; i++) { - sprintf(path, "hi%03d", i); - lfs_mkdir(&lfs, path) => 0; - } - - lfs_dir_open(&lfs, &dir, "/") => 0; - for (int i = 0; i < $MEDIUMSIZE; i++) { - if (i == 0) { - sprintf(path, "."); - } else if (i == 1) { - sprintf(path, ".."); - } else if (i == 2) { - sprintf(path, "hello"); - } else { - sprintf(path, "hi%03d", i); - } - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(path, info.name) => 0; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - for (int j = 0; j < $MEDIUMSIZE; j++) { - lfs_soff_t off = -1; - - lfs_dir_open(&lfs, &dir, "/") => 0; - for (int i = 0; i < $MEDIUMSIZE; i++) { - if (i == 0) { - sprintf(path, "."); - } else if (i == 1) { - sprintf(path, ".."); - } else if (i == 2) { - sprintf(path, "hello"); - } else { - sprintf(path, "hi%03d", i); - } - - if (i == j) { - off = lfs_dir_tell(&lfs, &dir); - off >= 0 => true; - } - - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(path, info.name) => 0; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - - lfs_dir_open(&lfs, &dir, "/") => 0; - lfs_dir_seek(&lfs, &dir, off) => 0; - for (int i = j; i < $MEDIUMSIZE; i++) { - if (i == 0) { - sprintf(path, "."); - } else if (i == 1) { - sprintf(path, ".."); - } else if (i == 2) { - sprintf(path, "hello"); - } else { - sprintf(path, "hi%03d", i); - } - - lfs_dir_read(&lfs, &dir, &info) => 1; - strcmp(path, info.name) => 0; - } - lfs_dir_read(&lfs, &dir, &info) => 0; - lfs_dir_close(&lfs, &dir) => 0; - } - - lfs_unmount(&lfs) => 0; -TEST - -scripts/results.py diff --git a/tests_/test_seek.toml b/tests/test_seek.toml similarity index 100% rename from tests_/test_seek.toml rename to tests/test_seek.toml diff --git a/tests/test_truncate.sh b/tests/test_truncate.sh deleted file mode 100755 index f33717d..0000000 --- a/tests/test_truncate.sh +++ /dev/null @@ -1,355 +0,0 @@ -#!/bin/bash -set -eu -export TEST_FILE=$0 -trap 'export TEST_LINE=$LINENO' DEBUG - -echo "=== Truncate tests ===" - -SMALLSIZE=32 -MEDIUMSIZE=2048 -LARGESIZE=8192 - -rm -rf blocks -scripts/test.py << TEST - lfs_format(&lfs, &cfg) => 0; -TEST - -echo "--- Simple truncate ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldynoop", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - - strcpy((char*)buffer, "hair"); - lfs_size_t size = strlen((char*)buffer); - for (lfs_off_t j = 0; j < $LARGESIZE; j += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_size(&lfs, &file) => $LARGESIZE; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDWR) => 0; - lfs_file_size(&lfs, &file) => $LARGESIZE; - - lfs_file_truncate(&lfs, &file, $MEDIUMSIZE) => 0; - lfs_file_size(&lfs, &file) => $MEDIUMSIZE; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDONLY) => 0; - lfs_file_size(&lfs, &file) => $MEDIUMSIZE; - - lfs_size_t size = strlen("hair"); - for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "hair", size) => 0; - } - lfs_file_read(&lfs, &file, buffer, size) => 0; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Truncate and read ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldyread", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - - strcpy((char*)buffer, "hair"); - lfs_size_t size = strlen((char*)buffer); - for (lfs_off_t j = 0; j < $LARGESIZE; j += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_size(&lfs, &file) => $LARGESIZE; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDWR) => 0; - lfs_file_size(&lfs, &file) => $LARGESIZE; - - lfs_file_truncate(&lfs, &file, $MEDIUMSIZE) => 0; - lfs_file_size(&lfs, &file) => $MEDIUMSIZE; - - lfs_size_t size = strlen("hair"); - for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "hair", size) => 0; - } - lfs_file_read(&lfs, &file, buffer, size) => 0; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDONLY) => 0; - lfs_file_size(&lfs, &file) => $MEDIUMSIZE; - - lfs_size_t size = strlen("hair"); - for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "hair", size) => 0; - } - lfs_file_read(&lfs, &file, buffer, size) => 0; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Write, truncate, and read ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "sequence", - LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC) => 0; - - lfs_size_t size = lfs.cfg->cache_size; - lfs_size_t qsize = size / 4; - uint8_t *wb = buffer; - uint8_t *rb = buffer + size; - for (lfs_off_t j = 0; j < size; ++j) { - wb[j] = j; - } - - /* Spread sequence over size */ - lfs_file_write(&lfs, &file, wb, size) => size; - lfs_file_size(&lfs, &file) => size; - lfs_file_tell(&lfs, &file) => size; - - lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0; - lfs_file_tell(&lfs, &file) => 0; - - /* Chop off the last quarter */ - lfs_size_t trunc = size - qsize; - lfs_file_truncate(&lfs, &file, trunc) => 0; - lfs_file_tell(&lfs, &file) => 0; - lfs_file_size(&lfs, &file) => trunc; - - /* Read should produce first 3/4 */ - lfs_file_read(&lfs, &file, rb, size) => trunc; - memcmp(rb, wb, trunc) => 0; - - /* Move to 1/4 */ - lfs_file_size(&lfs, &file) => trunc; - lfs_file_seek(&lfs, &file, qsize, LFS_SEEK_SET) => qsize; - lfs_file_tell(&lfs, &file) => qsize; - - /* Chop to 1/2 */ - trunc -= qsize; - lfs_file_truncate(&lfs, &file, trunc) => 0; - lfs_file_tell(&lfs, &file) => qsize; - lfs_file_size(&lfs, &file) => trunc; - - /* Read should produce second quarter */ - lfs_file_read(&lfs, &file, rb, size) => trunc - qsize; - memcmp(rb, wb + qsize, trunc - qsize) => 0; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -echo "--- Truncate and write ---" -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldywrite", - LFS_O_WRONLY | LFS_O_CREAT) => 0; - - strcpy((char*)buffer, "hair"); - lfs_size_t size = strlen((char*)buffer); - for (lfs_off_t j = 0; j < $LARGESIZE; j += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_size(&lfs, &file) => $LARGESIZE; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDWR) => 0; - lfs_file_size(&lfs, &file) => $LARGESIZE; - - lfs_file_truncate(&lfs, &file, $MEDIUMSIZE) => 0; - lfs_file_size(&lfs, &file) => $MEDIUMSIZE; - - strcpy((char*)buffer, "bald"); - lfs_size_t size = strlen((char*)buffer); - for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_size(&lfs, &file) => $MEDIUMSIZE; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - lfs_mount(&lfs, &cfg) => 0; - lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDONLY) => 0; - lfs_file_size(&lfs, &file) => $MEDIUMSIZE; - - lfs_size_t size = strlen("bald"); - for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "bald", size) => 0; - } - lfs_file_read(&lfs, &file, buffer, size) => 0; - - lfs_file_close(&lfs, &file) => 0; - lfs_unmount(&lfs) => 0; -TEST - -# More aggressive general truncation tests -truncate_test() { -STARTSIZES="$1" -STARTSEEKS="$2" -HOTSIZES="$3" -COLDSIZES="$4" -scripts/test.py << TEST - static const lfs_off_t startsizes[] = {$STARTSIZES}; - static const lfs_off_t startseeks[] = {$STARTSEEKS}; - static const lfs_off_t hotsizes[] = {$HOTSIZES}; - - lfs_mount(&lfs, &cfg) => 0; - - for (unsigned i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) { - sprintf(path, "hairyhead%d", i); - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; - - strcpy((char*)buffer, "hair"); - lfs_size_t size = strlen((char*)buffer); - for (lfs_off_t j = 0; j < startsizes[i]; j += size) { - lfs_file_write(&lfs, &file, buffer, size) => size; - } - lfs_file_size(&lfs, &file) => startsizes[i]; - - if (startseeks[i] != startsizes[i]) { - lfs_file_seek(&lfs, &file, - startseeks[i], LFS_SEEK_SET) => startseeks[i]; - } - - lfs_file_truncate(&lfs, &file, hotsizes[i]) => 0; - lfs_file_size(&lfs, &file) => hotsizes[i]; - - lfs_file_close(&lfs, &file) => 0; - } - - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - static const lfs_off_t startsizes[] = {$STARTSIZES}; - static const lfs_off_t hotsizes[] = {$HOTSIZES}; - static const lfs_off_t coldsizes[] = {$COLDSIZES}; - - lfs_mount(&lfs, &cfg) => 0; - - for (unsigned i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) { - sprintf(path, "hairyhead%d", i); - lfs_file_open(&lfs, &file, path, LFS_O_RDWR) => 0; - lfs_file_size(&lfs, &file) => hotsizes[i]; - - lfs_size_t size = strlen("hair"); - lfs_off_t j = 0; - for (; j < startsizes[i] && j < hotsizes[i]; j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "hair", size) => 0; - } - - for (; j < hotsizes[i]; j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "\0\0\0\0", size) => 0; - } - - lfs_file_truncate(&lfs, &file, coldsizes[i]) => 0; - lfs_file_size(&lfs, &file) => coldsizes[i]; - - lfs_file_close(&lfs, &file) => 0; - } - - lfs_unmount(&lfs) => 0; -TEST -scripts/test.py << TEST - static const lfs_off_t startsizes[] = {$STARTSIZES}; - static const lfs_off_t hotsizes[] = {$HOTSIZES}; - static const lfs_off_t coldsizes[] = {$COLDSIZES}; - - lfs_mount(&lfs, &cfg) => 0; - - for (unsigned i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) { - sprintf(path, "hairyhead%d", i); - lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; - lfs_file_size(&lfs, &file) => coldsizes[i]; - - lfs_size_t size = strlen("hair"); - lfs_off_t j = 0; - for (; j < startsizes[i] && j < hotsizes[i] && j < coldsizes[i]; - j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "hair", size) => 0; - } - - for (; j < coldsizes[i]; j += size) { - lfs_file_read(&lfs, &file, buffer, size) => size; - memcmp(buffer, "\0\0\0\0", size) => 0; - } - - lfs_file_close(&lfs, &file) => 0; - } - - lfs_unmount(&lfs) => 0; -TEST -} - -echo "--- Cold shrinking truncate ---" -truncate_test \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" - -echo "--- Cold expanding truncate ---" -truncate_test \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" - -echo "--- Warm shrinking truncate ---" -truncate_test \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - " 0, 0, 0, 0, 0" - -echo "--- Warm expanding truncate ---" -truncate_test \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" - -echo "--- Mid-file shrinking truncate ---" -truncate_test \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - " $LARGESIZE, $LARGESIZE, $LARGESIZE, $LARGESIZE, $LARGESIZE" \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - " 0, 0, 0, 0, 0" - -echo "--- Mid-file expanding truncate ---" -truncate_test \ - " 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE, 2*$LARGESIZE" \ - " 0, 0, $SMALLSIZE, $MEDIUMSIZE, $LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" \ - "2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE, 2*$LARGESIZE" - -scripts/results.py diff --git a/tests_/test_truncate.toml b/tests/test_truncate.toml similarity index 100% rename from tests_/test_truncate.toml rename to tests/test_truncate.toml