test_seek.toml 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. # simple file seek
  2. [cases.test_seek_read]
  3. defines = [
  4. {COUNT=132, SKIP=4},
  5. {COUNT=132, SKIP=128},
  6. {COUNT=200, SKIP=10},
  7. {COUNT=200, SKIP=100},
  8. {COUNT=4, SKIP=1},
  9. {COUNT=4, SKIP=2},
  10. ]
  11. code = '''
  12. lfs_t lfs;
  13. lfs_format(&lfs, cfg) => 0;
  14. lfs_mount(&lfs, cfg) => 0;
  15. lfs_file_t file;
  16. lfs_file_open(&lfs, &file, "kitty",
  17. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  18. size_t size = strlen("kittycatcat");
  19. uint8_t buffer[1024];
  20. memcpy(buffer, "kittycatcat", size);
  21. for (int j = 0; j < COUNT; j++) {
  22. lfs_file_write(&lfs, &file, buffer, size);
  23. }
  24. lfs_file_close(&lfs, &file) => 0;
  25. lfs_unmount(&lfs) => 0;
  26. lfs_mount(&lfs, cfg) => 0;
  27. lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY) => 0;
  28. lfs_soff_t pos = -1;
  29. size = strlen("kittycatcat");
  30. for (int i = 0; i < SKIP; i++) {
  31. lfs_file_read(&lfs, &file, buffer, size) => size;
  32. memcmp(buffer, "kittycatcat", size) => 0;
  33. pos = lfs_file_tell(&lfs, &file);
  34. }
  35. assert(pos >= 0);
  36. lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos;
  37. lfs_file_read(&lfs, &file, buffer, size) => size;
  38. memcmp(buffer, "kittycatcat", size) => 0;
  39. lfs_file_rewind(&lfs, &file) => 0;
  40. lfs_file_read(&lfs, &file, buffer, size) => size;
  41. memcmp(buffer, "kittycatcat", size) => 0;
  42. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size;
  43. lfs_file_read(&lfs, &file, buffer, size) => size;
  44. memcmp(buffer, "kittycatcat", size) => 0;
  45. lfs_file_seek(&lfs, &file, size, LFS_SEEK_CUR) => 3*size;
  46. lfs_file_read(&lfs, &file, buffer, size) => size;
  47. memcmp(buffer, "kittycatcat", size) => 0;
  48. lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos;
  49. lfs_file_read(&lfs, &file, buffer, size) => size;
  50. memcmp(buffer, "kittycatcat", size) => 0;
  51. lfs_file_seek(&lfs, &file, -size, LFS_SEEK_CUR) => pos;
  52. lfs_file_read(&lfs, &file, buffer, size) => size;
  53. memcmp(buffer, "kittycatcat", size) => 0;
  54. lfs_file_seek(&lfs, &file, -size, LFS_SEEK_END) >= 0 => 1;
  55. lfs_file_read(&lfs, &file, buffer, size) => size;
  56. memcmp(buffer, "kittycatcat", size) => 0;
  57. size = lfs_file_size(&lfs, &file);
  58. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size;
  59. lfs_file_close(&lfs, &file) => 0;
  60. lfs_unmount(&lfs) => 0;
  61. '''
  62. # simple file seek and write
  63. [cases.test_seek_write]
  64. defines = [
  65. {COUNT=132, SKIP=4},
  66. {COUNT=132, SKIP=128},
  67. {COUNT=200, SKIP=10},
  68. {COUNT=200, SKIP=100},
  69. {COUNT=4, SKIP=1},
  70. {COUNT=4, SKIP=2},
  71. ]
  72. code = '''
  73. lfs_t lfs;
  74. lfs_format(&lfs, cfg) => 0;
  75. lfs_mount(&lfs, cfg) => 0;
  76. lfs_file_t file;
  77. lfs_file_open(&lfs, &file, "kitty",
  78. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  79. size_t size = strlen("kittycatcat");
  80. uint8_t buffer[1024];
  81. memcpy(buffer, "kittycatcat", size);
  82. for (int j = 0; j < COUNT; j++) {
  83. lfs_file_write(&lfs, &file, buffer, size);
  84. }
  85. lfs_file_close(&lfs, &file) => 0;
  86. lfs_unmount(&lfs) => 0;
  87. lfs_mount(&lfs, cfg) => 0;
  88. lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
  89. lfs_soff_t pos = -1;
  90. size = strlen("kittycatcat");
  91. for (int i = 0; i < SKIP; i++) {
  92. lfs_file_read(&lfs, &file, buffer, size) => size;
  93. memcmp(buffer, "kittycatcat", size) => 0;
  94. pos = lfs_file_tell(&lfs, &file);
  95. }
  96. assert(pos >= 0);
  97. memcpy(buffer, "doggodogdog", size);
  98. lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos;
  99. lfs_file_write(&lfs, &file, buffer, size) => size;
  100. lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos;
  101. lfs_file_read(&lfs, &file, buffer, size) => size;
  102. memcmp(buffer, "doggodogdog", size) => 0;
  103. lfs_file_rewind(&lfs, &file) => 0;
  104. lfs_file_read(&lfs, &file, buffer, size) => size;
  105. memcmp(buffer, "kittycatcat", size) => 0;
  106. lfs_file_seek(&lfs, &file, pos, LFS_SEEK_SET) => pos;
  107. lfs_file_read(&lfs, &file, buffer, size) => size;
  108. memcmp(buffer, "doggodogdog", size) => 0;
  109. lfs_file_seek(&lfs, &file, -size, LFS_SEEK_END) >= 0 => 1;
  110. lfs_file_read(&lfs, &file, buffer, size) => size;
  111. memcmp(buffer, "kittycatcat", size) => 0;
  112. size = lfs_file_size(&lfs, &file);
  113. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => size;
  114. lfs_file_close(&lfs, &file) => 0;
  115. lfs_unmount(&lfs) => 0;
  116. '''
  117. # boundary seek and reads
  118. [cases.test_seek_boundary_read]
  119. defines.COUNT = 132
  120. code = '''
  121. lfs_t lfs;
  122. lfs_format(&lfs, cfg) => 0;
  123. lfs_mount(&lfs, cfg) => 0;
  124. lfs_file_t file;
  125. lfs_file_open(&lfs, &file, "kitty",
  126. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  127. size_t size = strlen("kittycatcat");
  128. uint8_t buffer[1024];
  129. memcpy(buffer, "kittycatcat", size);
  130. for (int j = 0; j < COUNT; j++) {
  131. lfs_file_write(&lfs, &file, buffer, size);
  132. }
  133. lfs_file_close(&lfs, &file) => 0;
  134. lfs_unmount(&lfs) => 0;
  135. lfs_mount(&lfs, cfg) => 0;
  136. lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY) => 0;
  137. size = strlen("kittycatcat");
  138. const lfs_soff_t offsets[] = {
  139. 512,
  140. 1024-4,
  141. 512+1,
  142. 1024-4+1,
  143. 512-1,
  144. 1024-4-1,
  145. 512-strlen("kittycatcat"),
  146. 1024-4-strlen("kittycatcat"),
  147. 512-strlen("kittycatcat")+1,
  148. 1024-4-strlen("kittycatcat")+1,
  149. 512-strlen("kittycatcat")-1,
  150. 1024-4-strlen("kittycatcat")-1,
  151. strlen("kittycatcat")*(COUNT-2)-1,
  152. };
  153. for (unsigned i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) {
  154. lfs_soff_t off = offsets[i];
  155. // read @ offset
  156. lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
  157. lfs_file_read(&lfs, &file, buffer, size) => size;
  158. memcmp(buffer,
  159. &"kittycatcatkittycatcat"[off % strlen("kittycatcat")],
  160. size) => 0;
  161. // read after
  162. lfs_file_seek(&lfs, &file, off+strlen("kittycatcat")+1, LFS_SEEK_SET)
  163. => off+strlen("kittycatcat")+1;
  164. lfs_file_read(&lfs, &file, buffer, size) => size;
  165. memcmp(buffer,
  166. &"kittycatcatkittycatcat"[(off+1) % strlen("kittycatcat")],
  167. size) => 0;
  168. // read before
  169. lfs_file_seek(&lfs, &file, off-strlen("kittycatcat")-1, LFS_SEEK_SET)
  170. => off-strlen("kittycatcat")-1;
  171. lfs_file_read(&lfs, &file, buffer, size) => size;
  172. memcmp(buffer,
  173. &"kittycatcatkittycatcat"[(off-1) % strlen("kittycatcat")],
  174. size) => 0;
  175. // read @ 0
  176. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
  177. lfs_file_read(&lfs, &file, buffer, size) => size;
  178. memcmp(buffer, "kittycatcat", size) => 0;
  179. // read @ offset
  180. lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
  181. lfs_file_read(&lfs, &file, buffer, size) => size;
  182. memcmp(buffer,
  183. &"kittycatcatkittycatcat"[off % strlen("kittycatcat")],
  184. size) => 0;
  185. // read after
  186. lfs_file_seek(&lfs, &file, off+strlen("kittycatcat")+1, LFS_SEEK_SET)
  187. => off+strlen("kittycatcat")+1;
  188. lfs_file_read(&lfs, &file, buffer, size) => size;
  189. memcmp(buffer,
  190. &"kittycatcatkittycatcat"[(off+1) % strlen("kittycatcat")],
  191. size) => 0;
  192. // read before
  193. lfs_file_seek(&lfs, &file, off-strlen("kittycatcat")-1, LFS_SEEK_SET)
  194. => off-strlen("kittycatcat")-1;
  195. lfs_file_read(&lfs, &file, buffer, size) => size;
  196. memcmp(buffer,
  197. &"kittycatcatkittycatcat"[(off-1) % strlen("kittycatcat")],
  198. size) => 0;
  199. // sync
  200. lfs_file_sync(&lfs, &file) => 0;
  201. // read @ 0
  202. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
  203. lfs_file_read(&lfs, &file, buffer, size) => size;
  204. memcmp(buffer, "kittycatcat", size) => 0;
  205. // read @ offset
  206. lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
  207. lfs_file_read(&lfs, &file, buffer, size) => size;
  208. memcmp(buffer,
  209. &"kittycatcatkittycatcat"[off % strlen("kittycatcat")],
  210. size) => 0;
  211. // read after
  212. lfs_file_seek(&lfs, &file, off+strlen("kittycatcat")+1, LFS_SEEK_SET)
  213. => off+strlen("kittycatcat")+1;
  214. lfs_file_read(&lfs, &file, buffer, size) => size;
  215. memcmp(buffer,
  216. &"kittycatcatkittycatcat"[(off+1) % strlen("kittycatcat")],
  217. size) => 0;
  218. // read before
  219. lfs_file_seek(&lfs, &file, off-strlen("kittycatcat")-1, LFS_SEEK_SET)
  220. => off-strlen("kittycatcat")-1;
  221. lfs_file_read(&lfs, &file, buffer, size) => size;
  222. memcmp(buffer,
  223. &"kittycatcatkittycatcat"[(off-1) % strlen("kittycatcat")],
  224. size) => 0;
  225. }
  226. lfs_file_close(&lfs, &file) => 0;
  227. lfs_unmount(&lfs) => 0;
  228. '''
  229. # boundary seek and writes
  230. [cases.test_seek_boundary_write]
  231. defines.COUNT = 132
  232. code = '''
  233. lfs_t lfs;
  234. lfs_format(&lfs, cfg) => 0;
  235. lfs_mount(&lfs, cfg) => 0;
  236. lfs_file_t file;
  237. lfs_file_open(&lfs, &file, "kitty",
  238. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  239. size_t size = strlen("kittycatcat");
  240. uint8_t buffer[1024];
  241. memcpy(buffer, "kittycatcat", size);
  242. for (int j = 0; j < COUNT; j++) {
  243. lfs_file_write(&lfs, &file, buffer, size);
  244. }
  245. lfs_file_close(&lfs, &file) => 0;
  246. lfs_unmount(&lfs) => 0;
  247. lfs_mount(&lfs, cfg) => 0;
  248. lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
  249. size = strlen("hedgehoghog");
  250. const lfs_soff_t offsets[] = {
  251. 512,
  252. 1024-4,
  253. 512+1,
  254. 1024-4+1,
  255. 512-1,
  256. 1024-4-1,
  257. 512-strlen("kittycatcat"),
  258. 1024-4-strlen("kittycatcat"),
  259. 512-strlen("kittycatcat")+1,
  260. 1024-4-strlen("kittycatcat")+1,
  261. 512-strlen("kittycatcat")-1,
  262. 1024-4-strlen("kittycatcat")-1,
  263. strlen("kittycatcat")*(COUNT-2)-1,
  264. };
  265. for (unsigned i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) {
  266. lfs_soff_t off = offsets[i];
  267. // write @ offset
  268. memcpy(buffer, "hedgehoghog", size);
  269. lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
  270. lfs_file_write(&lfs, &file, buffer, size) => size;
  271. // read @ offset
  272. lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
  273. lfs_file_read(&lfs, &file, buffer, size) => size;
  274. memcmp(buffer, "hedgehoghog", size) => 0;
  275. // read @ 0
  276. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
  277. lfs_file_read(&lfs, &file, buffer, size) => size;
  278. memcmp(buffer, "kittycatcat", size) => 0;
  279. // read @ offset
  280. lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
  281. lfs_file_read(&lfs, &file, buffer, size) => size;
  282. memcmp(buffer, "hedgehoghog", size) => 0;
  283. lfs_file_sync(&lfs, &file) => 0;
  284. // read @ 0
  285. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
  286. lfs_file_read(&lfs, &file, buffer, size) => size;
  287. memcmp(buffer, "kittycatcat", size) => 0;
  288. // read @ offset
  289. lfs_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
  290. lfs_file_read(&lfs, &file, buffer, size) => size;
  291. memcmp(buffer, "hedgehoghog", size) => 0;
  292. }
  293. lfs_file_close(&lfs, &file) => 0;
  294. lfs_unmount(&lfs) => 0;
  295. '''
  296. # out of bounds seek
  297. [cases.test_seek_out_of_bounds]
  298. defines = [
  299. {COUNT=132, SKIP=4},
  300. {COUNT=132, SKIP=128},
  301. {COUNT=200, SKIP=10},
  302. {COUNT=200, SKIP=100},
  303. {COUNT=4, SKIP=2},
  304. {COUNT=4, SKIP=3},
  305. ]
  306. code = '''
  307. lfs_t lfs;
  308. lfs_format(&lfs, cfg) => 0;
  309. lfs_mount(&lfs, cfg) => 0;
  310. lfs_file_t file;
  311. lfs_file_open(&lfs, &file, "kitty",
  312. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  313. size_t size = strlen("kittycatcat");
  314. uint8_t buffer[1024];
  315. memcpy(buffer, "kittycatcat", size);
  316. for (int j = 0; j < COUNT; j++) {
  317. lfs_file_write(&lfs, &file, buffer, size);
  318. }
  319. lfs_file_close(&lfs, &file) => 0;
  320. lfs_unmount(&lfs) => 0;
  321. lfs_mount(&lfs, cfg) => 0;
  322. lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
  323. size = strlen("kittycatcat");
  324. lfs_file_size(&lfs, &file) => COUNT*size;
  325. lfs_file_seek(&lfs, &file, (COUNT+SKIP)*size,
  326. LFS_SEEK_SET) => (COUNT+SKIP)*size;
  327. lfs_file_read(&lfs, &file, buffer, size) => 0;
  328. memcpy(buffer, "porcupineee", size);
  329. lfs_file_write(&lfs, &file, buffer, size) => size;
  330. lfs_file_seek(&lfs, &file, (COUNT+SKIP)*size,
  331. LFS_SEEK_SET) => (COUNT+SKIP)*size;
  332. lfs_file_read(&lfs, &file, buffer, size) => size;
  333. memcmp(buffer, "porcupineee", size) => 0;
  334. lfs_file_seek(&lfs, &file, COUNT*size,
  335. LFS_SEEK_SET) => COUNT*size;
  336. lfs_file_read(&lfs, &file, buffer, size) => size;
  337. memcmp(buffer, "\0\0\0\0\0\0\0\0\0\0\0", size) => 0;
  338. lfs_file_seek(&lfs, &file, -((COUNT+SKIP)*size),
  339. LFS_SEEK_CUR) => LFS_ERR_INVAL;
  340. lfs_file_tell(&lfs, &file) => (COUNT+1)*size;
  341. lfs_file_seek(&lfs, &file, -((COUNT+2*SKIP)*size),
  342. LFS_SEEK_END) => LFS_ERR_INVAL;
  343. lfs_file_tell(&lfs, &file) => (COUNT+1)*size;
  344. lfs_file_close(&lfs, &file) => 0;
  345. lfs_unmount(&lfs) => 0;
  346. '''
  347. # inline write and seek
  348. [cases.test_seek_inline_write]
  349. defines.SIZE = [2, 4, 128, 132]
  350. code = '''
  351. lfs_t lfs;
  352. lfs_format(&lfs, cfg) => 0;
  353. lfs_mount(&lfs, cfg) => 0;
  354. lfs_file_t file;
  355. lfs_file_open(&lfs, &file, "tinykitty",
  356. LFS_O_RDWR | LFS_O_CREAT) => 0;
  357. int j = 0;
  358. int k = 0;
  359. uint8_t buffer[1024];
  360. memcpy(buffer, "abcdefghijklmnopqrstuvwxyz", 26);
  361. for (unsigned i = 0; i < SIZE; i++) {
  362. lfs_file_write(&lfs, &file, &buffer[j++ % 26], 1) => 1;
  363. lfs_file_tell(&lfs, &file) => i+1;
  364. lfs_file_size(&lfs, &file) => i+1;
  365. }
  366. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
  367. lfs_file_tell(&lfs, &file) => 0;
  368. lfs_file_size(&lfs, &file) => SIZE;
  369. for (unsigned i = 0; i < SIZE; i++) {
  370. uint8_t c;
  371. lfs_file_read(&lfs, &file, &c, 1) => 1;
  372. c => buffer[k++ % 26];
  373. }
  374. lfs_file_sync(&lfs, &file) => 0;
  375. lfs_file_tell(&lfs, &file) => SIZE;
  376. lfs_file_size(&lfs, &file) => SIZE;
  377. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
  378. for (unsigned i = 0; i < SIZE; i++) {
  379. lfs_file_write(&lfs, &file, &buffer[j++ % 26], 1) => 1;
  380. lfs_file_tell(&lfs, &file) => i+1;
  381. lfs_file_size(&lfs, &file) => SIZE;
  382. lfs_file_sync(&lfs, &file) => 0;
  383. lfs_file_tell(&lfs, &file) => i+1;
  384. lfs_file_size(&lfs, &file) => SIZE;
  385. if (i < SIZE-2) {
  386. uint8_t c[3];
  387. lfs_file_seek(&lfs, &file, -1, LFS_SEEK_CUR) => i;
  388. lfs_file_read(&lfs, &file, &c, 3) => 3;
  389. lfs_file_tell(&lfs, &file) => i+3;
  390. lfs_file_size(&lfs, &file) => SIZE;
  391. lfs_file_seek(&lfs, &file, i+1, LFS_SEEK_SET) => i+1;
  392. lfs_file_tell(&lfs, &file) => i+1;
  393. lfs_file_size(&lfs, &file) => SIZE;
  394. }
  395. }
  396. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET) => 0;
  397. lfs_file_tell(&lfs, &file) => 0;
  398. lfs_file_size(&lfs, &file) => SIZE;
  399. for (unsigned i = 0; i < SIZE; i++) {
  400. uint8_t c;
  401. lfs_file_read(&lfs, &file, &c, 1) => 1;
  402. c => buffer[k++ % 26];
  403. }
  404. lfs_file_sync(&lfs, &file) => 0;
  405. lfs_file_tell(&lfs, &file) => SIZE;
  406. lfs_file_size(&lfs, &file) => SIZE;
  407. lfs_file_close(&lfs, &file) => 0;
  408. lfs_unmount(&lfs) => 0;
  409. '''
  410. # file seek and write with power-loss
  411. [cases.test_seek_reentrant_write]
  412. # must be power-of-2 for quadratic probing to be exhaustive
  413. defines.COUNT = [4, 64, 128]
  414. reentrant = true
  415. defines.POWERLOSS_BEHAVIOR = [
  416. 'LFS_EMUBD_POWERLOSS_NOOP',
  417. 'LFS_EMUBD_POWERLOSS_OOO',
  418. ]
  419. code = '''
  420. lfs_t lfs;
  421. int err = lfs_mount(&lfs, cfg);
  422. if (err) {
  423. lfs_format(&lfs, cfg) => 0;
  424. lfs_mount(&lfs, cfg) => 0;
  425. }
  426. lfs_file_t file;
  427. uint8_t buffer[1024];
  428. err = lfs_file_open(&lfs, &file, "kitty", LFS_O_RDONLY);
  429. assert(!err || err == LFS_ERR_NOENT);
  430. if (!err) {
  431. if (lfs_file_size(&lfs, &file) != 0) {
  432. lfs_file_size(&lfs, &file) => 11*COUNT;
  433. for (int j = 0; j < COUNT; j++) {
  434. memset(buffer, 0, 11+1);
  435. lfs_file_read(&lfs, &file, buffer, 11) => 11;
  436. assert(memcmp(buffer, "kittycatcat", 11) == 0 ||
  437. memcmp(buffer, "doggodogdog", 11) == 0);
  438. }
  439. }
  440. lfs_file_close(&lfs, &file) => 0;
  441. }
  442. lfs_file_open(&lfs, &file, "kitty", LFS_O_WRONLY | LFS_O_CREAT) => 0;
  443. if (lfs_file_size(&lfs, &file) == 0) {
  444. for (int j = 0; j < COUNT; j++) {
  445. strcpy((char*)buffer, "kittycatcat");
  446. size_t size = strlen((char*)buffer);
  447. lfs_file_write(&lfs, &file, buffer, size) => size;
  448. }
  449. }
  450. lfs_file_close(&lfs, &file) => 0;
  451. strcpy((char*)buffer, "doggodogdog");
  452. size_t size = strlen((char*)buffer);
  453. lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
  454. lfs_file_size(&lfs, &file) => COUNT*size;
  455. // seek and write using quadratic probing to touch all
  456. // 11-byte words in the file
  457. lfs_off_t off = 0;
  458. for (int j = 0; j < COUNT; j++) {
  459. off = (5*off + 1) % COUNT;
  460. lfs_file_seek(&lfs, &file, off*size, LFS_SEEK_SET) => off*size;
  461. lfs_file_read(&lfs, &file, buffer, size) => size;
  462. assert(memcmp(buffer, "kittycatcat", size) == 0 ||
  463. memcmp(buffer, "doggodogdog", size) == 0);
  464. if (memcmp(buffer, "doggodogdog", size) != 0) {
  465. lfs_file_seek(&lfs, &file, off*size, LFS_SEEK_SET) => off*size;
  466. strcpy((char*)buffer, "doggodogdog");
  467. lfs_file_write(&lfs, &file, buffer, size) => size;
  468. lfs_file_seek(&lfs, &file, off*size, LFS_SEEK_SET) => off*size;
  469. lfs_file_read(&lfs, &file, buffer, size) => size;
  470. assert(memcmp(buffer, "doggodogdog", size) == 0);
  471. lfs_file_sync(&lfs, &file) => 0;
  472. lfs_file_seek(&lfs, &file, off*size, LFS_SEEK_SET) => off*size;
  473. lfs_file_read(&lfs, &file, buffer, size) => size;
  474. assert(memcmp(buffer, "doggodogdog", size) == 0);
  475. }
  476. }
  477. lfs_file_close(&lfs, &file) => 0;
  478. lfs_file_open(&lfs, &file, "kitty", LFS_O_RDWR) => 0;
  479. lfs_file_size(&lfs, &file) => COUNT*size;
  480. for (int j = 0; j < COUNT; j++) {
  481. lfs_file_read(&lfs, &file, buffer, size) => size;
  482. assert(memcmp(buffer, "doggodogdog", size) == 0);
  483. }
  484. lfs_file_close(&lfs, &file) => 0;
  485. lfs_unmount(&lfs) => 0;
  486. '''
  487. # test possible overflow/underflow conditions
  488. #
  489. # note these need -fsanitize=undefined to consistently detect
  490. # overflow/underflow conditions
  491. [cases.test_seek_filemax]
  492. code = '''
  493. lfs_t lfs;
  494. lfs_format(&lfs, cfg) => 0;
  495. lfs_mount(&lfs, cfg) => 0;
  496. lfs_file_t file;
  497. lfs_file_open(&lfs, &file, "kitty",
  498. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  499. uint8_t buffer[1024];
  500. strcpy((char*)buffer, "kittycatcat");
  501. size_t size = strlen((char*)buffer);
  502. lfs_file_write(&lfs, &file, buffer, size) => size;
  503. // seek with LFS_SEEK_SET
  504. lfs_file_seek(&lfs, &file, LFS_FILE_MAX, LFS_SEEK_SET) => LFS_FILE_MAX;
  505. // seek with LFS_SEEK_CUR
  506. lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => LFS_FILE_MAX;
  507. // the file hasn't changed size, so seek end takes us back to the offset=0
  508. lfs_file_seek(&lfs, &file, +10, LFS_SEEK_END) => size+10;
  509. lfs_file_close(&lfs, &file) => 0;
  510. lfs_unmount(&lfs) => 0;
  511. '''
  512. [cases.test_seek_underflow]
  513. code = '''
  514. lfs_t lfs;
  515. lfs_format(&lfs, cfg) => 0;
  516. lfs_mount(&lfs, cfg) => 0;
  517. lfs_file_t file;
  518. lfs_file_open(&lfs, &file, "kitty",
  519. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  520. uint8_t buffer[1024];
  521. strcpy((char*)buffer, "kittycatcat");
  522. size_t size = strlen((char*)buffer);
  523. lfs_file_write(&lfs, &file, buffer, size) => size;
  524. // underflow with LFS_SEEK_CUR, should error
  525. lfs_file_seek(&lfs, &file, -(size+10), LFS_SEEK_CUR) => LFS_ERR_INVAL;
  526. lfs_file_seek(&lfs, &file, -LFS_FILE_MAX, LFS_SEEK_CUR) => LFS_ERR_INVAL;
  527. lfs_file_seek(&lfs, &file, -(size+LFS_FILE_MAX), LFS_SEEK_CUR)
  528. => LFS_ERR_INVAL;
  529. // underflow with LFS_SEEK_END, should error
  530. lfs_file_seek(&lfs, &file, -(size+10), LFS_SEEK_END) => LFS_ERR_INVAL;
  531. lfs_file_seek(&lfs, &file, -LFS_FILE_MAX, LFS_SEEK_END) => LFS_ERR_INVAL;
  532. lfs_file_seek(&lfs, &file, -(size+LFS_FILE_MAX), LFS_SEEK_END)
  533. => LFS_ERR_INVAL;
  534. // file pointer should not have changed
  535. lfs_file_tell(&lfs, &file) => size;
  536. lfs_file_close(&lfs, &file) => 0;
  537. lfs_unmount(&lfs) => 0;
  538. '''
  539. [cases.test_seek_overflow]
  540. code = '''
  541. lfs_t lfs;
  542. lfs_format(&lfs, cfg) => 0;
  543. lfs_mount(&lfs, cfg) => 0;
  544. lfs_file_t file;
  545. lfs_file_open(&lfs, &file, "kitty",
  546. LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
  547. uint8_t buffer[1024];
  548. strcpy((char*)buffer, "kittycatcat");
  549. size_t size = strlen((char*)buffer);
  550. lfs_file_write(&lfs, &file, buffer, size) => size;
  551. // seek to LFS_FILE_MAX
  552. lfs_file_seek(&lfs, &file, LFS_FILE_MAX, LFS_SEEK_SET) => LFS_FILE_MAX;
  553. // overflow with LFS_SEEK_CUR, should error
  554. lfs_file_seek(&lfs, &file, +10, LFS_SEEK_CUR) => LFS_ERR_INVAL;
  555. lfs_file_seek(&lfs, &file, +LFS_FILE_MAX, LFS_SEEK_CUR) => LFS_ERR_INVAL;
  556. // LFS_SEEK_SET/END don't care about the current file position, but we can
  557. // still overflow with a large offset
  558. // overflow with LFS_SEEK_SET, should error
  559. lfs_file_seek(&lfs, &file,
  560. +((uint32_t)LFS_FILE_MAX+10),
  561. LFS_SEEK_SET) => LFS_ERR_INVAL;
  562. lfs_file_seek(&lfs, &file,
  563. +((uint32_t)LFS_FILE_MAX+(uint32_t)LFS_FILE_MAX),
  564. LFS_SEEK_SET) => LFS_ERR_INVAL;
  565. // overflow with LFS_SEEK_END, should error
  566. lfs_file_seek(&lfs, &file, +(LFS_FILE_MAX-size+10), LFS_SEEK_END)
  567. => LFS_ERR_INVAL;
  568. lfs_file_seek(&lfs, &file, +(LFS_FILE_MAX-size+LFS_FILE_MAX), LFS_SEEK_END)
  569. => LFS_ERR_INVAL;
  570. // file pointer should not have changed
  571. lfs_file_tell(&lfs, &file) => LFS_FILE_MAX;
  572. lfs_file_close(&lfs, &file) => 0;
  573. lfs_unmount(&lfs) => 0;
  574. '''