stream_test.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. #include <furi.h>
  2. #include <toolbox/stream/stream.h>
  3. #include <toolbox/stream/string_stream.h>
  4. #include <toolbox/stream/file_stream.h>
  5. #include <storage/storage.h>
  6. #include "../minunit.h"
  7. static const char* stream_test_data = "I write differently from what I speak, "
  8. "I speak differently from what I think, "
  9. "I think differently from the way I ought to think, "
  10. "and so it all proceeds into deepest darkness.";
  11. static const char* stream_test_left_data = "There are two cardinal human sins ";
  12. static const char* stream_test_right_data =
  13. "from which all others derive: impatience and indolence.";
  14. MU_TEST_1(stream_composite_subtest, Stream* stream) {
  15. const size_t data_size = 128;
  16. uint8_t data[data_size];
  17. string_t string_lee;
  18. string_init_set(string_lee, "lee");
  19. // test that stream is empty
  20. // "" -> ""
  21. mu_check(stream_size(stream) == 0);
  22. mu_check(stream_eof(stream));
  23. mu_check(stream_tell(stream) == 0);
  24. mu_check(stream_read(stream, data, data_size) == 0);
  25. mu_check(stream_eof(stream));
  26. mu_check(stream_tell(stream) == 0);
  27. // write char
  28. // "" -> "2"
  29. mu_check(stream_write_char(stream, '2') == 1);
  30. mu_check(stream_size(stream) == 1);
  31. mu_check(stream_tell(stream) == 1);
  32. mu_check(stream_eof(stream));
  33. // test rewind and eof
  34. stream_rewind(stream);
  35. mu_check(stream_size(stream) == 1);
  36. mu_check(stream_tell(stream) == 0);
  37. mu_check(!stream_eof(stream));
  38. // add another char with replacement
  39. // "2" -> "1"
  40. mu_check(stream_write_char(stream, '1') == 1);
  41. mu_check(stream_size(stream) == 1);
  42. mu_check(stream_tell(stream) == 1);
  43. mu_check(stream_eof(stream));
  44. // write string
  45. // "1" -> "1337_69"
  46. mu_check(stream_write_cstring(stream, "337_69") == 6);
  47. mu_check(stream_size(stream) == 7);
  48. mu_check(stream_tell(stream) == 7);
  49. mu_check(stream_eof(stream));
  50. // read data
  51. memset(data, 0, data_size);
  52. stream_rewind(stream);
  53. mu_check(stream_read(stream, data, data_size) == 7);
  54. mu_check(strcmp((char*)data, "1337_69") == 0);
  55. // test misc seeks
  56. mu_check(stream_seek(stream, 2, StreamOffsetFromStart));
  57. mu_check(stream_tell(stream) == 2);
  58. mu_check(!stream_seek(stream, 9000, StreamOffsetFromStart));
  59. mu_check(stream_tell(stream) == 7);
  60. mu_check(stream_eof(stream));
  61. mu_check(stream_seek(stream, -3, StreamOffsetFromEnd));
  62. mu_check(stream_tell(stream) == 4);
  63. // write string with replacemet
  64. // "1337_69" -> "1337lee"
  65. mu_check(stream_write_string(stream, string_lee) == 3);
  66. mu_check(stream_size(stream) == 7);
  67. mu_check(stream_tell(stream) == 7);
  68. mu_check(stream_eof(stream));
  69. // append char
  70. // "1337lee" -> "1337leet"
  71. mu_check(stream_write(stream, (uint8_t*)"t", 1) == 1);
  72. mu_check(stream_size(stream) == 8);
  73. mu_check(stream_tell(stream) == 8);
  74. mu_check(stream_eof(stream));
  75. // read data
  76. memset(data, 0, data_size);
  77. stream_rewind(stream);
  78. mu_check(stream_read(stream, data, data_size) == 8);
  79. mu_check(strcmp((char*)data, "1337leet") == 0);
  80. mu_check(stream_tell(stream) == 8);
  81. mu_check(stream_eof(stream));
  82. // negative seek from current position -> clamp to 0
  83. mu_check(!stream_seek(stream, -9000, StreamOffsetFromCurrent));
  84. mu_check(stream_tell(stream) == 0);
  85. // negative seek from start position -> clamp to 0
  86. stream_rewind(stream);
  87. mu_check(!stream_seek(stream, -3, StreamOffsetFromStart));
  88. mu_check(stream_tell(stream) == 0);
  89. // zero seek from current position -> clamp to stream size
  90. mu_check(stream_seek(stream, 0, StreamOffsetFromEnd));
  91. mu_check(stream_tell(stream) == 8);
  92. // negative seek from end position -> clamp to 0
  93. mu_check(!stream_seek(stream, -9000, StreamOffsetFromEnd));
  94. mu_check(stream_tell(stream) == 0);
  95. // clean stream
  96. stream_clean(stream);
  97. mu_check(stream_size(stream) == 0);
  98. mu_check(stream_eof(stream));
  99. mu_check(stream_tell(stream) == 0);
  100. // write format
  101. // "" -> "dio666"
  102. mu_check(stream_write_format(stream, "%s%d", "dio", 666) == 6);
  103. mu_check(stream_size(stream) == 6);
  104. mu_check(stream_eof(stream));
  105. mu_check(stream_tell(stream) == 6);
  106. // read data
  107. memset(data, 0, data_size);
  108. stream_rewind(stream);
  109. mu_check(stream_read(stream, data, data_size) == 6);
  110. mu_check(strcmp((char*)data, "dio666") == 0);
  111. // clean and write cstring
  112. // "dio666" -> "" -> "1234567890"
  113. stream_clean(stream);
  114. mu_check(stream_write_cstring(stream, "1234567890") == 10);
  115. // delete 4 bytes from 1 pos
  116. // "1xxxx67890" -> "167890"
  117. mu_check(stream_seek(stream, 1, StreamOffsetFromStart));
  118. mu_check(stream_delete(stream, 4));
  119. mu_assert_int_eq(6, stream_size(stream));
  120. // read data
  121. memset(data, 0, data_size);
  122. stream_rewind(stream);
  123. mu_assert_int_eq(6, stream_read(stream, data, data_size));
  124. mu_check(strcmp((char*)data, "167890") == 0);
  125. // write cstring
  126. // "167890" -> "167890It Was Me, Dio!"
  127. mu_check(stream_write_cstring(stream, "It Was Me, Dio!") == 15);
  128. // delete 1337 bytes from 1 pos
  129. // and check that we can delete only 20 bytes
  130. // "1xxxxxxxxxxxxxxxxxxxx" -> "1"
  131. mu_check(stream_seek(stream, 1, StreamOffsetFromStart));
  132. mu_check(stream_delete(stream, 1337));
  133. mu_assert_int_eq(1, stream_size(stream));
  134. // read data
  135. memset(data, 0, data_size);
  136. stream_rewind(stream);
  137. mu_check(stream_read(stream, data, data_size) == 1);
  138. mu_check(strcmp((char*)data, "1") == 0);
  139. // write cstring from 0 pos, replacing 1 byte
  140. // "1" -> "Oh? You're roaching me?"
  141. mu_check(stream_rewind(stream));
  142. mu_assert_int_eq(23, stream_write_cstring(stream, "Oh? You're roaching me?"));
  143. // insert 11 bytes to 0 pos
  144. // "Oh? You're roaching me?" -> "Za Warudo! Oh? You're roaching me?"
  145. mu_check(stream_rewind(stream));
  146. mu_check(stream_insert(stream, (uint8_t*)"Za Warudo! ", 11));
  147. mu_assert_int_eq(34, stream_size(stream));
  148. // read data
  149. memset(data, 0, data_size);
  150. stream_rewind(stream);
  151. mu_assert_int_eq(34, stream_read(stream, data, data_size));
  152. mu_assert_string_eq("Za Warudo! Oh? You're roaching me?", (char*)data);
  153. // insert cstring to 22 pos
  154. // "Za Warudo! Oh? You're roaching me?" -> "Za Warudo! Oh? You're approaching me?"
  155. mu_check(stream_seek(stream, 22, StreamOffsetFromStart));
  156. mu_check(stream_insert_cstring(stream, "app"));
  157. mu_assert_int_eq(37, stream_size(stream));
  158. // read data
  159. memset(data, 0, data_size);
  160. stream_rewind(stream);
  161. mu_assert_int_eq(37, stream_read(stream, data, data_size));
  162. mu_assert_string_eq("Za Warudo! Oh? You're approaching me?", (char*)data);
  163. // insert cstring to the end of the stream
  164. // "Za Warudo! Oh? You're approaching me?" -> "Za Warudo! Oh? You're approaching me? It was me, Dio!"
  165. mu_check(stream_seek(stream, 0, StreamOffsetFromEnd));
  166. mu_check(stream_insert_cstring(stream, " It was me, Dio!"));
  167. mu_assert_int_eq(53, stream_size(stream));
  168. // read data
  169. memset(data, 0, data_size);
  170. stream_rewind(stream);
  171. mu_assert_int_eq(53, stream_read(stream, data, data_size));
  172. mu_assert_string_eq("Za Warudo! Oh? You're approaching me? It was me, Dio!", (char*)data);
  173. // delete 168430090 bytes from stream
  174. // and test that we can delete only 53
  175. mu_check(stream_rewind(stream));
  176. mu_check(stream_delete(stream, 0x0A0A0A0A));
  177. mu_assert_int_eq(0, stream_size(stream));
  178. mu_check(stream_eof(stream));
  179. mu_assert_int_eq(0, stream_tell(stream));
  180. // clean stream
  181. stream_clean(stream);
  182. mu_assert_int_eq(0, stream_size(stream));
  183. mu_check(stream_eof(stream));
  184. mu_assert_int_eq(0, stream_tell(stream));
  185. // insert formated string at the end of stream
  186. // "" -> "dio666"
  187. mu_check(stream_insert_format(stream, "%s%d", "dio", 666));
  188. mu_assert_int_eq(6, stream_size(stream));
  189. mu_check(stream_eof(stream));
  190. mu_assert_int_eq(6, stream_tell(stream));
  191. // insert formated string at the end of stream
  192. // "dio666" -> "dio666zlo555"
  193. mu_check(stream_insert_format(stream, "%s%d", "zlo", 555));
  194. mu_assert_int_eq(12, stream_size(stream));
  195. mu_check(stream_eof(stream));
  196. mu_assert_int_eq(12, stream_tell(stream));
  197. // insert formated string at the 6 pos
  198. // "dio666" -> "dio666baba13zlo555"
  199. mu_check(stream_seek(stream, 6, StreamOffsetFromStart));
  200. mu_check(stream_insert_format(stream, "%s%d", "baba", 13));
  201. mu_assert_int_eq(18, stream_size(stream));
  202. mu_assert_int_eq(12, stream_tell(stream));
  203. // read data
  204. memset(data, 0, data_size);
  205. stream_rewind(stream);
  206. mu_assert_int_eq(18, stream_read(stream, data, data_size));
  207. mu_assert_string_eq("dio666baba13zlo555", (char*)data);
  208. // delete 6 chars from pos 6 and insert 1 chars
  209. // "dio666baba13zlo555" -> "dio666xzlo555"
  210. mu_check(stream_seek(stream, 6, StreamOffsetFromStart));
  211. mu_check(stream_delete_and_insert_char(stream, 6, 'x'));
  212. mu_assert_int_eq(13, stream_size(stream));
  213. mu_assert_int_eq(7, stream_tell(stream));
  214. // read data
  215. memset(data, 0, data_size);
  216. stream_rewind(stream);
  217. mu_check(stream_read(stream, data, data_size) == 13);
  218. mu_assert_string_eq("dio666xzlo555", (char*)data);
  219. // delete 9000 chars from pos 6 and insert 3 chars from string
  220. // "dio666xzlo555" -> "dio666777"
  221. mu_check(stream_seek(stream, 6, StreamOffsetFromStart));
  222. mu_check(stream_delete_and_insert_cstring(stream, 9000, "777"));
  223. mu_assert_int_eq(9, stream_size(stream));
  224. mu_assert_int_eq(9, stream_tell(stream));
  225. mu_check(stream_eof(stream));
  226. string_clear(string_lee);
  227. }
  228. MU_TEST(stream_composite_test) {
  229. // test string stream
  230. Stream* stream;
  231. stream = string_stream_alloc();
  232. MU_RUN_TEST_1(stream_composite_subtest, stream);
  233. stream_free(stream);
  234. // test file stream
  235. Storage* storage = furi_record_open("storage");
  236. stream = file_stream_alloc(storage);
  237. mu_check(file_stream_open(stream, "/ext/filestream.str", FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
  238. MU_RUN_TEST_1(stream_composite_subtest, stream);
  239. stream_free(stream);
  240. furi_record_close("storage");
  241. }
  242. MU_TEST_1(stream_write_subtest, Stream* stream) {
  243. mu_assert_int_eq(strlen(stream_test_data), stream_write_cstring(stream, stream_test_data));
  244. }
  245. MU_TEST_1(stream_read_subtest, Stream* stream) {
  246. uint8_t data[256] = {0};
  247. mu_check(stream_rewind(stream));
  248. mu_assert_int_eq(strlen(stream_test_data), stream_read(stream, data, 256));
  249. mu_assert_string_eq(stream_test_data, (const char*)data);
  250. }
  251. MU_TEST(stream_write_read_save_load_test) {
  252. Stream* stream_orig = string_stream_alloc();
  253. Stream* stream_copy = string_stream_alloc();
  254. Storage* storage = furi_record_open("storage");
  255. // write, read
  256. MU_RUN_TEST_1(stream_write_subtest, stream_orig);
  257. MU_RUN_TEST_1(stream_read_subtest, stream_orig);
  258. // copy, read
  259. mu_assert_int_eq(strlen(stream_test_data), stream_copy_full(stream_orig, stream_copy));
  260. MU_RUN_TEST_1(stream_read_subtest, stream_orig);
  261. // save to file
  262. mu_check(stream_seek(stream_orig, 0, StreamOffsetFromStart));
  263. mu_assert_int_eq(
  264. strlen(stream_test_data),
  265. stream_save_to_file(stream_orig, storage, "/ext/filestream.str", FSOM_CREATE_ALWAYS));
  266. stream_free(stream_copy);
  267. stream_free(stream_orig);
  268. // load from file, read
  269. Stream* stream_new = string_stream_alloc();
  270. mu_assert_int_eq(
  271. strlen(stream_test_data),
  272. stream_load_from_file(stream_new, storage, "/ext/filestream.str"));
  273. MU_RUN_TEST_1(stream_read_subtest, stream_new);
  274. stream_free(stream_new);
  275. furi_record_close("storage");
  276. }
  277. MU_TEST_1(stream_split_subtest, Stream* stream) {
  278. stream_clean(stream);
  279. stream_write_cstring(stream, stream_test_left_data);
  280. stream_write_cstring(stream, stream_test_right_data);
  281. Stream* stream_left = string_stream_alloc();
  282. Stream* stream_right = string_stream_alloc();
  283. mu_check(stream_seek(stream, strlen(stream_test_left_data), StreamOffsetFromStart));
  284. mu_check(stream_split(stream, stream_left, stream_right));
  285. uint8_t data[256] = {0};
  286. mu_check(stream_rewind(stream_left));
  287. mu_assert_int_eq(strlen(stream_test_left_data), stream_read(stream_left, data, 256));
  288. mu_assert_string_eq(stream_test_left_data, (const char*)data);
  289. mu_check(stream_rewind(stream_right));
  290. mu_assert_int_eq(strlen(stream_test_right_data), stream_read(stream_right, data, 256));
  291. mu_assert_string_eq(stream_test_right_data, (const char*)data);
  292. stream_free(stream_right);
  293. stream_free(stream_left);
  294. }
  295. MU_TEST(stream_split_test) {
  296. // test string stream
  297. Stream* stream;
  298. stream = string_stream_alloc();
  299. MU_RUN_TEST_1(stream_split_subtest, stream);
  300. stream_free(stream);
  301. // test file stream
  302. Storage* storage = furi_record_open("storage");
  303. stream = file_stream_alloc(storage);
  304. mu_check(file_stream_open(stream, "/ext/filestream.str", FSAM_READ_WRITE, FSOM_CREATE_ALWAYS));
  305. MU_RUN_TEST_1(stream_split_subtest, stream);
  306. stream_free(stream);
  307. furi_record_close("storage");
  308. }
  309. MU_TEST_SUITE(stream_suite) {
  310. MU_RUN_TEST(stream_write_read_save_load_test);
  311. MU_RUN_TEST(stream_composite_test);
  312. MU_RUN_TEST(stream_split_test);
  313. }
  314. int run_minunit_test_stream() {
  315. MU_RUN_SUITE(stream_suite);
  316. return MU_EXIT_CODE;
  317. }