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