aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/makefile0
-rw-r--r--tests/src/csv-test.c627
2 files changed, 627 insertions, 0 deletions
diff --git a/tests/makefile b/tests/makefile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/makefile
diff --git a/tests/src/csv-test.c b/tests/src/csv-test.c
new file mode 100644
index 0000000..c99c049
--- /dev/null
+++ b/tests/src/csv-test.c
@@ -0,0 +1,627 @@
1#undef NDEBUG
2
3#include <assert.h>
4#include <setjmp.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "csv.h"
10
11#define FMEMOPEN(f, data) \
12 f = fmemopen(data, sizeof(data) - 1, "r"); \
13 assert(f != NULL)
14
15#define FMEMCLOSE(f) \
16 (void) fclose(f); \
17 f = NULL
18
19#define UNUSED(x) (void) (x)
20
21void
22test_empty_object(void)
23{
24 {
25 csv_t csv = { 0 };
26 assert(csv_nfields(&csv) == 0);
27 }
28
29 {
30 csv_t csv;
31 csv_init(&csv);
32 assert(csv_nfields(&csv) == 0);
33 }
34}
35
36void
37test_line_endings1(void)
38{
39 FILE *file = NULL;
40 csv_t csv = { 0 };
41
42 char data[] = "A,B,C\r\n"
43 "D,E,F\n";
44
45 FMEMOPEN(file, data);
46
47 assert(csv_read(&csv, file) == 3);
48 assert(csv_nfields(&csv) == 3);
49 assert(strcmp(csv_field(&csv, 0), "A") == 0);
50 assert(strcmp(csv_field(&csv, 1), "B") == 0);
51 assert(strcmp(csv_field(&csv, 2), "C") == 0);
52
53 assert(csv_read(&csv, file) == 3);
54 assert(csv_nfields(&csv) == 3);
55 assert(strcmp(csv_field(&csv, 0), "D") == 0);
56 assert(strcmp(csv_field(&csv, 1), "E") == 0);
57 assert(strcmp(csv_field(&csv, 2), "F") == 0);
58
59 assert(csv_read(&csv, file) == 0);
60
61 FMEMCLOSE(file);
62}
63
64void
65test_line_endings2(void)
66{
67 FILE *file = NULL;
68 csv_t csv = { 0 };
69
70 char data[] = "A,B,C\r\n"
71 "D,E,F";
72
73 FMEMOPEN(file, data);
74
75 assert(csv_read(&csv, file) == 3);
76 assert(csv_nfields(&csv) == 3);
77 assert(strcmp(csv_field(&csv, 0), "A") == 0);
78 assert(strcmp(csv_field(&csv, 1), "B") == 0);
79 assert(strcmp(csv_field(&csv, 2), "C") == 0);
80
81 assert(csv_read(&csv, file) == 3);
82 assert(csv_nfields(&csv) == 3);
83 assert(strcmp(csv_field(&csv, 0), "D") == 0);
84 assert(strcmp(csv_field(&csv, 1), "E") == 0);
85 assert(strcmp(csv_field(&csv, 2), "F") == 0);
86
87 assert(csv_read(&csv, file) == 0);
88
89 FMEMCLOSE(file);
90}
91
92void
93test_empty_fields(void)
94{
95 FILE *file = NULL;
96 csv_t csv = { 0 };
97
98 char data[] = "\n"
99 "\r"
100 "\r\n"
101 "\"\"\n"
102 "\"\"\r"
103 "\"\"\r\n"
104 ",\n"
105 ",\r"
106 ",\r\n"
107 "\"\",\"\"\n"
108 "\"\",\"\"\r"
109 "\"\",\"\"\r\n"
110 ",,\n"
111 ",,\r"
112 ",,\r\n"
113 "\"\",\"\",\n"
114 "\"\",\"\",\r"
115 "\"\",\"\",\r\n"
116 ",,";
117
118 FMEMOPEN(file, data);
119
120 // Line 1
121 assert(csv_read(&csv, file) == 1);
122 assert(csv_nfields(&csv) == 1);
123 assert(strcmp(csv_field(&csv, 0), "") == 0);
124
125 // Line 2
126 assert(csv_read(&csv, file) == 1);
127 assert(csv_nfields(&csv) == 1);
128 assert(strcmp(csv_field(&csv, 0), "") == 0);
129
130 // Line 3
131 assert(csv_read(&csv, file) == 1);
132 assert(csv_nfields(&csv) == 1);
133 assert(strcmp(csv_field(&csv, 0), "") == 0);
134
135 // Line 4
136 assert(csv_read(&csv, file) == 1);
137 assert(csv_nfields(&csv) == 1);
138 assert(strcmp(csv_field(&csv, 0), "") == 0);
139
140 // Line 5
141 assert(csv_read(&csv, file) == 1);
142 assert(csv_nfields(&csv) == 1);
143 assert(strcmp(csv_field(&csv, 0), "") == 0);
144
145 // Line 6
146 assert(csv_read(&csv, file) == 1);
147 assert(csv_nfields(&csv) == 1);
148 assert(strcmp(csv_field(&csv, 0), "") == 0);
149
150 // Line 7
151 assert(csv_read(&csv, file) == 2);
152 assert(csv_nfields(&csv) == 2);
153 assert(strcmp(csv_field(&csv, 0), "") == 0);
154 assert(strcmp(csv_field(&csv, 1), "") == 0);
155
156 // Line 8
157 assert(csv_read(&csv, file) == 2);
158 assert(csv_nfields(&csv) == 2);
159 assert(strcmp(csv_field(&csv, 0), "") == 0);
160 assert(strcmp(csv_field(&csv, 1), "") == 0);
161
162 // Line 9
163 assert(csv_read(&csv, file) == 2);
164 assert(csv_nfields(&csv) == 2);
165 assert(strcmp(csv_field(&csv, 0), "") == 0);
166 assert(strcmp(csv_field(&csv, 1), "") == 0);
167
168 // Line 10
169 assert(csv_read(&csv, file) == 2);
170 assert(csv_nfields(&csv) == 2);
171 assert(strcmp(csv_field(&csv, 0), "") == 0);
172 assert(strcmp(csv_field(&csv, 1), "") == 0);
173
174 // Line 11
175 assert(csv_read(&csv, file) == 2);
176 assert(csv_nfields(&csv) == 2);
177 assert(strcmp(csv_field(&csv, 0), "") == 0);
178 assert(strcmp(csv_field(&csv, 1), "") == 0);
179
180 // Line 12
181 assert(csv_read(&csv, file) == 2);
182 assert(csv_nfields(&csv) == 2);
183 assert(strcmp(csv_field(&csv, 0), "") == 0);
184 assert(strcmp(csv_field(&csv, 1), "") == 0);
185
186 // Line 13
187 assert(csv_read(&csv, file) == 3);
188 assert(csv_nfields(&csv) == 3);
189 assert(strcmp(csv_field(&csv, 0), "") == 0);
190 assert(strcmp(csv_field(&csv, 1), "") == 0);
191 assert(strcmp(csv_field(&csv, 2), "") == 0);
192
193 // Line 14
194 assert(csv_read(&csv, file) == 3);
195 assert(csv_nfields(&csv) == 3);
196 assert(strcmp(csv_field(&csv, 0), "") == 0);
197 assert(strcmp(csv_field(&csv, 1), "") == 0);
198 assert(strcmp(csv_field(&csv, 2), "") == 0);
199
200 // Line 15
201 assert(csv_read(&csv, file) == 3);
202 assert(csv_nfields(&csv) == 3);
203 assert(strcmp(csv_field(&csv, 0), "") == 0);
204 assert(strcmp(csv_field(&csv, 1), "") == 0);
205 assert(strcmp(csv_field(&csv, 2), "") == 0);
206
207 // Line 16
208 assert(csv_read(&csv, file) == 3);
209 assert(csv_nfields(&csv) == 3);
210 assert(strcmp(csv_field(&csv, 0), "") == 0);
211 assert(strcmp(csv_field(&csv, 1), "") == 0);
212 assert(strcmp(csv_field(&csv, 2), "") == 0);
213
214 // Line 17
215 assert(csv_read(&csv, file) == 3);
216 assert(csv_nfields(&csv) == 3);
217 assert(strcmp(csv_field(&csv, 0), "") == 0);
218 assert(strcmp(csv_field(&csv, 1), "") == 0);
219 assert(strcmp(csv_field(&csv, 2), "") == 0);
220
221 // Line 18
222 assert(csv_read(&csv, file) == 3);
223 assert(csv_nfields(&csv) == 3);
224 assert(strcmp(csv_field(&csv, 0), "") == 0);
225 assert(strcmp(csv_field(&csv, 1), "") == 0);
226 assert(strcmp(csv_field(&csv, 2), "") == 0);
227
228 // Line 19
229 assert(csv_read(&csv, file) == 3);
230 assert(csv_nfields(&csv) == 3);
231 assert(strcmp(csv_field(&csv, 0), "") == 0);
232 assert(strcmp(csv_field(&csv, 1), "") == 0);
233 assert(strcmp(csv_field(&csv, 2), "") == 0);
234
235 // EOF
236 assert(csv_read(&csv, file) == 0);
237
238 FMEMCLOSE(file);
239}
240
241void
242test_simple_fields(void)
243{
244 FILE *file = NULL;
245 csv_t csv = { 0 };
246
247 char data[] = "A\n"
248 "A\r"
249 "A\r\n"
250 "\"A\"\n"
251 "\"A\"\r"
252 "\"A\"\r\n"
253 "A,B\n"
254 "A,B\r"
255 "A,B\r\n"
256 "\"A\",\"B\"\n"
257 "\"A\",\"B\"\r"
258 "\"A\",\"B\"\r\n"
259 "A,B,C\n"
260 "A,B,C\r"
261 "A,B,C\r\n"
262 "\"A\",\"B\",C\n"
263 "\"A\",\"B\",C\r"
264 "\"A\",\"B\",C\r\n"
265 "A,B,C";
266
267 FMEMOPEN(file, data);
268
269 // Line 1
270 assert(csv_read(&csv, file) == 1);
271 assert(csv_nfields(&csv) == 1);
272 assert(strcmp(csv_field(&csv, 0), "A") == 0);
273
274 // Line 2
275 assert(csv_read(&csv, file) == 1);
276 assert(csv_nfields(&csv) == 1);
277 assert(strcmp(csv_field(&csv, 0), "A") == 0);
278
279 // Line 3
280 assert(csv_read(&csv, file) == 1);
281 assert(csv_nfields(&csv) == 1);
282 assert(strcmp(csv_field(&csv, 0), "A") == 0);
283
284 // Line 4
285 assert(csv_read(&csv, file) == 1);
286 assert(csv_nfields(&csv) == 1);
287 assert(strcmp(csv_field(&csv, 0), "A") == 0);
288
289 // Line 5
290 assert(csv_read(&csv, file) == 1);
291 assert(csv_nfields(&csv) == 1);
292 assert(strcmp(csv_field(&csv, 0), "A") == 0);
293
294 // Line 6
295 assert(csv_read(&csv, file) == 1);
296 assert(csv_nfields(&csv) == 1);
297 assert(strcmp(csv_field(&csv, 0), "A") == 0);
298
299 // Line 7
300 assert(csv_read(&csv, file) == 2);
301 assert(csv_nfields(&csv) == 2);
302 assert(strcmp(csv_field(&csv, 0), "A") == 0);
303 assert(strcmp(csv_field(&csv, 1), "B") == 0);
304
305 // Line 8
306 assert(csv_read(&csv, file) == 2);
307 assert(csv_nfields(&csv) == 2);
308 assert(strcmp(csv_field(&csv, 0), "A") == 0);
309 assert(strcmp(csv_field(&csv, 1), "B") == 0);
310
311 // Line 9
312 assert(csv_read(&csv, file) == 2);
313 assert(csv_nfields(&csv) == 2);
314 assert(strcmp(csv_field(&csv, 0), "A") == 0);
315 assert(strcmp(csv_field(&csv, 1), "B") == 0);
316
317 // Line 10
318 assert(csv_read(&csv, file) == 2);
319 assert(csv_nfields(&csv) == 2);
320 assert(strcmp(csv_field(&csv, 0), "A") == 0);
321 assert(strcmp(csv_field(&csv, 1), "B") == 0);
322
323 // Line 11
324 assert(csv_read(&csv, file) == 2);
325 assert(csv_nfields(&csv) == 2);
326 assert(strcmp(csv_field(&csv, 0), "A") == 0);
327 assert(strcmp(csv_field(&csv, 1), "B") == 0);
328
329 // Line 12
330 assert(csv_read(&csv, file) == 2);
331 assert(csv_nfields(&csv) == 2);
332 assert(strcmp(csv_field(&csv, 0), "A") == 0);
333 assert(strcmp(csv_field(&csv, 1), "B") == 0);
334
335 // Line 13
336 assert(csv_read(&csv, file) == 3);
337 assert(csv_nfields(&csv) == 3);
338 assert(strcmp(csv_field(&csv, 0), "A") == 0);
339 assert(strcmp(csv_field(&csv, 1), "B") == 0);
340 assert(strcmp(csv_field(&csv, 2), "C") == 0);
341
342 // Line 14
343 assert(csv_read(&csv, file) == 3);
344 assert(csv_nfields(&csv) == 3);
345 assert(strcmp(csv_field(&csv, 0), "A") == 0);
346 assert(strcmp(csv_field(&csv, 1), "B") == 0);
347 assert(strcmp(csv_field(&csv, 2), "C") == 0);
348
349 // Line 15
350 assert(csv_read(&csv, file) == 3);
351 assert(csv_nfields(&csv) == 3);
352 assert(strcmp(csv_field(&csv, 0), "A") == 0);
353 assert(strcmp(csv_field(&csv, 1), "B") == 0);
354 assert(strcmp(csv_field(&csv, 2), "C") == 0);
355
356 // Line 16
357 assert(csv_read(&csv, file) == 3);
358 assert(csv_nfields(&csv) == 3);
359 assert(strcmp(csv_field(&csv, 0), "A") == 0);
360 assert(strcmp(csv_field(&csv, 1), "B") == 0);
361 assert(strcmp(csv_field(&csv, 2), "C") == 0);
362
363 // Line 17
364 assert(csv_read(&csv, file) == 3);
365 assert(csv_nfields(&csv) == 3);
366 assert(strcmp(csv_field(&csv, 0), "A") == 0);
367 assert(strcmp(csv_field(&csv, 1), "B") == 0);
368 assert(strcmp(csv_field(&csv, 2), "C") == 0);
369
370 // Line 18
371 assert(csv_read(&csv, file) == 3);
372 assert(csv_nfields(&csv) == 3);
373 assert(strcmp(csv_field(&csv, 0), "A") == 0);
374 assert(strcmp(csv_field(&csv, 1), "B") == 0);
375 assert(strcmp(csv_field(&csv, 2), "C") == 0);
376
377 // Line 19
378 assert(csv_read(&csv, file) == 3);
379 assert(csv_nfields(&csv) == 3);
380 assert(strcmp(csv_field(&csv, 0), "A") == 0);
381 assert(strcmp(csv_field(&csv, 1), "B") == 0);
382 assert(strcmp(csv_field(&csv, 2), "C") == 0);
383
384 // EOF
385 assert(csv_read(&csv, file) == 0);
386
387 FMEMCLOSE(file);
388}
389
390void
391test_quoted_fields(void)
392{
393 FILE *file = NULL;
394 csv_t csv = { 0 };
395
396 char data[] = "foo \"baz\" bar,foo \"\"baz\"\" bar,\"foo \"\"baz\"\" bar\",\"foo \"baz\" bar\",\"foo \"\"baz\"\", bar\"";
397
398 FMEMOPEN(file, data);
399
400 assert(csv_read(&csv, file) == 5);
401 assert(csv_nfields(&csv) == 5);
402 assert(strcmp(csv_field(&csv, 0), "foo \"baz\" bar") == 0);
403 assert(strcmp(csv_field(&csv, 1), "foo \"\"baz\"\" bar") == 0);
404 assert(strcmp(csv_field(&csv, 2), "foo \"baz\" bar") == 0);
405 assert(strcmp(csv_field(&csv, 3), "foo \"baz\" bar") == 0);
406 assert(strcmp(csv_field(&csv, 4), "foo \"baz\", bar") == 0);
407
408 assert(csv_read(&csv, file) == 0);
409
410 FMEMCLOSE(file);
411}
412
413void
414test_wrong_quoted_field(void)
415{
416 FILE *file = NULL;
417 csv_t csv = { 0 };
418
419 char data[] = "\"foo";
420
421 FMEMOPEN(file, data);
422
423 assert(csv_read(&csv, file) == 1);
424 assert(csv_nfields(&csv) == 1);
425 assert(strcmp(csv_field(&csv, 0), "foo") == 0);
426
427 assert(csv_read(&csv, file) == 0);
428
429 FMEMCLOSE(file);
430}
431
432static void
433cb_error(csv_err_t err, void *cb_arg)
434{
435 longjmp(*((jmp_buf *) cb_arg), err);
436}
437
438void
439test_out_of_range_error(void)
440{
441 jmp_buf env;
442 csv_options_t csv_options = csv_default_options;
443 csv_options.cb_error = cb_error;
444 csv_options.cb_error_arg = &env;
445
446 csv_t csv;
447 csv_init_opt(&csv, &csv_options);
448
449 FILE *file = NULL;
450 char data[] = ",";
451
452 FMEMOPEN(file, data);
453
454 switch ( setjmp(env) ) {
455 case CSV_ERR_OK:
456 assert(csv_read(&csv, file) == 2);
457 assert(csv_nfields(&csv) == 2);
458
459 // force an "out of range"-Exception!
460 assert(strcmp(csv_field(&csv, 2), "will fail") == 0);
461 break;
462
463 case CSV_ERR_OUT_OF_RANGE:
464 csv_cleanup(&csv);
465 break;
466
467 default:
468 assert(!"this should not be happen!");
469 }
470
471 FMEMCLOSE(file);
472}
473
474void
475test_read_error(void)
476{
477 jmp_buf env;
478 csv_options_t csv_options = csv_default_options;
479 csv_options.cb_error = cb_error;
480 csv_options.cb_error_arg = &env;
481
482 csv_t csv;
483 csv_init_opt(&csv, &csv_options);
484
485 FILE *file = fopen("/dev/null", "r");
486 assert(file != NULL);
487 (void) fputc('T', file); // Set Error-Flag!
488
489 switch ( setjmp(env) ) {
490 case CSV_ERR_OK:
491 assert(csv_read(&csv, file) == 0);
492 break;
493
494 case CSV_ERR_IO_READ:
495 csv_cleanup(&csv);
496 break;
497
498 default:
499 assert(!"this should not be happen!");
500 }
501
502 (void) fclose(file);
503}
504
505void *
506my_allocate(size_t n, size_t size, void *cb_arg)
507{
508 UNUSED(cb_arg);
509
510 void *ptr = calloc(n, size);
511
512 return ptr;
513}
514
515void *
516my_allocate_null(size_t n, size_t size, void *cb_arg)
517{
518 UNUSED(n);
519 UNUSED(size);
520 UNUSED(cb_arg);
521
522 return NULL;
523}
524
525void *
526my_reallocate(void *ptr, size_t n, size_t size, void *cb_arg)
527{
528 UNUSED(ptr);
529 UNUSED(n);
530 UNUSED(size);
531 UNUSED(cb_arg);
532
533 return NULL;
534}
535
536void
537my_free(void *ptr, size_t n, size_t size, void *cb_arg)
538{
539 UNUSED(n);
540 UNUSED(size);
541 UNUSED(cb_arg);
542
543 free(ptr);
544}
545
546void
547test_allocation_error1(void)
548{
549 jmp_buf env;
550
551 csv_options_t csv_options = csv_default_options;
552 csv_options.cb_error = cb_error;
553 csv_options.cb_error_arg = &env;
554 csv_options.cb_allocate = my_allocate;
555 csv_options.cb_reallocate = my_reallocate;
556 csv_options.cb_free = my_free;
557
558 csv_t csv;
559 csv_init_opt(&csv, &csv_options);
560
561 char data[] = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T";
562
563 FILE *file = NULL;
564 FMEMOPEN(file, data);
565 assert(file != NULL);
566
567 switch ( setjmp(env) ) {
568 case CSV_ERR_OK:
569 assert(csv_read(&csv, file) == 20);
570 assert(!"this should not be happen!");
571 break;
572
573 case CSV_ERR_OUT_OF_MEMORY:
574 csv_cleanup(&csv);
575 break;
576
577 default:
578 assert(!"this should not be happen!");
579 }
580
581 FMEMCLOSE(file);
582}
583
584void
585show_version(void)
586{
587 const char *version = csv_version;
588
589 printf("libcsv - version: ");
590 for ( ; *version; ++version ) {
591 putchar(*version);
592 }
593
594 printf(", build date: ");
595 for ( ++version; *version; ++version ) {
596 putchar(*version);
597 }
598
599 printf(", build time: ");
600 for ( ++version; *version; ++version ) {
601 putchar(*version);
602 }
603 putchar('\n');
604}
605
606int
607main(void)
608{
609 show_version();
610
611 test_empty_object();
612 test_line_endings1();
613 test_line_endings2();
614 test_empty_fields();
615 test_simple_fields();
616 test_quoted_fields();
617 test_wrong_quoted_field();
618
619 test_out_of_range_error();
620 test_read_error();
621
622 test_allocation_error1();
623
624 puts("all tests passed...");
625
626 return EXIT_SUCCESS;
627}