test_csv.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <assert.h>
  4. #include <stdlib.h>
  5. #include "./csv.h"
  6. #define CSV_END 0
  7. #define CSV_COL 1
  8. #define CSV_ROW 2
  9. #define CSV_ERR 3
  10. #define DO_TEST(name, options) test_parser("test" #name, options, test ## name ## _data, \
  11. sizeof(test ## name ## _data) - 1, test ## name ## _results, \
  12. CSV_COMMA, CSV_QUOTE, NULL, NULL)
  13. #define DO_TEST_CUSTOM(name, options, d, q, s, t) test_parser("custom" #name, options, custom ## name ## _data, \
  14. sizeof(custom ## name ## _data) - 1, custom ## name ## _results, d, q, s, t)
  15. struct event {
  16. int event_type;
  17. int retval;
  18. size_t size; /* Number of bytes in this event or return value from csv_fini */
  19. char *data; /* Data for this event */
  20. };
  21. struct event *event_ptr;
  22. int event_idx;
  23. size_t row, col;
  24. void
  25. fail_parser (char * test_name, char * message)
  26. {
  27. fprintf(stderr, "Parser test %s failed on event %d: %s\n", test_name, event_idx, message);
  28. exit(EXIT_FAILURE);
  29. }
  30. void
  31. fail_writer (char * test_name, char * message)
  32. {
  33. fprintf(stderr, "Writer test %s failed: %s\n", test_name, message);
  34. exit(EXIT_FAILURE);
  35. }
  36. void
  37. cb1 (void *data, size_t len, void *t)
  38. {
  39. char * test_name = t;
  40. /* Make sure we were expecting a column */
  41. if (event_ptr->event_type != CSV_COL)
  42. fail_parser(test_name, "didn't expect a column");
  43. /* Check the actual size against the expected size */
  44. if (event_ptr->size != len)
  45. fail_parser(test_name, "actual data length doesn't match expected data length");
  46. /* Check the actual data against the expected data */
  47. if ((event_ptr->data == NULL || data == NULL)) {
  48. if (event_ptr->data != data)
  49. fail_parser(test_name, "actual data doesn't match expected data");
  50. }
  51. else if (memcmp(event_ptr->data, data, len) != 0)
  52. fail_parser(test_name, "actual data doesn't match expected data");
  53. event_idx++;
  54. event_ptr++;
  55. col++;
  56. }
  57. void
  58. cb2 (int c, void *t)
  59. {
  60. char * test_name = t;
  61. /* Make sure we were expecting an the end of a row */
  62. if (event_ptr->event_type != CSV_ROW)
  63. fail_parser(test_name, "didn't expect end of row");
  64. /* Check that the row ended with the character we expected */
  65. if (event_ptr->retval != c)
  66. fail_parser(test_name, "row ended with unexpected character");
  67. event_idx++;
  68. event_ptr++;
  69. col = 1;
  70. row++;
  71. }
  72. void
  73. test_parser (char *test_name, unsigned char options, void *input, size_t len, struct event expected[],
  74. char delimiter, char quote, int (*space_func)(unsigned char), int (*term_func)(unsigned char))
  75. {
  76. int result = 0;
  77. size_t retval;
  78. struct csv_parser p;
  79. size_t size;
  80. for (size = 1; size <= len; size++) {
  81. size_t bytes_processed = 0;
  82. csv_init(&p, options);
  83. csv_set_delim(&p, delimiter);
  84. csv_set_quote(&p, quote);
  85. csv_set_space_func(&p, space_func);
  86. csv_set_term_func(&p, term_func);
  87. row = col = 1;
  88. event_ptr = &expected[0];
  89. event_idx = 1;
  90. do {
  91. size_t bytes = size < len - bytes_processed ? size : len - bytes_processed;
  92. retval = csv_parse(&p, input + bytes_processed, bytes, cb1, cb2, test_name);
  93. if (retval != bytes) {
  94. if (event_ptr->event_type != CSV_ERR) {
  95. fail_parser(test_name, "unexpected parse error occurred");
  96. } else {
  97. csv_free(&p);
  98. return;
  99. }
  100. }
  101. bytes_processed += bytes;
  102. } while (bytes_processed < len);
  103. result = csv_fini(&p, cb1, cb2, test_name);
  104. if (result != 0) {
  105. if (event_ptr->event_type != CSV_ERR) {
  106. fail_parser(test_name, "unexpected parse error occurred");
  107. } else {
  108. csv_free(&p);
  109. return;
  110. }
  111. }
  112. csv_free(&p);
  113. if (event_ptr->event_type != CSV_END)
  114. fail_parser(test_name, "unexpected end of input");
  115. }
  116. }
  117. void
  118. test_writer (char * test_name, char *input, size_t input_len, char *expected, size_t expected_len)
  119. {
  120. size_t actual_len;
  121. char *temp = malloc(input_len*2 + 2);
  122. if (!temp) {
  123. fprintf(stderr, "Failed to allocate memory in test_writer!\n");
  124. exit(EXIT_FAILURE);
  125. }
  126. actual_len = csv_write(temp, input_len*2 + 2, input, input_len);
  127. if (actual_len != expected_len)
  128. fail_writer(test_name, "actual length doesn't match expected length");
  129. if (memcmp(temp, expected, actual_len) != 0)
  130. fail_writer(test_name, "actual data doesn't match expected data");
  131. }
  132. void
  133. test_writer2 (char * test_name, char *input, size_t input_len, char *expected, size_t expected_len, char quote)
  134. {
  135. size_t actual_len;
  136. char *temp = malloc(input_len*2 + 2);
  137. if (!temp) {
  138. fprintf(stderr, "Failed to allocate memory in test_writer!\n");
  139. exit(EXIT_FAILURE);
  140. }
  141. actual_len = csv_write2(temp, input_len*2 + 2, input, input_len, quote);
  142. if (actual_len != expected_len)
  143. fail_writer(test_name, "actual length doesn't match expected length");
  144. if (memcmp(temp, expected, actual_len) != 0)
  145. fail_writer(test_name, "actual data doesn't match expected data");
  146. }
  147. int main (void) {
  148. /* Parser Tests */
  149. /* Parser tests presented here consist of two parts:
  150. 1. the raw data to be parsed as an array of char
  151. 2. the behavior expected from attempting to parse the data
  152. The latter is encapsulated into an array of struct event, each event
  153. described the type of event that was expected at that point and details
  154. of the event. There are four event types:
  155. 1. CSV_END - signifies the successful end of parsing, no events should
  156. follow in this test
  157. 2. CSV_COL - signifies that a column or CSV element is expected to be
  158. submitted to the appropriate callback function
  159. 3. CSV_ROW - specifies the end of a row has been reached
  160. 4. CSV_ERR - signifies that an error is expected at this point, no
  161. further events should follow in this test
  162. In addition to the event type, an event is also characterized by a size
  163. and a data member in the event structure. The meaning of these fields
  164. depends on the event type.
  165. The size member for CSV_COL is the size of the expected data column,
  166. for CSV_ROW is it the size of the terminating character which should
  167. always be 1. The size for CSV_END should always be zero, for CSV_ERR
  168. the size is not used.
  169. The data member represents the actual data after parsing for a CSV_COL,
  170. the terminating character for CSV_ROW (the first character of the provided
  171. char array is the one used), and is not used for CSV_END or CSV_ERR, it
  172. should be NULL in these cases.
  173. */
  174. char test01_data[] = " 1,2 , 3 ,4,5\x0d\x0a";
  175. char test02_data[] = ",,,,,\x0a";
  176. char test03_data[] = "\",\",\",\",\"\"";
  177. char test04_data[] = "\"I call our world Flatland,\x0a"
  178. "not because we call it so,\x0a"
  179. "but to make its nature clearer\x0a"
  180. "to you, my happy readers,\x0a"
  181. "who are privileged to live in Space.\"";
  182. char test05_data[] = "\"\"\"a,b\"\"\",,\" \"\"\"\" \",\"\"\"\"\" \",\" \"\"\"\"\",\"\"\"\"\"\"";
  183. char test06_data[] = "\" a, b ,c \", a b c,";
  184. char test07_data[] = "\" \"\" \" \" \"\" \"";
  185. char test07b_data[] = "\" \"\" \" \" \"\" \"";
  186. char test08_data[] = "\" abc\" "
  187. " "
  188. " "
  189. " "
  190. " "
  191. " "
  192. " "
  193. " "
  194. " \", \"123\"";
  195. char test09_data[] = "";
  196. char test10_data[] = "a\x0a";
  197. char test11_data[] = "1,2 ,3,4\x0a";
  198. char test12_data[] = "\x0a\x0a\x0a\x0a";
  199. char test12b_data[] = "\x0a\x0a\x0a\x0a";
  200. char test13_data[] = "\"abc\"";
  201. char test14_data[] = "1, 2, 3,\x0a\x0d\x0a \"4\", \x0d,";
  202. char test15_data[] = "1, 2, 3,\x0a\x0d\x0a \"4\", \x0d\"\"";
  203. char test16_data[] = "\"1\",\"2\",\" 3 ";
  204. char test16b_data[] = "\"1\",\"2\",\" 3 ";
  205. char test17_data[] = " a\0b\0c ";
  206. char test18_data[] = "12345678901234567890123456789012";
  207. char test19_data[] = " , \"\" ,";
  208. /* Custom tests */
  209. char custom01_data[] = "'''a;b''';;' '''' ';''''' ';' ''''';''''''";
  210. /* |1|2|3|4|5| */
  211. struct event test01_results[] =
  212. { {CSV_COL, 0, 1, "1"},
  213. {CSV_COL, 0, 1, "2"},
  214. {CSV_COL, 0, 1, "3"},
  215. {CSV_COL, 0, 1, "4"},
  216. {CSV_COL, 0, 1, "5"},
  217. {CSV_ROW, '\x0d', 1, NULL}, {CSV_END, 0, 0, NULL} };
  218. /* ||||||| */
  219. struct event test02_results[] =
  220. { {CSV_COL, 0, 0, ""},
  221. {CSV_COL, 0, 0, ""},
  222. {CSV_COL, 0, 0, ""},
  223. {CSV_COL, 0, 0, ""},
  224. {CSV_COL, 0, 0, ""},
  225. {CSV_COL, 0, 0, ""},
  226. {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} };
  227. /* |,|,|| */
  228. struct event test03_results[] =
  229. { {CSV_COL, 0, 1, ","},
  230. {CSV_COL, 0, 1, ","},
  231. {CSV_COL, 0, 0, ""},
  232. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  233. struct event test04_results[] =
  234. { {CSV_COL, 0, 147, "I call our world Flatland,\x0a"
  235. "not because we call it so,\x0a"
  236. "but to make its nature clearer\x0a"
  237. "to you, my happy readers,\x0a"
  238. "who are privileged to live in Space."},
  239. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  240. /* |"a,b"|| "" |"" | ""|""| */
  241. struct event test05_results[] =
  242. { {CSV_COL, 0, 5, "\"a,b\""},
  243. {CSV_COL, 0, 0, ""},
  244. {CSV_COL, 0, 4, " \"\" "},
  245. {CSV_COL, 0, 3, "\"\" "},
  246. {CSV_COL, 0, 3, " \"\""},
  247. {CSV_COL, 0, 2, "\"\""},
  248. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  249. /* | a, b ,c |a b c|| */
  250. struct event test06_results[] =
  251. { {CSV_COL, 0, 9, " a, b ,c "},
  252. {CSV_COL, 0, 6, "a b c"},
  253. {CSV_COL, 0, 0, ""},
  254. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  255. /* | " " " " | */
  256. struct event test07_results[] =
  257. { {CSV_COL, 0, 9, " \" \" \" \" "},
  258. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  259. /* Will cause error with CSV_STRICT set */
  260. struct event test07b_results[] =
  261. { {CSV_ERR, 0, 0, NULL} };
  262. struct event test08_results[] =
  263. { {CSV_COL, 0, 463, " abc\" "
  264. " "
  265. " "
  266. " "
  267. " "
  268. " "
  269. " "
  270. " "
  271. " "},
  272. {CSV_COL, 0, 3, "123"},
  273. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  274. /* empty */
  275. struct event test09_results[] =
  276. { {CSV_END, 0, 0, NULL} };
  277. /* |a| */
  278. struct event test10_results[] =
  279. { {CSV_COL, 0, 1, "a"},
  280. {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} };
  281. /* |1|2|3|4| */
  282. struct event test11_results[] =
  283. { {CSV_COL, 0, 1, "1"},
  284. {CSV_COL, 0, 1, "2"},
  285. {CSV_COL, 0, 1, "3"},
  286. {CSV_COL, 0, 1, "4"},
  287. {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} };
  288. /* empty */
  289. struct event test12_results[] =
  290. { {CSV_END, 0, 0, NULL} };
  291. /* Test CSV_REPALL_NL */
  292. struct event test12b_results[] =
  293. { {CSV_ROW, '\x0a', 1, NULL},
  294. {CSV_ROW, '\x0a', 1, NULL},
  295. {CSV_ROW, '\x0a', 1, NULL},
  296. {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} };
  297. /* |abc| */
  298. struct event test13_results[] =
  299. { {CSV_COL, 0, 3, "abc"},
  300. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  301. /* |1|2|3||
  302. |4||
  303. ||| */
  304. struct event test14_results[] =
  305. { {CSV_COL, 0, 1, "1"},
  306. {CSV_COL, 0, 1, "2"},
  307. {CSV_COL, 0, 1, "3"},
  308. {CSV_COL, 0, 0, ""},
  309. {CSV_ROW, '\x0a', 1, NULL},
  310. {CSV_COL, 0, 1, "4"},
  311. {CSV_COL, 0, 0, ""},
  312. {CSV_ROW, '\x0d', 1, NULL},
  313. {CSV_COL, 0, 0, ""},
  314. {CSV_COL, 0, 0, ""},
  315. {CSV_ROW, -1, 0, NULL}, {CSV_END, 0, 0, NULL} };
  316. /* |1|2|3||
  317. |4||
  318. || */
  319. struct event test15_results[] =
  320. { {CSV_COL, 0, 1, "1"},
  321. {CSV_COL, 0, 1, "2"},
  322. {CSV_COL, 0, 1, "3"},
  323. {CSV_COL, 0, 0, ""},
  324. {CSV_ROW, '\x0a', 1, NULL},
  325. {CSV_COL, 0, 1, "4"},
  326. {CSV_COL, 0, 0, ""},
  327. {CSV_ROW, '\x0d', 1, NULL},
  328. {CSV_COL, 0, 0, ""},
  329. {CSV_ROW, -1, 0, NULL}, {CSV_END, 0, 0, NULL} };
  330. /* |1|2| 3 | */
  331. struct event test16_results[] =
  332. { {CSV_COL, 0, 1, "1"},
  333. {CSV_COL, 0, 1, "2"},
  334. {CSV_COL, 0, 3, " 3 "},
  335. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  336. /* Will cause an error with CSV_STRICT_FINI set */
  337. struct event test16b_results[] =
  338. { {CSV_COL, 0, 1, "1"},
  339. {CSV_COL, 0, 1, "2"},
  340. {CSV_ERR, 0, 0, NULL} };
  341. /* |a\0b\0c| */
  342. struct event test17_results[] =
  343. { {CSV_COL, 0, 5, "a\0b\0c"},
  344. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  345. /* Test CSV_EMPTY_IS_NULL */
  346. struct event test19_results[] =
  347. { {CSV_COL, 0, 0, NULL},
  348. {CSV_COL, 0, 0, ""},
  349. {CSV_COL, 0, 0, NULL},
  350. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  351. /* |'a;b'|| '' |'' | ''|''| */
  352. struct event custom01_results[] =
  353. { {CSV_COL, 0, 5, "'a;b'"},
  354. {CSV_COL, 0, 0, ""},
  355. {CSV_COL, 0, 4, " '' "},
  356. {CSV_COL, 0, 3, "'' "},
  357. {CSV_COL, 0, 3, " ''"},
  358. {CSV_COL, 0, 2, "''"},
  359. {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} };
  360. DO_TEST(01, 0);
  361. DO_TEST(01, CSV_STRICT);
  362. DO_TEST(01, CSV_STRICT | CSV_EMPTY_IS_NULL);
  363. DO_TEST(02, 0);
  364. DO_TEST(02, CSV_STRICT);
  365. DO_TEST(03, 0);
  366. DO_TEST(03, CSV_STRICT);
  367. DO_TEST(04, 0);
  368. DO_TEST(04, CSV_STRICT);
  369. DO_TEST(05, 0);
  370. DO_TEST(05, CSV_STRICT);
  371. DO_TEST(05, CSV_STRICT | CSV_STRICT_FINI);
  372. DO_TEST(06, 0);
  373. DO_TEST(06, CSV_STRICT);
  374. DO_TEST(07, 0);
  375. DO_TEST(07b, CSV_STRICT);
  376. DO_TEST(08, 0);
  377. DO_TEST(09, 0);
  378. DO_TEST(09, CSV_EMPTY_IS_NULL);
  379. DO_TEST(10, 0);
  380. DO_TEST(11, 0);
  381. DO_TEST(11, CSV_EMPTY_IS_NULL);
  382. DO_TEST(12, 0);
  383. DO_TEST(12, CSV_EMPTY_IS_NULL);
  384. DO_TEST(12b, CSV_REPALL_NL);
  385. DO_TEST(12b, CSV_REPALL_NL | CSV_EMPTY_IS_NULL);
  386. DO_TEST(13, 0);
  387. DO_TEST(14, 0);
  388. DO_TEST(14, CSV_STRICT);
  389. DO_TEST(15, 0);
  390. DO_TEST(15, CSV_STRICT);
  391. DO_TEST(16, 0);
  392. DO_TEST(16, CSV_STRICT);
  393. DO_TEST(16b, CSV_STRICT | CSV_STRICT_FINI);
  394. DO_TEST(16, 0);
  395. DO_TEST(16, CSV_STRICT);
  396. DO_TEST(17, 0);
  397. DO_TEST(17, CSV_STRICT);
  398. DO_TEST(17, CSV_STRICT | CSV_EMPTY_IS_NULL);
  399. DO_TEST(19, CSV_EMPTY_IS_NULL);
  400. DO_TEST_CUSTOM(01, 0, ';', '\'', NULL, NULL);
  401. /* Writer Tests */
  402. /* The writer tests are simpler, the test_writer function is used to
  403. test the csv_write function and takes five arguments: the name of
  404. the test, the data to convert, the length of that data, the expected
  405. resulting CSV data, and the expected length of the result.
  406. */
  407. test_writer("1", "abc", 3, "\"abc\"", 5);
  408. test_writer("2", "\"\"\"\"\"\"\"\"", 8, "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"", 18);
  409. test_writer2("1", "abc", 3, "'abc'", 5, '\'');
  410. test_writer2("2", "''''''''", 8, "''''''''''''''''''", 18, '\'');
  411. puts("All tests passed");
  412. return 0;
  413. }