common: Prepare for parsing mail sub-addresses.
[gnupg.git] / common / t-stringhelp.c
index db0e811..7c6fb80 100644 (file)
@@ -4,8 +4,8 @@
  *
  * This file is part of GnuPG.
  *
- * GnuPG is free software; you can redistribute it and/or modify it
- * under the terms of either
+ * GnuPG is free software; you can redistribute and/or modify this
+ * part of GnuPG under the terms of either
  *
  *   - the GNU Lesser General Public License as published by the Free
  *     Software Foundation; either version 3 of the License, or (at
@@ -26,7 +26,7 @@
  *
  * You should have received a copies of the GNU General Public License
  * and the GNU Lesser General Public License along with this program;
- * if not, see <http://www.gnu.org/licenses/>.
+ * if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -40,6 +40,7 @@
 #endif
 #include <unistd.h>
 #include <sys/types.h>
+#include <limits.h>
 
 #include "t-support.h"
 #include "stringhelp.h"
@@ -223,6 +224,7 @@ test_strconcat (void)
     fail (0);
   else if (errno != EINVAL)
     fail (0);
+  xfree (out);
 
 #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute.  */
   out = strconcat (NULL);
@@ -232,6 +234,8 @@ test_strconcat (void)
   out = strconcat (NULL, NULL);
   if (!out || *out)
     fail (1);
+  xfree (out);
+
   out = strconcat ("", NULL);
   if (!out || *out)
     fail (1);
@@ -283,6 +287,7 @@ test_xstrconcat (void)
                    "1", "2", "3", "4", "5", "6", "7", NULL);
   if (!out)
     fail (0);
+  xfree (out);
 
 #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute.  */
   out = xstrconcat (NULL);
@@ -292,6 +297,8 @@ test_xstrconcat (void)
   out = xstrconcat (NULL, NULL);
   if (!out)
     fail (1);
+  xfree (out);
+
   out = xstrconcat ("", NULL);
   if (!out || *out)
     fail (1);
@@ -534,6 +541,7 @@ test_strsplit (void)
             fail (tidx * 1000 + i + 1);
           }
 
+      xfree (fields);
       xfree (s2);
     }
 }
@@ -733,7 +741,82 @@ test_split_fields (void)
       if (field_count != field_count_expected)
         {
           printf ("%s: tidx %d: expected %d, got %d\n",
-                  __func__, tidx, i, field_count_expected, field_count);
+                  __func__, tidx, field_count_expected, field_count);
+          fail (tidx * 1000);
+        }
+      else
+        {
+          for (i = 0; i < field_count_expected; i ++)
+            if (strcmp (tv[tidx].fields_expected[i], fields[i]))
+              {
+                printf ("%s: tidx %d, field %d: expected '%s', got '%s'\n",
+                        __func__,
+                        tidx, i, tv[tidx].fields_expected[i], fields[i]);
+                fail (tidx * 1000 + i + 1);
+              }
+        }
+
+      xfree (s2);
+    }
+}
+
+
+static void
+test_split_fields_colon (void)
+{
+  struct {
+    const char *s;
+    int nfields;
+    const char *fields_expected[10];
+  } tv[] = {
+    {
+      "a:bc:cde:fghi:jklmn:  foo ", 6,
+      { "a", "bc", "cde", "fghi", "jklmn", "  foo ", NULL }
+    },
+    {
+      " a:bc: def ", 2,
+      { " a", "bc", NULL }
+    },
+    {
+      " a:bc :def ", 3,
+      { " a", "bc ", "def ", NULL }
+    },
+    {
+      " a:bc: def ", 4,
+      { " a", "bc", " def ", NULL }
+    },
+    {
+      "", 0,
+      { NULL }
+    }
+  };
+
+  int tidx;
+  char *fields[10];
+  int field_count_expected, nfields, field_count, i;
+  char *s2;
+
+  for (tidx = 0; tidx < DIM(tv); tidx++)
+    {
+      nfields = tv[tidx].nfields;
+      assert (nfields <= DIM (fields));
+
+      /* Count the fields.  */
+      for (field_count_expected = 0;
+           tv[tidx].fields_expected[field_count_expected];
+           field_count_expected ++)
+        ;
+      if (field_count_expected > nfields)
+        field_count_expected = nfields;
+
+      /* We need to copy s since split_fields modifies in place.  */
+      s2 = xstrdup (tv[tidx].s);
+      field_count = split_fields_colon (s2, fields, nfields);
+
+      if (field_count != field_count_expected)
+        {
+          printf ("%s: tidx %d: expected %d, got %d\n",
+                  __func__, tidx, field_count_expected, field_count);
           fail (tidx * 1000);
         }
       else
@@ -877,7 +960,12 @@ test_format_text (void)
     {
       struct test *test = &tests[i];
       char *result =
-        format_text (test->input, 0, test->target_cols, test->max_cols);
+        format_text (test->input, test->target_cols, test->max_cols);
+      if (!result)
+        {
+          fail (1);
+          exit (2);
+        }
       if (strcmp (result, test->expected) != 0)
         {
           printf ("%s: Test #%d failed.\nExpected: '%s'\nResult: '%s'\n",
@@ -896,45 +984,63 @@ static void
 test_compare_version_strings (void)
 {
   struct { const char *a; const char *b; int okay; } tests[] = {
-    { "1.0.0",   "1.0.0", 1 },
+    { "1.0.0",   "1.0.0", 0 },
     { "1.0.0-",  "1.0.0", 1 },
     { "1.0.0-1", "1.0.0", 1 },
     { "1.0.0.1", "1.0.0", 1 },
-    { "1.0.0",   "1.0.1", 0 },
-    { "1.0.0-",  "1.0.1", 0 },
-    { "1.0.0-1", "1.0.1", 0 },
-    { "1.0.0.1", "1.0.1", 0 },
-    { "1.0.0",   "1.1.0", 0 },
-    { "1.0.0-",  "1.1.0", 0 },
-    { "1.0.0-1", "1.1.0", 0 },
-    { "1.0.0.1", "1.1.0", 0 },
-
-    { "1.0.0",   "1.0.0-", 1 },
-    { "1.0.0",   "1.0.0-1", 1 },
-    { "1.0.0",   "1.0.0.1", 1 },
+    { "1.0.0",   "1.0.1", -1 },
+    { "1.0.0-",  "1.0.1", -1 },
+    { "1.0.0-1", "1.0.1", -1 },
+    { "1.0.0.1", "1.0.1", -1 },
+    { "1.0.0",   "1.1.0", -1 },
+    { "1.0.0-",  "1.1.0", -1 },
+    { "1.0.0-1", "1.1.0", -1 },
+    { "1.0.0.1", "1.1.0", -1 },
+
+    { "1.0.0",   "1.0.0-", -1 },
+    { "1.0.0",   "1.0.0-1", -1 },
+    { "1.0.0",   "1.0.0.1", -1 },
     { "1.1.0",   "1.0.0", 1 },
     { "1.1.1",   "1.1.0", 1 },
-    { "1.1.2",   "1.1.2", 1 },
+    { "1.1.2",   "1.1.2", 0 },
     { "1.1.2",   "1.0.2", 1 },
     { "1.1.2",   "0.0.2", 1 },
-    { "1.1.2",   "1.1.3", 0 },
+    { "1.1.2",   "1.1.3", -1 },
 
     { "0.99.1",  "0.9.9", 1 },
-    { "0.9.1",   "0.91.0", 0 },
+    { "0.9.1",   "0.91.0", -1 },
 
     { "1.5.3",   "1.5",  1 },
-    { "1.5.0",   "1.5",  1 },
-    { "1.4.99",  "1.5",  0 },
+    { "1.5.0",   "1.5",  0 },
+    { "1.4.99",  "1.5",  -1 },
     { "1.5",     "1.4.99",  1 },
-    { "1.5",     "1.5.0",  1 },
-    { "1.5",     "1.5.1",  0 },
+    { "1.5",     "1.5.0",  0 },
+    { "1.5",     "1.5.1",  -1 },
 
     { "1.5.3-x17",   "1.5-23",  1 },
 
     { "1.5.3a",   "1.5.3",  1 },
-    { "1.5.3a",   "1.5.3b",  1 },
-
-    { NULL, NULL, 0 }
+    { "1.5.3a",   "1.5.3b",  -1 },
+
+    { "3.1.4-ab", "3.1.4-ab", 0 },
+    { "3.1.4-ab", "3.1.4-ac", -1 },
+    { "3.1.4-ac", "3.1.4-ab", 1 },
+    { "3.1.4-ab", "3.1.4-abb", -1 },
+    { "3.1.4-abb", "3.1.4-ab", 1 },
+
+    { "",       "",   INT_MIN },
+    { NULL,     "",   INT_MIN },
+    { "1.2.3",  "",   INT_MIN },
+    { "1.2.3",  "2",  INT_MIN },
+
+    /* Test cases for validity of A.  */
+    { "",      NULL, INT_MIN },
+    { "1",     NULL, INT_MIN },
+    { "1.",    NULL, 0       },
+    { "1.0",   NULL, 0       },
+    { "1.0.",  NULL, 0       },
+    { "a1.2",  NULL, INT_MIN },
+    { NULL,    NULL, INT_MIN }
   };
   int idx;
   int res;
@@ -965,6 +1071,7 @@ main (int argc, char **argv)
   test_strsplit ();
   test_strtokenize ();
   test_split_fields ();
+  test_split_fields_colon ();
   test_compare_version_strings ();
   test_format_text ();