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 }