mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-10-30 16:15:40 +01:00
Instead of 1. defining LFS_STATICCFG and 2. defining all LFS_READ_SIZE, LFS_PROG_SIZE, etc. Configuration can now be made static by defining LFS_READ_SIZE, LFS_PROG_SIZE, etc. Thanks to a really large ifdef, if all configurations are provided, LFS_STATICCFG will be defined and the RAM cost fully removed. Additionally, we can remove the ROM cost of each struct cfg member, allowing code savings when config is only partially defined, which is perhaps more common. This moves all of the configuration logic in lfs.h, which has the nice side effect of keeping all of the decision making in the same location. The only catch is that we need to differentiate between the cfg->*_max and *_MAX limits. To do this I've renamed the configuration *_max to *_limit. Note that these two are slightly different, with *_max indicating the maximum supported by the current driver, and *_limit the maximum supported by the specific instance of littlefs. However if you do define a *_LIMIT, I've added an override for the relevant *_MAX, since I can't think of a time where you _wouldn't_ want to do that. --- This also required some tweaks in scripts/test.py in order to populate the lfs_cfg struct correctly. This happens since the test defines overlap littlefs's configuration defines. This does change what is being tested a bit, but hopefully that's not a real issue. Suggested by tim-nordell-nimbelink
395 lines
13 KiB
TOML
395 lines
13 KiB
TOML
[[case]] # simple truncate
|
|
define.MEDIUMSIZE = [32, 2048]
|
|
define.LARGESIZE = 8192
|
|
code = '''
|
|
lfs_formatcfg(&lfs, &cfg) => 0;
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
lfs_file_open(&lfs, &file, "baldynoop",
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
|
|
strcpy((char*)buffer, "hair");
|
|
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;
|
|
|
|
lfs_mountcfg(&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;
|
|
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
lfs_file_open(&lfs, &file, "baldynoop", LFS_O_RDONLY) => 0;
|
|
lfs_file_size(&lfs, &file) => MEDIUMSIZE;
|
|
|
|
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;
|
|
'''
|
|
|
|
[[case]] # truncate and read
|
|
define.MEDIUMSIZE = [32, 2048]
|
|
define.LARGESIZE = 8192
|
|
code = '''
|
|
lfs_formatcfg(&lfs, &cfg) => 0;
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
lfs_file_open(&lfs, &file, "baldyread",
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
|
|
strcpy((char*)buffer, "hair");
|
|
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;
|
|
|
|
lfs_mountcfg(&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;
|
|
|
|
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;
|
|
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
lfs_file_open(&lfs, &file, "baldyread", LFS_O_RDONLY) => 0;
|
|
lfs_file_size(&lfs, &file) => MEDIUMSIZE;
|
|
|
|
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;
|
|
'''
|
|
|
|
[[case]] # write, truncate, and read
|
|
code = '''
|
|
lfs_formatcfg(&lfs, &cfg) => 0;
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
lfs_file_open(&lfs, &file, "sequence",
|
|
LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC) => 0;
|
|
|
|
size = lfs_min(LFS_BUFFER_SIZE, sizeof(buffer)/2);
|
|
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;
|
|
'''
|
|
|
|
[[case]] # truncate and write
|
|
define.MEDIUMSIZE = [32, 2048]
|
|
define.LARGESIZE = 8192
|
|
code = '''
|
|
lfs_formatcfg(&lfs, &cfg) => 0;
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
lfs_file_open(&lfs, &file, "baldywrite",
|
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
|
|
|
strcpy((char*)buffer, "hair");
|
|
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;
|
|
|
|
lfs_mountcfg(&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");
|
|
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;
|
|
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
lfs_file_open(&lfs, &file, "baldywrite", LFS_O_RDONLY) => 0;
|
|
lfs_file_size(&lfs, &file) => MEDIUMSIZE;
|
|
|
|
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;
|
|
'''
|
|
|
|
[[case]] # truncate write under powerloss
|
|
define.SMALLSIZE = [4, 512]
|
|
define.MEDIUMSIZE = [32, 1024]
|
|
define.LARGESIZE = 2048
|
|
reentrant = true
|
|
code = '''
|
|
err = lfs_mountcfg(&lfs, &cfg);
|
|
if (err) {
|
|
lfs_formatcfg(&lfs, &cfg) => 0;
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
}
|
|
err = lfs_file_open(&lfs, &file, "baldy", LFS_O_RDONLY);
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
if (!err) {
|
|
size = lfs_file_size(&lfs, &file);
|
|
assert(size == 0 ||
|
|
size == LARGESIZE ||
|
|
size == MEDIUMSIZE ||
|
|
size == SMALLSIZE);
|
|
for (lfs_off_t j = 0; j < size; j += 4) {
|
|
lfs_file_read(&lfs, &file, buffer, 4) => 4;
|
|
assert(memcmp(buffer, "hair", 4) == 0 ||
|
|
memcmp(buffer, "bald", 4) == 0 ||
|
|
memcmp(buffer, "comb", 4) == 0);
|
|
}
|
|
lfs_file_close(&lfs, &file) => 0;
|
|
}
|
|
|
|
lfs_file_open(&lfs, &file, "baldy",
|
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
|
|
lfs_file_size(&lfs, &file) => 0;
|
|
strcpy((char*)buffer, "hair");
|
|
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_file_open(&lfs, &file, "baldy", 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");
|
|
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_file_open(&lfs, &file, "baldy", LFS_O_RDWR) => 0;
|
|
lfs_file_size(&lfs, &file) => MEDIUMSIZE;
|
|
lfs_file_truncate(&lfs, &file, SMALLSIZE) => 0;
|
|
lfs_file_size(&lfs, &file) => SMALLSIZE;
|
|
strcpy((char*)buffer, "comb");
|
|
size = strlen((char*)buffer);
|
|
for (lfs_off_t j = 0; j < SMALLSIZE; j += size) {
|
|
lfs_file_write(&lfs, &file, buffer, size) => size;
|
|
}
|
|
lfs_file_size(&lfs, &file) => SMALLSIZE;
|
|
lfs_file_close(&lfs, &file) => 0;
|
|
|
|
lfs_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[[case]] # more aggressive general truncation tests
|
|
define.CONFIG = 'range(6)'
|
|
define.SMALLSIZE = 32
|
|
define.MEDIUMSIZE = 2048
|
|
define.LARGESIZE = 8192
|
|
code = '''
|
|
#define COUNT 5
|
|
const struct {
|
|
lfs_off_t startsizes[COUNT];
|
|
lfs_off_t startseeks[COUNT];
|
|
lfs_off_t hotsizes[COUNT];
|
|
lfs_off_t coldsizes[COUNT];
|
|
} configs[] = {
|
|
// cold shrinking
|
|
{{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}},
|
|
// cold expanding
|
|
{{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}},
|
|
// warm shrinking truncate
|
|
{{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}},
|
|
// warm expanding truncate
|
|
{{ 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}},
|
|
// mid-file shrinking truncate
|
|
{{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}},
|
|
// mid-file expanding truncate
|
|
{{ 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}},
|
|
};
|
|
|
|
const lfs_off_t *startsizes = configs[CONFIG].startsizes;
|
|
const lfs_off_t *startseeks = configs[CONFIG].startseeks;
|
|
const lfs_off_t *hotsizes = configs[CONFIG].hotsizes;
|
|
const lfs_off_t *coldsizes = configs[CONFIG].coldsizes;
|
|
|
|
lfs_formatcfg(&lfs, &cfg) => 0;
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
|
|
for (unsigned i = 0; i < COUNT; 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");
|
|
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;
|
|
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
|
|
for (unsigned i = 0; i < COUNT; i++) {
|
|
sprintf(path, "hairyhead%d", i);
|
|
lfs_file_open(&lfs, &file, path, LFS_O_RDWR) => 0;
|
|
lfs_file_size(&lfs, &file) => hotsizes[i];
|
|
|
|
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;
|
|
|
|
lfs_mountcfg(&lfs, &cfg) => 0;
|
|
|
|
for (unsigned i = 0; i < COUNT; i++) {
|
|
sprintf(path, "hairyhead%d", i);
|
|
lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0;
|
|
lfs_file_size(&lfs, &file) => coldsizes[i];
|
|
|
|
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;
|
|
'''
|