diff --git a/tests/test_badblocks.toml b/tests/test_badblocks.toml index 208dad1f..9aca08ef 100644 --- a/tests/test_badblocks.toml +++ b/tests/test_badblocks.toml @@ -7,6 +7,8 @@ after = [ 'test_traversal', 'test_gc', 'test_mount', + 'test_ck', + 'test_compat', ] diff --git a/tests/test_compat.toml b/tests/test_compat.toml index c60d74dd..77a3a4c4 100644 --- a/tests/test_compat.toml +++ b/tests/test_compat.toml @@ -4,7 +4,7 @@ after = [ 'test_files', 'test_fwrite', 'test_forphans', - 'test_incompat', + 'test_mount', ] # Note, these tests are a bit special. They can run as-is to test various diff --git a/tests/test_grow.toml b/tests/test_grow.toml index 6b272200..b659c2a1 100644 --- a/tests/test_grow.toml +++ b/tests/test_grow.toml @@ -5,6 +5,7 @@ after = [ 'test_fwrite', 'test_forphans', 'test_alloc', + 'test_mount', ] diff --git a/tests/test_incompat.toml b/tests/test_incompat.toml deleted file mode 100644 index 5abf1013..00000000 --- a/tests/test_incompat.toml +++ /dev/null @@ -1,425 +0,0 @@ -# Test (in)compatibility-related things -# -# Unlike test_compat, this focuses on specific corner-cases -# -after = ['test_mtree', 'test_dirs', 'test_files'] - - -## incompatiblity tests ## - -# test that we fail if we find no magic -[cases.test_incompat_no_magic] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // delete the magic string - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_RM | LFSR_TAG_MAGIC, 0, - LFSR_DATA_NULL()))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_CORRUPT; -''' - -# test that we fail if we find bad magic -[cases.test_incompat_bad_magic] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // tweak the magic string - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_MAGIC, 0, - LFSR_DATA_BUF("lottlefs", 8)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_CORRUPT; -''' - -# test that we fail to mount after a major version bump -[cases.test_incompat_major] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // bump the major version - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_VERSION, 0, - LFSR_DATA_BUF(((const uint8_t[2]){ - LFS_DISK_VERSION_MAJOR+1, - 0}), 2)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test that we fail to mount after a minor version bump -[cases.test_incompat_minor] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // bump the minor version - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_VERSION, 0, - LFSR_DATA_BUF(((const uint8_t[2]){ - LFS_DISK_VERSION_MAJOR, - LFS_DISK_VERSION_MINOR+1}), 2)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test that we fail to mount incompatible rcompat flags -[cases.test_incompat_rcompat] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set the nonstandard rcompat flag, this will always be incompatible - // with standard littlefs - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_RCOMPAT, 0, - LFSR_DATA_RCOMPAT( - LFSR_RCOMPAT_COMPAT - | LFSR_RCOMPAT_NONSTANDARD)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test that we fail to mount incompatible wcompat flags -[cases.test_incompat_wcompat] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set the nonstandard rcompat flag, this will always be incompatible - // with standard littlefs - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_WCOMPAT, 0, - LFSR_DATA_WCOMPAT( - LFSR_WCOMPAT_COMPAT - | LFSR_WCOMPAT_NONSTANDARD)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test that an incompatible ocompat flag is a noop -[cases.test_incompat_ocompat] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set the nonstandard ocompat flag, this will always be incompatible - // with standard littlefs - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_OCOMPAT, 0, - LFSR_DATA_OCOMPAT( - LFSR_OCOMPAT_COMPAT - | LFSR_OCOMPAT_NONSTANDARD)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should _not_ fail, ocompat should always be ignored - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_unmount(&lfs) => 0; -''' - -# these are just a bit harder to detect -[cases.test_incompat_rcompat_overflow] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set a really far rcompat flag - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR_CAT( - LFSR_TAG_RCOMPAT, 0, - LFSR_DATA_RCOMPAT(LFSR_RCOMPAT_COMPAT), - LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -[cases.test_incompat_wcompat_overflow] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set a really far wcompat flag - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR_CAT( - LFSR_TAG_WCOMPAT, 0, - LFSR_DATA_WCOMPAT(LFSR_WCOMPAT_COMPAT), - LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -[cases.test_incompat_ocompat_overflow] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set a really far ocompat flag - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR_CAT( - LFSR_TAG_OCOMPAT, 0, - LFSR_DATA_OCOMPAT(LFSR_OCOMPAT_COMPAT), - LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should _not_ fail, ocompat should always be ignored - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_unmount(&lfs) => 0; -''' - -# test that we fail to mount incompatible block sizes -[cases.test_incompat_block_size] -defines.INC_BLOCK_SIZE = ['BLOCK_SIZE/2', 'BLOCK_SIZE*2'] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set an incompatible block size - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_GEOMETRY, 0, - LFSR_DATA_GEOMETRY((&(lfsr_geometry_t){ - INC_BLOCK_SIZE, - BLOCK_COUNT}))))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test that we fail to mount after incompatible block counts -[cases.test_incompat_block_count] -defines.INC_BLOCK_COUNT = ['BLOCK_COUNT*2'] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set an incompatible block count - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_GEOMETRY, 0, - LFSR_DATA_GEOMETRY((&(lfsr_geometry_t){ - BLOCK_SIZE, - INC_BLOCK_COUNT}))))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test that we fail to mount after incompatible name limit -[cases.test_incompat_name_limit] -defines.INC_NAME_LIMIT = ['LFS_NAME_MAX*2'] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set an incompatible block size - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_NAMELIMIT, 0, - LFSR_DATA_LLEB128(INC_NAME_LIMIT)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test that we fail to mount after incompatible file limit -[cases.test_incompat_file_limit] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // set an incompatible file limit - // - // note we're messing around with internals to do this! this - // is not a user API - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR_CAT( - LFSR_TAG_FILELIMIT, 0, - // it's a bit difficult to test this since file limit - // is usually our integer limit, but we can force a - // larger value by inserting an extra byte into our - // leb128 encoding - LFSR_DATA_BUF("\xff", 1), - LFSR_DATA_LEB128(LFS_FILE_MAX)))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test what happens if we find an unknown config -[cases.test_incompat_unknown_config] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // create an unknown config - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( - LFSR_ATTR( - LFSR_TAG_CONFIG + 0x13, 0, - LFSR_DATA_BUF("oh no!", strlen("oh no!"))))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' - -# test what happens if we find an unknown file type -[cases.test_incompat_unknown_type] -in = 'lfs.c' -code = ''' - // create a superblock - lfs_t lfs; - lfsr_format(&lfs, CFG) => 0; - - // create some files - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_file_t file; - lfsr_file_open(&lfs, &file, "a", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfsr_file_write(&lfs, &file, - "hi a!", strlen("hi a!")) => strlen("hi a!"); - lfsr_file_close(&lfs, &file) => 0; - lfsr_file_open(&lfs, &file, "b", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfsr_file_write(&lfs, &file, - "oh no!", strlen("oh no!")) => strlen("oh no!"); - lfsr_file_close(&lfs, &file) => 0; - lfsr_file_open(&lfs, &file, "c", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; - lfsr_file_write(&lfs, &file, - "hi c!", strlen("hi c!")) => strlen("hi c!"); - lfsr_file_close(&lfs, &file) => 0; - lfsr_unmount(&lfs) => 0; - - // change a file's type to something unknown - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mdir_t mdir; - lfsr_did_t did; - const char *name; - lfs_size_t name_size; - lfsr_mtree_pathlookup(&lfs, "b", - &mdir, NULL, - &did, &name, &name_size) => LFS_ERR_EXIST; - lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR_NAME( - LFSR_TAG_SUB | (LFSR_TAG_NAME + 0x13), 0, - did, name, name_size))) => 0; - lfsr_unmount(&lfs) => 0; - - // mount should now fail - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; -''' diff --git a/tests/test_mount.toml b/tests/test_mount.toml index 62137afb..de9c0138 100644 --- a/tests/test_mount.toml +++ b/tests/test_mount.toml @@ -1,6 +1,7 @@ # Advanced mount tests after = ['test_mtree', 'test_traversal'] + # test we can mount [cases.test_mount_simple] code = ''' @@ -428,4 +429,421 @@ done:; -# TODO should we move test_incompat here? +## incompatiblity tests ## + +# test that we fail if we find no magic +[cases.test_mount_incompat_no_magic] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // delete the magic string + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_RM | LFSR_TAG_MAGIC, 0, + LFSR_DATA_NULL()))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_CORRUPT; +''' + +# test that we fail if we find bad magic +[cases.test_mount_incompat_bad_magic] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // tweak the magic string + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_MAGIC, 0, + LFSR_DATA_BUF("lottlefs", 8)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_CORRUPT; +''' + +# test that we fail to mount after a major version bump +[cases.test_mount_incompat_major] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // bump the major version + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_VERSION, 0, + LFSR_DATA_BUF(((const uint8_t[2]){ + LFS_DISK_VERSION_MAJOR+1, + 0}), 2)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test that we fail to mount after a minor version bump +[cases.test_mount_incompat_minor] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // bump the minor version + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_VERSION, 0, + LFSR_DATA_BUF(((const uint8_t[2]){ + LFS_DISK_VERSION_MAJOR, + LFS_DISK_VERSION_MINOR+1}), 2)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test that we fail to mount incompatible rcompat flags +[cases.test_mount_incompat_rcompat] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set the nonstandard rcompat flag, this will always be incompatible + // with standard littlefs + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_RCOMPAT, 0, + LFSR_DATA_RCOMPAT( + LFSR_RCOMPAT_COMPAT + | LFSR_RCOMPAT_NONSTANDARD)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test that we fail to mount incompatible wcompat flags +[cases.test_mount_incompat_wcompat] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set the nonstandard rcompat flag, this will always be incompatible + // with standard littlefs + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_WCOMPAT, 0, + LFSR_DATA_WCOMPAT( + LFSR_WCOMPAT_COMPAT + | LFSR_WCOMPAT_NONSTANDARD)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test that an incompatible ocompat flag is a noop +[cases.test_mount_incompat_ocompat] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set the nonstandard ocompat flag, this will always be incompatible + // with standard littlefs + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_OCOMPAT, 0, + LFSR_DATA_OCOMPAT( + LFSR_OCOMPAT_COMPAT + | LFSR_OCOMPAT_NONSTANDARD)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should _not_ fail, ocompat should always be ignored + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_unmount(&lfs) => 0; +''' + +# these are just a bit harder to detect +[cases.test_mount_incompat_rcompat_overflow] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set a really far rcompat flag + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR_CAT( + LFSR_TAG_RCOMPAT, 0, + LFSR_DATA_RCOMPAT(LFSR_RCOMPAT_COMPAT), + LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +[cases.test_mount_incompat_wcompat_overflow] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set a really far wcompat flag + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR_CAT( + LFSR_TAG_WCOMPAT, 0, + LFSR_DATA_WCOMPAT(LFSR_WCOMPAT_COMPAT), + LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +[cases.test_mount_incompat_ocompat_overflow] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set a really far ocompat flag + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR_CAT( + LFSR_TAG_OCOMPAT, 0, + LFSR_DATA_OCOMPAT(LFSR_OCOMPAT_COMPAT), + LFSR_DATA_BUF("\x00\x00\x00\x00\x80", 5)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should _not_ fail, ocompat should always be ignored + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_unmount(&lfs) => 0; +''' + +# test that we fail to mount incompatible block sizes +[cases.test_mount_incompat_block_size] +defines.INC_BLOCK_SIZE = ['BLOCK_SIZE/2', 'BLOCK_SIZE*2'] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set an incompatible block size + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_GEOMETRY, 0, + LFSR_DATA_GEOMETRY((&(lfsr_geometry_t){ + INC_BLOCK_SIZE, + BLOCK_COUNT}))))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test that we fail to mount after incompatible block counts +[cases.test_mount_incompat_block_count] +defines.INC_BLOCK_COUNT = ['BLOCK_COUNT*2'] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set an incompatible block count + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_GEOMETRY, 0, + LFSR_DATA_GEOMETRY((&(lfsr_geometry_t){ + BLOCK_SIZE, + INC_BLOCK_COUNT}))))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test that we fail to mount after incompatible name limit +[cases.test_mount_incompat_name_limit] +defines.INC_NAME_LIMIT = ['LFS_NAME_MAX*2'] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set an incompatible block size + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_NAMELIMIT, 0, + LFSR_DATA_LLEB128(INC_NAME_LIMIT)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test that we fail to mount after incompatible file limit +[cases.test_mount_incompat_file_limit] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // set an incompatible file limit + // + // note we're messing around with internals to do this! this + // is not a user API + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR_CAT( + LFSR_TAG_FILELIMIT, 0, + // it's a bit difficult to test this since file limit + // is usually our integer limit, but we can force a + // larger value by inserting an extra byte into our + // leb128 encoding + LFSR_DATA_BUF("\xff", 1), + LFSR_DATA_LEB128(LFS_FILE_MAX)))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test what happens if we find an unknown config +[cases.test_mount_incompat_unknown_config] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // create an unknown config + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_CONFIG + 0x13, 0, + LFSR_DATA_BUF("oh no!", strlen("oh no!"))))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' + +# test what happens if we find an unknown file type +[cases.test_mount_incompat_unknown_type] +in = 'lfs.c' +code = ''' + // create a superblock + lfs_t lfs; + lfsr_format(&lfs, CFG) => 0; + + // create some files + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "a", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_write(&lfs, &file, + "hi a!", strlen("hi a!")) => strlen("hi a!"); + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "b", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_write(&lfs, &file, + "oh no!", strlen("oh no!")) => strlen("oh no!"); + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_write(&lfs, &file, + "hi c!", strlen("hi c!")) => strlen("hi c!"); + lfsr_file_close(&lfs, &file) => 0; + lfsr_unmount(&lfs) => 0; + + // change a file's type to something unknown + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mdir_t mdir; + lfsr_did_t did; + const char *name; + lfs_size_t name_size; + lfsr_mtree_pathlookup(&lfs, "b", + &mdir, NULL, + &did, &name, &name_size) => LFS_ERR_EXIST; + lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( + LFSR_ATTR_NAME( + LFSR_TAG_SUB | (LFSR_TAG_NAME + 0x13), 0, + did, name, name_size))) => 0; + lfsr_unmount(&lfs) => 0; + + // mount should now fail + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_NOTSUP; +''' diff --git a/tests/test_powerloss.toml b/tests/test_powerloss.toml index 4bb55155..2331efdb 100644 --- a/tests/test_powerloss.toml +++ b/tests/test_powerloss.toml @@ -11,6 +11,8 @@ after = [ 'test_traversal', 'test_gc', 'test_mount', + 'test_ck', + 'test_compat', ]