1# There are already a number of tests that test general operations under 2# power-loss (see the reentrant attribute). These tests are for explicitly 3# testing specific corner cases. 4 5# only a revision count 6[cases.test_powerloss_only_rev] 7code = ''' 8 lfs_t lfs; 9 lfs_format(&lfs, cfg) => 0; 10 11 lfs_mount(&lfs, cfg) => 0; 12 lfs_mkdir(&lfs, "notebook") => 0; 13 lfs_file_t file; 14 lfs_file_open(&lfs, &file, "notebook/paper", 15 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; 16 char buffer[256]; 17 strcpy(buffer, "hello"); 18 lfs_size_t size = strlen("hello"); 19 for (int i = 0; i < 5; i++) { 20 lfs_file_write(&lfs, &file, buffer, size) => size; 21 lfs_file_sync(&lfs, &file) => 0; 22 } 23 lfs_file_close(&lfs, &file) => 0; 24 25 char rbuffer[256]; 26 lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; 27 for (int i = 0; i < 5; i++) { 28 lfs_file_read(&lfs, &file, rbuffer, size) => size; 29 assert(memcmp(rbuffer, buffer, size) == 0); 30 } 31 lfs_file_close(&lfs, &file) => 0; 32 lfs_unmount(&lfs) => 0; 33 34 // get pair/rev count 35 lfs_mount(&lfs, cfg) => 0; 36 lfs_dir_t dir; 37 lfs_dir_open(&lfs, &dir, "notebook") => 0; 38 lfs_block_t pair[2] = {dir.m.pair[0], dir.m.pair[1]}; 39 uint32_t rev = dir.m.rev; 40 lfs_dir_close(&lfs, &dir) => 0; 41 lfs_unmount(&lfs) => 0; 42 43 // write just the revision count 44 uint8_t bbuffer[BLOCK_SIZE]; 45 cfg->read(cfg, pair[1], 0, bbuffer, BLOCK_SIZE) => 0; 46 47 memcpy(bbuffer, &(uint32_t){lfs_tole32(rev+1)}, sizeof(uint32_t)); 48 49 cfg->erase(cfg, pair[1]) => 0; 50 cfg->prog(cfg, pair[1], 0, bbuffer, BLOCK_SIZE) => 0; 51 52 lfs_mount(&lfs, cfg) => 0; 53 54 // can read? 55 lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; 56 for (int i = 0; i < 5; i++) { 57 lfs_file_read(&lfs, &file, rbuffer, size) => size; 58 assert(memcmp(rbuffer, buffer, size) == 0); 59 } 60 lfs_file_close(&lfs, &file) => 0; 61 62 // can write? 63 lfs_file_open(&lfs, &file, "notebook/paper", 64 LFS_O_WRONLY | LFS_O_APPEND) => 0; 65 strcpy(buffer, "goodbye"); 66 size = strlen("goodbye"); 67 for (int i = 0; i < 5; i++) { 68 lfs_file_write(&lfs, &file, buffer, size) => size; 69 lfs_file_sync(&lfs, &file) => 0; 70 } 71 lfs_file_close(&lfs, &file) => 0; 72 73 lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; 74 strcpy(buffer, "hello"); 75 size = strlen("hello"); 76 for (int i = 0; i < 5; i++) { 77 lfs_file_read(&lfs, &file, rbuffer, size) => size; 78 assert(memcmp(rbuffer, buffer, size) == 0); 79 } 80 strcpy(buffer, "goodbye"); 81 size = strlen("goodbye"); 82 for (int i = 0; i < 5; i++) { 83 lfs_file_read(&lfs, &file, rbuffer, size) => size; 84 assert(memcmp(rbuffer, buffer, size) == 0); 85 } 86 lfs_file_close(&lfs, &file) => 0; 87 88 lfs_unmount(&lfs) => 0; 89''' 90 91# partial prog, may not be byte in order! 92[cases.test_powerloss_partial_prog] 93if = ''' 94 PROG_SIZE < BLOCK_SIZE 95 && (DISK_VERSION == 0 || DISK_VERSION >= 0x00020001) 96''' 97defines.BYTE_OFF = ["0", "PROG_SIZE-1", "PROG_SIZE/2"] 98defines.BYTE_VALUE = [0x33, 0xcc] 99in = "lfs.c" 100code = ''' 101 lfs_t lfs; 102 lfs_format(&lfs, cfg) => 0; 103 104 lfs_mount(&lfs, cfg) => 0; 105 lfs_mkdir(&lfs, "notebook") => 0; 106 lfs_file_t file; 107 lfs_file_open(&lfs, &file, "notebook/paper", 108 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; 109 char buffer[256]; 110 strcpy(buffer, "hello"); 111 lfs_size_t size = strlen("hello"); 112 for (int i = 0; i < 5; i++) { 113 lfs_file_write(&lfs, &file, buffer, size) => size; 114 lfs_file_sync(&lfs, &file) => 0; 115 } 116 lfs_file_close(&lfs, &file) => 0; 117 118 char rbuffer[256]; 119 lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; 120 for (int i = 0; i < 5; i++) { 121 lfs_file_read(&lfs, &file, rbuffer, size) => size; 122 assert(memcmp(rbuffer, buffer, size) == 0); 123 } 124 lfs_file_close(&lfs, &file) => 0; 125 lfs_unmount(&lfs) => 0; 126 127 // imitate a partial prog, value should not matter, if littlefs 128 // doesn't notice the partial prog testbd will assert 129 130 // get offset to next prog 131 lfs_mount(&lfs, cfg) => 0; 132 lfs_dir_t dir; 133 lfs_dir_open(&lfs, &dir, "notebook") => 0; 134 lfs_block_t block = dir.m.pair[0]; 135 lfs_off_t off = dir.m.off; 136 lfs_dir_close(&lfs, &dir) => 0; 137 lfs_unmount(&lfs) => 0; 138 139 // tweak byte 140 uint8_t bbuffer[BLOCK_SIZE]; 141 cfg->read(cfg, block, 0, bbuffer, BLOCK_SIZE) => 0; 142 143 bbuffer[off + BYTE_OFF] = BYTE_VALUE; 144 145 cfg->erase(cfg, block) => 0; 146 cfg->prog(cfg, block, 0, bbuffer, BLOCK_SIZE) => 0; 147 148 lfs_mount(&lfs, cfg) => 0; 149 150 // can read? 151 lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; 152 for (int i = 0; i < 5; i++) { 153 lfs_file_read(&lfs, &file, rbuffer, size) => size; 154 assert(memcmp(rbuffer, buffer, size) == 0); 155 } 156 lfs_file_close(&lfs, &file) => 0; 157 158 // can write? 159 lfs_file_open(&lfs, &file, "notebook/paper", 160 LFS_O_WRONLY | LFS_O_APPEND) => 0; 161 strcpy(buffer, "goodbye"); 162 size = strlen("goodbye"); 163 for (int i = 0; i < 5; i++) { 164 lfs_file_write(&lfs, &file, buffer, size) => size; 165 lfs_file_sync(&lfs, &file) => 0; 166 } 167 lfs_file_close(&lfs, &file) => 0; 168 169 lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0; 170 strcpy(buffer, "hello"); 171 size = strlen("hello"); 172 for (int i = 0; i < 5; i++) { 173 lfs_file_read(&lfs, &file, rbuffer, size) => size; 174 assert(memcmp(rbuffer, buffer, size) == 0); 175 } 176 strcpy(buffer, "goodbye"); 177 size = strlen("goodbye"); 178 for (int i = 0; i < 5; i++) { 179 lfs_file_read(&lfs, &file, rbuffer, size) => size; 180 assert(memcmp(rbuffer, buffer, size) == 0); 181 } 182 lfs_file_close(&lfs, &file) => 0; 183 184 lfs_unmount(&lfs) => 0; 185''' 186