lib_ringfs_tests.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. * Copyright © 2014 Kosma Moczek <kosma@cloudyourcar.com>
  3. * This program is free software. It comes without any warranty, to the extent
  4. * permitted by applicable law. You can redistribute it and/or modify it under
  5. * the terms of the Do What The Fuck You Want To Public License, Version 2, as
  6. * published by Sam Hocevar. See the COPYING file for more details.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <stdbool.h>
  11. #include <string.h>
  12. //#include <check.h>
  13. #include "lib_ringfs.h"
  14. #include "flash_ram.h"
  15. /* Flashsim tests. */
  16. START_TEST(test_flash_ram)
  17. {
  18. printf("# test_flash_ram\n");
  19. struct flash_ram *smallsim = flash_ram_open("tests/test.sim", 1024, 16);
  20. uint8_t buf[48];
  21. uint8_t data[16];
  22. flash_ram_sector_erase(smallsim, 0);
  23. flash_ram_sector_erase(smallsim, 16);
  24. flash_ram_sector_erase(smallsim, 32);
  25. memset(data, 0x5a, 16);
  26. flash_ram_program(smallsim, 16, data, 16);
  27. flash_ram_read(smallsim, 0, buf, 48);
  28. for (int i=0; i<16; i++)
  29. ck_assert_int_eq(buf[i], 0xff);
  30. for (int i=16; i<32; i++)
  31. ck_assert_int_eq(buf[i], 0x5a);
  32. for (int i=32; i<48; i++)
  33. ck_assert_int_eq(buf[i], 0xff);
  34. memset(data, 0x01, 16);
  35. flash_ram_program(smallsim, 0, data, 16);
  36. memset(data, 0x10, 16);
  37. flash_ram_program(smallsim, 32, data, 16);
  38. flash_ram_sector_erase(smallsim, 16);
  39. flash_ram_read(smallsim, 0, buf, 48);
  40. for (int i=0; i<16; i++)
  41. ck_assert_int_eq(buf[i], 0x01);
  42. for (int i=16; i<32; i++)
  43. ck_assert_int_eq(buf[i], 0xff);
  44. for (int i=32; i<48; i++)
  45. ck_assert_int_eq(buf[i], 0x10);
  46. free(smallsim);
  47. }
  48. END_TEST
  49. /* Flash simulator + MTD partition fixture. */
  50. static struct flash_ram *sim;
  51. static int op_sector_erase(struct ringfs_flash_partition *flash, int address)
  52. {
  53. (void) flash;
  54. flash_ram_sector_erase(sim, address);
  55. return 0;
  56. }
  57. static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size)
  58. {
  59. (void) flash;
  60. flash_ram_program(sim, address, data, size);
  61. return size;
  62. }
  63. static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size)
  64. {
  65. (void) flash;
  66. flash_ram_read(sim, address, data, size);
  67. return size;
  68. }
  69. /*
  70. * A really small filesystem: 3 slots per sector, 15 slots total.
  71. * Has the benefit of causing frequent wraparounds, potentially finding
  72. * more bugs.
  73. */
  74. static struct ringfs_flash_partition flash = {
  75. .sector_size = 32,
  76. .sector_offset = 4,
  77. .sector_count = 6,
  78. .sector_erase = op_sector_erase,
  79. .program = op_program,
  80. .read = op_read,
  81. };
  82. static void fixture_flash_ram_setup(void)
  83. {
  84. sim = flash_ram_open("tests/ringfs.sim",
  85. flash.sector_size * (flash.sector_offset + flash.sector_count),
  86. flash.sector_size);
  87. }
  88. static void fixture_flash_ram_teardown(void)
  89. {
  90. flash_ram_close(sim);
  91. sim = NULL;
  92. }
  93. /* RingFS tests. */
  94. #define DEFAULT_VERSION 0x000000042
  95. typedef int object_t;
  96. #define SECTOR_HEADER_SIZE 8
  97. #define SLOT_HEADER_SIZE 4
  98. static void assert_loc_equiv_to_offset(const struct ringfs *fs, const struct ringfs_loc *loc, int offset)
  99. {
  100. int loc_offset = loc->sector * fs->slots_per_sector + loc->slot;
  101. ck_assert_int_eq(offset, loc_offset);
  102. }
  103. static void assert_scan_integrity(const struct ringfs *fs)
  104. {
  105. struct ringfs newfs;
  106. ringfs_init(&newfs, fs->flash, fs->version, fs->object_size);
  107. ck_assert(ringfs_scan(&newfs) == 0);
  108. ck_assert_int_eq(newfs.read.sector, fs->read.sector);
  109. ck_assert_int_eq(newfs.read.slot, fs->read.slot);
  110. ck_assert_int_eq(newfs.write.sector, fs->write.sector);
  111. ck_assert_int_eq(newfs.write.slot, fs->write.slot);
  112. }
  113. START_TEST(test_ringfs_format)
  114. {
  115. printf("# test_ringfs_format\n");
  116. struct ringfs fs1;
  117. printf("## ringfs_init()\n");
  118. ringfs_init(&fs1, &flash, DEFAULT_VERSION, sizeof(object_t));
  119. printf("## ringfs_format()\n");
  120. ringfs_format(&fs1);
  121. }
  122. END_TEST
  123. START_TEST(test_ringfs_scan)
  124. {
  125. printf("# test_ringfs_scan\n");
  126. /* first format a filesystem */
  127. struct ringfs fs1;
  128. printf("## ringfs_init()\n");
  129. ringfs_init(&fs1, &flash, DEFAULT_VERSION, sizeof(object_t));
  130. printf("## ringfs_format()\n");
  131. ringfs_format(&fs1);
  132. /* now try to scan it */
  133. struct ringfs fs2;
  134. printf("## ringfs_init()\n");
  135. ringfs_init(&fs2, &flash, DEFAULT_VERSION, sizeof(object_t));
  136. printf("## ringfs_scan()\n");
  137. ck_assert(ringfs_scan(&fs2) == 0);
  138. /* this is an empty FS, should start with this: */
  139. ck_assert_int_eq(fs2.slots_per_sector, (flash.sector_size-SECTOR_HEADER_SIZE)/(SLOT_HEADER_SIZE+sizeof(object_t)));
  140. assert_loc_equiv_to_offset(&fs2, &fs2.read, 0);
  141. assert_loc_equiv_to_offset(&fs2, &fs2.cursor, 0);
  142. assert_loc_equiv_to_offset(&fs2, &fs2.write, 0);
  143. /* now insert some objects */
  144. ck_assert(ringfs_append(&fs2, (int[]) { 0x11 }) == 0);
  145. ck_assert(ringfs_append(&fs2, (int[]) { 0x22 }) == 0);
  146. ck_assert(ringfs_append(&fs2, (int[]) { 0x33 }) == 0);
  147. /* rescan */
  148. printf("## ringfs_scan()\n");
  149. ck_assert(ringfs_scan(&fs2) == 0);
  150. /* make sure the objects are there */
  151. ck_assert(ringfs_count_exact(&fs2) == 3);
  152. /* scan should fail if we supply a different version */
  153. struct ringfs fs3;
  154. printf("## ringfs_init()\n");
  155. ringfs_init(&fs3, &flash, DEFAULT_VERSION+1, sizeof(object_t));
  156. printf("## ringfs_scan()\n");
  157. ck_assert(ringfs_scan(&fs3) != 0);
  158. }
  159. END_TEST
  160. START_TEST(test_ringfs_append)
  161. {
  162. printf("# test_ringfs_append\n");
  163. /* first format a filesystem */
  164. int obj;
  165. struct ringfs fs;
  166. printf("## ringfs_init()\n");
  167. ringfs_init(&fs, &flash, DEFAULT_VERSION, sizeof(object_t));
  168. printf("## ringfs_format()\n");
  169. ringfs_format(&fs);
  170. /* fetches before appends should not change anything */
  171. for (int i=0; i<3; i++) {
  172. printf("## ringfs_fetch()\n");
  173. ck_assert(ringfs_fetch(&fs, &obj) < 0);
  174. }
  175. assert_loc_equiv_to_offset(&fs, &fs.read, 0);
  176. assert_loc_equiv_to_offset(&fs, &fs.write, 0);
  177. assert_loc_equiv_to_offset(&fs, &fs.cursor, 0);
  178. assert_scan_integrity(&fs);
  179. /* now we're brave and we write some data */
  180. for (int i=0; i<3; i++) {
  181. printf("## ringfs_append()\n");
  182. ringfs_append(&fs, (int[]) { 0x11*(i+1) });
  183. /* make sure the write head has advanced */
  184. assert_loc_equiv_to_offset(&fs, &fs.write, i+1);
  185. assert_scan_integrity(&fs);
  186. }
  187. /* now we fetch at it. */
  188. for (int i=0; i<3; i++) {
  189. printf("## ringfs_fetch()\n");
  190. ck_assert(ringfs_fetch(&fs, &obj) == 0);
  191. ck_assert_int_eq(obj, 0x11*(i+1));
  192. /* make sure the cursor head has advanced */
  193. assert_loc_equiv_to_offset(&fs, &fs.cursor, i+1);
  194. }
  195. /* there should be no data left */
  196. ck_assert(ringfs_fetch(&fs, &obj) < 0);
  197. /* test the rewind. */
  198. ck_assert(ringfs_rewind(&fs) == 0);
  199. assert_loc_equiv_to_offset(&fs, &fs.cursor, 0);
  200. /* try to read the objects once again. */
  201. for (int i=0; i<3; i++) {
  202. printf("## ringfs_fetch()\n");
  203. ck_assert(ringfs_fetch(&fs, &obj) == 0);
  204. ck_assert_int_eq(obj, 0x11*(i+1));
  205. }
  206. }
  207. END_TEST
  208. START_TEST(test_ringfs_discard)
  209. {
  210. printf("# test_ringfs_discard\n");
  211. struct ringfs fs;
  212. printf("## ringfs_init()\n");
  213. ringfs_init(&fs, &flash, DEFAULT_VERSION, sizeof(object_t));
  214. printf("## ringfs_format()\n");
  215. ringfs_format(&fs);
  216. /* write some records */
  217. for (int i=0; i<4; i++) {
  218. printf("## ringfs_append()\n");
  219. ringfs_append(&fs, (int[]) { 0x11*(i+1) });
  220. assert_scan_integrity(&fs);
  221. }
  222. /* read some of them */
  223. int obj;
  224. for (int i=0; i<2; i++) {
  225. printf("## ringfs_fetch()\n");
  226. ck_assert(ringfs_fetch(&fs, &obj) == 0);
  227. ck_assert_int_eq(obj, 0x11*(i+1));
  228. }
  229. /* discard whatever was read */
  230. ck_assert(ringfs_discard(&fs) == 0);
  231. assert_scan_integrity(&fs);
  232. /* make sure we're consistent */
  233. assert_loc_equiv_to_offset(&fs, &fs.read, 2);
  234. assert_loc_equiv_to_offset(&fs, &fs.cursor, 2);
  235. assert_loc_equiv_to_offset(&fs, &fs.write, 4);
  236. /* read the rest of the records */
  237. for (int i=2; i<4; i++) {
  238. printf("## ringfs_fetch()\n");
  239. ck_assert(ringfs_fetch(&fs, &obj) == 0);
  240. ck_assert_int_eq(obj, 0x11*(i+1));
  241. }
  242. /* discard them */
  243. ck_assert(ringfs_discard(&fs) == 0);
  244. assert_loc_equiv_to_offset(&fs, &fs.read, 4);
  245. assert_loc_equiv_to_offset(&fs, &fs.cursor, 4);
  246. assert_loc_equiv_to_offset(&fs, &fs.write, 4);
  247. assert_scan_integrity(&fs);
  248. }
  249. END_TEST
  250. START_TEST(test_ringfs_capacity)
  251. {
  252. printf("# test_ringfs_capacity\n");
  253. struct ringfs fs;
  254. ringfs_init(&fs, &flash, DEFAULT_VERSION, sizeof(object_t));
  255. int slots_per_sector = (flash.sector_size-SECTOR_HEADER_SIZE)/(SLOT_HEADER_SIZE+sizeof(object_t));
  256. int sectors = flash.sector_count;
  257. ck_assert_int_eq(ringfs_capacity(&fs), (sectors-1) * slots_per_sector);
  258. }
  259. END_TEST
  260. START_TEST(test_ringfs_count)
  261. {
  262. printf("# test_ringfs_count\n");
  263. int obj;
  264. struct ringfs fs;
  265. ringfs_init(&fs, &flash, DEFAULT_VERSION, sizeof(object_t));
  266. ringfs_format(&fs);
  267. ck_assert(ringfs_count_exact(&fs) == 0);
  268. printf("## write some records\n");
  269. for (int i=0; i<10; i++)
  270. ringfs_append(&fs, (int[]) { 0x11*(i+1) });
  271. ck_assert_int_eq(ringfs_count_exact(&fs), 10);
  272. ck_assert_int_eq(ringfs_count_estimate(&fs), 10);
  273. printf("## rescan\n");
  274. ck_assert(ringfs_scan(&fs) == 0);
  275. ck_assert_int_eq(ringfs_count_exact(&fs), 10);
  276. ck_assert_int_eq(ringfs_count_estimate(&fs), 10);
  277. printf("## append more records\n");
  278. for (int i=10; i<13; i++)
  279. ringfs_append(&fs, (int[]) { 0x11*(i+1) });
  280. ck_assert_int_eq(ringfs_count_exact(&fs), 13);
  281. ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
  282. printf("## fetch some objects without discard\n");
  283. for (int i=0; i<4; i++) {
  284. ck_assert(ringfs_fetch(&fs, &obj) == 0);
  285. ck_assert_int_eq(obj, 0x11*(i+1));
  286. }
  287. ck_assert_int_eq(ringfs_count_exact(&fs), 13);
  288. ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
  289. printf("## rescan\n");
  290. ck_assert(ringfs_scan(&fs) == 0);
  291. ck_assert_int_eq(ringfs_count_exact(&fs), 13);
  292. ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
  293. printf("## fetch some objects with discard\n");
  294. for (int i=0; i<4; i++) {
  295. ck_assert(ringfs_fetch(&fs, &obj) == 0);
  296. ck_assert_int_eq(obj, 0x11*(i+1));
  297. }
  298. ck_assert_int_eq(ringfs_count_exact(&fs), 13);
  299. ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
  300. ck_assert(ringfs_discard(&fs) == 0);
  301. ck_assert_int_eq(ringfs_count_exact(&fs), 9);
  302. ck_assert_int_eq(ringfs_count_estimate(&fs), 9);
  303. printf("## fill the segment\n");
  304. int count = fs.slots_per_sector - 1;
  305. for (int i=0; i<count; i++)
  306. ringfs_append(&fs, (int[]) { 0x42 });
  307. ck_assert_int_eq(ringfs_count_exact(&fs), 9+count);
  308. ck_assert_int_eq(ringfs_count_estimate(&fs), 9+count);
  309. printf("## extra synthetic tests for estimation\n");
  310. /* wrapping around */
  311. fs.read = (struct ringfs_loc) { fs.flash->sector_count - 1, fs.slots_per_sector - 1 };
  312. fs.write = (struct ringfs_loc) { 0, 0 };
  313. ck_assert_int_eq(ringfs_count_estimate(&fs), 1);
  314. }
  315. END_TEST
  316. START_TEST(test_ringfs_overflow)
  317. {
  318. printf("# test_ringfs_overflow\n");
  319. printf("## format\n");
  320. struct ringfs fs;
  321. ringfs_init(&fs, &flash, DEFAULT_VERSION, sizeof(object_t));
  322. ringfs_format(&fs);
  323. int capacity = ringfs_capacity(&fs);
  324. printf("## fill filesystem to the brim\n");
  325. for (int i=0; i<capacity; i++)
  326. ringfs_append(&fs, (int[]) { i });
  327. ck_assert_int_eq(ringfs_count_exact(&fs), capacity);
  328. assert_scan_integrity(&fs);
  329. /* won't hurt to stress it a little bit! */
  330. for (int round=0; round<3; round++) {
  331. printf("## add one more object\n");
  332. ringfs_append(&fs, (int[]) { 0x42 });
  333. /* should kill one entire sector to make space */
  334. ck_assert_int_eq(ringfs_count_exact(&fs), capacity - fs.slots_per_sector + 1);
  335. assert_scan_integrity(&fs);
  336. printf("## fill back up to the sector capacity\n");
  337. for (int i=0; i<fs.slots_per_sector-1; i++)
  338. ringfs_append(&fs, (int[]) { i });
  339. ck_assert_int_eq(ringfs_count_exact(&fs), capacity);
  340. assert_scan_integrity(&fs);
  341. }
  342. }
  343. END_TEST
  344. Suite *ringfs_suite(void)
  345. {
  346. Suite *s = suite_create ("ringfs");
  347. TCase *tc;
  348. tc = tcase_create("flash_ram");
  349. tcase_add_test(tc, test_flash_ram);
  350. suite_add_tcase(s, tc);
  351. tc = tcase_create("ringfs");
  352. tcase_add_checked_fixture(tc, fixture_flash_ram_setup, fixture_flash_ram_teardown);
  353. tcase_add_test(tc, test_ringfs_format);
  354. tcase_add_test(tc, test_ringfs_scan);
  355. tcase_add_test(tc, test_ringfs_append);
  356. tcase_add_test(tc, test_ringfs_discard);
  357. tcase_add_test(tc, test_ringfs_capacity);
  358. tcase_add_test(tc, test_ringfs_count);
  359. tcase_add_test(tc, test_ringfs_overflow);
  360. suite_add_tcase(s, tc);
  361. return s;
  362. }
  363. int main()
  364. {
  365. int number_failed;
  366. Suite *s = ringfs_suite();
  367. SRunner *sr = srunner_create(s);
  368. srunner_run_all(sr, CK_NORMAL);
  369. number_failed = srunner_ntests_failed(sr);
  370. srunner_free(sr);
  371. return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  372. }
  373. /* vim: set ts=4 sw=4 et: */