1 #include <stdio.h>
2 #include <string.h>
3 #include "lib/minunit.h"
4 #include "lib/mlr_globals.h"
5 #include "lib/mlrutil.h"
6 #include "containers/lrec.h"
7 #include "containers/sllv.h"
8 #include "input/lrec_readers.h"
9 
10 int tests_run         = 0;
11 int tests_failed      = 0;
12 int assertions_run    = 0;
13 int assertions_failed = 0;
14 
15 // ----------------------------------------------------------------
test_lrec_unbacked_api()16 static char* test_lrec_unbacked_api() {
17 	lrec_t* prec = lrec_unbacked_alloc();
18 	mu_assert_lf(prec->field_count == 0);
19 
20 	lrec_put(prec, "x", "3", NO_FREE);
21 	mu_assert_lf(prec->field_count == 1);
22 	mu_assert_lf(streq(lrec_get(prec, "x"), "3"));
23 
24 	lrec_put(prec, "y", "4", NO_FREE);
25 	mu_assert_lf(prec->field_count == 2);
26 	mu_assert_lf(streq(lrec_get(prec, "x"), "3"));
27 	mu_assert_lf(streq(lrec_get(prec, "y"), "4"));
28 
29 	lrec_put(prec, "x", "5", NO_FREE);
30 	mu_assert_lf(prec->field_count == 2);
31 	mu_assert_lf(streq(lrec_get(prec, "x"), "5"));
32 	mu_assert_lf(streq(lrec_get(prec, "y"), "4"));
33 
34 	lrec_remove(prec, "x");
35 	mu_assert_lf(prec->field_count == 1);
36 	mu_assert_lf(lrec_get(prec, "x") == NULL);
37 
38 	// Non-replacing-rename case
39 	//lrec_dump_titled("Before rename", prec);
40 	lrec_rename(prec, "y", "z", FALSE);
41 	//lrec_dump_titled("After rename", prec);
42 	mu_assert_lf(prec->field_count == 1);
43 	mu_assert_lf(lrec_get(prec, "x") == NULL);
44 	mu_assert_lf(lrec_get(prec, "y") == NULL);
45 	mu_assert_lf(streq(lrec_get(prec, "z"), "4"));
46 
47 	lrec_free(prec);
48 
49 	// Replacing-rename case
50 	prec = lrec_unbacked_alloc();
51 
52 	lrec_put(prec, "x", "3", NO_FREE);
53 	lrec_put(prec, "y", "4", NO_FREE);
54 	lrec_put(prec, "z", "5", NO_FREE);
55 	mu_assert_lf(prec->field_count == 3);
56 
57 	//lrec_dump_titled("Before rename", prec);
58 	lrec_rename(prec, "y", "z", FALSE);
59 	//lrec_dump_titled("After rename", prec);
60 
61 	mu_assert_lf(prec->field_count == 2);
62 	mu_assert_lf(streq(lrec_get(prec, "x"), "3"));
63 	mu_assert_lf(lrec_get(prec, "y") == NULL);
64 	mu_assert_lf(streq(lrec_get(prec, "z"), "4"));
65 
66 	lrec_free(prec);
67 
68 	return NULL;
69 }
70 
71 // ----------------------------------------------------------------
test_lrec_dkvp_api()72 static char* test_lrec_dkvp_api() {
73 	char* line = mlr_strdup_or_die("w=2,x=3,y=4,z=5");
74 
75 	lrec_t* prec = lrec_parse_stdio_dkvp_single_sep(line, ',', '=', FALSE);
76 	mu_assert_lf(prec->field_count == 4);
77 
78 	mu_assert_lf(streq(lrec_get(prec, "w"), "2"));
79 	mu_assert_lf(streq(lrec_get(prec, "x"), "3"));
80 	mu_assert_lf(streq(lrec_get(prec, "y"), "4"));
81 	mu_assert_lf(streq(lrec_get(prec, "z"), "5"));
82 
83 	lrec_remove(prec, "w");
84 	mu_assert_lf(prec->field_count == 3);
85 	mu_assert_lf(lrec_get(prec, "w") == NULL);
86 
87 	// Non-replacing-rename case
88 	//lrec_dump_titled("Before rename", prec);
89 	lrec_rename(prec, "x", "u", FALSE);
90 	//lrec_dump_titled("After rename", prec);
91 	mu_assert_lf(prec->field_count == 3);
92 	mu_assert_lf(lrec_get(prec, "x") == NULL);
93 	mu_assert_lf(streq(lrec_get(prec, "u"), "3"));
94 
95 	// Replacing-rename case
96 	//lrec_dump_titled("Before rename", prec);
97 	lrec_rename(prec, "y", "z", FALSE);
98 	//lrec_dump_titled("After rename", prec);
99 
100 	mu_assert_lf(prec->field_count == 2);
101 	mu_assert_lf(streq(lrec_get(prec, "u"), "3"));
102 	mu_assert_lf(lrec_get(prec, "y") == NULL);
103 	mu_assert_lf(streq(lrec_get(prec, "z"), "4"));
104 
105 	lrec_free(prec);
106 
107 	return NULL;
108 }
109 
110 // ----------------------------------------------------------------
test_lrec_nidx_api()111 static char* test_lrec_nidx_api() {
112 	char* line = mlr_strdup_or_die("a,b,c,d");
113 	lrec_t* prec = lrec_parse_stdio_nidx_single_sep(line, ',', FALSE);
114 	mu_assert_lf(prec->field_count == 4);
115 
116 	mu_assert_lf(streq(lrec_get(prec, "1"), "a"));
117 	mu_assert_lf(streq(lrec_get(prec, "2"), "b"));
118 	mu_assert_lf(streq(lrec_get(prec, "3"), "c"));
119 	mu_assert_lf(streq(lrec_get(prec, "4"), "d"));
120 
121 	lrec_remove(prec, "1");
122 	mu_assert_lf(prec->field_count == 3);
123 	mu_assert_lf(lrec_get(prec, "1") == NULL);
124 
125 	// Non-replacing-rename case
126 	lrec_dump_titled("Before rename", prec);
127 	lrec_rename(prec, "2", "u", FALSE);
128 	lrec_dump_titled("After rename", prec);
129 	mu_assert_lf(prec->field_count == 3);
130 	mu_assert_lf(lrec_get(prec, "2") == NULL);
131 	mu_assert_lf(streq(lrec_get(prec, "u"), "b"));
132 
133 	// Replacing-rename case
134 	lrec_dump_titled("Before rename", prec);
135 	lrec_rename(prec, "3", "4", FALSE);
136 	lrec_dump_titled("After rename", prec);
137 
138 	mu_assert_lf(prec->field_count == 2);
139 	mu_assert_lf(streq(lrec_get(prec, "u"), "b"));
140 	mu_assert_lf(lrec_get(prec, "3") == NULL);
141 	mu_assert_lf(streq(lrec_get(prec, "4"), "c"));
142 
143 	lrec_free(prec);
144 
145 	return NULL;
146 }
147 
148 // ----------------------------------------------------------------
test_lrec_csv_api()149 static char* test_lrec_csv_api() {
150 	char* hdr_line = mlr_strdup_or_die("w,x,y,z");
151 	slls_t* hdr_fields = split_csvlite_header_line_single_ifs(hdr_line, ',', FALSE);
152 	header_keeper_t* pheader_keeper = header_keeper_alloc(hdr_line, hdr_fields);
153 
154 	char* data_line_1 = mlr_strdup_or_die("2,3,4,5");
155 	lrec_t* prec_1 = lrec_parse_stdio_csvlite_data_line_single_ifs(pheader_keeper, "test-file", 999,
156 		data_line_1, ',', FALSE, FALSE);
157 
158 	char* data_line_2 = mlr_strdup_or_die("6,7,8,9");
159 	lrec_t* prec_2 = lrec_parse_stdio_csvlite_data_line_single_ifs(pheader_keeper, "test-file", 999,
160 		data_line_2, ',', FALSE, FALSE);
161 
162 	mu_assert_lf(prec_1->field_count == 4);
163 	mu_assert_lf(prec_2->field_count == 4);
164 
165 	mu_assert_lf(streq(lrec_get(prec_1, "w"), "2"));
166 	mu_assert_lf(streq(lrec_get(prec_1, "x"), "3"));
167 	mu_assert_lf(streq(lrec_get(prec_1, "y"), "4"));
168 	mu_assert_lf(streq(lrec_get(prec_1, "z"), "5"));
169 
170 	mu_assert_lf(streq(lrec_get(prec_2, "w"), "6"));
171 	mu_assert_lf(streq(lrec_get(prec_2, "x"), "7"));
172 	mu_assert_lf(streq(lrec_get(prec_2, "y"), "8"));
173 	mu_assert_lf(streq(lrec_get(prec_2, "z"), "9"));
174 
175 	lrec_remove(prec_1, "w");
176 	mu_assert_lf(prec_1->field_count == 3);
177 	mu_assert_lf(prec_2->field_count == 4);
178 	mu_assert_lf(lrec_get(prec_1, "w") == NULL);
179 	mu_assert_lf(streq(lrec_get(prec_2, "w"), "6"));
180 
181 	// Non-replacing-rename case
182 	//lrec_dump_titled("Before rename", prec_1);
183 	lrec_rename(prec_1, "x", "u", FALSE);
184 	//lrec_dump_titled("After rename", prec_1);
185 	mu_assert_lf(prec_1->field_count == 3);
186 	mu_assert_lf(lrec_get(prec_1, "x") == NULL);
187 	mu_assert_lf(streq(lrec_get(prec_1, "u"), "3"));
188 
189 	// Replacing-rename case
190 	//lrec_dump_titled("Before rename", prec_2);
191 	lrec_rename(prec_2, "y", "z", FALSE);
192 	//lrec_dump_titled("After rename", prec_2);
193 
194 	mu_assert_lf(prec_2->field_count == 3);
195 	mu_assert_lf(streq(lrec_get(prec_2, "w"), "6"));
196 	mu_assert_lf(streq(lrec_get(prec_2, "x"), "7"));
197 	mu_assert_lf(lrec_get(prec_2, "y") == NULL);
198 	mu_assert_lf(streq(lrec_get(prec_2, "z"), "8"));
199 
200 	lrec_free(prec_1);
201 	lrec_free(prec_2);
202 
203 	return NULL;
204 }
205 
206 // ----------------------------------------------------------------
test_lrec_csv_api_disjoint_allocs()207 static char* test_lrec_csv_api_disjoint_allocs() {
208 	char* hdr_line = mlr_strdup_or_die("w,x,y,z");
209 	slls_t* hdr_fields = split_csvlite_header_line_single_ifs(hdr_line, ',', FALSE);
210 	header_keeper_t* pheader_keeper = header_keeper_alloc(hdr_line, hdr_fields);
211 
212 
213 	char* data_line_1 = mlr_strdup_or_die("2,3,4,5");
214 	lrec_t* prec_1 = lrec_parse_stdio_csvlite_data_line_single_ifs(pheader_keeper, "test-file", 999,
215 		data_line_1, ',', FALSE, FALSE);
216 
217 	mu_assert_lf(prec_1->field_count == 4);
218 
219 	mu_assert_lf(streq(lrec_get(prec_1, "w"), "2"));
220 	mu_assert_lf(streq(lrec_get(prec_1, "x"), "3"));
221 	mu_assert_lf(streq(lrec_get(prec_1, "y"), "4"));
222 	mu_assert_lf(streq(lrec_get(prec_1, "z"), "5"));
223 
224 	lrec_remove(prec_1, "w");
225 	mu_assert_lf(prec_1->field_count == 3);
226 	mu_assert_lf(lrec_get(prec_1, "w") == NULL);
227 
228 	lrec_rename(prec_1, "x", "u", FALSE);
229 	mu_assert_lf(prec_1->field_count == 3);
230 	mu_assert_lf(lrec_get(prec_1, "x") == NULL);
231 	mu_assert_lf(streq(lrec_get(prec_1, "u"), "3"));
232 
233 	lrec_free(prec_1);
234 
235 
236 	char* data_line_2 = mlr_strdup_or_die("6,7,8,9");
237 	lrec_t* prec_2 = lrec_parse_stdio_csvlite_data_line_single_ifs(pheader_keeper, "test-file", 999,
238 		data_line_2, ',', FALSE, FALSE);
239 
240 	mu_assert_lf(prec_2->field_count == 4);
241 
242 	mu_assert_lf(streq(lrec_get(prec_2, "w"), "6"));
243 	mu_assert_lf(streq(lrec_get(prec_2, "x"), "7"));
244 	mu_assert_lf(streq(lrec_get(prec_2, "y"), "8"));
245 	mu_assert_lf(streq(lrec_get(prec_2, "z"), "9"));
246 
247 	mu_assert_lf(prec_2->field_count == 4);
248 	mu_assert_lf(streq(lrec_get(prec_2, "w"), "6"));
249 
250 	lrec_rename(prec_2, "y", "z", FALSE);
251 
252 	mu_assert_lf(prec_2->field_count == 3);
253 	mu_assert_lf(streq(lrec_get(prec_2, "w"), "6"));
254 	mu_assert_lf(streq(lrec_get(prec_2, "x"), "7"));
255 	mu_assert_lf(lrec_get(prec_2, "y") == NULL);
256 	mu_assert_lf(streq(lrec_get(prec_2, "z"), "8"));
257 
258 	lrec_free(prec_2);
259 
260 	return NULL;
261 }
262 
263 // ----------------------------------------------------------------
test_lrec_xtab_api()264 static char* test_lrec_xtab_api() {
265 	char* line_1 = mlr_strdup_or_die("w 2");
266 	char* line_2 = mlr_strdup_or_die("x    3");
267 	char* line_3 = mlr_strdup_or_die("y 4");
268 	char* line_4 = mlr_strdup_or_die("z  5");
269 	slls_t* pxtab_lines = slls_alloc();
270 	slls_append_with_free(pxtab_lines, line_1);
271 	slls_append_with_free(pxtab_lines, line_2);
272 	slls_append_with_free(pxtab_lines, line_3);
273 	slls_append_with_free(pxtab_lines, line_4);
274 
275 	lrec_t* prec = lrec_parse_stdio_xtab_single_ips(pxtab_lines, ' ', TRUE);
276 	mu_assert_lf(prec->field_count == 4);
277 
278 	mu_assert_lf(streq(lrec_get(prec, "w"), "2"));
279 	mu_assert_lf(streq(lrec_get(prec, "x"), "3"));
280 	mu_assert_lf(streq(lrec_get(prec, "y"), "4"));
281 	mu_assert_lf(streq(lrec_get(prec, "z"), "5"));
282 
283 	lrec_remove(prec, "w");
284 	mu_assert_lf(prec->field_count == 3);
285 	mu_assert_lf(lrec_get(prec, "w") == NULL);
286 
287 	// Non-replacing-rename case
288 	//lrec_dump_titled("Before rename", prec);
289 	lrec_rename(prec, "x", "u", FALSE);
290 	//lrec_dump_titled("After rename", prec);
291 	mu_assert_lf(prec->field_count == 3);
292 	mu_assert_lf(lrec_get(prec, "x") == NULL);
293 	mu_assert_lf(streq(lrec_get(prec, "u"), "3"));
294 
295 	// Replacing-rename case
296 	//lrec_dump_titled("Before rename", prec);
297 	lrec_rename(prec, "y", "z", FALSE);
298 	//lrec_dump_titled("After rename", prec);
299 
300 	mu_assert_lf(prec->field_count == 2);
301 	mu_assert_lf(streq(lrec_get(prec, "u"), "3"));
302 	mu_assert_lf(lrec_get(prec, "y") == NULL);
303 	mu_assert_lf(streq(lrec_get(prec, "z"), "4"));
304 
305 	lrec_free(prec);
306 
307 	return NULL;
308 }
309 
310 // ----------------------------------------------------------------
test_lrec_put_after()311 static char* test_lrec_put_after() {
312 	printf("TEST_LREC_PUT_AFTER ENTER\n");
313 
314 	lrec_t* prec = lrec_literal_1("a", "1");
315 	lrece_t* pe = NULL;
316 
317 	printf("BEFORE: "); lrec_print(prec);
318 	mu_assert_lf(prec->field_count == 1);
319 	char* value = lrec_get_ext(prec, "nosuch", &pe);
320 	mu_assert_lf(value == NULL);
321 	mu_assert_lf(pe == NULL);
322 
323 	value = lrec_get_ext(prec, "a", &pe);
324 	mu_assert_lf(value != NULL);
325 	mu_assert_lf(pe != NULL);
326 	mu_assert_lf(streq(value, "1"));
327 	lrec_put_after(prec, pe, "a", "2", NO_FREE);
328 	printf("AFTER : "); lrec_print(prec);
329 	mu_assert_lf(prec->field_count == 1);
330 	value = lrec_get_ext(prec, "a", &pe);
331 	mu_assert_lf(value != NULL);
332 	mu_assert_lf(pe != NULL);
333 	mu_assert_lf(streq(value, "2"));
334 	lrec_free(prec);
335 
336 	prec = lrec_literal_1("a", "1");
337 	printf("BEFORE: "); lrec_print(prec);
338 	value = lrec_get_ext(prec, "a", &pe);
339 	mu_assert_lf(pe != NULL);
340 	mu_assert_lf(streq(value, "1"));
341 
342 	lrec_put_after(prec, pe, "b", "3", NO_FREE);
343 	printf("AFTER : "); lrec_print(prec);
344 	mu_assert_lf(prec->field_count == 2);
345 	value = lrec_get(prec, "a");
346 	mu_assert_lf(value != NULL);
347 	mu_assert_lf(streq(value, "1"));
348 	value = lrec_get(prec, "b");
349 	mu_assert_lf(value != NULL);
350 	mu_assert_lf(streq(value, "3"));
351 	mu_assert_lf(streq(prec->phead->key, "a"));
352 	mu_assert_lf(streq(prec->phead->pnext->key, "b"));
353 	mu_assert_lf(streq(prec->phead->value, "1"));
354 	mu_assert_lf(streq(prec->phead->pnext->value, "3"));
355 	mu_assert_lf(prec->phead->pnext->pnext == NULL);
356 	lrec_free(prec);
357 
358 
359 	prec = lrec_literal_2("a", "1", "b", "2");
360 	printf("BEFORE: "); lrec_print(prec);
361 	mu_assert_lf(prec->field_count == 2);
362 	value = lrec_get_ext(prec, "a", &pe);
363 	mu_assert_lf(value != NULL);
364 	mu_assert_lf(pe != NULL);
365 	mu_assert_lf(streq(value, "1"));
366 
367 	lrec_put_after(prec, pe, "z", "9", NO_FREE);
368 	printf("AFTER : "); lrec_print(prec);
369 	mu_assert_lf(prec->field_count == 3);
370 	mu_assert_lf(streq(prec->phead->key, "a"));
371 	mu_assert_lf(streq(prec->phead->pnext->key, "z"));
372 	mu_assert_lf(streq(prec->phead->pnext->pnext->key, "b"));
373 	mu_assert_lf(streq(prec->phead->value, "1"));
374 	mu_assert_lf(streq(prec->phead->pnext->value, "9"));
375 	mu_assert_lf(streq(prec->phead->pnext->pnext->value, "2"));
376 	mu_assert_lf(prec->phead->pnext->pnext->pnext == NULL);
377 	lrec_free(prec);
378 
379 
380 	prec = lrec_literal_2("a", "1", "b", "2");
381 	printf("BEFORE: "); lrec_print(prec);
382 	mu_assert_lf(prec->field_count == 2);
383 	value = lrec_get_ext(prec, "b", &pe);
384 	mu_assert_lf(value != NULL);
385 	mu_assert_lf(pe != NULL);
386 	mu_assert_lf(streq(value, "2"));
387 
388 	lrec_put_after(prec, pe, "z", "9", NO_FREE);
389 	printf("AFTER : "); lrec_print(prec);
390 	mu_assert_lf(prec->field_count == 3);
391 	mu_assert_lf(streq(prec->phead->key, "a"));
392 	mu_assert_lf(streq(prec->phead->pnext->key, "b"));
393 	mu_assert_lf(streq(prec->phead->pnext->pnext->key, "z"));
394 	mu_assert_lf(streq(prec->phead->value, "1"));
395 	mu_assert_lf(streq(prec->phead->pnext->value, "2"));
396 	mu_assert_lf(streq(prec->phead->pnext->pnext->value, "9"));
397 	mu_assert_lf(prec->phead->pnext->pnext->pnext == NULL);
398 	lrec_free(prec);
399 
400 	printf("TEST_LREC_PUT_AFTER EXIT\n");
401 	return NULL;
402 }
403 
404 // ================================================================
run_all_tests()405 static char * run_all_tests() {
406 	mu_run_test(test_lrec_unbacked_api);
407 	mu_run_test(test_lrec_dkvp_api);
408 	mu_run_test(test_lrec_nidx_api);
409 	mu_run_test(test_lrec_csv_api);
410 	mu_run_test(test_lrec_csv_api_disjoint_allocs);
411 	mu_run_test(test_lrec_xtab_api);
412 	mu_run_test(test_lrec_put_after);
413 	return 0;
414 }
415 
main(int argc,char ** argv)416 int main(int argc, char **argv) {
417 	mlr_global_init(argv[0], NULL);
418 	printf("TEST_LREC ENTER\n");
419 	char *result = run_all_tests();
420 	printf("\n");
421 	if (result != 0) {
422 		printf("Not all unit tests passed\n");
423 	}
424 	else {
425 		printf("TEST_LREC: ALL UNIT TESTS PASSED\n");
426 	}
427 	printf("Tests      passed: %d of %d\n", tests_run - tests_failed, tests_run);
428 	printf("Assertions passed: %d of %d\n", assertions_run - assertions_failed, assertions_run);
429 
430 	return result != 0;
431 }
432