test_spiffs.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /*
  2. * test_spiffs.c
  3. *
  4. * Created on: Jun 19, 2013
  5. * Author: petera
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "params_test.h"
  11. #include "spiffs.h"
  12. #include "spiffs_nucleus.h"
  13. #include "testrunner.h"
  14. #include "test_spiffs.h"
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <fcntl.h>
  18. #include <dirent.h>
  19. #include <unistd.h>
  20. static unsigned char area[PHYS_FLASH_SIZE];
  21. static int erases[256];
  22. static char _path[256];
  23. static u32_t bytes_rd = 0;
  24. static u32_t bytes_wr = 0;
  25. static u32_t reads = 0;
  26. static u32_t writes = 0;
  27. static u32_t error_after_bytes_written = 0;
  28. static u32_t error_after_bytes_read = 0;
  29. static char error_after_bytes_written_once_only = 0;
  30. static char error_after_bytes_read_once_only = 0;
  31. static char log_flash_ops = 1;
  32. static u32_t fs_check_fixes = 0;
  33. spiffs __fs;
  34. static u8_t _work[LOG_PAGE*2];
  35. static u8_t _fds[FD_BUF_SIZE];
  36. static u8_t _cache[CACHE_BUF_SIZE];
  37. static int check_valid_flash = 1;
  38. #define TEST_PATH "test_data/"
  39. char *make_test_fname(const char *name) {
  40. sprintf(_path, "%s%s", TEST_PATH, name);
  41. return _path;
  42. }
  43. void clear_test_path() {
  44. DIR *dp;
  45. struct dirent *ep;
  46. dp = opendir(TEST_PATH);
  47. if (dp != NULL) {
  48. while ((ep = readdir(dp))) {
  49. if (ep->d_name[0] != '.') {
  50. sprintf(_path, "%s%s", TEST_PATH, ep->d_name);
  51. remove(_path);
  52. }
  53. }
  54. closedir(dp);
  55. }
  56. }
  57. static s32_t _read(u32_t addr, u32_t size, u8_t *dst) {
  58. if (log_flash_ops) {
  59. bytes_rd += size;
  60. reads++;
  61. if (error_after_bytes_read > 0 && bytes_rd >= error_after_bytes_read) {
  62. if (error_after_bytes_read_once_only) {
  63. error_after_bytes_read = 0;
  64. }
  65. return SPIFFS_ERR_TEST;
  66. }
  67. }
  68. if (addr < __fs.cfg.phys_addr) {
  69. printf("FATAL read addr too low %08x < %08x\n", addr, SPIFFS_PHYS_ADDR);
  70. exit(0);
  71. }
  72. if (addr + size > __fs.cfg.phys_addr + __fs.cfg.phys_size) {
  73. printf("FATAL read addr too high %08x + %08x > %08x\n", addr, size, SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE);
  74. exit(0);
  75. }
  76. memcpy(dst, &area[addr], size);
  77. return 0;
  78. }
  79. static s32_t _write(u32_t addr, u32_t size, u8_t *src) {
  80. int i;
  81. //printf("wr %08x %i\n", addr, size);
  82. if (log_flash_ops) {
  83. bytes_wr += size;
  84. writes++;
  85. if (error_after_bytes_written > 0 && bytes_wr >= error_after_bytes_written) {
  86. if (error_after_bytes_written_once_only) {
  87. error_after_bytes_written = 0;
  88. }
  89. return SPIFFS_ERR_TEST;
  90. }
  91. }
  92. if (addr < __fs.cfg.phys_addr) {
  93. printf("FATAL write addr too low %08x < %08x\n", addr, SPIFFS_PHYS_ADDR);
  94. exit(0);
  95. }
  96. if (addr + size > __fs.cfg.phys_addr + __fs.cfg.phys_size) {
  97. printf("FATAL write addr too high %08x + %08x > %08x\n", addr, size, SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE);
  98. exit(0);
  99. }
  100. for (i = 0; i < size; i++) {
  101. if (((addr + i) & (__fs.cfg.log_page_size-1)) != offsetof(spiffs_page_header, flags)) {
  102. if (check_valid_flash && ((area[addr + i] ^ src[i]) & src[i])) {
  103. printf("trying to write %02x to %02x at addr %08x\n", src[i], area[addr + i], addr+i);
  104. spiffs_page_ix pix = (addr + i) / LOG_PAGE;
  105. dump_page(&__fs, pix);
  106. return -1;
  107. }
  108. }
  109. area[addr + i] &= src[i];
  110. }
  111. return 0;
  112. }
  113. static s32_t _erase(u32_t addr, u32_t size) {
  114. if (addr & (__fs.cfg.phys_erase_block-1)) {
  115. printf("trying to erase at addr %08x, out of boundary\n", addr);
  116. return -1;
  117. }
  118. if (size & (__fs.cfg.phys_erase_block-1)) {
  119. printf("trying to erase at with size %08x, out of boundary\n", size);
  120. return -1;
  121. }
  122. erases[(addr-__fs.cfg.phys_addr)/__fs.cfg.phys_erase_block]++;
  123. memset(&area[addr], 0xff, size);
  124. return 0;
  125. }
  126. void hexdump_mem(u8_t *b, u32_t len) {
  127. while (len--) {
  128. if ((((intptr_t)b)&0x1f) == 0) {
  129. printf("\n");
  130. }
  131. printf("%02x", *b++);
  132. }
  133. printf("\n");
  134. }
  135. void hexdump(u32_t addr, u32_t len) {
  136. int remainder = (addr % 32) == 0 ? 0 : 32 - (addr % 32);
  137. u32_t a;
  138. for (a = addr - remainder; a < addr+len; a++) {
  139. if ((a & 0x1f) == 0) {
  140. if (a != addr) {
  141. printf(" ");
  142. int j;
  143. for (j = 0; j < 32; j++) {
  144. if (a-32+j < addr)
  145. printf(" ");
  146. else {
  147. printf("%c", (area[a-32+j] < 32 || area[a-32+j] >= 0x7f) ? '.' : area[a-32+j]);
  148. }
  149. }
  150. }
  151. printf("%s %08x: ", a<=addr ? "":"\n", a);
  152. }
  153. if (a < addr) {
  154. printf(" ");
  155. } else {
  156. printf("%02x", area[a]);
  157. }
  158. }
  159. int j;
  160. printf(" ");
  161. for (j = 0; j < 32; j++) {
  162. if (a-32+j < addr)
  163. printf(" ");
  164. else {
  165. printf("%c", (area[a-32+j] < 32 || area[a-32+j] >= 0x7f) ? '.' : area[a-32+j]);
  166. }
  167. }
  168. printf("\n");
  169. }
  170. void dump_page(spiffs *fs, spiffs_page_ix p) {
  171. printf("page %04x ", p);
  172. u32_t addr = SPIFFS_PAGE_TO_PADDR(fs, p);
  173. if (p % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
  174. // obj lu page
  175. printf("OBJ_LU");
  176. } else {
  177. u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs , p)) +
  178. SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, p) * sizeof(spiffs_obj_id);
  179. spiffs_obj_id obj_id = *((spiffs_obj_id *)&area[obj_id_addr]);
  180. // data page
  181. spiffs_page_header *ph = (spiffs_page_header *)&area[addr];
  182. printf("DATA %04x:%04x ", obj_id, ph->span_ix);
  183. printf("%s", ((ph->flags & SPIFFS_PH_FLAG_FINAL) == 0) ? "FIN " : "fin ");
  184. printf("%s", ((ph->flags & SPIFFS_PH_FLAG_DELET) == 0) ? "DEL " : "del ");
  185. printf("%s", ((ph->flags & SPIFFS_PH_FLAG_INDEX) == 0) ? "IDX " : "idx ");
  186. printf("%s", ((ph->flags & SPIFFS_PH_FLAG_USED) == 0) ? "USD " : "usd ");
  187. printf("%s ", ((ph->flags & SPIFFS_PH_FLAG_IXDELE) == 0) ? "IDL " : "idl ");
  188. if (obj_id & SPIFFS_OBJ_ID_IX_FLAG) {
  189. // object index
  190. printf("OBJ_IX");
  191. if (ph->span_ix == 0) {
  192. printf("_HDR ");
  193. spiffs_page_object_ix_header *oix_hdr = (spiffs_page_object_ix_header *)&area[addr];
  194. printf("'%s' %i bytes type:%02x", oix_hdr->name, oix_hdr->size, oix_hdr->type);
  195. }
  196. } else {
  197. // data page
  198. printf("CONTENT");
  199. }
  200. }
  201. printf("\n");
  202. u32_t len = fs->cfg.log_page_size;
  203. hexdump(addr, len);
  204. }
  205. void area_write(u32_t addr, u8_t *buf, u32_t size) {
  206. int i;
  207. for (i = 0; i < size; i++) {
  208. area[addr + i] = *buf++;
  209. }
  210. }
  211. void area_read(u32_t addr, u8_t *buf, u32_t size) {
  212. int i;
  213. for (i = 0; i < size; i++) {
  214. *buf++ = area[addr + i];
  215. }
  216. }
  217. void dump_erase_counts(spiffs *fs) {
  218. spiffs_block_ix bix;
  219. printf(" BLOCK |\n");
  220. printf(" AGE COUNT|\n");
  221. for (bix = 0; bix < fs->block_count; bix++) {
  222. printf("----%3i ----|", bix);
  223. }
  224. printf("\n");
  225. for (bix = 0; bix < fs->block_count; bix++) {
  226. spiffs_obj_id erase_mark;
  227. _spiffs_rd(fs, 0, 0, SPIFFS_ERASE_COUNT_PADDR(fs, bix), sizeof(spiffs_obj_id), (u8_t *)&erase_mark);
  228. if (erases[bix] == 0) {
  229. printf(" |");
  230. } else {
  231. printf("%7i %4i|", (fs->max_erase_count - erase_mark), erases[bix]);
  232. }
  233. }
  234. printf("\n");
  235. }
  236. void dump_flash_access_stats() {
  237. printf(" RD: %10i reads %10i bytes %10i avg bytes/read\n", reads, bytes_rd, reads == 0 ? 0 : (bytes_rd / reads));
  238. printf(" WR: %10i writes %10i bytes %10i avg bytes/write\n", writes, bytes_wr, writes == 0 ? 0 : (bytes_wr / writes));
  239. }
  240. static u32_t old_perc = 999;
  241. static void spiffs_check_cb_f(spiffs_check_type type, spiffs_check_report report,
  242. u32_t arg1, u32_t arg2) {
  243. /* if (report == SPIFFS_CHECK_PROGRESS && old_perc != arg1) {
  244. old_perc = arg1;
  245. printf("CHECK REPORT: ");
  246. switch(type) {
  247. case SPIFFS_CHECK_LOOKUP:
  248. printf("LU "); break;
  249. case SPIFFS_CHECK_INDEX:
  250. printf("IX "); break;
  251. case SPIFFS_CHECK_PAGE:
  252. printf("PA "); break;
  253. }
  254. printf("%i%%\n", arg1 * 100 / 256);
  255. }*/
  256. if (report != SPIFFS_CHECK_PROGRESS) {
  257. if (report != SPIFFS_CHECK_ERROR) fs_check_fixes++;
  258. printf(" check: ");
  259. switch (type) {
  260. case SPIFFS_CHECK_INDEX:
  261. printf("INDEX "); break;
  262. case SPIFFS_CHECK_LOOKUP:
  263. printf("LOOKUP "); break;
  264. case SPIFFS_CHECK_PAGE:
  265. printf("PAGE "); break;
  266. default:
  267. printf("???? "); break;
  268. }
  269. if (report == SPIFFS_CHECK_ERROR) {
  270. printf("ERROR %i", arg1);
  271. } else if (report == SPIFFS_CHECK_DELETE_BAD_FILE) {
  272. printf("DELETE BAD FILE %04x", arg1);
  273. } else if (report == SPIFFS_CHECK_DELETE_ORPHANED_INDEX) {
  274. printf("DELETE ORPHANED INDEX %04x", arg1);
  275. } else if (report == SPIFFS_CHECK_DELETE_PAGE) {
  276. printf("DELETE PAGE %04x", arg1);
  277. } else if (report == SPIFFS_CHECK_FIX_INDEX) {
  278. printf("FIX INDEX %04x:%04x", arg1, arg2);
  279. } else if (report == SPIFFS_CHECK_FIX_LOOKUP) {
  280. printf("FIX INDEX %04x:%04x", arg1, arg2);
  281. } else {
  282. printf("??");
  283. }
  284. printf("\n");
  285. }
  286. }
  287. void fs_reset_specific(u32_t phys_addr, u32_t phys_size,
  288. u32_t phys_sector_size,
  289. u32_t log_block_size, u32_t log_page_size) {
  290. memset(area, 0xcc, sizeof(area));
  291. memset(&area[phys_addr], 0xff, phys_size);
  292. spiffs_config c;
  293. c.hal_erase_f = _erase;
  294. c.hal_read_f = _read;
  295. c.hal_write_f = _write;
  296. c.log_block_size = log_block_size;
  297. c.log_page_size = log_page_size;
  298. c.phys_addr = phys_addr;
  299. c.phys_erase_block = phys_sector_size;
  300. c.phys_size = phys_size;
  301. memset(erases,0,sizeof(erases));
  302. memset(_cache,0,sizeof(_cache));
  303. SPIFFS_mount(&__fs, &c, _work, _fds, sizeof(_fds), _cache, sizeof(_cache), spiffs_check_cb_f);
  304. clear_flash_ops_log();
  305. log_flash_ops = 1;
  306. fs_check_fixes = 0;
  307. }
  308. void fs_reset() {
  309. fs_reset_specific(SPIFFS_PHYS_ADDR, SPIFFS_FLASH_SIZE, SECTOR_SIZE, LOG_BLOCK, LOG_PAGE);
  310. }
  311. void set_flash_ops_log(int enable) {
  312. log_flash_ops = enable;
  313. }
  314. void clear_flash_ops_log() {
  315. bytes_rd = 0;
  316. bytes_wr = 0;
  317. reads = 0;
  318. writes = 0;
  319. error_after_bytes_read = 0;
  320. error_after_bytes_written = 0;
  321. }
  322. u32_t get_flash_ops_log_read_bytes() {
  323. return bytes_rd;
  324. }
  325. u32_t get_flash_ops_log_write_bytes() {
  326. return bytes_wr;
  327. }
  328. void invoke_error_after_read_bytes(u32_t b, char once_only) {
  329. error_after_bytes_read = b;
  330. error_after_bytes_read_once_only = once_only;
  331. }
  332. void invoke_error_after_write_bytes(u32_t b, char once_only) {
  333. error_after_bytes_written = b;
  334. error_after_bytes_written_once_only = once_only;
  335. }
  336. void fs_set_validate_flashing(int i) {
  337. check_valid_flash = i;
  338. }
  339. void real_assert(int c, const char *n, const char *file, int l) {
  340. if (c == 0) {
  341. printf("ASSERT: %s %s @ %i\n", (n ? n : ""), file, l);
  342. printf("fs errno:%i\n", __fs.err_code);
  343. exit(0);
  344. }
  345. }
  346. int read_and_verify(char *name) {
  347. s32_t res;
  348. int fd = SPIFFS_open(&__fs, name, SPIFFS_RDONLY, 0);
  349. if (fd < 0) {
  350. printf(" read_and_verify: could not open file %s\n", name);
  351. return fd;
  352. }
  353. return read_and_verify_fd(fd, name);
  354. }
  355. int read_and_verify_fd(spiffs_file fd, char *name) {
  356. s32_t res;
  357. int pfd = open(make_test_fname(name), O_RDONLY);
  358. spiffs_stat s;
  359. res = SPIFFS_fstat(&__fs, fd, &s);
  360. if (res < 0) {
  361. printf(" read_and_verify: could not stat file %s\n", name);
  362. return res;
  363. }
  364. if (s.size == 0) {
  365. SPIFFS_close(&__fs, fd);
  366. close(pfd);
  367. return 0;
  368. }
  369. //printf("verifying %s, len %i\n", name, s.size);
  370. int offs = 0;
  371. u8_t buf_d[256];
  372. u8_t buf_v[256];
  373. while (offs < s.size) {
  374. int read_len = MIN(s.size - offs, sizeof(buf_d));
  375. res = SPIFFS_read(&__fs, fd, buf_d, read_len);
  376. if (res < 0) {
  377. printf(" read_and_verify: could not read file %s offs:%i len:%i filelen:%i\n", name, offs, read_len, s.size);
  378. return res;
  379. }
  380. int pres = read(pfd, buf_v, read_len);
  381. (void)pres;
  382. //printf("reading offs:%i len:%i spiffs_res:%i posix_res:%i\n", offs, read_len, res, pres);
  383. int i;
  384. int veri_ok = 1;
  385. for (i = 0; veri_ok && i < read_len; i++) {
  386. if (buf_d[i] != buf_v[i]) {
  387. printf("file verification mismatch @ %i, %02x %c != %02x %c\n", offs+i, buf_d[i], buf_d[i], buf_v[i], buf_v[i]);
  388. int j = MAX(0, i-16);
  389. int k = MIN(sizeof(buf_d), i+16);
  390. k = MIN(s.size-offs, k);
  391. int l;
  392. for (l = j; l < k; l++) {
  393. printf("%c", buf_d[l] > 31 ? buf_d[l] : '.');
  394. }
  395. printf("\n");
  396. for (l = j; l < k; l++) {
  397. printf("%c", buf_v[l] > 31 ? buf_v[l] : '.');
  398. }
  399. printf("\n");
  400. veri_ok = 0;
  401. }
  402. }
  403. if (!veri_ok) {
  404. SPIFFS_close(&__fs, fd);
  405. close(pfd);
  406. printf("data mismatch\n");
  407. return -1;
  408. }
  409. offs += read_len;
  410. }
  411. SPIFFS_close(&__fs, fd);
  412. close(pfd);
  413. return 0;
  414. }
  415. static void test_on_stop(test *t) {
  416. printf(" spiffs errno:%i\n", SPIFFS_errno(&__fs));
  417. #if SPIFFS_TEST_VISUALISATION
  418. SPIFFS_vis(FS);
  419. #endif
  420. }
  421. void memrand(u8_t *b, int len) {
  422. int i;
  423. for (i = 0; i < len; i++) {
  424. b[i] = rand();
  425. }
  426. }
  427. int test_create_file(char *name) {
  428. spiffs_stat s;
  429. spiffs_file fd;
  430. int res = SPIFFS_creat(FS, name, 0);
  431. CHECK_RES(res);
  432. fd = SPIFFS_open(FS, name, SPIFFS_RDONLY, 0);
  433. CHECK(fd >= 0);
  434. res = SPIFFS_fstat(FS, fd, &s);
  435. CHECK_RES(res);
  436. CHECK(strcmp((char*)s.name, name) == 0);
  437. CHECK(s.size == 0);
  438. SPIFFS_close(FS, fd);
  439. return 0;
  440. }
  441. int test_create_and_write_file(char *name, int size, int chunk_size) {
  442. int res;
  443. spiffs_file fd;
  444. printf(" create and write %s", name);
  445. res = test_create_file(name);
  446. if (res < 0) {
  447. printf(" failed creation, %i\n",res);
  448. }
  449. CHECK(res >= 0);
  450. fd = SPIFFS_open(FS, name, SPIFFS_APPEND | SPIFFS_RDWR, 0);
  451. if (res < 0) {
  452. printf(" failed open, %i\n",res);
  453. }
  454. CHECK(fd >= 0);
  455. int pfd = open(make_test_fname(name), O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
  456. int offset = 0;
  457. int mark = 0;
  458. while (offset < size) {
  459. int len = MIN(size-offset, chunk_size);
  460. if (offset > mark) {
  461. mark += size/16;
  462. printf(".");
  463. fflush(stdout);
  464. }
  465. u8_t *buf = malloc(len);
  466. memrand(buf, len);
  467. res = SPIFFS_write(FS, fd, buf, len);
  468. write(pfd, buf, len);
  469. free(buf);
  470. if (res < 0) {
  471. printf("\n error @ offset %i, res %i\n", offset, res);
  472. }
  473. offset += len;
  474. CHECK(res >= 0);
  475. }
  476. printf("\n");
  477. close(pfd);
  478. spiffs_stat stat;
  479. res = SPIFFS_fstat(FS, fd, &stat);
  480. if (res < 0) {
  481. printf(" failed fstat, %i\n",res);
  482. }
  483. CHECK(res >= 0);
  484. if (stat.size != size) {
  485. printf(" failed size, %i != %i\n", stat.size, size);
  486. }
  487. CHECK(stat.size == size);
  488. SPIFFS_close(FS, fd);
  489. return 0;
  490. }
  491. #if SPIFFS_CACHE
  492. #if SPIFFS_CACHE_STATS
  493. static u32_t chits_tot = 0;
  494. static u32_t cmiss_tot = 0;
  495. #endif
  496. #endif
  497. void _setup_test_only() {
  498. fs_set_validate_flashing(1);
  499. test_init(test_on_stop);
  500. }
  501. void _setup() {
  502. fs_reset();
  503. _setup_test_only();
  504. }
  505. void _teardown() {
  506. printf(" free blocks : %i of %i\n", (FS)->free_blocks, (FS)->block_count);
  507. printf(" pages allocated : %i\n", (FS)->stats_p_allocated);
  508. printf(" pages deleted : %i\n", (FS)->stats_p_deleted);
  509. #if SPIFFS_GC_STATS
  510. printf(" gc runs : %i\n", (FS)->stats_gc_runs);
  511. #endif
  512. #if SPIFFS_CACHE
  513. #if SPIFFS_CACHE_STATS
  514. chits_tot += (FS)->cache_hits;
  515. cmiss_tot += (FS)->cache_misses;
  516. printf(" cache hits : %i (sum %i)\n", (FS)->cache_hits, chits_tot);
  517. printf(" cache misses : %i (sum %i)\n", (FS)->cache_misses, cmiss_tot);
  518. printf(" cache utiliz : %f\n", ((float)chits_tot/(float)(chits_tot + cmiss_tot)));
  519. #endif
  520. #endif
  521. dump_flash_access_stats();
  522. clear_flash_ops_log();
  523. #if SPIFFS_GC_STATS
  524. if ((FS)->stats_gc_runs > 0)
  525. #endif
  526. dump_erase_counts(FS);
  527. printf(" fs consistency check:\n");
  528. SPIFFS_check(FS);
  529. clear_test_path();
  530. //hexdump_mem(&area[SPIFFS_PHYS_ADDR - 16], 32);
  531. //hexdump_mem(&area[SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE - 16], 32);
  532. }
  533. u32_t tfile_get_size(tfile_size s) {
  534. switch (s) {
  535. case EMPTY:
  536. return 0;
  537. case SMALL:
  538. return SPIFFS_DATA_PAGE_SIZE(FS)/2;
  539. case MEDIUM:
  540. return SPIFFS_DATA_PAGE_SIZE(FS) * (SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS));
  541. case LARGE:
  542. return (FS)->cfg.phys_size/3;
  543. }
  544. return 0;
  545. }
  546. int run_file_config(int cfg_count, tfile_conf* cfgs, int max_runs, int max_concurrent_files, int dbg) {
  547. int res;
  548. tfile *tfiles = malloc(sizeof(tfile) * max_concurrent_files);
  549. memset(tfiles, 0, sizeof(tfile) * max_concurrent_files);
  550. int run = 0;
  551. int cur_config_ix = 0;
  552. char name[32];
  553. while (run < max_runs) {
  554. if (dbg) printf(" run %i/%i\n", run, max_runs);
  555. int i;
  556. for (i = 0; i < max_concurrent_files; i++) {
  557. sprintf(name, "file%i_%i", (1+run), i);
  558. tfile *tf = &tfiles[i];
  559. if (tf->state == 0 && cur_config_ix < cfg_count) {
  560. // create a new file
  561. strcpy(tf->name, name);
  562. tf->state = 1;
  563. tf->cfg = cfgs[cur_config_ix];
  564. int size = tfile_get_size(tf->cfg.tsize);
  565. if (dbg) printf(" create new %s with cfg %i/%i, size %i\n", name, (1+cur_config_ix), cfg_count, size);
  566. if (tf->cfg.tsize == EMPTY) {
  567. res = SPIFFS_creat(FS, name, 0);
  568. CHECK_RES(res);
  569. int pfd = open(make_test_fname(name), O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
  570. close(pfd);
  571. int extra_flags = tf->cfg.ttype == APPENDED ? SPIFFS_APPEND : 0;
  572. spiffs_file fd = SPIFFS_open(FS, name, extra_flags | SPIFFS_RDWR, 0);
  573. CHECK(fd > 0);
  574. tf->fd = fd;
  575. } else {
  576. int extra_flags = tf->cfg.ttype == APPENDED ? SPIFFS_APPEND : 0;
  577. spiffs_file fd = SPIFFS_open(FS, name, extra_flags | SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_RDWR, 0);
  578. CHECK(fd > 0);
  579. extra_flags = tf->cfg.ttype == APPENDED ? O_APPEND : 0;
  580. int pfd = open(make_test_fname(name), extra_flags | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
  581. tf->fd = fd;
  582. u8_t *buf = malloc(size);
  583. memrand(buf, size);
  584. res = SPIFFS_write(FS, fd, buf, size);
  585. CHECK_RES(res);
  586. write(pfd, buf, size);
  587. close(pfd);
  588. free(buf);
  589. res = read_and_verify(name);
  590. CHECK_RES(res);
  591. }
  592. cur_config_ix++;
  593. } else if (tf->state > 0) {
  594. // hande file lifecycle
  595. switch (tf->cfg.ttype) {
  596. case UNTAMPERED: {
  597. break;
  598. }
  599. case APPENDED: {
  600. if (dbg) printf(" appending %s\n", tf->name);
  601. int size = SPIFFS_DATA_PAGE_SIZE(FS)*3;
  602. u8_t *buf = malloc(size);
  603. memrand(buf, size);
  604. res = SPIFFS_write(FS, tf->fd, buf, size);
  605. CHECK_RES(res);
  606. int pfd = open(make_test_fname(tf->name), O_APPEND | O_RDWR);
  607. write(pfd, buf, size);
  608. close(pfd);
  609. free(buf);
  610. res = read_and_verify(tf->name);
  611. CHECK_RES(res);
  612. break;
  613. }
  614. case MODIFIED: {
  615. if (dbg) printf(" modify %s\n", tf->name);
  616. spiffs_stat stat;
  617. res = SPIFFS_fstat(FS, tf->fd, &stat);
  618. CHECK_RES(res);
  619. int size = stat.size / tf->cfg.tlife + SPIFFS_DATA_PAGE_SIZE(FS)/3;
  620. int offs = (stat.size / tf->cfg.tlife) * tf->state;
  621. res = SPIFFS_lseek(FS, tf->fd, offs, SPIFFS_SEEK_SET);
  622. CHECK_RES(res);
  623. u8_t *buf = malloc(size);
  624. memrand(buf, size);
  625. res = SPIFFS_write(FS, tf->fd, buf, size);
  626. CHECK_RES(res);
  627. int pfd = open(make_test_fname(tf->name), O_RDWR);
  628. lseek(pfd, offs, SEEK_SET);
  629. write(pfd, buf, size);
  630. close(pfd);
  631. free(buf);
  632. res = read_and_verify(tf->name);
  633. CHECK_RES(res);
  634. break;
  635. }
  636. case REWRITTEN: {
  637. if (tf->fd > 0) {
  638. SPIFFS_close(FS, tf->fd);
  639. }
  640. if (dbg) printf(" rewriting %s\n", tf->name);
  641. spiffs_file fd = SPIFFS_open(FS, tf->name, SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_RDWR, 0);
  642. CHECK(fd > 0);
  643. int pfd = open(make_test_fname(tf->name), O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
  644. tf->fd = fd;
  645. int size = tfile_get_size(tf->cfg.tsize);
  646. u8_t *buf = malloc(size);
  647. memrand(buf, size);
  648. res = SPIFFS_write(FS, fd, buf, size);
  649. CHECK_RES(res);
  650. write(pfd, buf, size);
  651. close(pfd);
  652. free(buf);
  653. res = read_and_verify(tf->name);
  654. CHECK_RES(res);
  655. break;
  656. }
  657. }
  658. tf->state++;
  659. if (tf->state > tf->cfg.tlife) {
  660. // file outlived its time, kill it
  661. if (tf->fd > 0) {
  662. SPIFFS_close(FS, tf->fd);
  663. }
  664. if (dbg) printf(" removing %s\n", tf->name);
  665. res = read_and_verify(tf->name);
  666. CHECK_RES(res);
  667. res = SPIFFS_remove(FS, tf->name);
  668. CHECK_RES(res);
  669. remove(make_test_fname(tf->name));
  670. memset(tf, 0, sizeof(tf));
  671. }
  672. }
  673. }
  674. run++;
  675. }
  676. free(tfiles);
  677. return 0;
  678. }