## There are already a number of tests that test general operations under ## power-loss (see the reentrant attribute). These tests are for explicitly ## testing specific corner cases. # ## only a revision count #[cases.test_powerloss_only_rev] #code = ''' # lfs_t lfs; # lfs_format(&lfs, cfg) => 0; # # lfs_mount(&lfs, cfg) => 0; # lfs_mkdir(&lfs, "notebook") => 0; # lfs_file_t file; # lfs_file_open(&lfs, &file, "notebook/paper", # LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; # char buffer[256]; # strcpy(buffer, "hello"); # lfs_size_t size = strlen("hello"); # for (int i = 0; i < 5; i++) { # lfs_file_write(&lfs, &file, buffer, size) => size; # lfs_file_sync(&lfs, &file) => 0; # } # lfs_file_close(&lfs, &file) => 0; # # char rbuffer[256]; # lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # lfs_file_close(&lfs, &file) => 0; # lfs_unmount(&lfs) => 0; # # // get pair/rev count # lfs_mount(&lfs, cfg) => 0; # lfs_dir_t dir; # lfs_dir_open(&lfs, &dir, "notebook") => 0; # lfs_block_t pair[2] = {dir.m.pair[0], dir.m.pair[1]}; # uint32_t rev = dir.m.rev; # lfs_dir_close(&lfs, &dir) => 0; # lfs_unmount(&lfs) => 0; # # // write just the revision count # uint8_t bbuffer[BLOCK_SIZE]; # cfg->read(cfg, pair[1], 0, bbuffer, BLOCK_SIZE) => 0; # # memcpy(bbuffer, &(uint32_t){lfs_tole32(rev+1)}, sizeof(uint32_t)); # # cfg->erase(cfg, pair[1]) => 0; # cfg->prog(cfg, pair[1], 0, bbuffer, BLOCK_SIZE) => 0; # # lfs_mount(&lfs, cfg) => 0; # # // can read? # lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # lfs_file_close(&lfs, &file) => 0; # # // can write? # lfs_file_open(&lfs, &file, "notebook/paper", # LFS_O_WRONLY | LFS_O_APPEND) => 0; # strcpy(buffer, "goodbye"); # size = strlen("goodbye"); # for (int i = 0; i < 5; i++) { # lfs_file_write(&lfs, &file, buffer, size) => size; # lfs_file_sync(&lfs, &file) => 0; # } # lfs_file_close(&lfs, &file) => 0; # # lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; # strcpy(buffer, "hello"); # size = strlen("hello"); # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # strcpy(buffer, "goodbye"); # size = strlen("goodbye"); # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # lfs_file_close(&lfs, &file) => 0; # # lfs_unmount(&lfs) => 0; #''' # ## partial prog, may not be byte in order! #[cases.test_powerloss_partial_prog] #if = "PROG_SIZE < BLOCK_SIZE" #defines.BYTE_OFF = ["0", "PROG_SIZE-1", "PROG_SIZE/2"] #defines.BYTE_VALUE = [0x33, 0xcc] #in = "lfs.c" #code = ''' # lfs_t lfs; # lfs_format(&lfs, cfg) => 0; # # lfs_mount(&lfs, cfg) => 0; # lfs_mkdir(&lfs, "notebook") => 0; # lfs_file_t file; # lfs_file_open(&lfs, &file, "notebook/paper", # LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; # char buffer[256]; # strcpy(buffer, "hello"); # lfs_size_t size = strlen("hello"); # for (int i = 0; i < 5; i++) { # lfs_file_write(&lfs, &file, buffer, size) => size; # lfs_file_sync(&lfs, &file) => 0; # } # lfs_file_close(&lfs, &file) => 0; # # char rbuffer[256]; # lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # lfs_file_close(&lfs, &file) => 0; # lfs_unmount(&lfs) => 0; # # // imitate a partial prog, value should not matter, if littlefs # // doesn't notice the partial prog testbd will assert # # // get offset to next prog # lfs_mount(&lfs, cfg) => 0; # lfs_dir_t dir; # lfs_dir_open(&lfs, &dir, "notebook") => 0; # lfs_block_t block = dir.m.pair[0]; # lfs_off_t off = dir.m.off; # lfs_dir_close(&lfs, &dir) => 0; # lfs_unmount(&lfs) => 0; # # // tweak byte # uint8_t bbuffer[BLOCK_SIZE]; # cfg->read(cfg, block, 0, bbuffer, BLOCK_SIZE) => 0; # # bbuffer[off + BYTE_OFF] = BYTE_VALUE; # # cfg->erase(cfg, block) => 0; # cfg->prog(cfg, block, 0, bbuffer, BLOCK_SIZE) => 0; # # lfs_mount(&lfs, cfg) => 0; # # // can read? # lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # lfs_file_close(&lfs, &file) => 0; # # // can write? # lfs_file_open(&lfs, &file, "notebook/paper", # LFS_O_WRONLY | LFS_O_APPEND) => 0; # strcpy(buffer, "goodbye"); # size = strlen("goodbye"); # for (int i = 0; i < 5; i++) { # lfs_file_write(&lfs, &file, buffer, size) => size; # lfs_file_sync(&lfs, &file) => 0; # } # lfs_file_close(&lfs, &file) => 0; # # lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; # strcpy(buffer, "hello"); # size = strlen("hello"); # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # strcpy(buffer, "goodbye"); # size = strlen("goodbye"); # for (int i = 0; i < 5; i++) { # lfs_file_read(&lfs, &file, rbuffer, size) => size; # assert(memcmp(rbuffer, buffer, size) == 0); # } # lfs_file_close(&lfs, &file) => 0; # # lfs_unmount(&lfs) => 0; #'''