Line data Source code
1 : /* t-stringhelp.c - Regression tests for stringhelp.c
2 : * Copyright (C) 2007 Free Software Foundation, Inc.
3 : * 2015 g10 Code GmbH
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify it
8 : * under the terms of either
9 : *
10 : * - the GNU Lesser General Public License as published by the Free
11 : * Software Foundation; either version 3 of the License, or (at
12 : * your option) any later version.
13 : *
14 : * or
15 : *
16 : * - the GNU General Public License as published by the Free
17 : * Software Foundation; either version 2 of the License, or (at
18 : * your option) any later version.
19 : *
20 : * or both in parallel, as here.
21 : *
22 : * GnuPG is distributed in the hope that it will be useful, but
23 : * WITHOUT ANY WARRANTY; without even the implied warranty of
24 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 : * General Public License for more details.
26 : *
27 : * You should have received a copies of the GNU General Public License
28 : * and the GNU Lesser General Public License along with this program;
29 : * if not, see <http://www.gnu.org/licenses/>.
30 : */
31 :
32 : #include <config.h>
33 : #include <stdio.h>
34 : #include <stdlib.h>
35 : #include <string.h>
36 : #include <errno.h>
37 : #ifdef HAVE_PWD_H
38 : # include <pwd.h>
39 : #endif
40 : #include <unistd.h>
41 : #include <sys/types.h>
42 :
43 : #include "stringhelp.h"
44 :
45 : #include "t-support.h"
46 :
47 :
48 : static char *home_buffer;
49 :
50 :
51 : const char *
52 1 : gethome (void)
53 : {
54 1 : if (!home_buffer)
55 : {
56 1 : char *home = getenv("HOME");
57 :
58 1 : if(home)
59 1 : home_buffer = xstrdup (home);
60 : #if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H)
61 : else
62 : {
63 : struct passwd *pwd;
64 :
65 0 : pwd = getpwuid (getuid());
66 0 : if (pwd)
67 0 : home_buffer = xstrdup (pwd->pw_dir);
68 : }
69 : #endif
70 : }
71 1 : return home_buffer;
72 : }
73 :
74 :
75 : static char *
76 1 : mygetcwd (void)
77 : {
78 : char *buffer;
79 1 : size_t size = 100;
80 :
81 : for (;;)
82 : {
83 1 : buffer = xmalloc (size+1);
84 : #ifdef HAVE_W32CE_SYSTEM
85 : strcpy (buffer, "/"); /* Always "/". */
86 : return buffer;
87 : #else
88 1 : if (getcwd (buffer, size) == buffer)
89 2 : return buffer;
90 0 : xfree (buffer);
91 0 : if (errno != ERANGE)
92 : {
93 0 : fprintf (stderr,"error getting current cwd: %s\n",
94 0 : strerror (errno));
95 0 : exit (2);
96 : }
97 0 : size *= 2;
98 : #endif
99 0 : }
100 : }
101 :
102 :
103 : static void
104 1 : test_percent_escape (void)
105 : {
106 : char *result;
107 : static struct {
108 : const char *extra;
109 : const char *value;
110 : const char *expected;
111 : } tests[] =
112 : {
113 : { NULL, "", "" },
114 : { NULL, "%", "%25" },
115 : { NULL, "%%", "%25%25" },
116 : { NULL, " %", " %25" },
117 : { NULL, ":", "%3a" },
118 : { NULL, " :", " %3a" },
119 : { NULL, ": ", "%3a " },
120 : { NULL, " : ", " %3a " },
121 : { NULL, "::", "%3a%3a" },
122 : { NULL, ": :", "%3a %3a" },
123 : { NULL, "%:", "%25%3a" },
124 : { NULL, ":%", "%3a%25" },
125 : { "\\\n:", ":%", "%3a%25" },
126 : { "\\\n:", "\\:%", "%5c%3a%25" },
127 : { "\\\n:", "\n:%", "%0a%3a%25" },
128 : { "\\\n:", "\xff:%", "\xff%3a%25" },
129 : { "\\\n:", "\xfe:%", "\xfe%3a%25" },
130 : { "\\\n:", "\x01:%", "\x01%3a%25" },
131 : { "\x01", "\x01:%", "%01%3a%25" },
132 : { "\xfe", "\xfe:%", "%fe%3a%25" },
133 : { "\xfe", "\xff:%", "\xff%3a%25" },
134 :
135 : { NULL, NULL, NULL }
136 : };
137 : int testno;
138 :
139 1 : result = percent_escape (NULL, NULL);
140 1 : if (result)
141 0 : fail (0);
142 22 : for (testno=0; tests[testno].value; testno++)
143 : {
144 21 : result = percent_escape (tests[testno].value, tests[testno].extra);
145 21 : if (!result)
146 0 : fail (testno);
147 21 : if (strcmp (result, tests[testno].expected))
148 0 : fail (testno);
149 21 : xfree (result);
150 : }
151 :
152 1 : }
153 :
154 :
155 : static void
156 1 : test_compare_filenames (void)
157 : {
158 : struct {
159 : const char *a;
160 : const char *b;
161 : int result;
162 1 : } tests[] = {
163 : { "", "", 0 },
164 : { "", "a", -1 },
165 : { "a", "", 1 },
166 : { "a", "a", 0 },
167 : { "a", "aa", -1 },
168 : { "aa", "a", 1 },
169 : { "a", "b", -1 },
170 :
171 : #ifdef HAVE_W32_SYSTEM
172 : { "a", "A", 0 },
173 : { "A", "a", 0 },
174 : { "foo/bar", "foo\\bar", 0 },
175 : { "foo\\bar", "foo/bar", 0 },
176 : { "foo\\", "foo/", 0 },
177 : { "foo/", "foo\\", 0 },
178 : #endif /*HAVE_W32_SYSTEM*/
179 : { NULL, NULL, 0}
180 : };
181 : int testno, result;
182 :
183 8 : for (testno=0; tests[testno].a; testno++)
184 : {
185 7 : result = compare_filenames (tests[testno].a, tests[testno].b);
186 7 : result = result < 0? -1 : result > 0? 1 : 0;
187 7 : if (result != tests[testno].result)
188 0 : fail (testno);
189 : }
190 1 : }
191 :
192 :
193 : static void
194 1 : test_strconcat (void)
195 : {
196 : char *out;
197 :
198 1 : out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
199 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
200 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
201 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
202 : "1", "2", "3", "4", "5", "6", "7", NULL);
203 1 : if (!out)
204 0 : fail (0);
205 : else
206 1 : xfree (out);
207 1 : out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
208 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
209 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
210 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
211 : "1", "2", "3", "4", "5", "6", "7", "8", NULL);
212 1 : if (out)
213 0 : fail (0);
214 1 : else if (errno != EINVAL)
215 0 : fail (0);
216 :
217 1 : out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
218 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
219 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
220 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
221 : "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL);
222 1 : if (out)
223 0 : fail (0);
224 1 : else if (errno != EINVAL)
225 0 : fail (0);
226 :
227 : #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */
228 : out = strconcat (NULL);
229 : if (!out || *out)
230 : fail (1);
231 : #endif
232 1 : out = strconcat (NULL, NULL);
233 1 : if (!out || *out)
234 0 : fail (1);
235 1 : out = strconcat ("", NULL);
236 1 : if (!out || *out)
237 0 : fail (1);
238 1 : xfree (out);
239 :
240 1 : out = strconcat ("", "", NULL);
241 1 : if (!out || *out)
242 0 : fail (2);
243 1 : xfree (out);
244 :
245 1 : out = strconcat ("a", "b", NULL);
246 1 : if (!out || strcmp (out, "ab"))
247 0 : fail (3);
248 1 : xfree (out);
249 1 : out = strconcat ("a", "b", "c", NULL);
250 1 : if (!out || strcmp (out, "abc"))
251 0 : fail (3);
252 1 : xfree (out);
253 :
254 1 : out = strconcat ("a", "b", "cc", NULL);
255 1 : if (!out || strcmp (out, "abcc"))
256 0 : fail (4);
257 1 : xfree (out);
258 1 : out = strconcat ("a1", "b1", "c1", NULL);
259 1 : if (!out || strcmp (out, "a1b1c1"))
260 0 : fail (4);
261 1 : xfree (out);
262 :
263 1 : out = strconcat ("", " long b ", "", "--even-longer--", NULL);
264 1 : if (!out || strcmp (out, " long b --even-longer--"))
265 0 : fail (5);
266 1 : xfree (out);
267 :
268 1 : out = strconcat ("", " long b ", "", "--even-longer--", NULL);
269 1 : if (!out || strcmp (out, " long b --even-longer--"))
270 0 : fail (5);
271 1 : xfree (out);
272 1 : }
273 :
274 : static void
275 1 : test_xstrconcat (void)
276 : {
277 : char *out;
278 :
279 1 : out = xstrconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
280 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
281 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
282 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
283 : "1", "2", "3", "4", "5", "6", "7", NULL);
284 1 : if (!out)
285 0 : fail (0);
286 :
287 : #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */
288 : out = xstrconcat (NULL);
289 : if (!out)
290 : fail (1);
291 : #endif
292 1 : out = xstrconcat (NULL, NULL);
293 1 : if (!out)
294 0 : fail (1);
295 1 : out = xstrconcat ("", NULL);
296 1 : if (!out || *out)
297 0 : fail (1);
298 1 : xfree (out);
299 :
300 1 : out = xstrconcat ("", "", NULL);
301 1 : if (!out || *out)
302 0 : fail (2);
303 1 : xfree (out);
304 :
305 1 : out = xstrconcat ("a", "b", NULL);
306 1 : if (!out || strcmp (out, "ab"))
307 0 : fail (3);
308 1 : xfree (out);
309 1 : out = xstrconcat ("a", "b", "c", NULL);
310 1 : if (!out || strcmp (out, "abc"))
311 0 : fail (3);
312 1 : xfree (out);
313 :
314 1 : out = xstrconcat ("a", "b", "cc", NULL);
315 1 : if (!out || strcmp (out, "abcc"))
316 0 : fail (4);
317 1 : xfree (out);
318 1 : out = xstrconcat ("a1", "b1", "c1", NULL);
319 1 : if (!out || strcmp (out, "a1b1c1"))
320 0 : fail (4);
321 1 : xfree (out);
322 :
323 1 : out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
324 1 : if (!out || strcmp (out, " long b --even-longer--"))
325 0 : fail (5);
326 1 : xfree (out);
327 :
328 1 : out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
329 1 : if (!out || strcmp (out, " long b --even-longer--"))
330 0 : fail (5);
331 1 : xfree (out);
332 1 : }
333 :
334 :
335 : static void
336 1 : test_make_filename_try (void)
337 : {
338 : char *out;
339 1 : const char *home = gethome ();
340 1 : size_t homelen = home? strlen (home):0;
341 :
342 1 : out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
343 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
344 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
345 : "1", "2", "3", NULL);
346 1 : if (out)
347 0 : fail (0);
348 1 : else if (errno != EINVAL)
349 0 : fail (0);
350 1 : xfree (out);
351 1 : out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
352 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
353 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
354 : "1", "2", "3", "4", NULL);
355 1 : if (out)
356 0 : fail (0);
357 1 : else if (errno != EINVAL)
358 0 : fail (0);
359 1 : xfree (out);
360 :
361 1 : out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
362 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
363 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
364 : "1", "2", NULL);
365 1 : if (!out || strcmp (out,
366 : "1/2/3/4/5/6/7/8/9/10/"
367 : "1/2/3/4/5/6/7/8/9/10/"
368 : "1/2/3/4/5/6/7/8/9/10/"
369 : "1/2"))
370 0 : fail (0);
371 1 : xfree (out);
372 :
373 1 : out = make_filename_try ("foo", "~/bar", "baz/cde", NULL);
374 1 : if (!out || strcmp (out, "foo/~/bar/baz/cde"))
375 0 : fail (1);
376 1 : xfree (out);
377 :
378 1 : out = make_filename_try ("foo", "~/bar", "baz/cde/", NULL);
379 1 : if (!out || strcmp (out, "foo/~/bar/baz/cde/"))
380 0 : fail (1);
381 1 : xfree (out);
382 :
383 1 : out = make_filename_try ("/foo", "~/bar", "baz/cde/", NULL);
384 1 : if (!out || strcmp (out, "/foo/~/bar/baz/cde/"))
385 0 : fail (1);
386 1 : xfree (out);
387 :
388 1 : out = make_filename_try ("//foo", "~/bar", "baz/cde/", NULL);
389 1 : if (!out || strcmp (out, "//foo/~/bar/baz/cde/"))
390 0 : fail (1);
391 1 : xfree (out);
392 :
393 1 : out = make_filename_try ("", "~/bar", "baz/cde", NULL);
394 1 : if (!out || strcmp (out, "/~/bar/baz/cde"))
395 0 : fail (1);
396 1 : xfree (out);
397 :
398 :
399 1 : out = make_filename_try ("~/foo", "bar", NULL);
400 1 : if (!out)
401 0 : fail (2);
402 1 : if (home)
403 : {
404 1 : if (strlen (out) < homelen + 7)
405 0 : fail (2);
406 1 : if (strncmp (out, home, homelen))
407 0 : fail (2);
408 1 : if (strcmp (out+homelen, "/foo/bar"))
409 0 : fail (2);
410 : }
411 : else
412 : {
413 0 : if (strcmp (out, "~/foo/bar"))
414 0 : fail (2);
415 : }
416 1 : xfree (out);
417 :
418 1 : out = make_filename_try ("~", "bar", NULL);
419 1 : if (!out)
420 0 : fail (2);
421 1 : if (home)
422 : {
423 1 : if (strlen (out) < homelen + 3)
424 0 : fail (2);
425 1 : if (strncmp (out, home, homelen))
426 0 : fail (2);
427 1 : if (strcmp (out+homelen, "/bar"))
428 0 : fail (2);
429 : }
430 : else
431 : {
432 0 : if (strcmp (out, "~/bar"))
433 0 : fail (2);
434 : }
435 1 : xfree (out);
436 1 : }
437 :
438 :
439 : static void
440 1 : test_make_absfilename_try (void)
441 : {
442 : char *out;
443 1 : char *cwd = mygetcwd ();
444 1 : size_t cwdlen = strlen (cwd);
445 :
446 1 : out = make_absfilename_try ("foo", "bar", NULL);
447 1 : if (!out)
448 0 : fail (0);
449 1 : if (strlen (out) < cwdlen + 7)
450 0 : fail (0);
451 1 : if (strncmp (out, cwd, cwdlen))
452 0 : fail (0);
453 1 : if (strcmp (out+cwdlen, "/foo/bar"))
454 0 : fail (0);
455 1 : xfree (out);
456 :
457 1 : out = make_absfilename_try ("./foo", NULL);
458 1 : if (!out)
459 0 : fail (1);
460 1 : if (strlen (out) < cwdlen + 5)
461 0 : fail (1);
462 1 : if (strncmp (out, cwd, cwdlen))
463 0 : fail (1);
464 1 : if (strcmp (out+cwdlen, "/./foo"))
465 0 : fail (1);
466 1 : xfree (out);
467 :
468 1 : out = make_absfilename_try (".", NULL);
469 1 : if (!out)
470 0 : fail (2);
471 1 : if (strlen (out) < cwdlen)
472 0 : fail (2);
473 1 : if (strncmp (out, cwd, cwdlen))
474 0 : fail (2);
475 1 : if (strcmp (out+cwdlen, ""))
476 0 : fail (2);
477 1 : xfree (out);
478 :
479 1 : xfree (cwd);
480 1 : }
481 :
482 : static void
483 1 : test_strsplit (void)
484 : {
485 : struct {
486 : const char *s;
487 : char delim;
488 : char replacement;
489 : const char *fields_expected[10];
490 1 : } tv[] = {
491 : {
492 : "a:bc:cde:fghi:jklmn::foo:", ':', '\0',
493 : { "a", "bc", "cde", "fghi", "jklmn", "", "foo", "", NULL }
494 : },
495 : {
496 : ",a,bc,,def,", ',', '!',
497 : { "!a!bc!!def!", "a!bc!!def!", "bc!!def!", "!def!", "def!", "", NULL }
498 : },
499 : {
500 : "", ':', ',',
501 : { "", NULL }
502 : }
503 : };
504 :
505 : int tidx;
506 :
507 4 : for (tidx = 0; tidx < DIM(tv); tidx++)
508 : {
509 : char *s2;
510 : int field_count;
511 : char **fields;
512 : int field_count_expected;
513 : int i;
514 :
515 : /* Count the fields. */
516 21 : for (field_count_expected = 0;
517 18 : tv[tidx].fields_expected[field_count_expected];
518 15 : field_count_expected ++)
519 : ;
520 :
521 : /* We need to copy s since strsplit modifies it in place. */
522 3 : s2 = xstrdup (tv[tidx].s);
523 3 : fields = strsplit (s2, tv[tidx].delim, tv[tidx].replacement,
524 : &field_count);
525 :
526 3 : if (field_count != field_count_expected)
527 0 : fail (tidx * 1000);
528 :
529 18 : for (i = 0; i < field_count_expected; i ++)
530 15 : if (strcmp (tv[tidx].fields_expected[i], fields[i]) != 0)
531 : {
532 0 : printf ("For field %d, expected '%s', but got '%s'\n",
533 0 : i, tv[tidx].fields_expected[i], fields[i]);
534 0 : fail (tidx * 1000 + i + 1);
535 : }
536 :
537 3 : xfree (s2);
538 : }
539 1 : }
540 :
541 :
542 :
543 : static void
544 1 : test_strtokenize (void)
545 : {
546 : struct {
547 : const char *s;
548 : const char *delim;
549 : const char *fields_expected[10];
550 1 : } tv[] = {
551 : {
552 : "", ":",
553 : { "", NULL }
554 : },
555 : {
556 : "a", ":",
557 : { "a", NULL }
558 : },
559 : {
560 : ":", ":",
561 : { "", "", NULL }
562 : },
563 : {
564 : "::", ":",
565 : { "", "", "", NULL }
566 : },
567 : {
568 : "a:b:c", ":",
569 : { "a", "b", "c", NULL }
570 : },
571 : {
572 : "a:b:", ":",
573 : { "a", "b", "", NULL }
574 : },
575 : {
576 : "a:b", ":",
577 : { "a", "b", NULL }
578 : },
579 : {
580 : "aa:b:cd", ":",
581 : { "aa", "b", "cd", NULL }
582 : },
583 : {
584 : "aa::b:cd", ":",
585 : { "aa", "", "b", "cd", NULL }
586 : },
587 : {
588 : "::b:cd", ":",
589 : { "", "", "b", "cd", NULL }
590 : },
591 : {
592 : "aa: : b:cd ", ":",
593 : { "aa", "", "b", "cd", NULL }
594 : },
595 : {
596 : " aa: : b: cd ", ":",
597 : { "aa", "", "b", "cd", NULL }
598 : },
599 : {
600 : " ", ":",
601 : { "", NULL }
602 : },
603 : {
604 : " :", ":",
605 : { "", "", NULL }
606 : },
607 : {
608 : " : ", ":",
609 : { "", "", NULL }
610 : },
611 : {
612 : ": ", ":",
613 : { "", "", NULL }
614 : },
615 : {
616 : ": x ", ":",
617 : { "", "x", NULL }
618 : },
619 : {
620 : "a:bc:cde:fghi:jklmn::foo:", ":",
621 : { "a", "bc", "cde", "fghi", "jklmn", "", "foo", "", NULL }
622 : },
623 : {
624 : ",a,bc,,def,", ",",
625 : { "", "a", "bc", "", "def", "", NULL }
626 : },
627 : {
628 : " a ", " ",
629 : { "", "a", "", NULL }
630 : },
631 : {
632 : " ", " ",
633 : { "", "", NULL }
634 : },
635 : {
636 : "", " ",
637 : { "", NULL }
638 : }
639 : };
640 :
641 : int tidx;
642 :
643 23 : for (tidx = 0; tidx < DIM(tv); tidx++)
644 : {
645 : char **fields;
646 : int field_count;
647 : int field_count_expected;
648 : int i;
649 :
650 107 : for (field_count_expected = 0;
651 85 : tv[tidx].fields_expected[field_count_expected];
652 63 : field_count_expected ++)
653 : ;
654 :
655 22 : fields = strtokenize (tv[tidx].s, tv[tidx].delim);
656 22 : if (!fields)
657 0 : fail (tidx * 1000);
658 : else
659 : {
660 22 : for (field_count = 0; fields[field_count]; field_count++)
661 : ;
662 22 : if (field_count != field_count_expected)
663 0 : fail (tidx * 1000);
664 : else
665 : {
666 85 : for (i = 0; i < field_count_expected; i++)
667 63 : if (strcmp (tv[tidx].fields_expected[i], fields[i]))
668 : {
669 0 : printf ("For field %d, expected '%s', but got '%s'\n",
670 0 : i, tv[tidx].fields_expected[i], fields[i]);
671 0 : fail (tidx * 1000 + i + 1);
672 : }
673 : }
674 : }
675 :
676 22 : xfree (fields);
677 : }
678 1 : }
679 :
680 :
681 : int
682 1 : main (int argc, char **argv)
683 : {
684 : (void)argc;
685 : (void)argv;
686 :
687 1 : test_percent_escape ();
688 1 : test_compare_filenames ();
689 1 : test_strconcat ();
690 1 : test_xstrconcat ();
691 1 : test_make_filename_try ();
692 1 : test_make_absfilename_try ();
693 1 : test_strsplit ();
694 1 : test_strtokenize ();
695 :
696 1 : xfree (home_buffer);
697 1 : return 0;
698 : }
|