1# allocator tests 2# note for these to work there are a number constraints on the device geometry 3if = 'BLOCK_CYCLES == -1' 4 5# parallel allocation test 6[cases.test_alloc_parallel] 7defines.FILES = 3 8defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)' 9defines.GC = [false, true] 10code = ''' 11 const char *names[] = {"bacon", "eggs", "pancakes"}; 12 lfs_file_t files[FILES]; 13 14 lfs_t lfs; 15 lfs_format(&lfs, cfg) => 0; 16 lfs_mount(&lfs, cfg) => 0; 17 lfs_mkdir(&lfs, "breakfast") => 0; 18 lfs_unmount(&lfs) => 0; 19 20 lfs_mount(&lfs, cfg) => 0; 21 for (int n = 0; n < FILES; n++) { 22 char path[1024]; 23 sprintf(path, "breakfast/%s", names[n]); 24 lfs_file_open(&lfs, &files[n], path, 25 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; 26 } 27 for (int n = 0; n < FILES; n++) { 28 if (GC) { 29 lfs_fs_gc(&lfs) => 0; 30 } 31 size_t size = strlen(names[n]); 32 for (lfs_size_t i = 0; i < SIZE; i += size) { 33 lfs_file_write(&lfs, &files[n], names[n], size) => size; 34 } 35 } 36 for (int n = 0; n < FILES; n++) { 37 lfs_file_close(&lfs, &files[n]) => 0; 38 } 39 lfs_unmount(&lfs) => 0; 40 41 lfs_mount(&lfs, cfg) => 0; 42 for (int n = 0; n < FILES; n++) { 43 char path[1024]; 44 sprintf(path, "breakfast/%s", names[n]); 45 lfs_file_t file; 46 lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 47 size_t size = strlen(names[n]); 48 for (lfs_size_t i = 0; i < SIZE; i += size) { 49 uint8_t buffer[1024]; 50 lfs_file_read(&lfs, &file, buffer, size) => size; 51 assert(memcmp(buffer, names[n], size) == 0); 52 } 53 lfs_file_close(&lfs, &file) => 0; 54 } 55 lfs_unmount(&lfs) => 0; 56''' 57 58# serial allocation test 59[cases.test_alloc_serial] 60defines.FILES = 3 61defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)' 62defines.GC = [false, true] 63code = ''' 64 const char *names[] = {"bacon", "eggs", "pancakes"}; 65 66 lfs_t lfs; 67 lfs_format(&lfs, cfg) => 0; 68 lfs_mount(&lfs, cfg) => 0; 69 lfs_mkdir(&lfs, "breakfast") => 0; 70 lfs_unmount(&lfs) => 0; 71 72 for (int n = 0; n < FILES; n++) { 73 lfs_mount(&lfs, cfg) => 0; 74 char path[1024]; 75 sprintf(path, "breakfast/%s", names[n]); 76 lfs_file_t file; 77 lfs_file_open(&lfs, &file, path, 78 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; 79 size_t size = strlen(names[n]); 80 uint8_t buffer[1024]; 81 memcpy(buffer, names[n], size); 82 for (int i = 0; i < SIZE; i += size) { 83 if (GC) { 84 lfs_fs_gc(&lfs) => 0; 85 } 86 lfs_file_write(&lfs, &file, buffer, size) => size; 87 } 88 lfs_file_close(&lfs, &file) => 0; 89 lfs_unmount(&lfs) => 0; 90 } 91 92 lfs_mount(&lfs, cfg) => 0; 93 for (int n = 0; n < FILES; n++) { 94 char path[1024]; 95 sprintf(path, "breakfast/%s", names[n]); 96 lfs_file_t file; 97 lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 98 size_t size = strlen(names[n]); 99 for (int i = 0; i < SIZE; i += size) { 100 uint8_t buffer[1024]; 101 lfs_file_read(&lfs, &file, buffer, size) => size; 102 assert(memcmp(buffer, names[n], size) == 0); 103 } 104 lfs_file_close(&lfs, &file) => 0; 105 } 106 lfs_unmount(&lfs) => 0; 107''' 108 109# parallel allocation reuse test 110[cases.test_alloc_parallel_reuse] 111defines.FILES = 3 112defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)' 113defines.CYCLES = [1, 10] 114code = ''' 115 const char *names[] = {"bacon", "eggs", "pancakes"}; 116 lfs_file_t files[FILES]; 117 118 lfs_t lfs; 119 lfs_format(&lfs, cfg) => 0; 120 121 for (int c = 0; c < CYCLES; c++) { 122 lfs_mount(&lfs, cfg) => 0; 123 lfs_mkdir(&lfs, "breakfast") => 0; 124 lfs_unmount(&lfs) => 0; 125 126 lfs_mount(&lfs, cfg) => 0; 127 for (int n = 0; n < FILES; n++) { 128 char path[1024]; 129 sprintf(path, "breakfast/%s", names[n]); 130 lfs_file_open(&lfs, &files[n], path, 131 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; 132 } 133 for (int n = 0; n < FILES; n++) { 134 size_t size = strlen(names[n]); 135 for (int i = 0; i < SIZE; i += size) { 136 lfs_file_write(&lfs, &files[n], names[n], size) => size; 137 } 138 } 139 for (int n = 0; n < FILES; n++) { 140 lfs_file_close(&lfs, &files[n]) => 0; 141 } 142 lfs_unmount(&lfs) => 0; 143 144 lfs_mount(&lfs, cfg) => 0; 145 for (int n = 0; n < FILES; n++) { 146 char path[1024]; 147 sprintf(path, "breakfast/%s", names[n]); 148 lfs_file_t file; 149 lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 150 size_t size = strlen(names[n]); 151 for (int i = 0; i < SIZE; i += size) { 152 uint8_t buffer[1024]; 153 lfs_file_read(&lfs, &file, buffer, size) => size; 154 assert(memcmp(buffer, names[n], size) == 0); 155 } 156 lfs_file_close(&lfs, &file) => 0; 157 } 158 lfs_unmount(&lfs) => 0; 159 160 lfs_mount(&lfs, cfg) => 0; 161 for (int n = 0; n < FILES; n++) { 162 char path[1024]; 163 sprintf(path, "breakfast/%s", names[n]); 164 lfs_remove(&lfs, path) => 0; 165 } 166 lfs_remove(&lfs, "breakfast") => 0; 167 lfs_unmount(&lfs) => 0; 168 } 169''' 170 171# serial allocation reuse test 172[cases.test_alloc_serial_reuse] 173defines.FILES = 3 174defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)' 175defines.CYCLES = [1, 10] 176code = ''' 177 const char *names[] = {"bacon", "eggs", "pancakes"}; 178 179 lfs_t lfs; 180 lfs_format(&lfs, cfg) => 0; 181 182 for (int c = 0; c < CYCLES; c++) { 183 lfs_mount(&lfs, cfg) => 0; 184 lfs_mkdir(&lfs, "breakfast") => 0; 185 lfs_unmount(&lfs) => 0; 186 187 for (int n = 0; n < FILES; n++) { 188 lfs_mount(&lfs, cfg) => 0; 189 char path[1024]; 190 sprintf(path, "breakfast/%s", names[n]); 191 lfs_file_t file; 192 lfs_file_open(&lfs, &file, path, 193 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; 194 size_t size = strlen(names[n]); 195 uint8_t buffer[1024]; 196 memcpy(buffer, names[n], size); 197 for (int i = 0; i < SIZE; i += size) { 198 lfs_file_write(&lfs, &file, buffer, size) => size; 199 } 200 lfs_file_close(&lfs, &file) => 0; 201 lfs_unmount(&lfs) => 0; 202 } 203 204 lfs_mount(&lfs, cfg) => 0; 205 for (int n = 0; n < FILES; n++) { 206 char path[1024]; 207 sprintf(path, "breakfast/%s", names[n]); 208 lfs_file_t file; 209 lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 210 size_t size = strlen(names[n]); 211 for (int i = 0; i < SIZE; i += size) { 212 uint8_t buffer[1024]; 213 lfs_file_read(&lfs, &file, buffer, size) => size; 214 assert(memcmp(buffer, names[n], size) == 0); 215 } 216 lfs_file_close(&lfs, &file) => 0; 217 } 218 lfs_unmount(&lfs) => 0; 219 220 lfs_mount(&lfs, cfg) => 0; 221 for (int n = 0; n < FILES; n++) { 222 char path[1024]; 223 sprintf(path, "breakfast/%s", names[n]); 224 lfs_remove(&lfs, path) => 0; 225 } 226 lfs_remove(&lfs, "breakfast") => 0; 227 lfs_unmount(&lfs) => 0; 228 } 229''' 230 231# exhaustion test 232[cases.test_alloc_exhaustion] 233code = ''' 234 lfs_t lfs; 235 lfs_format(&lfs, cfg) => 0; 236 lfs_mount(&lfs, cfg) => 0; 237 lfs_file_t file; 238 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 239 size_t size = strlen("exhaustion"); 240 uint8_t buffer[1024]; 241 memcpy(buffer, "exhaustion", size); 242 lfs_file_write(&lfs, &file, buffer, size) => size; 243 lfs_file_sync(&lfs, &file) => 0; 244 245 size = strlen("blahblahblahblah"); 246 memcpy(buffer, "blahblahblahblah", size); 247 lfs_ssize_t res; 248 while (true) { 249 res = lfs_file_write(&lfs, &file, buffer, size); 250 if (res < 0) { 251 break; 252 } 253 254 res => size; 255 } 256 res => LFS_ERR_NOSPC; 257 258 // note that lfs_fs_gc should not error here 259 lfs_fs_gc(&lfs) => 0; 260 261 lfs_file_close(&lfs, &file) => 0; 262 lfs_unmount(&lfs) => 0; 263 264 lfs_mount(&lfs, cfg) => 0; 265 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); 266 size = strlen("exhaustion"); 267 lfs_file_size(&lfs, &file) => size; 268 lfs_file_read(&lfs, &file, buffer, size) => size; 269 memcmp(buffer, "exhaustion", size) => 0; 270 lfs_file_close(&lfs, &file) => 0; 271 lfs_unmount(&lfs) => 0; 272''' 273 274# exhaustion wraparound test 275[cases.test_alloc_exhaustion_wraparound] 276defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-4)) / 3)' 277code = ''' 278 lfs_t lfs; 279 lfs_format(&lfs, cfg) => 0; 280 lfs_mount(&lfs, cfg) => 0; 281 282 lfs_file_t file; 283 lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT); 284 size_t size = strlen("buffering"); 285 uint8_t buffer[1024]; 286 memcpy(buffer, "buffering", size); 287 for (int i = 0; i < SIZE; i += size) { 288 lfs_file_write(&lfs, &file, buffer, size) => size; 289 } 290 lfs_file_close(&lfs, &file) => 0; 291 lfs_remove(&lfs, "padding") => 0; 292 293 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 294 size = strlen("exhaustion"); 295 memcpy(buffer, "exhaustion", size); 296 lfs_file_write(&lfs, &file, buffer, size) => size; 297 lfs_file_sync(&lfs, &file) => 0; 298 299 size = strlen("blahblahblahblah"); 300 memcpy(buffer, "blahblahblahblah", size); 301 lfs_ssize_t res; 302 while (true) { 303 res = lfs_file_write(&lfs, &file, buffer, size); 304 if (res < 0) { 305 break; 306 } 307 308 res => size; 309 } 310 res => LFS_ERR_NOSPC; 311 312 // note that lfs_fs_gc should not error here 313 lfs_fs_gc(&lfs) => 0; 314 315 lfs_file_close(&lfs, &file) => 0; 316 lfs_unmount(&lfs) => 0; 317 318 lfs_mount(&lfs, cfg) => 0; 319 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY); 320 size = strlen("exhaustion"); 321 lfs_file_size(&lfs, &file) => size; 322 lfs_file_read(&lfs, &file, buffer, size) => size; 323 memcmp(buffer, "exhaustion", size) => 0; 324 lfs_file_close(&lfs, &file) => 0; 325 lfs_remove(&lfs, "exhaustion") => 0; 326 lfs_unmount(&lfs) => 0; 327''' 328 329# dir exhaustion test 330[cases.test_alloc_dir_exhaustion] 331code = ''' 332 lfs_t lfs; 333 lfs_format(&lfs, cfg) => 0; 334 lfs_mount(&lfs, cfg) => 0; 335 336 // find out max file size 337 lfs_mkdir(&lfs, "exhaustiondir") => 0; 338 size_t size = strlen("blahblahblahblah"); 339 uint8_t buffer[1024]; 340 memcpy(buffer, "blahblahblahblah", size); 341 lfs_file_t file; 342 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 343 int count = 0; 344 int err; 345 while (true) { 346 err = lfs_file_write(&lfs, &file, buffer, size); 347 if (err < 0) { 348 break; 349 } 350 351 count += 1; 352 } 353 err => LFS_ERR_NOSPC; 354 // note that lfs_fs_gc should not error here 355 lfs_fs_gc(&lfs) => 0; 356 lfs_file_close(&lfs, &file) => 0; 357 358 lfs_remove(&lfs, "exhaustion") => 0; 359 lfs_remove(&lfs, "exhaustiondir") => 0; 360 361 // see if dir fits with max file size 362 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 363 for (int i = 0; i < count; i++) { 364 lfs_file_write(&lfs, &file, buffer, size) => size; 365 } 366 lfs_file_close(&lfs, &file) => 0; 367 368 lfs_mkdir(&lfs, "exhaustiondir") => 0; 369 lfs_remove(&lfs, "exhaustiondir") => 0; 370 lfs_remove(&lfs, "exhaustion") => 0; 371 372 // see if dir fits with > max file size 373 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 374 for (int i = 0; i < count+1; i++) { 375 lfs_file_write(&lfs, &file, buffer, size) => size; 376 } 377 lfs_file_close(&lfs, &file) => 0; 378 379 lfs_mkdir(&lfs, "exhaustiondir") => LFS_ERR_NOSPC; 380 381 lfs_remove(&lfs, "exhaustion") => 0; 382 lfs_unmount(&lfs) => 0; 383''' 384 385# what if we have a bad block during an allocation scan? 386[cases.test_alloc_bad_blocks] 387in = "lfs.c" 388defines.ERASE_CYCLES = 0xffffffff 389defines.BADBLOCK_BEHAVIOR = 'LFS_EMUBD_BADBLOCK_READERROR' 390code = ''' 391 lfs_t lfs; 392 lfs_format(&lfs, cfg) => 0; 393 lfs_mount(&lfs, cfg) => 0; 394 // first fill to exhaustion to find available space 395 lfs_file_t file; 396 lfs_file_open(&lfs, &file, "pacman", LFS_O_WRONLY | LFS_O_CREAT) => 0; 397 uint8_t buffer[1024]; 398 strcpy((char*)buffer, "waka"); 399 size_t size = strlen("waka"); 400 lfs_size_t filesize = 0; 401 while (true) { 402 lfs_ssize_t res = lfs_file_write(&lfs, &file, buffer, size); 403 assert(res == (lfs_ssize_t)size || res == LFS_ERR_NOSPC); 404 if (res == LFS_ERR_NOSPC) { 405 break; 406 } 407 filesize += size; 408 } 409 lfs_file_close(&lfs, &file) => 0; 410 // now fill all but a couple of blocks of the filesystem with data 411 filesize -= 3*BLOCK_SIZE; 412 lfs_file_open(&lfs, &file, "pacman", LFS_O_WRONLY | LFS_O_CREAT) => 0; 413 strcpy((char*)buffer, "waka"); 414 size = strlen("waka"); 415 for (lfs_size_t i = 0; i < filesize/size; i++) { 416 lfs_file_write(&lfs, &file, buffer, size) => size; 417 } 418 lfs_file_close(&lfs, &file) => 0; 419 // also save head of file so we can error during lookahead scan 420 lfs_block_t fileblock = file.ctz.head; 421 lfs_unmount(&lfs) => 0; 422 423 // remount to force an alloc scan 424 lfs_mount(&lfs, cfg) => 0; 425 426 // but mark the head of our file as a "bad block", this is force our 427 // scan to bail early 428 lfs_emubd_setwear(cfg, fileblock, 0xffffffff) => 0; 429 lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0; 430 strcpy((char*)buffer, "chomp"); 431 size = strlen("chomp"); 432 while (true) { 433 lfs_ssize_t res = lfs_file_write(&lfs, &file, buffer, size); 434 assert(res == (lfs_ssize_t)size || res == LFS_ERR_CORRUPT); 435 if (res == LFS_ERR_CORRUPT) { 436 break; 437 } 438 } 439 lfs_file_close(&lfs, &file) => 0; 440 441 // now reverse the "bad block" and try to write the file again until we 442 // run out of space 443 lfs_emubd_setwear(cfg, fileblock, 0) => 0; 444 lfs_file_open(&lfs, &file, "ghost", LFS_O_WRONLY | LFS_O_CREAT) => 0; 445 strcpy((char*)buffer, "chomp"); 446 size = strlen("chomp"); 447 while (true) { 448 lfs_ssize_t res = lfs_file_write(&lfs, &file, buffer, size); 449 assert(res == (lfs_ssize_t)size || res == LFS_ERR_NOSPC); 450 if (res == LFS_ERR_NOSPC) { 451 break; 452 } 453 } 454 // note that lfs_fs_gc should not error here 455 lfs_fs_gc(&lfs) => 0; 456 lfs_file_close(&lfs, &file) => 0; 457 458 lfs_unmount(&lfs) => 0; 459 460 // check that the disk isn't hurt 461 lfs_mount(&lfs, cfg) => 0; 462 lfs_file_open(&lfs, &file, "pacman", LFS_O_RDONLY) => 0; 463 strcpy((char*)buffer, "waka"); 464 size = strlen("waka"); 465 for (lfs_size_t i = 0; i < filesize/size; i++) { 466 uint8_t rbuffer[4]; 467 lfs_file_read(&lfs, &file, rbuffer, size) => size; 468 assert(memcmp(rbuffer, buffer, size) == 0); 469 } 470 lfs_file_close(&lfs, &file) => 0; 471 lfs_unmount(&lfs) => 0; 472''' 473 474 475# Below, I don't like these tests. They're fragile and depend _heavily_ 476# on the geometry of the block device. But they are valuable. Eventually they 477# should be removed and replaced with generalized tests. 478 479# chained dir exhaustion test 480[cases.test_alloc_chained_dir_exhaustion] 481if = 'ERASE_SIZE == 512' 482defines.ERASE_COUNT = 1024 483code = ''' 484 lfs_t lfs; 485 lfs_format(&lfs, cfg) => 0; 486 lfs_mount(&lfs, cfg) => 0; 487 488 // find out max file size 489 lfs_mkdir(&lfs, "exhaustiondir") => 0; 490 for (int i = 0; i < 10; i++) { 491 char path[1024]; 492 sprintf(path, "dirwithanexhaustivelylongnameforpadding%d", i); 493 lfs_mkdir(&lfs, path) => 0; 494 } 495 size_t size = strlen("blahblahblahblah"); 496 uint8_t buffer[1024]; 497 memcpy(buffer, "blahblahblahblah", size); 498 lfs_file_t file; 499 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 500 int count = 0; 501 int err; 502 while (true) { 503 err = lfs_file_write(&lfs, &file, buffer, size); 504 if (err < 0) { 505 break; 506 } 507 508 count += 1; 509 } 510 err => LFS_ERR_NOSPC; 511 lfs_file_close(&lfs, &file) => 0; 512 513 lfs_remove(&lfs, "exhaustion") => 0; 514 lfs_remove(&lfs, "exhaustiondir") => 0; 515 for (int i = 0; i < 10; i++) { 516 char path[1024]; 517 sprintf(path, "dirwithanexhaustivelylongnameforpadding%d", i); 518 lfs_remove(&lfs, path) => 0; 519 } 520 521 // see that chained dir fails 522 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 523 for (int i = 0; i < count+1; i++) { 524 lfs_file_write(&lfs, &file, buffer, size) => size; 525 } 526 lfs_file_sync(&lfs, &file) => 0; 527 528 for (int i = 0; i < 10; i++) { 529 char path[1024]; 530 sprintf(path, "dirwithanexhaustivelylongnameforpadding%d", i); 531 lfs_mkdir(&lfs, path) => 0; 532 } 533 534 lfs_mkdir(&lfs, "exhaustiondir") => LFS_ERR_NOSPC; 535 536 // shorten file to try a second chained dir 537 while (true) { 538 err = lfs_mkdir(&lfs, "exhaustiondir"); 539 if (err != LFS_ERR_NOSPC) { 540 break; 541 } 542 543 lfs_ssize_t filesize = lfs_file_size(&lfs, &file); 544 filesize > 0 => true; 545 546 lfs_file_truncate(&lfs, &file, filesize - size) => 0; 547 lfs_file_sync(&lfs, &file) => 0; 548 } 549 err => 0; 550 551 lfs_mkdir(&lfs, "exhaustiondir2") => LFS_ERR_NOSPC; 552 553 lfs_file_close(&lfs, &file) => 0; 554 lfs_unmount(&lfs) => 0; 555''' 556 557# split dir test 558[cases.test_alloc_split_dir] 559if = 'ERASE_SIZE == 512' 560defines.ERASE_COUNT = 1024 561code = ''' 562 lfs_t lfs; 563 lfs_format(&lfs, cfg) => 0; 564 lfs_mount(&lfs, cfg) => 0; 565 566 // create one block hole for half a directory 567 lfs_file_t file; 568 lfs_file_open(&lfs, &file, "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0; 569 for (lfs_size_t i = 0; i < cfg->block_size; i += 2) { 570 uint8_t buffer[1024]; 571 memcpy(&buffer[i], "hi", 2); 572 } 573 uint8_t buffer[1024]; 574 lfs_file_write(&lfs, &file, buffer, cfg->block_size) => cfg->block_size; 575 lfs_file_close(&lfs, &file) => 0; 576 577 lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT); 578 size_t size = strlen("blahblahblahblah"); 579 memcpy(buffer, "blahblahblahblah", size); 580 for (lfs_size_t i = 0; 581 i < (cfg->block_count-4)*(cfg->block_size-8); 582 i += size) { 583 lfs_file_write(&lfs, &file, buffer, size) => size; 584 } 585 lfs_file_close(&lfs, &file) => 0; 586 587 // remount to force reset of lookahead 588 lfs_unmount(&lfs) => 0; 589 lfs_mount(&lfs, cfg) => 0; 590 591 // open hole 592 lfs_remove(&lfs, "bump") => 0; 593 594 lfs_mkdir(&lfs, "splitdir") => 0; 595 lfs_file_open(&lfs, &file, "splitdir/bump", 596 LFS_O_WRONLY | LFS_O_CREAT) => 0; 597 for (lfs_size_t i = 0; i < cfg->block_size; i += 2) { 598 memcpy(&buffer[i], "hi", 2); 599 } 600 lfs_file_write(&lfs, &file, buffer, 2*cfg->block_size) => LFS_ERR_NOSPC; 601 lfs_file_close(&lfs, &file) => 0; 602 603 lfs_unmount(&lfs) => 0; 604''' 605 606# outdated lookahead test 607[cases.test_alloc_outdated_lookahead] 608if = 'ERASE_SIZE == 512' 609defines.ERASE_COUNT = 1024 610code = ''' 611 lfs_t lfs; 612 lfs_format(&lfs, cfg) => 0; 613 lfs_mount(&lfs, cfg) => 0; 614 615 // fill completely with two files 616 lfs_file_t file; 617 lfs_file_open(&lfs, &file, "exhaustion1", 618 LFS_O_WRONLY | LFS_O_CREAT) => 0; 619 size_t size = strlen("blahblahblahblah"); 620 uint8_t buffer[1024]; 621 memcpy(buffer, "blahblahblahblah", size); 622 for (lfs_size_t i = 0; 623 i < ((cfg->block_count-2)/2)*(cfg->block_size-8); 624 i += size) { 625 lfs_file_write(&lfs, &file, buffer, size) => size; 626 } 627 lfs_file_close(&lfs, &file) => 0; 628 629 lfs_file_open(&lfs, &file, "exhaustion2", 630 LFS_O_WRONLY | LFS_O_CREAT) => 0; 631 size = strlen("blahblahblahblah"); 632 memcpy(buffer, "blahblahblahblah", size); 633 for (lfs_size_t i = 0; 634 i < ((cfg->block_count-2+1)/2)*(cfg->block_size-8); 635 i += size) { 636 lfs_file_write(&lfs, &file, buffer, size) => size; 637 } 638 lfs_file_close(&lfs, &file) => 0; 639 640 // remount to force reset of lookahead 641 lfs_unmount(&lfs) => 0; 642 lfs_mount(&lfs, cfg) => 0; 643 644 // rewrite one file 645 lfs_file_open(&lfs, &file, "exhaustion1", 646 LFS_O_WRONLY | LFS_O_TRUNC) => 0; 647 lfs_file_sync(&lfs, &file) => 0; 648 size = strlen("blahblahblahblah"); 649 memcpy(buffer, "blahblahblahblah", size); 650 for (lfs_size_t i = 0; 651 i < ((cfg->block_count-2)/2)*(cfg->block_size-8); 652 i += size) { 653 lfs_file_write(&lfs, &file, buffer, size) => size; 654 } 655 lfs_file_close(&lfs, &file) => 0; 656 657 // rewrite second file, this requires lookahead does not 658 // use old population 659 lfs_file_open(&lfs, &file, "exhaustion2", 660 LFS_O_WRONLY | LFS_O_TRUNC) => 0; 661 lfs_file_sync(&lfs, &file) => 0; 662 size = strlen("blahblahblahblah"); 663 memcpy(buffer, "blahblahblahblah", size); 664 for (lfs_size_t i = 0; 665 i < ((cfg->block_count-2+1)/2)*(cfg->block_size-8); 666 i += size) { 667 lfs_file_write(&lfs, &file, buffer, size) => size; 668 } 669 lfs_file_close(&lfs, &file) => 0; 670 671 lfs_unmount(&lfs) => 0; 672''' 673 674# outdated lookahead and split dir test 675[cases.test_alloc_outdated_lookahead_split_dir] 676if = 'ERASE_SIZE == 512' 677defines.ERASE_COUNT = 1024 678code = ''' 679 lfs_t lfs; 680 lfs_format(&lfs, cfg) => 0; 681 lfs_mount(&lfs, cfg) => 0; 682 683 // fill completely with two files 684 lfs_file_t file; 685 lfs_file_open(&lfs, &file, "exhaustion1", 686 LFS_O_WRONLY | LFS_O_CREAT) => 0; 687 size_t size = strlen("blahblahblahblah"); 688 uint8_t buffer[1024]; 689 memcpy(buffer, "blahblahblahblah", size); 690 for (lfs_size_t i = 0; 691 i < ((cfg->block_count-2)/2)*(cfg->block_size-8); 692 i += size) { 693 lfs_file_write(&lfs, &file, buffer, size) => size; 694 } 695 lfs_file_close(&lfs, &file) => 0; 696 697 lfs_file_open(&lfs, &file, "exhaustion2", 698 LFS_O_WRONLY | LFS_O_CREAT) => 0; 699 size = strlen("blahblahblahblah"); 700 memcpy(buffer, "blahblahblahblah", size); 701 for (lfs_size_t i = 0; 702 i < ((cfg->block_count-2+1)/2)*(cfg->block_size-8); 703 i += size) { 704 lfs_file_write(&lfs, &file, buffer, size) => size; 705 } 706 lfs_file_close(&lfs, &file) => 0; 707 708 // remount to force reset of lookahead 709 lfs_unmount(&lfs) => 0; 710 lfs_mount(&lfs, cfg) => 0; 711 712 // rewrite one file with a hole of one block 713 lfs_file_open(&lfs, &file, "exhaustion1", 714 LFS_O_WRONLY | LFS_O_TRUNC) => 0; 715 lfs_file_sync(&lfs, &file) => 0; 716 size = strlen("blahblahblahblah"); 717 memcpy(buffer, "blahblahblahblah", size); 718 for (lfs_size_t i = 0; 719 i < ((cfg->block_count-2)/2 - 1)*(cfg->block_size-8); 720 i += size) { 721 lfs_file_write(&lfs, &file, buffer, size) => size; 722 } 723 lfs_file_close(&lfs, &file) => 0; 724 725 // try to allocate a directory, should fail! 726 lfs_mkdir(&lfs, "split") => LFS_ERR_NOSPC; 727 728 // file should not fail 729 lfs_file_open(&lfs, &file, "notasplit", 730 LFS_O_WRONLY | LFS_O_CREAT) => 0; 731 lfs_file_write(&lfs, &file, "hi", 2) => 2; 732 lfs_file_close(&lfs, &file) => 0; 733 734 lfs_unmount(&lfs) => 0; 735''' 736