dcd5a453fd5730d83bc72b3f6723556b45f32a88
[gnupg.git] / common / t-stringhelp.c
1 /* t-stringhelp.c - Regression tests for stringhelp.c
2  * Copyright (C) 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of JNLIB, which is a subsystem of GnuPG.
5  *
6  * JNLIB is free software; you can redistribute it and/or modify it
7  * under the terms of either
8  *
9  *   - the GNU Lesser General Public License as published by the Free
10  *     Software Foundation; either version 3 of the License, or (at
11  *     your option) any later version.
12  *
13  * or
14  *
15  *   - the GNU General Public License as published by the Free
16  *     Software Foundation; either version 2 of the License, or (at
17  *     your option) any later version.
18  *
19  * or both in parallel, as here.
20  *
21  * JNLIB is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * General Public License for more details.
25  *
26  * You should have received a copies of the GNU General Public License
27  * and the GNU Lesser General Public License along with this program;
28  * if not, see <http://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 #ifdef HAVE_PWD_H
37 # include <pwd.h>
38 #endif
39 #include <unistd.h>
40 #include <sys/types.h>
41
42 #include "stringhelp.h"
43
44 #include "t-support.h"
45
46
47 static char *home_buffer;
48
49
50 const char *
51 gethome (void)
52 {
53   if (!home_buffer)
54     {
55       char *home = getenv("HOME");
56
57       if(home)
58         home_buffer = xstrdup (home);
59 #if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H)
60       else
61         {
62           struct passwd *pwd;
63
64           pwd = getpwuid (getuid());
65           if (pwd)
66             home_buffer = xstrdup (pwd->pw_dir);
67         }
68 #endif
69     }
70   return home_buffer;
71 }
72
73
74 static char *
75 mygetcwd (void)
76 {
77   char *buffer;
78   size_t size = 100;
79
80   for (;;)
81     {
82       buffer = xmalloc (size+1);
83 #ifdef HAVE_W32CE_SYSTEM
84       strcpy (buffer, "/");  /* Always "/".  */
85       return buffer;
86 #else
87       if (getcwd (buffer, size) == buffer)
88         return buffer;
89       xfree (buffer);
90       if (errno != ERANGE)
91         {
92           fprintf (stderr,"error getting current cwd: %s\n",
93                    strerror (errno));
94           exit (2);
95         }
96       size *= 2;
97 #endif
98     }
99 }
100
101
102 static void
103 test_percent_escape (void)
104 {
105   char *result;
106   static struct {
107     const char *extra;
108     const char *value;
109     const char *expected;
110   } tests[] =
111     {
112       { NULL, "", "" },
113       { NULL, "%", "%25" },
114       { NULL, "%%", "%25%25" },
115       { NULL, " %", " %25" },
116       { NULL, ":", "%3a" },
117       { NULL, " :", " %3a" },
118       { NULL, ": ", "%3a " },
119       { NULL, " : ", " %3a " },
120       { NULL, "::", "%3a%3a" },
121       { NULL, ": :", "%3a %3a" },
122       { NULL, "%:", "%25%3a" },
123       { NULL, ":%", "%3a%25" },
124       { "\\\n:", ":%", "%3a%25" },
125       { "\\\n:", "\\:%", "%5c%3a%25" },
126       { "\\\n:", "\n:%", "%0a%3a%25" },
127       { "\\\n:", "\xff:%", "\xff%3a%25" },
128       { "\\\n:", "\xfe:%", "\xfe%3a%25" },
129       { "\\\n:", "\x01:%", "\x01%3a%25" },
130       { "\x01",  "\x01:%", "%01%3a%25" },
131       { "\xfe",  "\xfe:%", "%fe%3a%25" },
132       { "\xfe",  "\xff:%", "\xff%3a%25" },
133
134       { NULL, NULL, NULL }
135     };
136   int testno;
137
138   result = percent_escape (NULL, NULL);
139   if (result)
140     fail (0);
141   for (testno=0; tests[testno].value; testno++)
142     {
143       result = percent_escape (tests[testno].value, tests[testno].extra);
144       if (!result)
145         fail (testno);
146       if (strcmp (result, tests[testno].expected))
147         fail (testno);
148       xfree (result);
149     }
150
151 }
152
153
154 static void
155 test_compare_filenames (void)
156 {
157   struct {
158     const char *a;
159     const char *b;
160     int result;
161   } tests[] = {
162     { "", "", 0 },
163     { "", "a", -1 },
164     { "a", "", 1 },
165     { "a", "a", 0 },
166     { "a", "aa", -1 },
167     { "aa", "a", 1 },
168     { "a",  "b", -1  },
169
170 #ifdef HAVE_W32_SYSTEM
171     { "a", "A", 0 },
172     { "A", "a", 0 },
173     { "foo/bar", "foo\\bar", 0 },
174     { "foo\\bar", "foo/bar", 0 },
175     { "foo\\", "foo/", 0 },
176     { "foo/", "foo\\", 0 },
177 #endif /*HAVE_W32_SYSTEM*/
178     { NULL, NULL, 0}
179   };
180   int testno, result;
181
182   for (testno=0; tests[testno].a; testno++)
183     {
184       result = compare_filenames (tests[testno].a, tests[testno].b);
185       result = result < 0? -1 : result > 0? 1 : 0;
186       if (result != tests[testno].result)
187         fail (testno);
188     }
189 }
190
191
192 static void
193 test_strconcat (void)
194 {
195   char *out;
196
197   out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
198                    "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", NULL);
202   if (!out)
203     fail (0);
204   else
205     xfree (out);
206   out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
207                    "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", NULL);
211   if (out)
212     fail (0);
213   else if (errno != EINVAL)
214     fail (0);
215
216   out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
217                    "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", NULL);
221   if (out)
222     fail (0);
223   else if (errno != EINVAL)
224     fail (0);
225
226 #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute.  */
227   out = strconcat (NULL);
228   if (!out || *out)
229     fail (1);
230 #endif
231   out = strconcat (NULL, NULL);
232   if (!out || *out)
233     fail (1);
234   out = strconcat ("", NULL);
235   if (!out || *out)
236     fail (1);
237   xfree (out);
238
239   out = strconcat ("", "", NULL);
240   if (!out || *out)
241     fail (2);
242   xfree (out);
243
244   out = strconcat ("a", "b", NULL);
245   if (!out || strcmp (out, "ab"))
246     fail (3);
247   xfree (out);
248   out = strconcat ("a", "b", "c", NULL);
249   if (!out || strcmp (out, "abc"))
250     fail (3);
251   xfree (out);
252
253   out = strconcat ("a", "b", "cc", NULL);
254   if (!out || strcmp (out, "abcc"))
255     fail (4);
256   xfree (out);
257   out = strconcat ("a1", "b1", "c1", NULL);
258   if (!out || strcmp (out, "a1b1c1"))
259     fail (4);
260   xfree (out);
261
262   out = strconcat ("", " long b ", "", "--even-longer--", NULL);
263   if (!out || strcmp (out, " long b --even-longer--"))
264     fail (5);
265   xfree (out);
266
267   out = strconcat ("", " long b ", "", "--even-longer--", NULL);
268   if (!out || strcmp (out, " long b --even-longer--"))
269     fail (5);
270   xfree (out);
271 }
272
273 static void
274 test_xstrconcat (void)
275 {
276   char *out;
277
278   out = xstrconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
279                    "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", NULL);
283   if (!out)
284     fail (0);
285
286 #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute.  */
287   out = xstrconcat (NULL);
288   if (!out)
289     fail (1);
290 #endif
291   out = xstrconcat (NULL, NULL);
292   if (!out)
293     fail (1);
294   out = xstrconcat ("", NULL);
295   if (!out || *out)
296     fail (1);
297   xfree (out);
298
299   out = xstrconcat ("", "", NULL);
300   if (!out || *out)
301     fail (2);
302   xfree (out);
303
304   out = xstrconcat ("a", "b", NULL);
305   if (!out || strcmp (out, "ab"))
306     fail (3);
307   xfree (out);
308   out = xstrconcat ("a", "b", "c", NULL);
309   if (!out || strcmp (out, "abc"))
310     fail (3);
311   xfree (out);
312
313   out = xstrconcat ("a", "b", "cc", NULL);
314   if (!out || strcmp (out, "abcc"))
315     fail (4);
316   xfree (out);
317   out = xstrconcat ("a1", "b1", "c1", NULL);
318   if (!out || strcmp (out, "a1b1c1"))
319     fail (4);
320   xfree (out);
321
322   out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
323   if (!out || strcmp (out, " long b --even-longer--"))
324     fail (5);
325   xfree (out);
326
327   out = xstrconcat ("", " long b ", "", "--even-longer--", NULL);
328   if (!out || strcmp (out, " long b --even-longer--"))
329     fail (5);
330   xfree (out);
331 }
332
333
334 static void
335 test_make_filename_try (void)
336 {
337   char *out;
338   const char *home = gethome ();
339   size_t homelen = home? strlen (home):0;
340
341   out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
342                            "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", NULL);
345   if (out)
346     fail (0);
347   else if (errno != EINVAL)
348     fail (0);
349   xfree (out);
350   out = make_filename_try ("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", "4", "5", "6", "7", "8", "9", "10",
353                            "1", "2", "3", "4", NULL);
354   if (out)
355     fail (0);
356   else if (errno != EINVAL)
357     fail (0);
358   xfree (out);
359
360   out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
361                            "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
362                            "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
363                            "1", "2", NULL);
364   if (!out || strcmp (out,
365                       "1/2/3/4/5/6/7/8/9/10/"
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"))
369     fail (0);
370   xfree (out);
371
372   out = make_filename_try ("foo", "~/bar", "baz/cde", NULL);
373   if (!out || strcmp (out, "foo/~/bar/baz/cde"))
374     fail (1);
375   xfree (out);
376
377   out = make_filename_try ("foo", "~/bar", "baz/cde/", NULL);
378   if (!out || strcmp (out, "foo/~/bar/baz/cde/"))
379     fail (1);
380   xfree (out);
381
382   out = make_filename_try ("/foo", "~/bar", "baz/cde/", NULL);
383   if (!out || strcmp (out, "/foo/~/bar/baz/cde/"))
384     fail (1);
385   xfree (out);
386
387   out = make_filename_try ("//foo", "~/bar", "baz/cde/", NULL);
388   if (!out || strcmp (out, "//foo/~/bar/baz/cde/"))
389     fail (1);
390   xfree (out);
391
392   out = make_filename_try ("", "~/bar", "baz/cde", NULL);
393   if (!out || strcmp (out, "/~/bar/baz/cde"))
394     fail (1);
395   xfree (out);
396
397
398   out = make_filename_try ("~/foo", "bar", NULL);
399   if (!out)
400     fail (2);
401   if (home)
402     {
403       if (strlen (out) < homelen + 7)
404         fail (2);
405       if (strncmp (out, home, homelen))
406         fail (2);
407       if (strcmp (out+homelen, "/foo/bar"))
408         fail (2);
409     }
410   else
411     {
412       if (strcmp (out, "~/foo/bar"))
413         fail (2);
414     }
415   xfree (out);
416
417   out = make_filename_try ("~", "bar", NULL);
418   if (!out)
419     fail (2);
420   if (home)
421     {
422       if (strlen (out) < homelen + 3)
423         fail (2);
424       if (strncmp (out, home, homelen))
425         fail (2);
426       if (strcmp (out+homelen, "/bar"))
427         fail (2);
428     }
429   else
430     {
431       if (strcmp (out, "~/bar"))
432         fail (2);
433     }
434   xfree (out);
435 }
436
437
438 static void
439 test_make_absfilename_try (void)
440 {
441   char *out;
442   char *cwd = mygetcwd ();
443   size_t cwdlen = strlen (cwd);
444
445   out = make_absfilename_try ("foo", "bar", NULL);
446   if (!out)
447     fail (0);
448   if (strlen (out) < cwdlen + 7)
449     fail (0);
450   if (strncmp (out, cwd, cwdlen))
451     fail (0);
452   if (strcmp (out+cwdlen, "/foo/bar"))
453     fail (0);
454   xfree (out);
455
456   out = make_absfilename_try ("./foo", NULL);
457   if (!out)
458     fail (1);
459   if (strlen (out) < cwdlen + 5)
460     fail (1);
461   if (strncmp (out, cwd, cwdlen))
462     fail (1);
463   if (strcmp (out+cwdlen, "/./foo"))
464     fail (1);
465   xfree (out);
466
467   out = make_absfilename_try (".", NULL);
468   if (!out)
469     fail (2);
470   if (strlen (out) < cwdlen)
471     fail (2);
472   if (strncmp (out, cwd, cwdlen))
473     fail (2);
474   if (strcmp (out+cwdlen, ""))
475     fail (2);
476   xfree (out);
477
478   xfree (cwd);
479 }
480
481
482 int
483 main (int argc, char **argv)
484 {
485   (void)argc;
486   (void)argv;
487
488   test_percent_escape ();
489   test_compare_filenames ();
490   test_strconcat ();
491   test_xstrconcat ();
492   test_make_filename_try ();
493   test_make_absfilename_try ();
494
495   xfree (home_buffer);
496   return 0;
497 }