merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

test_validators.c (6511B)


      1 /*
      2   This file is part of TALER
      3   (C) 2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 
     17 /**
     18  * @file util/test_validators.c
     19  * @brief Tests for validators.
     20  * @author Christian Grothoff (ivan@avalos.me)
     21  */
     22 #include "taler/platform.h"
     23 #include <gnunet/gnunet_util_lib.h>
     24 #include "taler/taler_merchant_util.h"
     25 
     26 static bool
     27 check_email (void)
     28 {
     29   struct
     30   {
     31     const char *email;
     32     bool expected;
     33   } tests[] = {
     34     /* Valid emails */
     35     {"user@example.com", true},
     36     {"john.doe@example.co.uk", true},
     37     {"alice+tag@domain.org", true},
     38     {"test_underscore@test.example", true},
     39     {"user!special@example.com", true},
     40     {"first.last@sub.domain.example.com", true},
     41     {"\"john doe\"@example.com", true},
     42     {"\"very.unusual.@.unusual.com\"@example.com", true},
     43     {"user@192.168.1.1", true},
     44     {"user@[192.168.1.1]", true},
     45     {"user@[IPv6:2001:db8::1]", true},
     46     {"user@[IPv6::1]", true},
     47     {"a@b.c", true},
     48     {"test+123@test-domain.org", true},
     49     {"_test@example.com", true},
     50     {"1234567890@example.com", true},
     51 
     52     /* Invalid emails */
     53     {"", false},
     54     {"plainaddress", false},
     55     {"@example.com", false},
     56     {"user@", false},
     57     {"user name@example.com", false},
     58     {"user@domain", false},  /* No TLD - debatable, but common validation */
     59     {"user..name@example.com", false},
     60     {".user@example.com", false},
     61     {"user.@example.com", false},
     62     {"user@.example.com", false},
     63     {"user@example.com.", false},
     64     {"user@-example.com", false},
     65     {"user@example-.com", false},
     66     {"user@@example.com", false},
     67     {"user@exam ple.com", false},
     68     {"user@[256.256.256.256]", false},
     69     {"user@[IPv6:zzzz::1]", false},
     70   };
     71 
     72   unsigned int num_tests = sizeof (tests) / sizeof (tests[0]);
     73   unsigned int passed = 0;
     74   unsigned int failed = 0;
     75 
     76   for (unsigned int i = 0; i < num_tests; i++)
     77   {
     78     bool result = TALER_MERCHANT_email_valid (tests[i].email);
     79     bool success = (result == tests[i].expected);
     80 
     81     if (success)
     82     {
     83       passed++;
     84       continue;
     85     }
     86     failed++;
     87     fprintf (stderr,
     88              "FAIL: \"%s\" -> %s (expected %s)\n",
     89              tests[i].email ? tests[i].email : "(NULL)",
     90              result ? "VALID" : "INVALID",
     91              tests[i].expected ? "VALID" : "INVALID");
     92   }
     93   return (failed > 0) ? 1 : 0;
     94 }
     95 
     96 
     97 static bool
     98 check_phone (void)
     99 {
    100   struct
    101   {
    102     const char *phone;
    103     const char *expected_normalized;
    104     bool allow_letters;
    105   } tests[] = {
    106     /* Valid phone numbers with +CC - digits only */
    107     {"+1-202-555-0173", "+12025550173", false},
    108     {"+1 202 555 0173", "+12025550173", false},
    109     {"+1 (202) 555-0173", "+12025550173", false},
    110     {"+33142685300", "+33142685300", false},
    111     {"+33 1 42 68 53 00", "+33142685300", false},
    112     {"+44 20 7946 0958", "+442079460958", false},
    113     {"+44.20.7946.0958", "+442079460958", false},
    114     {"+49-30-12345678", "+493012345678", false},
    115     {"+886 2 2345 6789", "+886223456789", false},
    116     {"+1-800-555-0123", "+18005550123", false},
    117     {"+81-3-1234-5678", "+81312345678", false},
    118     {"+39 06 6994 0255", "+390669940255", false},
    119     {"+34-91-577-3200", "+34915773200", false},
    120     {"+46 8 123456", "+468123456", false},
    121     {"+1(555)1234567", "+15551234567", false},
    122     {"+1-555-1234567", "+15551234567", false},
    123     {"+358 9 1234567", "+35891234567", false},
    124     {"+1 202-555.0173", "+12025550173", false},
    125     {"+7 495 123-45-67", "+74951234567", false},
    126 
    127     /* Valid phone numbers with letters (allow_letters=true) */
    128     {"+1-800-CALL-NOW", "+18002255669", true},
    129     {"+1-800-FLOWERS", "+18003569377", true},
    130     {"+1-888-PIZZA", "+188874992", true},
    131     {"+1 800 CALL NOW", "+18002255669", true},
    132     {"+44-HELLO-WORLD", "+444355696753", true},
    133     {"+1-555-ABCDEFGH", "+155522233344", true},
    134 
    135     /* Letters should fail when allow_letters=false */
    136     {"+1-800-CALL-NOW", NULL, false},
    137     {"+1-800-FLOWERS", NULL, false},
    138 
    139     /* Invalid phone numbers */
    140     {NULL, NULL, false},
    141     {"", NULL, false},
    142     {"202-555-0173", NULL, false},          /* Missing + */
    143     {"1-202-555-0173", NULL, false},        /* Missing + */
    144     {"+1", NULL, false},                    /* Only country code */
    145     {"+1 abc def ghij", NULL, false},       /* Invalid format */
    146     {"1-800-555-0123", NULL, false},        /* No plus sign */
    147     {"++1-202-555-0173", NULL, false},      /* Double plus */
    148     {"+1--202-555-0173", NULL, false},      /* Double hyphen */
    149     {"+12025550173 ", NULL, false},         /* Trailing space */
    150     {" +12025550173", NULL, false},         /* Leading space */
    151     {"+1 (555", NULL, false},               /* Unclosed parenthesis */
    152     {"+1 555)", NULL, false},               /* Unmatched closing paren */
    153     {"+1-555-", NULL, false},               /* Trailing hyphen */
    154     {"+1-555-01a3", NULL, false},           /* Lowercase letter without allow_letters */
    155     {"+1 (202", NULL, false},               /* Unmatched paren */
    156   };
    157 
    158   unsigned int num_tests = sizeof (tests) / sizeof (tests[0]);
    159   unsigned int passed = 0;
    160   unsigned int failed = 0;
    161 
    162   for (unsigned int i = 0; i < num_tests; i++)
    163   {
    164     char *result = TALER_MERCHANT_phone_valid (tests[i].phone,
    165                                                tests[i].allow_letters);
    166     bool success;
    167 
    168     if (NULL == tests[i].expected_normalized)
    169     {
    170       success = (NULL == result);
    171     }
    172     else
    173     {
    174       success = (NULL != result &&
    175                  0 == strcmp (result,
    176                               tests[i].expected_normalized));
    177     }
    178     if (success)
    179     {
    180       passed++;
    181     }
    182     else
    183     {
    184       failed++;
    185       fprintf (stderr,
    186                "FAIL: (`%s' (letters=%s) -> `%s'",
    187                tests[i].phone,
    188                tests[i].allow_letters ? "true" : "false",
    189                result);
    190     }
    191     GNUNET_free (result);
    192   }
    193   return (failed > 0) ? 1 : 0;
    194 }
    195 
    196 
    197 int
    198 main (void)
    199 {
    200   if (! check_email ())
    201     return 1;
    202   if (! check_phone ())
    203     return 1;
    204   return 0;
    205 }