LCOV - code coverage report
Current view: top level - common - t-stringhelp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 241 346 69.7 %
Date: 2016-11-29 15:00:56 Functions: 14 15 93.3 %

          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             : }

Generated by: LCOV version 1.11