1# specific corner cases worth explicitly testing for 2[[case]] # dangling split dir test 3define.ITERATIONS = 20 4define.COUNT = 10 5define.LFS_BLOCK_CYCLES = [8, 1] 6code = ''' 7 lfs_format(&lfs, &cfg) => 0; 8 // fill up filesystem so only ~16 blocks are left 9 lfs_mount(&lfs, &cfg) => 0; 10 lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; 11 memset(buffer, 0, 512); 12 while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { 13 lfs_file_write(&lfs, &file, buffer, 512) => 512; 14 } 15 lfs_file_close(&lfs, &file) => 0; 16 // make a child dir to use in bounded space 17 lfs_mkdir(&lfs, "child") => 0; 18 lfs_unmount(&lfs) => 0; 19 20 lfs_mount(&lfs, &cfg) => 0; 21 for (int j = 0; j < ITERATIONS; j++) { 22 for (int i = 0; i < COUNT; i++) { 23 sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); 24 lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; 25 lfs_file_close(&lfs, &file) => 0; 26 } 27 28 lfs_dir_open(&lfs, &dir, "child") => 0; 29 lfs_dir_read(&lfs, &dir, &info) => 1; 30 lfs_dir_read(&lfs, &dir, &info) => 1; 31 for (int i = 0; i < COUNT; i++) { 32 sprintf(path, "test%03d_loooooooooooooooooong_name", i); 33 lfs_dir_read(&lfs, &dir, &info) => 1; 34 strcmp(info.name, path) => 0; 35 } 36 lfs_dir_read(&lfs, &dir, &info) => 0; 37 lfs_dir_close(&lfs, &dir) => 0; 38 39 if (j == ITERATIONS-1) { 40 break; 41 } 42 43 for (int i = 0; i < COUNT; i++) { 44 sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); 45 lfs_remove(&lfs, path) => 0; 46 } 47 } 48 lfs_unmount(&lfs) => 0; 49 50 lfs_mount(&lfs, &cfg) => 0; 51 lfs_dir_open(&lfs, &dir, "child") => 0; 52 lfs_dir_read(&lfs, &dir, &info) => 1; 53 lfs_dir_read(&lfs, &dir, &info) => 1; 54 for (int i = 0; i < COUNT; i++) { 55 sprintf(path, "test%03d_loooooooooooooooooong_name", i); 56 lfs_dir_read(&lfs, &dir, &info) => 1; 57 strcmp(info.name, path) => 0; 58 } 59 lfs_dir_read(&lfs, &dir, &info) => 0; 60 lfs_dir_close(&lfs, &dir) => 0; 61 for (int i = 0; i < COUNT; i++) { 62 sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); 63 lfs_remove(&lfs, path) => 0; 64 } 65 lfs_unmount(&lfs) => 0; 66''' 67 68[[case]] # outdated head test 69define.ITERATIONS = 20 70define.COUNT = 10 71define.LFS_BLOCK_CYCLES = [8, 1] 72code = ''' 73 lfs_format(&lfs, &cfg) => 0; 74 // fill up filesystem so only ~16 blocks are left 75 lfs_mount(&lfs, &cfg) => 0; 76 lfs_file_open(&lfs, &file, "padding", LFS_O_CREAT | LFS_O_WRONLY) => 0; 77 memset(buffer, 0, 512); 78 while (LFS_BLOCK_COUNT - lfs_fs_size(&lfs) > 16) { 79 lfs_file_write(&lfs, &file, buffer, 512) => 512; 80 } 81 lfs_file_close(&lfs, &file) => 0; 82 // make a child dir to use in bounded space 83 lfs_mkdir(&lfs, "child") => 0; 84 lfs_unmount(&lfs) => 0; 85 86 lfs_mount(&lfs, &cfg) => 0; 87 for (int j = 0; j < ITERATIONS; j++) { 88 for (int i = 0; i < COUNT; i++) { 89 sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); 90 lfs_file_open(&lfs, &file, path, LFS_O_CREAT | LFS_O_WRONLY) => 0; 91 lfs_file_close(&lfs, &file) => 0; 92 } 93 94 lfs_dir_open(&lfs, &dir, "child") => 0; 95 lfs_dir_read(&lfs, &dir, &info) => 1; 96 lfs_dir_read(&lfs, &dir, &info) => 1; 97 for (int i = 0; i < COUNT; i++) { 98 sprintf(path, "test%03d_loooooooooooooooooong_name", i); 99 lfs_dir_read(&lfs, &dir, &info) => 1; 100 strcmp(info.name, path) => 0; 101 info.size => 0; 102 103 sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); 104 lfs_file_open(&lfs, &file, path, LFS_O_WRONLY) => 0; 105 lfs_file_write(&lfs, &file, "hi", 2) => 2; 106 lfs_file_close(&lfs, &file) => 0; 107 } 108 lfs_dir_read(&lfs, &dir, &info) => 0; 109 110 lfs_dir_rewind(&lfs, &dir) => 0; 111 lfs_dir_read(&lfs, &dir, &info) => 1; 112 lfs_dir_read(&lfs, &dir, &info) => 1; 113 for (int i = 0; i < COUNT; i++) { 114 sprintf(path, "test%03d_loooooooooooooooooong_name", i); 115 lfs_dir_read(&lfs, &dir, &info) => 1; 116 strcmp(info.name, path) => 0; 117 info.size => 2; 118 119 sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); 120 lfs_file_open(&lfs, &file, path, LFS_O_WRONLY) => 0; 121 lfs_file_write(&lfs, &file, "hi", 2) => 2; 122 lfs_file_close(&lfs, &file) => 0; 123 } 124 lfs_dir_read(&lfs, &dir, &info) => 0; 125 126 lfs_dir_rewind(&lfs, &dir) => 0; 127 lfs_dir_read(&lfs, &dir, &info) => 1; 128 lfs_dir_read(&lfs, &dir, &info) => 1; 129 for (int i = 0; i < COUNT; i++) { 130 sprintf(path, "test%03d_loooooooooooooooooong_name", i); 131 lfs_dir_read(&lfs, &dir, &info) => 1; 132 strcmp(info.name, path) => 0; 133 info.size => 2; 134 } 135 lfs_dir_read(&lfs, &dir, &info) => 0; 136 lfs_dir_close(&lfs, &dir) => 0; 137 138 for (int i = 0; i < COUNT; i++) { 139 sprintf(path, "child/test%03d_loooooooooooooooooong_name", i); 140 lfs_remove(&lfs, path) => 0; 141 } 142 } 143 lfs_unmount(&lfs) => 0; 144''' 145 146[[case]] # reentrant testing for relocations, this is the same as the 147 # orphan testing, except here we also set block_cycles so that 148 # almost every tree operation needs a relocation 149reentrant = true 150# TODO fix this case, caused by non-DAG trees 151if = '!(DEPTH == 3 && LFS_CACHE_SIZE != 64)' 152define = [ 153 {FILES=6, DEPTH=1, CYCLES=20, LFS_BLOCK_CYCLES=1}, 154 {FILES=26, DEPTH=1, CYCLES=20, LFS_BLOCK_CYCLES=1}, 155 {FILES=3, DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1}, 156] 157code = ''' 158 err = lfs_mount(&lfs, &cfg); 159 if (err) { 160 lfs_format(&lfs, &cfg) => 0; 161 lfs_mount(&lfs, &cfg) => 0; 162 } 163 164 srand(1); 165 const char alpha[] = "abcdefghijklmnopqrstuvwxyz"; 166 for (int i = 0; i < CYCLES; i++) { 167 // create random path 168 char full_path[256]; 169 for (int d = 0; d < DEPTH; d++) { 170 sprintf(&full_path[2*d], "/%c", alpha[rand() % FILES]); 171 } 172 173 // if it does not exist, we create it, else we destroy 174 int res = lfs_stat(&lfs, full_path, &info); 175 if (res == LFS_ERR_NOENT) { 176 // create each directory in turn, ignore if dir already exists 177 for (int d = 0; d < DEPTH; d++) { 178 strcpy(path, full_path); 179 path[2*d+2] = '\0'; 180 err = lfs_mkdir(&lfs, path); 181 assert(!err || err == LFS_ERR_EXIST); 182 } 183 184 for (int d = 0; d < DEPTH; d++) { 185 strcpy(path, full_path); 186 path[2*d+2] = '\0'; 187 lfs_stat(&lfs, path, &info) => 0; 188 assert(strcmp(info.name, &path[2*d+1]) == 0); 189 assert(info.type == LFS_TYPE_DIR); 190 } 191 } else { 192 // is valid dir? 193 assert(strcmp(info.name, &full_path[2*(DEPTH-1)+1]) == 0); 194 assert(info.type == LFS_TYPE_DIR); 195 196 // try to delete path in reverse order, ignore if dir is not empty 197 for (int d = DEPTH-1; d >= 0; d--) { 198 strcpy(path, full_path); 199 path[2*d+2] = '\0'; 200 err = lfs_remove(&lfs, path); 201 assert(!err || err == LFS_ERR_NOTEMPTY); 202 } 203 204 lfs_stat(&lfs, full_path, &info) => LFS_ERR_NOENT; 205 } 206 } 207 lfs_unmount(&lfs) => 0; 208''' 209 210[[case]] # reentrant testing for relocations, but now with random renames! 211reentrant = true 212# TODO fix this case, caused by non-DAG trees 213if = '!(DEPTH == 3 && LFS_CACHE_SIZE != 64)' 214define = [ 215 {FILES=6, DEPTH=1, CYCLES=20, LFS_BLOCK_CYCLES=1}, 216 {FILES=26, DEPTH=1, CYCLES=20, LFS_BLOCK_CYCLES=1}, 217 {FILES=3, DEPTH=3, CYCLES=20, LFS_BLOCK_CYCLES=1}, 218] 219code = ''' 220 err = lfs_mount(&lfs, &cfg); 221 if (err) { 222 lfs_format(&lfs, &cfg) => 0; 223 lfs_mount(&lfs, &cfg) => 0; 224 } 225 226 srand(1); 227 const char alpha[] = "abcdefghijklmnopqrstuvwxyz"; 228 for (int i = 0; i < CYCLES; i++) { 229 // create random path 230 char full_path[256]; 231 for (int d = 0; d < DEPTH; d++) { 232 sprintf(&full_path[2*d], "/%c", alpha[rand() % FILES]); 233 } 234 235 // if it does not exist, we create it, else we destroy 236 int res = lfs_stat(&lfs, full_path, &info); 237 assert(!res || res == LFS_ERR_NOENT); 238 if (res == LFS_ERR_NOENT) { 239 // create each directory in turn, ignore if dir already exists 240 for (int d = 0; d < DEPTH; d++) { 241 strcpy(path, full_path); 242 path[2*d+2] = '\0'; 243 err = lfs_mkdir(&lfs, path); 244 assert(!err || err == LFS_ERR_EXIST); 245 } 246 247 for (int d = 0; d < DEPTH; d++) { 248 strcpy(path, full_path); 249 path[2*d+2] = '\0'; 250 lfs_stat(&lfs, path, &info) => 0; 251 assert(strcmp(info.name, &path[2*d+1]) == 0); 252 assert(info.type == LFS_TYPE_DIR); 253 } 254 } else { 255 assert(strcmp(info.name, &full_path[2*(DEPTH-1)+1]) == 0); 256 assert(info.type == LFS_TYPE_DIR); 257 258 // create new random path 259 char new_path[256]; 260 for (int d = 0; d < DEPTH; d++) { 261 sprintf(&new_path[2*d], "/%c", alpha[rand() % FILES]); 262 } 263 264 // if new path does not exist, rename, otherwise destroy 265 res = lfs_stat(&lfs, new_path, &info); 266 assert(!res || res == LFS_ERR_NOENT); 267 if (res == LFS_ERR_NOENT) { 268 // stop once some dir is renamed 269 for (int d = 0; d < DEPTH; d++) { 270 strcpy(&path[2*d], &full_path[2*d]); 271 path[2*d+2] = '\0'; 272 strcpy(&path[128+2*d], &new_path[2*d]); 273 path[128+2*d+2] = '\0'; 274 err = lfs_rename(&lfs, path, path+128); 275 assert(!err || err == LFS_ERR_NOTEMPTY); 276 if (!err) { 277 strcpy(path, path+128); 278 } 279 } 280 281 for (int d = 0; d < DEPTH; d++) { 282 strcpy(path, new_path); 283 path[2*d+2] = '\0'; 284 lfs_stat(&lfs, path, &info) => 0; 285 assert(strcmp(info.name, &path[2*d+1]) == 0); 286 assert(info.type == LFS_TYPE_DIR); 287 } 288 289 lfs_stat(&lfs, full_path, &info) => LFS_ERR_NOENT; 290 } else { 291 // try to delete path in reverse order, 292 // ignore if dir is not empty 293 for (int d = DEPTH-1; d >= 0; d--) { 294 strcpy(path, full_path); 295 path[2*d+2] = '\0'; 296 err = lfs_remove(&lfs, path); 297 assert(!err || err == LFS_ERR_NOTEMPTY); 298 } 299 300 lfs_stat(&lfs, full_path, &info) => LFS_ERR_NOENT; 301 } 302 } 303 } 304 lfs_unmount(&lfs) => 0; 305''' 306