Files
littlefs/tests/test_incompat.toml
T
Christopher Haster 1e41fc07fe Split out test_incompat tests and added a few more cases
Unlike the other test_compat tests, the test_incompat tests cover
specific corner cases and don't require any special linking. We probably
always want to run these, and keeping them merged with test_compat risks
the entire suite being omitted at some point.

The test_compat tests are a bit special and probably deserves a
dedicated test suite.
2024-06-09 02:43:27 -05:00

319 lines
9.0 KiB
TOML

# Test (in)compatibility-related things
#
# Unlike test_compat, this focuses on specific corner-cases
#
after = [
'test_dirs',
'test_files',
'test_fwrite',
'test_forphans',
]
## incompatiblity tests ##
# 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, 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, CFG) => LFS_ERR_INVAL;
'''
# 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, 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, CFG) => LFS_ERR_INVAL;
'''
# 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, 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, CFG) => LFS_ERR_INVAL;
'''
# 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, 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, CFG) => LFS_ERR_INVAL;
'''
# 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, 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, 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, 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, CFG) => LFS_ERR_INVAL;
'''
[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, 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, CFG) => LFS_ERR_INVAL;
'''
[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, 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, 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, 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, CFG) => LFS_ERR_INVAL;
'''
# 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, 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, CFG) => LFS_ERR_INVAL;
'''
# 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, 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, CFG) => LFS_ERR_INVAL;
'''
# 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, 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, CFG) => LFS_ERR_INVAL;
'''