1# Test for compatibility between different littlefs versions 2# 3# Note, these tests are a bit special. They expect to be linked against two 4# different versions of littlefs: 5# - lfs => the new/current version of littlefs 6# - lfsp => the previous version of littlefs 7# 8# If lfsp is not linked, and LFSP is not defined, these tests will alias 9# the relevant lfs types/functions as necessary so at least the tests can 10# themselves be tested locally. 11# 12# But to get value from these tests, it's expected that the previous version 13# of littlefs be linked in during CI, with the help of scripts/changeprefix.py 14# 15 16# alias littlefs symbols as needed 17# 18# there may be a better way to do this, but oh well, explicit aliases works 19code = ''' 20#ifdef LFSP 21#define STRINGIZE(x) STRINGIZE_(x) 22#define STRINGIZE_(x) #x 23#include STRINGIZE(LFSP) 24#else 25#define LFSP_DISK_VERSION LFS_DISK_VERSION 26#define LFSP_DISK_VERSION_MAJOR LFS_DISK_VERSION_MAJOR 27#define LFSP_DISK_VERSION_MINOR LFS_DISK_VERSION_MINOR 28#define lfsp_t lfs_t 29#define lfsp_config lfs_config 30#define lfsp_format lfs_format 31#define lfsp_mount lfs_mount 32#define lfsp_unmount lfs_unmount 33#define lfsp_fsinfo lfs_fsinfo 34#define lfsp_fs_stat lfs_fs_stat 35#define lfsp_dir_t lfs_dir_t 36#define lfsp_info lfs_info 37#define LFSP_TYPE_REG LFS_TYPE_REG 38#define LFSP_TYPE_DIR LFS_TYPE_DIR 39#define lfsp_mkdir lfs_mkdir 40#define lfsp_dir_open lfs_dir_open 41#define lfsp_dir_read lfs_dir_read 42#define lfsp_dir_close lfs_dir_close 43#define lfsp_file_t lfs_file_t 44#define LFSP_O_RDONLY LFS_O_RDONLY 45#define LFSP_O_WRONLY LFS_O_WRONLY 46#define LFSP_O_CREAT LFS_O_CREAT 47#define LFSP_O_EXCL LFS_O_EXCL 48#define LFSP_SEEK_SET LFS_SEEK_SET 49#define lfsp_file_open lfs_file_open 50#define lfsp_file_write lfs_file_write 51#define lfsp_file_read lfs_file_read 52#define lfsp_file_seek lfs_file_seek 53#define lfsp_file_close lfs_file_close 54#endif 55''' 56 57 58 59## forward-compatibility tests ## 60 61# test we can mount in a new version 62[cases.test_compat_forward_mount] 63if = ''' 64 LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR 65 && DISK_VERSION == 0 66''' 67code = ''' 68 // create the previous version 69 struct lfsp_config cfgp; 70 memcpy(&cfgp, cfg, sizeof(cfgp)); 71 lfsp_t lfsp; 72 lfsp_format(&lfsp, &cfgp) => 0; 73 74 // confirm the previous mount works 75 lfsp_mount(&lfsp, &cfgp) => 0; 76 lfsp_unmount(&lfsp) => 0; 77 78 79 // now test the new mount 80 lfs_t lfs; 81 lfs_mount(&lfs, cfg) => 0; 82 83 // we should be able to read the version using lfs_fs_stat 84 struct lfs_fsinfo fsinfo; 85 lfs_fs_stat(&lfs, &fsinfo) => 0; 86 assert(fsinfo.disk_version == LFSP_DISK_VERSION); 87 88 lfs_unmount(&lfs) => 0; 89''' 90 91# test we can read dirs in a new version 92[cases.test_compat_forward_read_dirs] 93defines.COUNT = 5 94if = ''' 95 LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR 96 && DISK_VERSION == 0 97''' 98code = ''' 99 // create the previous version 100 struct lfsp_config cfgp; 101 memcpy(&cfgp, cfg, sizeof(cfgp)); 102 lfsp_t lfsp; 103 lfsp_format(&lfsp, &cfgp) => 0; 104 105 // write COUNT dirs 106 lfsp_mount(&lfsp, &cfgp) => 0; 107 for (lfs_size_t i = 0; i < COUNT; i++) { 108 char name[8]; 109 sprintf(name, "dir%03d", i); 110 lfsp_mkdir(&lfsp, name) => 0; 111 } 112 lfsp_unmount(&lfsp) => 0; 113 114 115 // mount the new version 116 lfs_t lfs; 117 lfs_mount(&lfs, cfg) => 0; 118 119 // we should be able to read the version using lfs_fs_stat 120 struct lfs_fsinfo fsinfo; 121 lfs_fs_stat(&lfs, &fsinfo) => 0; 122 assert(fsinfo.disk_version == LFSP_DISK_VERSION); 123 124 // can we list the directories? 125 lfs_dir_t dir; 126 lfs_dir_open(&lfs, &dir, "/") => 0; 127 struct lfs_info info; 128 lfs_dir_read(&lfs, &dir, &info) => 1; 129 assert(info.type == LFS_TYPE_DIR); 130 assert(strcmp(info.name, ".") == 0); 131 lfs_dir_read(&lfs, &dir, &info) => 1; 132 assert(info.type == LFS_TYPE_DIR); 133 assert(strcmp(info.name, "..") == 0); 134 135 for (lfs_size_t i = 0; i < COUNT; i++) { 136 lfs_dir_read(&lfs, &dir, &info) => 1; 137 assert(info.type == LFS_TYPE_DIR); 138 char name[8]; 139 sprintf(name, "dir%03d", i); 140 assert(strcmp(info.name, name) == 0); 141 } 142 143 lfs_dir_read(&lfs, &dir, &info) => 0; 144 lfs_dir_close(&lfs, &dir) => 0; 145 146 lfs_unmount(&lfs) => 0; 147''' 148 149# test we can read files in a new version 150[cases.test_compat_forward_read_files] 151defines.COUNT = 5 152defines.SIZE = [4, 32, 512, 8192] 153defines.CHUNK = 4 154if = ''' 155 LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR 156 && DISK_VERSION == 0 157''' 158code = ''' 159 // create the previous version 160 struct lfsp_config cfgp; 161 memcpy(&cfgp, cfg, sizeof(cfgp)); 162 lfsp_t lfsp; 163 lfsp_format(&lfsp, &cfgp) => 0; 164 165 // write COUNT files 166 lfsp_mount(&lfsp, &cfgp) => 0; 167 uint32_t prng = 42; 168 for (lfs_size_t i = 0; i < COUNT; i++) { 169 lfsp_file_t file; 170 char name[8]; 171 sprintf(name, "file%03d", i); 172 lfsp_file_open(&lfsp, &file, name, 173 LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0; 174 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 175 uint8_t chunk[CHUNK]; 176 for (lfs_size_t k = 0; k < CHUNK; k++) { 177 chunk[k] = TEST_PRNG(&prng) & 0xff; 178 } 179 180 lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK; 181 } 182 lfsp_file_close(&lfsp, &file) => 0; 183 } 184 lfsp_unmount(&lfsp) => 0; 185 186 187 // mount the new version 188 lfs_t lfs; 189 lfs_mount(&lfs, cfg) => 0; 190 191 // we should be able to read the version using lfs_fs_stat 192 struct lfs_fsinfo fsinfo; 193 lfs_fs_stat(&lfs, &fsinfo) => 0; 194 assert(fsinfo.disk_version == LFSP_DISK_VERSION); 195 196 // can we list the files? 197 lfs_dir_t dir; 198 lfs_dir_open(&lfs, &dir, "/") => 0; 199 struct lfs_info info; 200 lfs_dir_read(&lfs, &dir, &info) => 1; 201 assert(info.type == LFS_TYPE_DIR); 202 assert(strcmp(info.name, ".") == 0); 203 lfs_dir_read(&lfs, &dir, &info) => 1; 204 assert(info.type == LFS_TYPE_DIR); 205 assert(strcmp(info.name, "..") == 0); 206 207 for (lfs_size_t i = 0; i < COUNT; i++) { 208 lfs_dir_read(&lfs, &dir, &info) => 1; 209 assert(info.type == LFS_TYPE_REG); 210 char name[8]; 211 sprintf(name, "file%03d", i); 212 assert(strcmp(info.name, name) == 0); 213 assert(info.size == SIZE); 214 } 215 216 lfs_dir_read(&lfs, &dir, &info) => 0; 217 218 // now can we read the files? 219 prng = 42; 220 for (lfs_size_t i = 0; i < COUNT; i++) { 221 lfs_file_t file; 222 char name[8]; 223 sprintf(name, "file%03d", i); 224 lfs_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0; 225 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 226 uint8_t chunk[CHUNK]; 227 lfs_file_read(&lfs, &file, chunk, CHUNK) => CHUNK; 228 229 for (lfs_size_t k = 0; k < CHUNK; k++) { 230 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 231 } 232 } 233 lfs_file_close(&lfs, &file) => 0; 234 } 235 236 lfs_unmount(&lfs) => 0; 237''' 238 239# test we can read files in dirs in a new version 240[cases.test_compat_forward_read_files_in_dirs] 241defines.COUNT = 5 242defines.SIZE = [4, 32, 512, 8192] 243defines.CHUNK = 4 244if = ''' 245 LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR 246 && DISK_VERSION == 0 247''' 248code = ''' 249 // create the previous version 250 struct lfsp_config cfgp; 251 memcpy(&cfgp, cfg, sizeof(cfgp)); 252 lfsp_t lfsp; 253 lfsp_format(&lfsp, &cfgp) => 0; 254 255 // write COUNT files+dirs 256 lfsp_mount(&lfsp, &cfgp) => 0; 257 uint32_t prng = 42; 258 for (lfs_size_t i = 0; i < COUNT; i++) { 259 char name[16]; 260 sprintf(name, "dir%03d", i); 261 lfsp_mkdir(&lfsp, name) => 0; 262 263 lfsp_file_t file; 264 sprintf(name, "dir%03d/file%03d", i, i); 265 lfsp_file_open(&lfsp, &file, name, 266 LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0; 267 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 268 uint8_t chunk[CHUNK]; 269 for (lfs_size_t k = 0; k < CHUNK; k++) { 270 chunk[k] = TEST_PRNG(&prng) & 0xff; 271 } 272 273 lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK; 274 } 275 lfsp_file_close(&lfsp, &file) => 0; 276 } 277 lfsp_unmount(&lfsp) => 0; 278 279 280 // mount the new version 281 lfs_t lfs; 282 lfs_mount(&lfs, cfg) => 0; 283 284 // we should be able to read the version using lfs_fs_stat 285 struct lfs_fsinfo fsinfo; 286 lfs_fs_stat(&lfs, &fsinfo) => 0; 287 assert(fsinfo.disk_version == LFSP_DISK_VERSION); 288 289 // can we list the directories? 290 lfs_dir_t dir; 291 lfs_dir_open(&lfs, &dir, "/") => 0; 292 struct lfs_info info; 293 lfs_dir_read(&lfs, &dir, &info) => 1; 294 assert(info.type == LFS_TYPE_DIR); 295 assert(strcmp(info.name, ".") == 0); 296 lfs_dir_read(&lfs, &dir, &info) => 1; 297 assert(info.type == LFS_TYPE_DIR); 298 assert(strcmp(info.name, "..") == 0); 299 300 for (lfs_size_t i = 0; i < COUNT; i++) { 301 lfs_dir_read(&lfs, &dir, &info) => 1; 302 assert(info.type == LFS_TYPE_DIR); 303 char name[8]; 304 sprintf(name, "dir%03d", i); 305 assert(strcmp(info.name, name) == 0); 306 } 307 308 lfs_dir_read(&lfs, &dir, &info) => 0; 309 lfs_dir_close(&lfs, &dir) => 0; 310 311 // can we list the files? 312 for (lfs_size_t i = 0; i < COUNT; i++) { 313 char name[8]; 314 sprintf(name, "dir%03d", i); 315 lfs_dir_t dir; 316 lfs_dir_open(&lfs, &dir, name) => 0; 317 struct lfs_info info; 318 lfs_dir_read(&lfs, &dir, &info) => 1; 319 assert(info.type == LFS_TYPE_DIR); 320 assert(strcmp(info.name, ".") == 0); 321 lfs_dir_read(&lfs, &dir, &info) => 1; 322 assert(info.type == LFS_TYPE_DIR); 323 assert(strcmp(info.name, "..") == 0); 324 325 lfs_dir_read(&lfs, &dir, &info) => 1; 326 assert(info.type == LFS_TYPE_REG); 327 sprintf(name, "file%03d", i); 328 assert(strcmp(info.name, name) == 0); 329 assert(info.size == SIZE); 330 331 lfs_dir_read(&lfs, &dir, &info) => 0; 332 lfs_dir_close(&lfs, &dir) => 0; 333 } 334 335 // now can we read the files? 336 prng = 42; 337 for (lfs_size_t i = 0; i < COUNT; i++) { 338 lfs_file_t file; 339 char name[16]; 340 sprintf(name, "dir%03d/file%03d", i, i); 341 lfs_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0; 342 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 343 uint8_t chunk[CHUNK]; 344 lfs_file_read(&lfs, &file, chunk, CHUNK) => CHUNK; 345 346 for (lfs_size_t k = 0; k < CHUNK; k++) { 347 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 348 } 349 } 350 lfs_file_close(&lfs, &file) => 0; 351 } 352 353 lfs_unmount(&lfs) => 0; 354''' 355 356# test we can write dirs in a new version 357[cases.test_compat_forward_write_dirs] 358defines.COUNT = 10 359if = ''' 360 LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR 361 && DISK_VERSION == 0 362''' 363code = ''' 364 // create the previous version 365 struct lfsp_config cfgp; 366 memcpy(&cfgp, cfg, sizeof(cfgp)); 367 lfsp_t lfsp; 368 lfsp_format(&lfsp, &cfgp) => 0; 369 370 // write COUNT/2 dirs 371 lfsp_mount(&lfsp, &cfgp) => 0; 372 for (lfs_size_t i = 0; i < COUNT/2; i++) { 373 char name[8]; 374 sprintf(name, "dir%03d", i); 375 lfsp_mkdir(&lfsp, name) => 0; 376 } 377 lfsp_unmount(&lfsp) => 0; 378 379 380 // mount the new version 381 lfs_t lfs; 382 lfs_mount(&lfs, cfg) => 0; 383 384 // we should be able to read the version using lfs_fs_stat 385 struct lfs_fsinfo fsinfo; 386 lfs_fs_stat(&lfs, &fsinfo) => 0; 387 assert(fsinfo.disk_version == LFSP_DISK_VERSION); 388 389 // write another COUNT/2 dirs 390 for (lfs_size_t i = COUNT/2; i < COUNT; i++) { 391 char name[8]; 392 sprintf(name, "dir%03d", i); 393 lfs_mkdir(&lfs, name) => 0; 394 } 395 396 // can we list the directories? 397 lfs_dir_t dir; 398 lfs_dir_open(&lfs, &dir, "/") => 0; 399 struct lfs_info info; 400 lfs_dir_read(&lfs, &dir, &info) => 1; 401 assert(info.type == LFS_TYPE_DIR); 402 assert(strcmp(info.name, ".") == 0); 403 lfs_dir_read(&lfs, &dir, &info) => 1; 404 assert(info.type == LFS_TYPE_DIR); 405 assert(strcmp(info.name, "..") == 0); 406 407 for (lfs_size_t i = 0; i < COUNT; i++) { 408 lfs_dir_read(&lfs, &dir, &info) => 1; 409 assert(info.type == LFS_TYPE_DIR); 410 char name[8]; 411 sprintf(name, "dir%03d", i); 412 assert(strcmp(info.name, name) == 0); 413 } 414 415 lfs_dir_read(&lfs, &dir, &info) => 0; 416 lfs_dir_close(&lfs, &dir) => 0; 417 418 lfs_unmount(&lfs) => 0; 419''' 420 421# test we can write files in a new version 422[cases.test_compat_forward_write_files] 423defines.COUNT = 5 424defines.SIZE = [4, 32, 512, 8192] 425defines.CHUNK = 2 426if = ''' 427 LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR 428 && DISK_VERSION == 0 429''' 430code = ''' 431 // create the previous version 432 struct lfsp_config cfgp; 433 memcpy(&cfgp, cfg, sizeof(cfgp)); 434 lfsp_t lfsp; 435 lfsp_format(&lfsp, &cfgp) => 0; 436 437 // write half COUNT files 438 lfsp_mount(&lfsp, &cfgp) => 0; 439 uint32_t prng = 42; 440 for (lfs_size_t i = 0; i < COUNT; i++) { 441 // write half 442 lfsp_file_t file; 443 char name[8]; 444 sprintf(name, "file%03d", i); 445 lfsp_file_open(&lfsp, &file, name, 446 LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0; 447 for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) { 448 uint8_t chunk[CHUNK]; 449 for (lfs_size_t k = 0; k < CHUNK; k++) { 450 chunk[k] = TEST_PRNG(&prng) & 0xff; 451 } 452 453 lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK; 454 } 455 lfsp_file_close(&lfsp, &file) => 0; 456 457 // skip the other half but keep our prng reproducible 458 for (lfs_size_t j = SIZE/2; j < SIZE; j++) { 459 TEST_PRNG(&prng); 460 } 461 } 462 lfsp_unmount(&lfsp) => 0; 463 464 465 // mount the new version 466 lfs_t lfs; 467 lfs_mount(&lfs, cfg) => 0; 468 469 // we should be able to read the version using lfs_fs_stat 470 struct lfs_fsinfo fsinfo; 471 lfs_fs_stat(&lfs, &fsinfo) => 0; 472 assert(fsinfo.disk_version == LFSP_DISK_VERSION); 473 474 // write half COUNT files 475 prng = 42; 476 for (lfs_size_t i = 0; i < COUNT; i++) { 477 // skip half but keep our prng reproducible 478 for (lfs_size_t j = 0; j < SIZE/2; j++) { 479 TEST_PRNG(&prng); 480 } 481 482 // write the other half 483 lfs_file_t file; 484 char name[8]; 485 sprintf(name, "file%03d", i); 486 lfs_file_open(&lfs, &file, name, LFS_O_WRONLY) => 0; 487 lfs_file_seek(&lfs, &file, SIZE/2, LFS_SEEK_SET) => SIZE/2; 488 489 for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) { 490 uint8_t chunk[CHUNK]; 491 for (lfs_size_t k = 0; k < CHUNK; k++) { 492 chunk[k] = TEST_PRNG(&prng) & 0xff; 493 } 494 495 lfs_file_write(&lfs, &file, chunk, CHUNK) => CHUNK; 496 } 497 lfs_file_close(&lfs, &file) => 0; 498 } 499 500 // can we list the files? 501 lfs_dir_t dir; 502 lfs_dir_open(&lfs, &dir, "/") => 0; 503 struct lfs_info info; 504 lfs_dir_read(&lfs, &dir, &info) => 1; 505 assert(info.type == LFS_TYPE_DIR); 506 assert(strcmp(info.name, ".") == 0); 507 lfs_dir_read(&lfs, &dir, &info) => 1; 508 assert(info.type == LFS_TYPE_DIR); 509 assert(strcmp(info.name, "..") == 0); 510 511 for (lfs_size_t i = 0; i < COUNT; i++) { 512 lfs_dir_read(&lfs, &dir, &info) => 1; 513 assert(info.type == LFS_TYPE_REG); 514 char name[8]; 515 sprintf(name, "file%03d", i); 516 assert(strcmp(info.name, name) == 0); 517 assert(info.size == SIZE); 518 } 519 520 lfs_dir_read(&lfs, &dir, &info) => 0; 521 522 // now can we read the files? 523 prng = 42; 524 for (lfs_size_t i = 0; i < COUNT; i++) { 525 lfs_file_t file; 526 char name[8]; 527 sprintf(name, "file%03d", i); 528 lfs_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0; 529 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 530 uint8_t chunk[CHUNK]; 531 lfs_file_read(&lfs, &file, chunk, CHUNK) => CHUNK; 532 533 for (lfs_size_t k = 0; k < CHUNK; k++) { 534 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 535 } 536 } 537 lfs_file_close(&lfs, &file) => 0; 538 } 539 540 lfs_unmount(&lfs) => 0; 541''' 542 543# test we can write files in dirs in a new version 544[cases.test_compat_forward_write_files_in_dirs] 545defines.COUNT = 5 546defines.SIZE = [4, 32, 512, 8192] 547defines.CHUNK = 2 548if = ''' 549 LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR 550 && DISK_VERSION == 0 551''' 552code = ''' 553 // create the previous version 554 struct lfsp_config cfgp; 555 memcpy(&cfgp, cfg, sizeof(cfgp)); 556 lfsp_t lfsp; 557 lfsp_format(&lfsp, &cfgp) => 0; 558 559 // write half COUNT files 560 lfsp_mount(&lfsp, &cfgp) => 0; 561 uint32_t prng = 42; 562 for (lfs_size_t i = 0; i < COUNT; i++) { 563 char name[16]; 564 sprintf(name, "dir%03d", i); 565 lfsp_mkdir(&lfsp, name) => 0; 566 567 // write half 568 lfsp_file_t file; 569 sprintf(name, "dir%03d/file%03d", i, i); 570 lfsp_file_open(&lfsp, &file, name, 571 LFSP_O_WRONLY | LFSP_O_CREAT | LFSP_O_EXCL) => 0; 572 for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) { 573 uint8_t chunk[CHUNK]; 574 for (lfs_size_t k = 0; k < CHUNK; k++) { 575 chunk[k] = TEST_PRNG(&prng) & 0xff; 576 } 577 578 lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK; 579 } 580 lfsp_file_close(&lfsp, &file) => 0; 581 582 // skip the other half but keep our prng reproducible 583 for (lfs_size_t j = SIZE/2; j < SIZE; j++) { 584 TEST_PRNG(&prng); 585 } 586 } 587 lfsp_unmount(&lfsp) => 0; 588 589 590 // mount the new version 591 lfs_t lfs; 592 lfs_mount(&lfs, cfg) => 0; 593 594 // we should be able to read the version using lfs_fs_stat 595 struct lfs_fsinfo fsinfo; 596 lfs_fs_stat(&lfs, &fsinfo) => 0; 597 assert(fsinfo.disk_version == LFSP_DISK_VERSION); 598 599 // write half COUNT files 600 prng = 42; 601 for (lfs_size_t i = 0; i < COUNT; i++) { 602 // skip half but keep our prng reproducible 603 for (lfs_size_t j = 0; j < SIZE/2; j++) { 604 TEST_PRNG(&prng); 605 } 606 607 // write the other half 608 lfs_file_t file; 609 char name[16]; 610 sprintf(name, "dir%03d/file%03d", i, i); 611 lfs_file_open(&lfs, &file, name, LFS_O_WRONLY) => 0; 612 lfs_file_seek(&lfs, &file, SIZE/2, LFS_SEEK_SET) => SIZE/2; 613 614 for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) { 615 uint8_t chunk[CHUNK]; 616 for (lfs_size_t k = 0; k < CHUNK; k++) { 617 chunk[k] = TEST_PRNG(&prng) & 0xff; 618 } 619 620 lfs_file_write(&lfs, &file, chunk, CHUNK) => CHUNK; 621 } 622 lfs_file_close(&lfs, &file) => 0; 623 } 624 625 // can we list the directories? 626 lfs_dir_t dir; 627 lfs_dir_open(&lfs, &dir, "/") => 0; 628 struct lfs_info info; 629 lfs_dir_read(&lfs, &dir, &info) => 1; 630 assert(info.type == LFS_TYPE_DIR); 631 assert(strcmp(info.name, ".") == 0); 632 lfs_dir_read(&lfs, &dir, &info) => 1; 633 assert(info.type == LFS_TYPE_DIR); 634 assert(strcmp(info.name, "..") == 0); 635 636 for (lfs_size_t i = 0; i < COUNT; i++) { 637 lfs_dir_read(&lfs, &dir, &info) => 1; 638 assert(info.type == LFS_TYPE_DIR); 639 char name[8]; 640 sprintf(name, "dir%03d", i); 641 assert(strcmp(info.name, name) == 0); 642 } 643 644 lfs_dir_read(&lfs, &dir, &info) => 0; 645 lfs_dir_close(&lfs, &dir) => 0; 646 647 // can we list the files? 648 for (lfs_size_t i = 0; i < COUNT; i++) { 649 char name[8]; 650 sprintf(name, "dir%03d", i); 651 lfs_dir_t dir; 652 lfs_dir_open(&lfs, &dir, name) => 0; 653 struct lfs_info info; 654 lfs_dir_read(&lfs, &dir, &info) => 1; 655 assert(info.type == LFS_TYPE_DIR); 656 assert(strcmp(info.name, ".") == 0); 657 lfs_dir_read(&lfs, &dir, &info) => 1; 658 assert(info.type == LFS_TYPE_DIR); 659 assert(strcmp(info.name, "..") == 0); 660 661 lfs_dir_read(&lfs, &dir, &info) => 1; 662 assert(info.type == LFS_TYPE_REG); 663 sprintf(name, "file%03d", i); 664 assert(strcmp(info.name, name) == 0); 665 assert(info.size == SIZE); 666 667 lfs_dir_read(&lfs, &dir, &info) => 0; 668 lfs_dir_close(&lfs, &dir) => 0; 669 } 670 671 // now can we read the files? 672 prng = 42; 673 for (lfs_size_t i = 0; i < COUNT; i++) { 674 lfs_file_t file; 675 char name[16]; 676 sprintf(name, "dir%03d/file%03d", i, i); 677 lfs_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0; 678 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 679 uint8_t chunk[CHUNK]; 680 lfs_file_read(&lfs, &file, chunk, CHUNK) => CHUNK; 681 682 for (lfs_size_t k = 0; k < CHUNK; k++) { 683 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 684 } 685 } 686 lfs_file_close(&lfs, &file) => 0; 687 } 688 689 lfs_unmount(&lfs) => 0; 690''' 691 692 693 694## backwards-compatibility tests ## 695 696# test we can mount in an old version 697[cases.test_compat_backward_mount] 698if = ''' 699 LFS_DISK_VERSION == LFSP_DISK_VERSION 700 && DISK_VERSION == 0 701''' 702code = ''' 703 // create the new version 704 lfs_t lfs; 705 lfs_format(&lfs, cfg) => 0; 706 707 // confirm the new mount works 708 lfs_mount(&lfs, cfg) => 0; 709 lfs_unmount(&lfs) => 0; 710 711 // now test the previous mount 712 struct lfsp_config cfgp; 713 memcpy(&cfgp, cfg, sizeof(cfgp)); 714 lfsp_t lfsp; 715 lfsp_mount(&lfsp, &cfgp) => 0; 716 717 lfsp_unmount(&lfsp) => 0; 718''' 719 720# test we can read dirs in an old version 721[cases.test_compat_backward_read_dirs] 722defines.COUNT = 5 723if = ''' 724 LFS_DISK_VERSION == LFSP_DISK_VERSION 725 && DISK_VERSION == 0 726''' 727code = ''' 728 // create the new version 729 lfs_t lfs; 730 lfs_format(&lfs, cfg) => 0; 731 732 // write COUNT dirs 733 lfs_mount(&lfs, cfg) => 0; 734 for (lfs_size_t i = 0; i < COUNT; i++) { 735 char name[8]; 736 sprintf(name, "dir%03d", i); 737 lfs_mkdir(&lfs, name) => 0; 738 } 739 lfs_unmount(&lfs) => 0; 740 741 742 // mount the new version 743 struct lfsp_config cfgp; 744 memcpy(&cfgp, cfg, sizeof(cfgp)); 745 lfsp_t lfsp; 746 lfsp_mount(&lfsp, &cfgp) => 0; 747 748 // can we list the directories? 749 lfsp_dir_t dir; 750 lfsp_dir_open(&lfsp, &dir, "/") => 0; 751 struct lfsp_info info; 752 lfsp_dir_read(&lfsp, &dir, &info) => 1; 753 assert(info.type == LFSP_TYPE_DIR); 754 assert(strcmp(info.name, ".") == 0); 755 lfsp_dir_read(&lfsp, &dir, &info) => 1; 756 assert(info.type == LFSP_TYPE_DIR); 757 assert(strcmp(info.name, "..") == 0); 758 759 for (lfs_size_t i = 0; i < COUNT; i++) { 760 lfsp_dir_read(&lfsp, &dir, &info) => 1; 761 assert(info.type == LFSP_TYPE_DIR); 762 char name[8]; 763 sprintf(name, "dir%03d", i); 764 assert(strcmp(info.name, name) == 0); 765 } 766 767 lfsp_dir_read(&lfsp, &dir, &info) => 0; 768 lfsp_dir_close(&lfsp, &dir) => 0; 769 770 lfsp_unmount(&lfsp) => 0; 771''' 772 773# test we can read files in an old version 774[cases.test_compat_backward_read_files] 775defines.COUNT = 5 776defines.SIZE = [4, 32, 512, 8192] 777defines.CHUNK = 4 778if = ''' 779 LFS_DISK_VERSION == LFSP_DISK_VERSION 780 && DISK_VERSION == 0 781''' 782code = ''' 783 // create the new version 784 lfs_t lfs; 785 lfs_format(&lfs, cfg) => 0; 786 787 // write COUNT files 788 lfs_mount(&lfs, cfg) => 0; 789 uint32_t prng = 42; 790 for (lfs_size_t i = 0; i < COUNT; i++) { 791 lfs_file_t file; 792 char name[8]; 793 sprintf(name, "file%03d", i); 794 lfs_file_open(&lfs, &file, name, 795 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; 796 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 797 uint8_t chunk[CHUNK]; 798 for (lfs_size_t k = 0; k < CHUNK; k++) { 799 chunk[k] = TEST_PRNG(&prng) & 0xff; 800 } 801 802 lfs_file_write(&lfs, &file, chunk, CHUNK) => CHUNK; 803 } 804 lfs_file_close(&lfs, &file) => 0; 805 } 806 lfs_unmount(&lfs) => 0; 807 808 809 // mount the previous version 810 struct lfsp_config cfgp; 811 memcpy(&cfgp, cfg, sizeof(cfgp)); 812 lfsp_t lfsp; 813 lfsp_mount(&lfsp, &cfgp) => 0; 814 815 // can we list the files? 816 lfsp_dir_t dir; 817 lfsp_dir_open(&lfsp, &dir, "/") => 0; 818 struct lfsp_info info; 819 lfsp_dir_read(&lfsp, &dir, &info) => 1; 820 assert(info.type == LFSP_TYPE_DIR); 821 assert(strcmp(info.name, ".") == 0); 822 lfsp_dir_read(&lfsp, &dir, &info) => 1; 823 assert(info.type == LFSP_TYPE_DIR); 824 assert(strcmp(info.name, "..") == 0); 825 826 for (lfs_size_t i = 0; i < COUNT; i++) { 827 lfsp_dir_read(&lfsp, &dir, &info) => 1; 828 assert(info.type == LFSP_TYPE_REG); 829 char name[8]; 830 sprintf(name, "file%03d", i); 831 assert(strcmp(info.name, name) == 0); 832 assert(info.size == SIZE); 833 } 834 835 lfsp_dir_read(&lfsp, &dir, &info) => 0; 836 837 // now can we read the files? 838 prng = 42; 839 for (lfs_size_t i = 0; i < COUNT; i++) { 840 lfsp_file_t file; 841 char name[8]; 842 sprintf(name, "file%03d", i); 843 lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0; 844 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 845 uint8_t chunk[CHUNK]; 846 lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK; 847 848 for (lfs_size_t k = 0; k < CHUNK; k++) { 849 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 850 } 851 } 852 lfsp_file_close(&lfsp, &file) => 0; 853 } 854 855 lfsp_unmount(&lfsp) => 0; 856''' 857 858# test we can read files in dirs in an old version 859[cases.test_compat_backward_read_files_in_dirs] 860defines.COUNT = 5 861defines.SIZE = [4, 32, 512, 8192] 862defines.CHUNK = 4 863if = ''' 864 LFS_DISK_VERSION == LFSP_DISK_VERSION 865 && DISK_VERSION == 0 866''' 867code = ''' 868 // create the new version 869 lfs_t lfs; 870 lfs_format(&lfs, cfg) => 0; 871 872 // write COUNT files+dirs 873 lfs_mount(&lfs, cfg) => 0; 874 uint32_t prng = 42; 875 for (lfs_size_t i = 0; i < COUNT; i++) { 876 char name[16]; 877 sprintf(name, "dir%03d", i); 878 lfs_mkdir(&lfs, name) => 0; 879 880 lfs_file_t file; 881 sprintf(name, "dir%03d/file%03d", i, i); 882 lfs_file_open(&lfs, &file, name, 883 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; 884 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 885 uint8_t chunk[CHUNK]; 886 for (lfs_size_t k = 0; k < CHUNK; k++) { 887 chunk[k] = TEST_PRNG(&prng) & 0xff; 888 } 889 890 lfs_file_write(&lfs, &file, chunk, CHUNK) => CHUNK; 891 } 892 lfs_file_close(&lfs, &file) => 0; 893 } 894 lfs_unmount(&lfs) => 0; 895 896 897 // mount the previous version 898 struct lfsp_config cfgp; 899 memcpy(&cfgp, cfg, sizeof(cfgp)); 900 lfsp_t lfsp; 901 lfsp_mount(&lfsp, &cfgp) => 0; 902 903 // can we list the directories? 904 lfsp_dir_t dir; 905 lfsp_dir_open(&lfsp, &dir, "/") => 0; 906 struct lfsp_info info; 907 lfsp_dir_read(&lfsp, &dir, &info) => 1; 908 assert(info.type == LFSP_TYPE_DIR); 909 assert(strcmp(info.name, ".") == 0); 910 lfsp_dir_read(&lfsp, &dir, &info) => 1; 911 assert(info.type == LFSP_TYPE_DIR); 912 assert(strcmp(info.name, "..") == 0); 913 914 for (lfs_size_t i = 0; i < COUNT; i++) { 915 lfsp_dir_read(&lfsp, &dir, &info) => 1; 916 assert(info.type == LFSP_TYPE_DIR); 917 char name[8]; 918 sprintf(name, "dir%03d", i); 919 assert(strcmp(info.name, name) == 0); 920 } 921 922 lfsp_dir_read(&lfsp, &dir, &info) => 0; 923 lfsp_dir_close(&lfsp, &dir) => 0; 924 925 // can we list the files? 926 for (lfs_size_t i = 0; i < COUNT; i++) { 927 char name[8]; 928 sprintf(name, "dir%03d", i); 929 lfsp_dir_t dir; 930 lfsp_dir_open(&lfsp, &dir, name) => 0; 931 struct lfsp_info info; 932 lfsp_dir_read(&lfsp, &dir, &info) => 1; 933 assert(info.type == LFSP_TYPE_DIR); 934 assert(strcmp(info.name, ".") == 0); 935 lfsp_dir_read(&lfsp, &dir, &info) => 1; 936 assert(info.type == LFSP_TYPE_DIR); 937 assert(strcmp(info.name, "..") == 0); 938 939 lfsp_dir_read(&lfsp, &dir, &info) => 1; 940 assert(info.type == LFSP_TYPE_REG); 941 sprintf(name, "file%03d", i); 942 assert(strcmp(info.name, name) == 0); 943 assert(info.size == SIZE); 944 945 lfsp_dir_read(&lfsp, &dir, &info) => 0; 946 lfsp_dir_close(&lfsp, &dir) => 0; 947 } 948 949 // now can we read the files? 950 prng = 42; 951 for (lfs_size_t i = 0; i < COUNT; i++) { 952 lfsp_file_t file; 953 char name[16]; 954 sprintf(name, "dir%03d/file%03d", i, i); 955 lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0; 956 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 957 uint8_t chunk[CHUNK]; 958 lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK; 959 960 for (lfs_size_t k = 0; k < CHUNK; k++) { 961 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 962 } 963 } 964 lfsp_file_close(&lfsp, &file) => 0; 965 } 966 967 lfsp_unmount(&lfsp) => 0; 968''' 969 970# test we can write dirs in an old version 971[cases.test_compat_backward_write_dirs] 972defines.COUNT = 10 973if = ''' 974 LFS_DISK_VERSION == LFSP_DISK_VERSION 975 && DISK_VERSION == 0 976''' 977code = ''' 978 // create the new version 979 lfs_t lfs; 980 lfs_format(&lfs, cfg) => 0; 981 982 // write COUNT/2 dirs 983 lfs_mount(&lfs, cfg) => 0; 984 for (lfs_size_t i = 0; i < COUNT/2; i++) { 985 char name[8]; 986 sprintf(name, "dir%03d", i); 987 lfs_mkdir(&lfs, name) => 0; 988 } 989 lfs_unmount(&lfs) => 0; 990 991 992 // mount the previous version 993 struct lfsp_config cfgp; 994 memcpy(&cfgp, cfg, sizeof(cfgp)); 995 lfsp_t lfsp; 996 lfsp_mount(&lfsp, &cfgp) => 0; 997 998 // write another COUNT/2 dirs 999 for (lfs_size_t i = COUNT/2; i < COUNT; i++) { 1000 char name[8]; 1001 sprintf(name, "dir%03d", i); 1002 lfsp_mkdir(&lfsp, name) => 0; 1003 } 1004 1005 // can we list the directories? 1006 lfsp_dir_t dir; 1007 lfsp_dir_open(&lfsp, &dir, "/") => 0; 1008 struct lfsp_info info; 1009 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1010 assert(info.type == LFSP_TYPE_DIR); 1011 assert(strcmp(info.name, ".") == 0); 1012 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1013 assert(info.type == LFSP_TYPE_DIR); 1014 assert(strcmp(info.name, "..") == 0); 1015 1016 for (lfs_size_t i = 0; i < COUNT; i++) { 1017 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1018 assert(info.type == LFSP_TYPE_DIR); 1019 char name[8]; 1020 sprintf(name, "dir%03d", i); 1021 assert(strcmp(info.name, name) == 0); 1022 } 1023 1024 lfsp_dir_read(&lfsp, &dir, &info) => 0; 1025 lfsp_dir_close(&lfsp, &dir) => 0; 1026 1027 lfsp_unmount(&lfsp) => 0; 1028''' 1029 1030# test we can write files in an old version 1031[cases.test_compat_backward_write_files] 1032defines.COUNT = 5 1033defines.SIZE = [4, 32, 512, 8192] 1034defines.CHUNK = 2 1035if = ''' 1036 LFS_DISK_VERSION == LFSP_DISK_VERSION 1037 && DISK_VERSION == 0 1038''' 1039code = ''' 1040 // create the previous version 1041 lfs_t lfs; 1042 lfs_format(&lfs, cfg) => 0; 1043 1044 // write half COUNT files 1045 lfs_mount(&lfs, cfg) => 0; 1046 uint32_t prng = 42; 1047 for (lfs_size_t i = 0; i < COUNT; i++) { 1048 // write half 1049 lfs_file_t file; 1050 char name[8]; 1051 sprintf(name, "file%03d", i); 1052 lfs_file_open(&lfs, &file, name, 1053 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; 1054 for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) { 1055 uint8_t chunk[CHUNK]; 1056 for (lfs_size_t k = 0; k < CHUNK; k++) { 1057 chunk[k] = TEST_PRNG(&prng) & 0xff; 1058 } 1059 1060 lfs_file_write(&lfs, &file, chunk, CHUNK) => CHUNK; 1061 } 1062 lfs_file_close(&lfs, &file) => 0; 1063 1064 // skip the other half but keep our prng reproducible 1065 for (lfs_size_t j = SIZE/2; j < SIZE; j++) { 1066 TEST_PRNG(&prng); 1067 } 1068 } 1069 lfs_unmount(&lfs) => 0; 1070 1071 1072 // mount the new version 1073 struct lfsp_config cfgp; 1074 memcpy(&cfgp, cfg, sizeof(cfgp)); 1075 lfsp_t lfsp; 1076 lfsp_mount(&lfsp, &cfgp) => 0; 1077 1078 // write half COUNT files 1079 prng = 42; 1080 for (lfs_size_t i = 0; i < COUNT; i++) { 1081 // skip half but keep our prng reproducible 1082 for (lfs_size_t j = 0; j < SIZE/2; j++) { 1083 TEST_PRNG(&prng); 1084 } 1085 1086 // write the other half 1087 lfsp_file_t file; 1088 char name[8]; 1089 sprintf(name, "file%03d", i); 1090 lfsp_file_open(&lfsp, &file, name, LFSP_O_WRONLY) => 0; 1091 lfsp_file_seek(&lfsp, &file, SIZE/2, LFSP_SEEK_SET) => SIZE/2; 1092 1093 for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) { 1094 uint8_t chunk[CHUNK]; 1095 for (lfs_size_t k = 0; k < CHUNK; k++) { 1096 chunk[k] = TEST_PRNG(&prng) & 0xff; 1097 } 1098 1099 lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK; 1100 } 1101 lfsp_file_close(&lfsp, &file) => 0; 1102 } 1103 1104 // can we list the files? 1105 lfsp_dir_t dir; 1106 lfsp_dir_open(&lfsp, &dir, "/") => 0; 1107 struct lfsp_info info; 1108 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1109 assert(info.type == LFSP_TYPE_DIR); 1110 assert(strcmp(info.name, ".") == 0); 1111 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1112 assert(info.type == LFSP_TYPE_DIR); 1113 assert(strcmp(info.name, "..") == 0); 1114 1115 for (lfs_size_t i = 0; i < COUNT; i++) { 1116 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1117 assert(info.type == LFSP_TYPE_REG); 1118 char name[8]; 1119 sprintf(name, "file%03d", i); 1120 assert(strcmp(info.name, name) == 0); 1121 assert(info.size == SIZE); 1122 } 1123 1124 lfsp_dir_read(&lfsp, &dir, &info) => 0; 1125 1126 // now can we read the files? 1127 prng = 42; 1128 for (lfs_size_t i = 0; i < COUNT; i++) { 1129 lfsp_file_t file; 1130 char name[8]; 1131 sprintf(name, "file%03d", i); 1132 lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0; 1133 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 1134 uint8_t chunk[CHUNK]; 1135 lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK; 1136 1137 for (lfs_size_t k = 0; k < CHUNK; k++) { 1138 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 1139 } 1140 } 1141 lfsp_file_close(&lfsp, &file) => 0; 1142 } 1143 1144 lfsp_unmount(&lfsp) => 0; 1145''' 1146 1147# test we can write files in dirs in an old version 1148[cases.test_compat_backward_write_files_in_dirs] 1149defines.COUNT = 5 1150defines.SIZE = [4, 32, 512, 8192] 1151defines.CHUNK = 2 1152if = ''' 1153 LFS_DISK_VERSION == LFSP_DISK_VERSION 1154 && DISK_VERSION == 0 1155''' 1156code = ''' 1157 // create the previous version 1158 lfs_t lfs; 1159 lfs_format(&lfs, cfg) => 0; 1160 1161 // write half COUNT files 1162 lfs_mount(&lfs, cfg) => 0; 1163 uint32_t prng = 42; 1164 for (lfs_size_t i = 0; i < COUNT; i++) { 1165 char name[16]; 1166 sprintf(name, "dir%03d", i); 1167 lfs_mkdir(&lfs, name) => 0; 1168 1169 // write half 1170 lfs_file_t file; 1171 sprintf(name, "dir%03d/file%03d", i, i); 1172 lfs_file_open(&lfs, &file, name, 1173 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; 1174 for (lfs_size_t j = 0; j < SIZE/2; j += CHUNK) { 1175 uint8_t chunk[CHUNK]; 1176 for (lfs_size_t k = 0; k < CHUNK; k++) { 1177 chunk[k] = TEST_PRNG(&prng) & 0xff; 1178 } 1179 1180 lfs_file_write(&lfs, &file, chunk, CHUNK) => CHUNK; 1181 } 1182 lfs_file_close(&lfs, &file) => 0; 1183 1184 // skip the other half but keep our prng reproducible 1185 for (lfs_size_t j = SIZE/2; j < SIZE; j++) { 1186 TEST_PRNG(&prng); 1187 } 1188 } 1189 lfs_unmount(&lfs) => 0; 1190 1191 1192 // mount the new version 1193 struct lfsp_config cfgp; 1194 memcpy(&cfgp, cfg, sizeof(cfgp)); 1195 lfsp_t lfsp; 1196 lfsp_mount(&lfsp, &cfgp) => 0; 1197 1198 // write half COUNT files 1199 prng = 42; 1200 for (lfs_size_t i = 0; i < COUNT; i++) { 1201 // skip half but keep our prng reproducible 1202 for (lfs_size_t j = 0; j < SIZE/2; j++) { 1203 TEST_PRNG(&prng); 1204 } 1205 1206 // write the other half 1207 lfsp_file_t file; 1208 char name[16]; 1209 sprintf(name, "dir%03d/file%03d", i, i); 1210 lfsp_file_open(&lfsp, &file, name, LFSP_O_WRONLY) => 0; 1211 lfsp_file_seek(&lfsp, &file, SIZE/2, LFSP_SEEK_SET) => SIZE/2; 1212 1213 for (lfs_size_t j = SIZE/2; j < SIZE; j += CHUNK) { 1214 uint8_t chunk[CHUNK]; 1215 for (lfs_size_t k = 0; k < CHUNK; k++) { 1216 chunk[k] = TEST_PRNG(&prng) & 0xff; 1217 } 1218 1219 lfsp_file_write(&lfsp, &file, chunk, CHUNK) => CHUNK; 1220 } 1221 lfsp_file_close(&lfsp, &file) => 0; 1222 } 1223 1224 // can we list the directories? 1225 lfsp_dir_t dir; 1226 lfsp_dir_open(&lfsp, &dir, "/") => 0; 1227 struct lfsp_info info; 1228 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1229 assert(info.type == LFSP_TYPE_DIR); 1230 assert(strcmp(info.name, ".") == 0); 1231 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1232 assert(info.type == LFSP_TYPE_DIR); 1233 assert(strcmp(info.name, "..") == 0); 1234 1235 for (lfs_size_t i = 0; i < COUNT; i++) { 1236 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1237 assert(info.type == LFSP_TYPE_DIR); 1238 char name[8]; 1239 sprintf(name, "dir%03d", i); 1240 assert(strcmp(info.name, name) == 0); 1241 } 1242 1243 lfsp_dir_read(&lfsp, &dir, &info) => 0; 1244 lfsp_dir_close(&lfsp, &dir) => 0; 1245 1246 // can we list the files? 1247 for (lfs_size_t i = 0; i < COUNT; i++) { 1248 char name[8]; 1249 sprintf(name, "dir%03d", i); 1250 lfsp_dir_t dir; 1251 lfsp_dir_open(&lfsp, &dir, name) => 0; 1252 struct lfsp_info info; 1253 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1254 assert(info.type == LFSP_TYPE_DIR); 1255 assert(strcmp(info.name, ".") == 0); 1256 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1257 assert(info.type == LFSP_TYPE_DIR); 1258 assert(strcmp(info.name, "..") == 0); 1259 1260 lfsp_dir_read(&lfsp, &dir, &info) => 1; 1261 assert(info.type == LFSP_TYPE_REG); 1262 sprintf(name, "file%03d", i); 1263 assert(strcmp(info.name, name) == 0); 1264 assert(info.size == SIZE); 1265 1266 lfsp_dir_read(&lfsp, &dir, &info) => 0; 1267 lfsp_dir_close(&lfsp, &dir) => 0; 1268 } 1269 1270 // now can we read the files? 1271 prng = 42; 1272 for (lfs_size_t i = 0; i < COUNT; i++) { 1273 lfsp_file_t file; 1274 char name[16]; 1275 sprintf(name, "dir%03d/file%03d", i, i); 1276 lfsp_file_open(&lfsp, &file, name, LFSP_O_RDONLY) => 0; 1277 for (lfs_size_t j = 0; j < SIZE; j += CHUNK) { 1278 uint8_t chunk[CHUNK]; 1279 lfsp_file_read(&lfsp, &file, chunk, CHUNK) => CHUNK; 1280 1281 for (lfs_size_t k = 0; k < CHUNK; k++) { 1282 assert(chunk[k] == TEST_PRNG(&prng) & 0xff); 1283 } 1284 } 1285 lfsp_file_close(&lfsp, &file) => 0; 1286 } 1287 1288 lfsp_unmount(&lfsp) => 0; 1289''' 1290 1291 1292 1293## incompatiblity tests ## 1294 1295# test that we fail to mount after a major version bump 1296[cases.test_compat_major_incompat] 1297in = 'lfs.c' 1298code = ''' 1299 // create a superblock 1300 lfs_t lfs; 1301 lfs_format(&lfs, cfg) => 0; 1302 1303 // bump the major version 1304 // 1305 // note we're messing around with internals to do this! this 1306 // is not a user API 1307 lfs_mount(&lfs, cfg) => 0; 1308 lfs_mdir_t mdir; 1309 lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; 1310 lfs_superblock_t superblock = { 1311 .version = LFS_DISK_VERSION + 0x00010000, 1312 .block_size = lfs.cfg->block_size, 1313 .block_count = lfs.cfg->block_count, 1314 .name_max = lfs.name_max, 1315 .file_max = lfs.file_max, 1316 .attr_max = lfs.attr_max, 1317 }; 1318 lfs_superblock_tole32(&superblock); 1319 lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS( 1320 {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)), 1321 &superblock})) => 0; 1322 lfs_unmount(&lfs) => 0; 1323 1324 // mount should now fail 1325 lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; 1326''' 1327 1328# test that we fail to mount after a minor version bump 1329[cases.test_compat_minor_incompat] 1330in = 'lfs.c' 1331code = ''' 1332 // create a superblock 1333 lfs_t lfs; 1334 lfs_format(&lfs, cfg) => 0; 1335 1336 // bump the minor version 1337 // 1338 // note we're messing around with internals to do this! this 1339 // is not a user API 1340 lfs_mount(&lfs, cfg) => 0; 1341 lfs_mdir_t mdir; 1342 lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; 1343 lfs_superblock_t superblock = { 1344 .version = LFS_DISK_VERSION + 0x00000001, 1345 .block_size = lfs.cfg->block_size, 1346 .block_count = lfs.cfg->block_count, 1347 .name_max = lfs.name_max, 1348 .file_max = lfs.file_max, 1349 .attr_max = lfs.attr_max, 1350 }; 1351 lfs_superblock_tole32(&superblock); 1352 lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS( 1353 {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)), 1354 &superblock})) => 0; 1355 lfs_unmount(&lfs) => 0; 1356 1357 // mount should now fail 1358 lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; 1359''' 1360 1361# test that we correctly bump the minor version 1362[cases.test_compat_minor_bump] 1363in = 'lfs.c' 1364if = ''' 1365 LFS_DISK_VERSION_MINOR > 0 1366 && DISK_VERSION == 0 1367''' 1368code = ''' 1369 // create a superblock 1370 lfs_t lfs; 1371 lfs_format(&lfs, cfg) => 0; 1372 lfs_mount(&lfs, cfg) => 0; 1373 lfs_file_t file; 1374 lfs_file_open(&lfs, &file, "test", 1375 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; 1376 lfs_file_write(&lfs, &file, "testtest", 8) => 8; 1377 lfs_file_close(&lfs, &file) => 0; 1378 lfs_unmount(&lfs) => 0; 1379 1380 // write an old minor version 1381 // 1382 // note we're messing around with internals to do this! this 1383 // is not a user API 1384 lfs_mount(&lfs, cfg) => 0; 1385 lfs_mdir_t mdir; 1386 lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0; 1387 lfs_superblock_t superblock = { 1388 .version = LFS_DISK_VERSION - 0x00000001, 1389 .block_size = lfs.cfg->block_size, 1390 .block_count = lfs.cfg->block_count, 1391 .name_max = lfs.name_max, 1392 .file_max = lfs.file_max, 1393 .attr_max = lfs.attr_max, 1394 }; 1395 lfs_superblock_tole32(&superblock); 1396 lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS( 1397 {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)), 1398 &superblock})) => 0; 1399 lfs_unmount(&lfs) => 0; 1400 1401 // mount should still work 1402 lfs_mount(&lfs, cfg) => 0; 1403 1404 struct lfs_fsinfo fsinfo; 1405 lfs_fs_stat(&lfs, &fsinfo) => 0; 1406 assert(fsinfo.disk_version == LFS_DISK_VERSION-1); 1407 1408 lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0; 1409 uint8_t buffer[8]; 1410 lfs_file_read(&lfs, &file, buffer, 8) => 8; 1411 assert(memcmp(buffer, "testtest", 8) == 0); 1412 lfs_file_close(&lfs, &file) => 0; 1413 1414 // minor version should be unchanged 1415 lfs_fs_stat(&lfs, &fsinfo) => 0; 1416 assert(fsinfo.disk_version == LFS_DISK_VERSION-1); 1417 1418 lfs_unmount(&lfs) => 0; 1419 1420 // if we write, we need to bump the minor version 1421 lfs_mount(&lfs, cfg) => 0; 1422 1423 lfs_fs_stat(&lfs, &fsinfo) => 0; 1424 assert(fsinfo.disk_version == LFS_DISK_VERSION-1); 1425 1426 lfs_file_open(&lfs, &file, "test", LFS_O_WRONLY | LFS_O_TRUNC) => 0; 1427 lfs_file_write(&lfs, &file, "teeeeest", 8) => 8; 1428 lfs_file_close(&lfs, &file) => 0; 1429 1430 // minor version should be changed 1431 lfs_fs_stat(&lfs, &fsinfo) => 0; 1432 assert(fsinfo.disk_version == LFS_DISK_VERSION); 1433 1434 lfs_unmount(&lfs) => 0; 1435 1436 // and of course mount should still work 1437 lfs_mount(&lfs, cfg) => 0; 1438 1439 // minor version should have changed 1440 lfs_fs_stat(&lfs, &fsinfo) => 0; 1441 assert(fsinfo.disk_version == LFS_DISK_VERSION); 1442 1443 lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0; 1444 lfs_file_read(&lfs, &file, buffer, 8) => 8; 1445 assert(memcmp(buffer, "teeeeest", 8) == 0); 1446 lfs_file_close(&lfs, &file) => 0; 1447 1448 // yep, still changed 1449 lfs_fs_stat(&lfs, &fsinfo) => 0; 1450 assert(fsinfo.disk_version == LFS_DISK_VERSION); 1451 1452 lfs_unmount(&lfs) => 0; 1453''' 1454