5be7bae518
The previous system of relying on test name prefixes for ordering was simple, but organizing tests by dependencies and topologically sorting during compilation is 1. more flexible and 2. simplifies test names, which get typed a lot. Note these are not "hard" dependencies, each test suite should work fine in isolation. These "after" dependencies just hint an ordering when all tests are ran. As such, it's worth noting the tests should NOT error of a dependency is missing. This unfortunately makes it a bit hard to catch typos, but allows faster compilation of a subset of tests. --- To make this work the way tests are linked has changed from using custom linker section (fun linker magic!) to a weakly linked array appended to every source file (also fun linker magic!). At least with this method test.py has strict control over the test ordering, and doesn't depend on 1. the order in which the linker merges sections, and 2. the order tests are passed to test.py. I didn't realize the previous system was so fragile.
251 lines
6.7 KiB
TOML
251 lines
6.7 KiB
TOML
# Block device tests
|
|
#
|
|
# These tests don't really test littlefs at all, they are here only to make
|
|
# sure the underlying block device is working.
|
|
#
|
|
# Note we use 251, a prime, in places to avoid aliasing powers of 2.
|
|
#
|
|
|
|
[cases.test_bd_one_block]
|
|
defines.READ = ['READ_SIZE', 'BLOCK_SIZE']
|
|
defines.PROG = ['PROG_SIZE', 'BLOCK_SIZE']
|
|
code = '''
|
|
uint8_t buffer[lfs_max(READ, PROG)];
|
|
|
|
// write data
|
|
cfg->erase(cfg, 0) => 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += PROG) {
|
|
for (lfs_off_t j = 0; j < PROG; j++) {
|
|
buffer[j] = (i+j) % 251;
|
|
}
|
|
cfg->prog(cfg, 0, i, buffer, PROG) => 0;
|
|
}
|
|
|
|
// read data
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, 0, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (i+j) % 251);
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_bd_two_block]
|
|
defines.READ = ['READ_SIZE', 'BLOCK_SIZE']
|
|
defines.PROG = ['PROG_SIZE', 'BLOCK_SIZE']
|
|
code = '''
|
|
uint8_t buffer[lfs_max(READ, PROG)];
|
|
lfs_block_t block;
|
|
|
|
// write block 0
|
|
block = 0;
|
|
cfg->erase(cfg, block) => 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += PROG) {
|
|
for (lfs_off_t j = 0; j < PROG; j++) {
|
|
buffer[j] = (block+i+j) % 251;
|
|
}
|
|
cfg->prog(cfg, block, i, buffer, PROG) => 0;
|
|
}
|
|
|
|
// read block 0
|
|
block = 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
// write block 1
|
|
block = 1;
|
|
cfg->erase(cfg, block) => 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += PROG) {
|
|
for (lfs_off_t j = 0; j < PROG; j++) {
|
|
buffer[j] = (block+i+j) % 251;
|
|
}
|
|
cfg->prog(cfg, block, i, buffer, PROG) => 0;
|
|
}
|
|
|
|
// read block 1
|
|
block = 1;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
// read block 0 again
|
|
block = 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_bd_last_block]
|
|
defines.READ = ['READ_SIZE', 'BLOCK_SIZE']
|
|
defines.PROG = ['PROG_SIZE', 'BLOCK_SIZE']
|
|
code = '''
|
|
uint8_t buffer[lfs_max(READ, PROG)];
|
|
lfs_block_t block;
|
|
|
|
// write block 0
|
|
block = 0;
|
|
cfg->erase(cfg, block) => 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += PROG) {
|
|
for (lfs_off_t j = 0; j < PROG; j++) {
|
|
buffer[j] = (block+i+j) % 251;
|
|
}
|
|
cfg->prog(cfg, block, i, buffer, PROG) => 0;
|
|
}
|
|
|
|
// read block 0
|
|
block = 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
// write block n-1
|
|
block = cfg->block_count-1;
|
|
cfg->erase(cfg, block) => 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += PROG) {
|
|
for (lfs_off_t j = 0; j < PROG; j++) {
|
|
buffer[j] = (block+i+j) % 251;
|
|
}
|
|
cfg->prog(cfg, block, i, buffer, PROG) => 0;
|
|
}
|
|
|
|
// read block n-1
|
|
block = cfg->block_count-1;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
// read block 0 again
|
|
block = 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
'''
|
|
|
|
[cases.test_bd_powers_of_two]
|
|
defines.READ = ['READ_SIZE', 'BLOCK_SIZE']
|
|
defines.PROG = ['PROG_SIZE', 'BLOCK_SIZE']
|
|
code = '''
|
|
uint8_t buffer[lfs_max(READ, PROG)];
|
|
|
|
// write/read every power of 2
|
|
lfs_block_t block = 1;
|
|
while (block < cfg->block_count) {
|
|
// write
|
|
cfg->erase(cfg, block) => 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += PROG) {
|
|
for (lfs_off_t j = 0; j < PROG; j++) {
|
|
buffer[j] = (block+i+j) % 251;
|
|
}
|
|
cfg->prog(cfg, block, i, buffer, PROG) => 0;
|
|
}
|
|
|
|
// read
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
block *= 2;
|
|
}
|
|
|
|
// read every power of 2 again
|
|
block = 1;
|
|
while (block < cfg->block_count) {
|
|
// read
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
block *= 2;
|
|
}
|
|
'''
|
|
|
|
[cases.test_bd_fibonacci]
|
|
defines.READ = ['READ_SIZE', 'BLOCK_SIZE']
|
|
defines.PROG = ['PROG_SIZE', 'BLOCK_SIZE']
|
|
code = '''
|
|
uint8_t buffer[lfs_max(READ, PROG)];
|
|
|
|
// write/read every fibonacci number on our device
|
|
lfs_block_t block = 1;
|
|
lfs_block_t block_ = 1;
|
|
while (block < cfg->block_count) {
|
|
// write
|
|
cfg->erase(cfg, block) => 0;
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += PROG) {
|
|
for (lfs_off_t j = 0; j < PROG; j++) {
|
|
buffer[j] = (block+i+j) % 251;
|
|
}
|
|
cfg->prog(cfg, block, i, buffer, PROG) => 0;
|
|
}
|
|
|
|
// read
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
lfs_block_t nblock = block + block_;
|
|
block_ = block;
|
|
block = nblock;
|
|
}
|
|
|
|
// read every fibonacci number again
|
|
block = 1;
|
|
block_ = 1;
|
|
while (block < cfg->block_count) {
|
|
// read
|
|
for (lfs_off_t i = 0; i < cfg->block_size; i += READ) {
|
|
cfg->read(cfg, block, i, buffer, READ) => 0;
|
|
|
|
for (lfs_off_t j = 0; j < READ; j++) {
|
|
LFS_ASSERT(buffer[j] == (block+i+j) % 251);
|
|
}
|
|
}
|
|
|
|
lfs_block_t nblock = block + block_;
|
|
block_ = block;
|
|
block = nblock;
|
|
}
|
|
'''
|
|
|
|
|
|
|
|
|