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 <https://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 : #include <assert.h>
38 : #ifdef HAVE_PWD_H
39 : # include <pwd.h>
40 : #endif
41 : #include <unistd.h>
42 : #include <sys/types.h>
43 : #include <limits.h>
44 :
45 : #include "t-support.h"
46 : #include "stringhelp.h"
47 :
48 :
49 : static char *home_buffer;
50 :
51 :
52 : const char *
53 1 : gethome (void)
54 : {
55 1 : if (!home_buffer)
56 : {
57 1 : char *home = getenv("HOME");
58 :
59 1 : if(home)
60 1 : home_buffer = xstrdup (home);
61 : #if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H)
62 : else
63 : {
64 : struct passwd *pwd;
65 :
66 0 : pwd = getpwuid (getuid());
67 0 : if (pwd)
68 0 : home_buffer = xstrdup (pwd->pw_dir);
69 : }
70 : #endif
71 : }
72 1 : return home_buffer;
73 : }
74 :
75 :
76 : static char *
77 1 : mygetcwd (void)
78 : {
79 : char *buffer;
80 1 : size_t size = 100;
81 :
82 : for (;;)
83 : {
84 1 : buffer = xmalloc (size+1);
85 : #ifdef HAVE_W32CE_SYSTEM
86 : strcpy (buffer, "/"); /* Always "/". */
87 : return buffer;
88 : #else
89 1 : if (getcwd (buffer, size) == buffer)
90 2 : return buffer;
91 0 : xfree (buffer);
92 0 : if (errno != ERANGE)
93 : {
94 0 : fprintf (stderr,"error getting current cwd: %s\n",
95 0 : strerror (errno));
96 0 : exit (2);
97 : }
98 0 : size *= 2;
99 : #endif
100 0 : }
101 : }
102 :
103 :
104 : static void
105 1 : test_percent_escape (void)
106 : {
107 : char *result;
108 : static struct {
109 : const char *extra;
110 : const char *value;
111 : const char *expected;
112 : } tests[] =
113 : {
114 : { NULL, "", "" },
115 : { NULL, "%", "%25" },
116 : { NULL, "%%", "%25%25" },
117 : { NULL, " %", " %25" },
118 : { NULL, ":", "%3a" },
119 : { NULL, " :", " %3a" },
120 : { NULL, ": ", "%3a " },
121 : { NULL, " : ", " %3a " },
122 : { NULL, "::", "%3a%3a" },
123 : { NULL, ": :", "%3a %3a" },
124 : { NULL, "%:", "%25%3a" },
125 : { NULL, ":%", "%3a%25" },
126 : { "\\\n:", ":%", "%3a%25" },
127 : { "\\\n:", "\\:%", "%5c%3a%25" },
128 : { "\\\n:", "\n:%", "%0a%3a%25" },
129 : { "\\\n:", "\xff:%", "\xff%3a%25" },
130 : { "\\\n:", "\xfe:%", "\xfe%3a%25" },
131 : { "\\\n:", "\x01:%", "\x01%3a%25" },
132 : { "\x01", "\x01:%", "%01%3a%25" },
133 : { "\xfe", "\xfe:%", "%fe%3a%25" },
134 : { "\xfe", "\xff:%", "\xff%3a%25" },
135 :
136 : { NULL, NULL, NULL }
137 : };
138 : int testno;
139 :
140 1 : result = percent_escape (NULL, NULL);
141 1 : if (result)
142 0 : fail (0);
143 22 : for (testno=0; tests[testno].value; testno++)
144 : {
145 21 : result = percent_escape (tests[testno].value, tests[testno].extra);
146 21 : if (!result)
147 0 : fail (testno);
148 21 : else if (strcmp (result, tests[testno].expected))
149 0 : fail (testno);
150 21 : xfree (result);
151 : }
152 :
153 1 : }
154 :
155 :
156 : static void
157 1 : test_compare_filenames (void)
158 : {
159 : struct {
160 : const char *a;
161 : const char *b;
162 : int result;
163 1 : } tests[] = {
164 : { "", "", 0 },
165 : { "", "a", -1 },
166 : { "a", "", 1 },
167 : { "a", "a", 0 },
168 : { "a", "aa", -1 },
169 : { "aa", "a", 1 },
170 : { "a", "b", -1 },
171 :
172 : #ifdef HAVE_W32_SYSTEM
173 : { "a", "A", 0 },
174 : { "A", "a", 0 },
175 : { "foo/bar", "foo\\bar", 0 },
176 : { "foo\\bar", "foo/bar", 0 },
177 : { "foo\\", "foo/", 0 },
178 : { "foo/", "foo\\", 0 },
179 : #endif /*HAVE_W32_SYSTEM*/
180 : { NULL, NULL, 0}
181 : };
182 : int testno, result;
183 :
184 8 : for (testno=0; tests[testno].a; testno++)
185 : {
186 7 : result = compare_filenames (tests[testno].a, tests[testno].b);
187 7 : result = result < 0? -1 : result > 0? 1 : 0;
188 7 : if (result != tests[testno].result)
189 0 : fail (testno);
190 : }
191 1 : }
192 :
193 :
194 : static void
195 1 : test_strconcat (void)
196 : {
197 : char *out;
198 :
199 1 : out = strconcat ("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", "8", "9", "10",
203 : "1", "2", "3", "4", "5", "6", "7", NULL);
204 1 : if (!out)
205 0 : fail (0);
206 : else
207 1 : xfree (out);
208 1 : out = strconcat ("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", "9", "10",
212 : "1", "2", "3", "4", "5", "6", "7", "8", NULL);
213 1 : if (out)
214 0 : fail (0);
215 1 : else if (errno != EINVAL)
216 0 : fail (0);
217 :
218 1 : out = strconcat ("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", "10",
222 : "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL);
223 1 : if (out)
224 0 : fail (0);
225 1 : else if (errno != EINVAL)
226 0 : fail (0);
227 1 : xfree (out);
228 :
229 : #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */
230 : out = strconcat (NULL);
231 : if (!out || *out)
232 : fail (1);
233 : #endif
234 1 : out = strconcat (NULL, NULL);
235 1 : if (!out || *out)
236 0 : fail (1);
237 1 : xfree (out);
238 :
239 1 : out = strconcat ("", NULL);
240 1 : if (!out || *out)
241 0 : fail (1);
242 1 : xfree (out);
243 :
244 1 : out = strconcat ("", "", NULL);
245 1 : if (!out || *out)
246 0 : fail (2);
247 1 : xfree (out);
248 :
249 1 : out = strconcat ("a", "b", NULL);
250 1 : if (!out || strcmp (out, "ab"))
251 0 : fail (3);
252 1 : xfree (out);
253 1 : out = strconcat ("a", "b", "c", NULL);
254 1 : if (!out || strcmp (out, "abc"))
255 0 : fail (3);
256 1 : xfree (out);
257 :
258 1 : out = strconcat ("a", "b", "cc", NULL);
259 1 : if (!out || strcmp (out, "abcc"))
260 0 : fail (4);
261 1 : xfree (out);
262 1 : out = strconcat ("a1", "b1", "c1", NULL);
263 1 : if (!out || strcmp (out, "a1b1c1"))
264 0 : fail (4);
265 1 : xfree (out);
266 :
267 1 : out = strconcat ("", " long b ", "", "--even-longer--", NULL);
268 1 : if (!out || strcmp (out, " long b --even-longer--"))
269 0 : fail (5);
270 1 : xfree (out);
271 :
272 1 : out = strconcat ("", " long b ", "", "--even-longer--", NULL);
273 1 : if (!out || strcmp (out, " long b --even-longer--"))
274 0 : fail (5);
275 1 : xfree (out);
276 1 : }
277 :
278 : static void
279 1 : test_xstrconcat (void)
280 : {
281 : char *out;
282 :
283 1 : out = xstrconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
284 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
285 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
286 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
287 : "1", "2", "3", "4", "5", "6", "7", NULL);
288 1 : if (!out)
289 0 : fail (0);
290 1 : xfree (out);
291 :
292 : #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */
293 : out = xstrconcat (NULL);
294 : if (!out)
295 : fail (1);
296 : #endif
297 1 : out = xstrconcat (NULL, NULL);
298 1 : if (!out)
299 0 : fail (1);
300 1 : xfree (out);
301 :
302 1 : out = xstrconcat ("", NULL);
303 1 : if (!out || *out)
304 0 : fail (1);
305 1 : xfree (out);
306 :
307 1 : out = xstrconcat ("", "", NULL);
308 1 : if (!out || *out)
309 0 : fail (2);
310 1 : xfree (out);
311 :
312 1 : out = xstrconcat ("a", "b", NULL);
313 1 : if (!out || strcmp (out, "ab"))
314 0 : fail (3);
315 1 : xfree (out);
316 1 : out = xstrconcat ("a", "b", "c", NULL);
317 1 : if (!out || strcmp (out, "abc"))
318 0 : fail (3);
319 1 : xfree (out);
320 :
321 1 : out = xstrconcat ("a", "b", "cc", NULL);
322 1 : if (!out || strcmp (out, "abcc"))
323 0 : fail (4);
324 1 : xfree (out);
325 1 : out = xstrconcat ("a1", "b1", "c1", NULL);
326 1 : if (!out || strcmp (out, "a1b1c1"))
327 0 : fail (4);
328 1 : xfree (out);
329 :
330 1 : out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
331 1 : if (!out || strcmp (out, " long b --even-longer--"))
332 0 : fail (5);
333 1 : xfree (out);
334 :
335 1 : out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
336 1 : if (!out || strcmp (out, " long b --even-longer--"))
337 0 : fail (5);
338 1 : xfree (out);
339 1 : }
340 :
341 :
342 : static void
343 1 : test_make_filename_try (void)
344 : {
345 : char *out;
346 1 : const char *home = gethome ();
347 1 : size_t homelen = home? strlen (home):0;
348 :
349 1 : out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
350 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
351 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
352 : "1", "2", "3", NULL);
353 1 : if (out)
354 0 : fail (0);
355 1 : else if (errno != EINVAL)
356 0 : fail (0);
357 1 : xfree (out);
358 1 : out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
359 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
360 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
361 : "1", "2", "3", "4", NULL);
362 1 : if (out)
363 0 : fail (0);
364 1 : else if (errno != EINVAL)
365 0 : fail (0);
366 1 : xfree (out);
367 :
368 1 : out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
369 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
370 : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
371 : "1", "2", NULL);
372 1 : if (!out || strcmp (out,
373 : "1/2/3/4/5/6/7/8/9/10/"
374 : "1/2/3/4/5/6/7/8/9/10/"
375 : "1/2/3/4/5/6/7/8/9/10/"
376 : "1/2"))
377 0 : fail (0);
378 1 : xfree (out);
379 :
380 1 : out = make_filename_try ("foo", "~/bar", "baz/cde", NULL);
381 1 : if (!out || strcmp (out, "foo/~/bar/baz/cde"))
382 0 : fail (1);
383 1 : xfree (out);
384 :
385 1 : out = make_filename_try ("foo", "~/bar", "baz/cde/", NULL);
386 1 : if (!out || strcmp (out, "foo/~/bar/baz/cde/"))
387 0 : fail (1);
388 1 : xfree (out);
389 :
390 1 : out = make_filename_try ("/foo", "~/bar", "baz/cde/", NULL);
391 1 : if (!out || strcmp (out, "/foo/~/bar/baz/cde/"))
392 0 : fail (1);
393 1 : xfree (out);
394 :
395 1 : out = make_filename_try ("//foo", "~/bar", "baz/cde/", NULL);
396 1 : if (!out || strcmp (out, "//foo/~/bar/baz/cde/"))
397 0 : fail (1);
398 1 : xfree (out);
399 :
400 1 : out = make_filename_try ("", "~/bar", "baz/cde", NULL);
401 1 : if (!out || strcmp (out, "/~/bar/baz/cde"))
402 0 : fail (1);
403 1 : xfree (out);
404 :
405 :
406 1 : out = make_filename_try ("~/foo", "bar", NULL);
407 1 : if (!out)
408 0 : fail (2);
409 1 : else if (home)
410 : {
411 1 : if (strlen (out) < homelen + 7)
412 0 : fail (2);
413 1 : else if (strncmp (out, home, homelen))
414 0 : fail (2);
415 1 : else if (strcmp (out+homelen, "/foo/bar"))
416 0 : fail (2);
417 : }
418 : else
419 : {
420 0 : if (strcmp (out, "~/foo/bar"))
421 0 : fail (2);
422 : }
423 1 : xfree (out);
424 :
425 1 : out = make_filename_try ("~", "bar", NULL);
426 1 : if (!out)
427 0 : fail (2);
428 1 : else if (home)
429 : {
430 1 : if (strlen (out) < homelen + 3)
431 0 : fail (2);
432 1 : else if (strncmp (out, home, homelen))
433 0 : fail (2);
434 1 : else if (strcmp (out+homelen, "/bar"))
435 0 : fail (2);
436 : }
437 : else
438 : {
439 0 : if (strcmp (out, "~/bar"))
440 0 : fail (2);
441 : }
442 1 : xfree (out);
443 1 : }
444 :
445 :
446 : static void
447 1 : test_make_absfilename_try (void)
448 : {
449 : char *out;
450 1 : char *cwd = mygetcwd ();
451 1 : size_t cwdlen = strlen (cwd);
452 :
453 1 : out = make_absfilename_try ("foo", "bar", NULL);
454 1 : if (!out)
455 0 : fail (0);
456 1 : else if (strlen (out) < cwdlen + 7)
457 0 : fail (0);
458 1 : else if (strncmp (out, cwd, cwdlen))
459 0 : fail (0);
460 1 : else if (strcmp (out+cwdlen, "/foo/bar"))
461 0 : fail (0);
462 1 : xfree (out);
463 :
464 1 : out = make_absfilename_try ("./foo", NULL);
465 1 : if (!out)
466 0 : fail (1);
467 1 : else if (strlen (out) < cwdlen + 5)
468 0 : fail (1);
469 1 : else if (strncmp (out, cwd, cwdlen))
470 0 : fail (1);
471 1 : else if (strcmp (out+cwdlen, "/./foo"))
472 0 : fail (1);
473 1 : xfree (out);
474 :
475 1 : out = make_absfilename_try (".", NULL);
476 1 : if (!out)
477 0 : fail (2);
478 1 : else if (strlen (out) < cwdlen)
479 0 : fail (2);
480 1 : else if (strncmp (out, cwd, cwdlen))
481 0 : fail (2);
482 1 : else if (strcmp (out+cwdlen, ""))
483 0 : fail (2);
484 1 : xfree (out);
485 :
486 1 : xfree (cwd);
487 1 : }
488 :
489 : static void
490 1 : test_strsplit (void)
491 : {
492 : struct {
493 : const char *s;
494 : char delim;
495 : char replacement;
496 : const char *fields_expected[10];
497 1 : } tv[] = {
498 : {
499 : "a:bc:cde:fghi:jklmn::foo:", ':', '\0',
500 : { "a", "bc", "cde", "fghi", "jklmn", "", "foo", "", NULL }
501 : },
502 : {
503 : ",a,bc,,def,", ',', '!',
504 : { "!a!bc!!def!", "a!bc!!def!", "bc!!def!", "!def!", "def!", "", NULL }
505 : },
506 : {
507 : "", ':', ',',
508 : { "", NULL }
509 : }
510 : };
511 :
512 : int tidx;
513 :
514 4 : for (tidx = 0; tidx < DIM(tv); tidx++)
515 : {
516 : char *s2;
517 : int field_count;
518 : char **fields;
519 : int field_count_expected;
520 : int i;
521 :
522 : /* Count the fields. */
523 21 : for (field_count_expected = 0;
524 18 : tv[tidx].fields_expected[field_count_expected];
525 15 : field_count_expected ++)
526 : ;
527 :
528 : /* We need to copy s since strsplit modifies it in place. */
529 3 : s2 = xstrdup (tv[tidx].s);
530 3 : fields = strsplit (s2, tv[tidx].delim, tv[tidx].replacement,
531 : &field_count);
532 :
533 3 : if (field_count != field_count_expected)
534 0 : fail (tidx * 1000);
535 :
536 18 : for (i = 0; i < field_count_expected; i ++)
537 15 : if (strcmp (tv[tidx].fields_expected[i], fields[i]) != 0)
538 : {
539 0 : printf ("For field %d, expected '%s', but got '%s'\n",
540 0 : i, tv[tidx].fields_expected[i], fields[i]);
541 0 : fail (tidx * 1000 + i + 1);
542 : }
543 :
544 3 : xfree (fields);
545 3 : xfree (s2);
546 : }
547 1 : }
548 :
549 :
550 :
551 : static void
552 1 : test_strtokenize (void)
553 : {
554 : struct {
555 : const char *s;
556 : const char *delim;
557 : const char *fields_expected[10];
558 1 : } tv[] = {
559 : {
560 : "", ":",
561 : { "", NULL }
562 : },
563 : {
564 : "a", ":",
565 : { "a", NULL }
566 : },
567 : {
568 : ":", ":",
569 : { "", "", NULL }
570 : },
571 : {
572 : "::", ":",
573 : { "", "", "", NULL }
574 : },
575 : {
576 : "a:b:c", ":",
577 : { "a", "b", "c", NULL }
578 : },
579 : {
580 : "a:b:", ":",
581 : { "a", "b", "", NULL }
582 : },
583 : {
584 : "a:b", ":",
585 : { "a", "b", NULL }
586 : },
587 : {
588 : "aa:b:cd", ":",
589 : { "aa", "b", "cd", NULL }
590 : },
591 : {
592 : "aa::b:cd", ":",
593 : { "aa", "", "b", "cd", NULL }
594 : },
595 : {
596 : "::b:cd", ":",
597 : { "", "", "b", "cd", NULL }
598 : },
599 : {
600 : "aa: : b:cd ", ":",
601 : { "aa", "", "b", "cd", NULL }
602 : },
603 : {
604 : " aa: : b: cd ", ":",
605 : { "aa", "", "b", "cd", NULL }
606 : },
607 : {
608 : " ", ":",
609 : { "", NULL }
610 : },
611 : {
612 : " :", ":",
613 : { "", "", NULL }
614 : },
615 : {
616 : " : ", ":",
617 : { "", "", NULL }
618 : },
619 : {
620 : ": ", ":",
621 : { "", "", NULL }
622 : },
623 : {
624 : ": x ", ":",
625 : { "", "x", NULL }
626 : },
627 : {
628 : "a:bc:cde:fghi:jklmn::foo:", ":",
629 : { "a", "bc", "cde", "fghi", "jklmn", "", "foo", "", NULL }
630 : },
631 : {
632 : ",a,bc,,def,", ",",
633 : { "", "a", "bc", "", "def", "", NULL }
634 : },
635 : {
636 : " a ", " ",
637 : { "", "a", "", NULL }
638 : },
639 : {
640 : " ", " ",
641 : { "", "", NULL }
642 : },
643 : {
644 : "", " ",
645 : { "", NULL }
646 : }
647 : };
648 :
649 : int tidx;
650 :
651 23 : for (tidx = 0; tidx < DIM(tv); tidx++)
652 : {
653 : char **fields;
654 : int field_count;
655 : int field_count_expected;
656 : int i;
657 :
658 107 : for (field_count_expected = 0;
659 85 : tv[tidx].fields_expected[field_count_expected];
660 63 : field_count_expected ++)
661 : ;
662 :
663 22 : fields = strtokenize (tv[tidx].s, tv[tidx].delim);
664 22 : if (!fields)
665 0 : fail (tidx * 1000);
666 : else
667 : {
668 22 : for (field_count = 0; fields[field_count]; field_count++)
669 : ;
670 22 : if (field_count != field_count_expected)
671 0 : fail (tidx * 1000);
672 : else
673 : {
674 85 : for (i = 0; i < field_count_expected; i++)
675 63 : if (strcmp (tv[tidx].fields_expected[i], fields[i]))
676 : {
677 0 : printf ("For field %d, expected '%s', but got '%s'\n",
678 0 : i, tv[tidx].fields_expected[i], fields[i]);
679 0 : fail (tidx * 1000 + i + 1);
680 : }
681 : }
682 : }
683 :
684 22 : xfree (fields);
685 : }
686 1 : }
687 :
688 :
689 : static void
690 1 : test_split_fields (void)
691 : {
692 : struct {
693 : const char *s;
694 : int nfields;
695 : const char *fields_expected[10];
696 1 : } tv[] = {
697 : {
698 : "a bc cde fghi jklmn foo ", 6,
699 : { "a", "bc", "cde", "fghi", "jklmn", "foo", NULL }
700 : },
701 : {
702 : " a bc def ", 2,
703 : { "a", "bc", "def", NULL }
704 : },
705 : {
706 : " a bc def ", 3,
707 : { "a", "bc", "def", NULL }
708 : },
709 : {
710 : " a bc def ", 4,
711 : { "a", "bc", "def", NULL }
712 : },
713 : {
714 : "", 0,
715 : { NULL }
716 : }
717 : };
718 :
719 : int tidx;
720 : char *fields[10];
721 : int field_count_expected, nfields, field_count, i;
722 : char *s2;
723 :
724 6 : for (tidx = 0; tidx < DIM(tv); tidx++)
725 : {
726 5 : nfields = tv[tidx].nfields;
727 5 : assert (nfields <= DIM (fields));
728 :
729 : /* Count the fields. */
730 25 : for (field_count_expected = 0;
731 20 : tv[tidx].fields_expected[field_count_expected];
732 15 : field_count_expected ++)
733 : ;
734 5 : if (field_count_expected > nfields)
735 1 : field_count_expected = nfields;
736 :
737 : /* We need to copy s since split_fields modifies in place. */
738 5 : s2 = xstrdup (tv[tidx].s);
739 5 : field_count = split_fields (s2, fields, nfields);
740 :
741 5 : if (field_count != field_count_expected)
742 : {
743 0 : printf ("%s: tidx %d: expected %d, got %d\n",
744 : __func__, tidx, field_count_expected, field_count);
745 0 : fail (tidx * 1000);
746 : }
747 : else
748 : {
749 19 : for (i = 0; i < field_count_expected; i ++)
750 14 : if (strcmp (tv[tidx].fields_expected[i], fields[i]))
751 : {
752 0 : printf ("%s: tidx %d, field %d: expected '%s', got '%s'\n",
753 : __func__,
754 : tidx, i, tv[tidx].fields_expected[i], fields[i]);
755 0 : fail (tidx * 1000 + i + 1);
756 : }
757 : }
758 :
759 5 : xfree (s2);
760 : }
761 1 : }
762 :
763 :
764 : static char *
765 0 : stresc (char *s)
766 : {
767 : char *p;
768 0 : int l = strlen (s) + 1;
769 :
770 0 : for (p = s; *p; p ++)
771 0 : if (*p == '\n')
772 0 : l ++;
773 :
774 0 : p = xmalloc (l);
775 0 : for (l = 0; *s; s ++, l ++)
776 : {
777 0 : if (*s == ' ')
778 0 : p[l] = '_';
779 0 : else if (*p == '\n')
780 : {
781 0 : p[l ++] = '\\';
782 0 : p[l ++] = 'n';
783 0 : p[l] = '\n';
784 : }
785 : else
786 0 : p[l] = *s;
787 : }
788 0 : p[l] = *s;
789 :
790 0 : return p;
791 : }
792 :
793 :
794 : static void
795 1 : test_format_text (void)
796 : {
797 : struct test
798 : {
799 : int target_cols, max_cols;
800 : char *input;
801 : char *expected;
802 : };
803 :
804 1 : struct test tests[] = {
805 : {
806 : 10, 12,
807 : "",
808 : "",
809 : },
810 : {
811 : 10, 12,
812 : " ",
813 : "",
814 : },
815 : {
816 : 10, 12,
817 : " ",
818 : "",
819 : },
820 : {
821 : 10, 12,
822 : " \n ",
823 : " \n",
824 : },
825 : {
826 : 10, 12,
827 : " \n \n ",
828 : " \n \n",
829 : },
830 : {
831 : 10, 12,
832 : "0123456789 0123456789 0",
833 : "0123456789\n0123456789\n0",
834 : },
835 : {
836 : 10, 12,
837 : " 0123456789 0123456789 0 ",
838 : " 0123456789\n0123456789\n0",
839 : },
840 : {
841 : 10, 12,
842 : "01 34 67 90 23 56 89 12 45 67 89 1",
843 : "01 34 67\n90 23 56\n89 12 45\n67 89 1"
844 : },
845 : {
846 : 10, 12,
847 : "01 34 67 90 23 56 89 12 45 67 89 1",
848 : "01 34 67\n90 23 56\n89 12 45\n67 89 1"
849 : },
850 : {
851 : 72, 80,
852 : "Warning: if you think you've seen more than 10 messages "
853 : "signed by this key, then this key might be a forgery! "
854 : "Carefully examine the email address for small variations "
855 : "(e.g., additional white space). If the key is suspect, "
856 : "then use 'gpg --tofu-policy bad \"FINGERPRINT\"' to mark it as being bad.\n",
857 : "Warning: if you think you've seen more than 10 messages signed by this\n"
858 : "key, then this key might be a forgery! Carefully examine the email\n"
859 : "address for small variations (e.g., additional white space). If the key\n"
860 : "is suspect, then use 'gpg --tofu-policy bad \"FINGERPRINT\"' to mark it as\n"
861 : "being bad.\n"
862 :
863 : },
864 : {
865 : 72, 80,
866 : "Normally, there is only a single key associated with an email "
867 : "address. However, people sometimes generate a new key if "
868 : "their key is too old or they think it might be compromised. "
869 : "Alternatively, a new key may indicate a man-in-the-middle "
870 : "attack! Before accepting this key, you should talk to or "
871 : "call the person to make sure this new key is legitimate.",
872 : "Normally, there is only a single key associated with an email "
873 : "address.\nHowever, people sometimes generate a new key if "
874 : "their key is too old or\nthey think it might be compromised. "
875 : "Alternatively, a new key may indicate\na man-in-the-middle "
876 : "attack! Before accepting this key, you should talk\nto or "
877 : "call the person to make sure this new key is legitimate.",
878 : }
879 : };
880 :
881 : int i;
882 1 : int failed = 0;
883 :
884 12 : for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i ++)
885 : {
886 11 : struct test *test = &tests[i];
887 11 : char *result =
888 11 : format_text (test->input, 0, test->target_cols, test->max_cols);
889 11 : if (strcmp (result, test->expected) != 0)
890 : {
891 0 : printf ("%s: Test #%d failed.\nExpected: '%s'\nResult: '%s'\n",
892 : __func__, i + 1, stresc (test->expected), stresc (result));
893 0 : failed ++;
894 : }
895 11 : xfree (result);
896 : }
897 :
898 1 : if (failed)
899 0 : fail(0);
900 1 : }
901 :
902 :
903 : static void
904 1 : test_compare_version_strings (void)
905 : {
906 1 : struct { const char *a; const char *b; int okay; } tests[] = {
907 : { "1.0.0", "1.0.0", 0 },
908 : { "1.0.0-", "1.0.0", 1 },
909 : { "1.0.0-1", "1.0.0", 1 },
910 : { "1.0.0.1", "1.0.0", 1 },
911 : { "1.0.0", "1.0.1", -1 },
912 : { "1.0.0-", "1.0.1", -1 },
913 : { "1.0.0-1", "1.0.1", -1 },
914 : { "1.0.0.1", "1.0.1", -1 },
915 : { "1.0.0", "1.1.0", -1 },
916 : { "1.0.0-", "1.1.0", -1 },
917 : { "1.0.0-1", "1.1.0", -1 },
918 : { "1.0.0.1", "1.1.0", -1 },
919 :
920 : { "1.0.0", "1.0.0-", -1 },
921 : { "1.0.0", "1.0.0-1", -1 },
922 : { "1.0.0", "1.0.0.1", -1 },
923 : { "1.1.0", "1.0.0", 1 },
924 : { "1.1.1", "1.1.0", 1 },
925 : { "1.1.2", "1.1.2", 0 },
926 : { "1.1.2", "1.0.2", 1 },
927 : { "1.1.2", "0.0.2", 1 },
928 : { "1.1.2", "1.1.3", -1 },
929 :
930 : { "0.99.1", "0.9.9", 1 },
931 : { "0.9.1", "0.91.0", -1 },
932 :
933 : { "1.5.3", "1.5", 1 },
934 : { "1.5.0", "1.5", 0 },
935 : { "1.4.99", "1.5", -1 },
936 : { "1.5", "1.4.99", 1 },
937 : { "1.5", "1.5.0", 0 },
938 : { "1.5", "1.5.1", -1 },
939 :
940 : { "1.5.3-x17", "1.5-23", 1 },
941 :
942 : { "1.5.3a", "1.5.3", 1 },
943 : { "1.5.3a", "1.5.3b", -1 },
944 :
945 : { "3.1.4-ab", "3.1.4-ab", 0 },
946 : { "3.1.4-ab", "3.1.4-ac", -1 },
947 : { "3.1.4-ac", "3.1.4-ab", 1 },
948 : { "3.1.4-ab", "3.1.4-abb", -1 },
949 : { "3.1.4-abb", "3.1.4-ab", 1 },
950 :
951 : { "", "", INT_MIN },
952 : { NULL, "", INT_MIN },
953 : { "1.2.3", "", INT_MIN },
954 : { "1.2.3", "2", INT_MIN },
955 :
956 : /* Test cases for validity of A. */
957 : { "", NULL, INT_MIN },
958 : { "1", NULL, INT_MIN },
959 : { "1.", NULL, 0 },
960 : { "1.0", NULL, 0 },
961 : { "1.0.", NULL, 0 },
962 : { "a1.2", NULL, INT_MIN },
963 : { NULL, NULL, INT_MIN }
964 : };
965 : int idx;
966 : int res;
967 :
968 49 : for (idx=0; idx < DIM(tests); idx++)
969 : {
970 48 : res = compare_version_strings (tests[idx].a, tests[idx].b);
971 : /* printf ("test %d: '%s' '%s' %d -> %d\n", */
972 : /* idx, tests[idx].a, tests[idx].b, tests[idx].okay, res); */
973 48 : if (res != tests[idx].okay)
974 0 : fail (idx);
975 : }
976 1 : }
977 :
978 :
979 : int
980 1 : main (int argc, char **argv)
981 : {
982 : (void)argc;
983 : (void)argv;
984 :
985 1 : test_percent_escape ();
986 1 : test_compare_filenames ();
987 1 : test_strconcat ();
988 1 : test_xstrconcat ();
989 1 : test_make_filename_try ();
990 1 : test_make_absfilename_try ();
991 1 : test_strsplit ();
992 1 : test_strtokenize ();
993 1 : test_split_fields ();
994 1 : test_compare_version_strings ();
995 1 : test_format_text ();
996 :
997 1 : xfree (home_buffer);
998 1 : return !!errcount;
999 : }
|