1 /* Tests for res_hnok and related functions.
2 Copyright (C) 2017-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <array_length.h>
20 #include <resolv.h>
21 #include <string.h>
22 #include <support/check.h>
23 #include <support/test-driver.h>
24
25 /* Bits which indicate which functions are supposed to report
26 success. */
27 enum
28 {
29 hnok = 1,
30 dnok = 2,
31 mailok = 4,
32 ownok = 8,
33 allnomailok = hnok | dnok | ownok,
34 allok = hnok | dnok | mailok | ownok
35 };
36
37 /* A string of 60 characters. */
38 #define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
39
40 /* A string of 63 characters (maximum label length). */
41 #define STRING63 STRING60 "zzz"
42
43 /* Combines a test name with the expected results. */
44 struct test_case
45 {
46 const char *dn;
47 unsigned int result; /* Combination of the *ok flags. */
48 };
49
50 static const struct test_case tests[] =
51 {
52 { "", allok },
53 { ".", allok },
54 { "..", 0 },
55 { "www", allnomailok },
56 { "www.", allnomailok },
57 { "example", allnomailok },
58 { "example.com", allok },
59 { "www.example.com", allok },
60 { "www.example.com.", allok },
61 { "www-.example.com.", allok },
62 { "www.-example.com.", allok },
63 { "*.example.com", dnok | mailok | ownok },
64 { "-v", dnok },
65 { "-v.example.com", mailok | dnok },
66 { "**.example.com", dnok | mailok },
67 { "www.example.com\\", 0 },
68 { STRING63, allnomailok },
69 { STRING63 ".", allnomailok },
70 { STRING63 "\\.", 0 },
71 { STRING63 "z", 0 },
72 { STRING63 ".example.com", allok },
73 { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok },
74 { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", allok },
75 { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", 0 },
76 { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", 0 },
77 { "hostmaster@mail.example.com", dnok | mailok },
78 { "hostmaster\\@mail.example.com", dnok | mailok },
79 { "with whitespace", 0 },
80 { "with\twhitespace", 0 },
81 { "with\nwhitespace", 0 },
82 { "with.whitespace ", 0 },
83 { "with.whitespace\t", 0 },
84 { "with.whitespace\n", 0 },
85 { "with\\ whitespace", 0 },
86 { "with\\\twhitespace", 0 },
87 { "with\\\nwhitespace", 0 },
88 { "with.whitespace\\ ", 0 },
89 { "with.whitespace\\\t", 0 },
90 { "with.whitespace\\\n", 0 },
91 };
92
93 /* Run test case *TEST with FUNC (named FUNCNAME) and report an error
94 if the result does not match the result flag at BIT. */
95 static void
one_test(const struct test_case * test,const char * funcname,int (* func)(const char *),unsigned int bit)96 one_test (const struct test_case *test, const char *funcname,
97 int (*func) (const char *), unsigned int bit)
98 {
99 int expected = (test->result & bit) != 0;
100 int actual = func (test->dn);
101 if (actual != expected)
102 {
103 support_record_failure ();
104 printf ("error: %s (\"%s\"): expected=%d, actual=%d\n",
105 funcname, test->dn, expected, actual);
106 }
107 }
108
109 /* Run 255 tests using all the bytes from 1 to 255, surround the byte
110 with the strings PREFIX and SUFFIX, and check that FUNC (named
111 FUNCNAME) accepts only those bytes listed in ACCEPTED. */
112 static void
one_char(const char * prefix,const char * accepted,const char * suffix,const char * funcname,int (* func)(const char *))113 one_char (const char *prefix, const char *accepted, const char *suffix,
114 const char *funcname, int (*func) (const char *))
115 {
116 for (int ch = 1; ch <= 255; ++ch)
117 {
118 char dn[1024];
119 snprintf (dn, sizeof (dn), "%s%c%s", prefix, ch, suffix);
120 int expected = strchr (accepted, ch) != NULL;
121 int actual = func (dn);
122 if (actual != expected)
123 {
124 support_record_failure ();
125 printf ("error: %s (\"%s\"): expected=%d, actual=%d\n",
126 funcname, dn, expected, actual);
127 }
128 }
129 }
130
131 #define LETTERSDIGITS \
132 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
133
134 #define PRINTABLE \
135 "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~"
136
137 static int
do_test(void)138 do_test (void)
139 {
140 for (const struct test_case *test = tests; test < array_end (tests); ++test)
141 {
142 if (test_verbose)
143 printf ("info: testing domain name [[[%s]]] (0x%x)\n",
144 test->dn, test->result);
145 one_test (test, "res_hnok", res_hnok, hnok);
146 one_test (test, "res_dnok", res_dnok, dnok);
147 one_test (test, "res_mailok", res_mailok, mailok);
148 one_test (test, "res_ownok", res_ownok, ownok);
149 }
150
151 one_char
152 ("", LETTERSDIGITS "._", "", "res_hnok", res_hnok);
153 one_char
154 ("middle",
155 LETTERSDIGITS ".-_\\", /* "middle\\suffix" == "middlesuffix", so good. */
156 "suffix", "res_hnok", res_hnok);
157 one_char
158 ("middle",
159 LETTERSDIGITS ".-_" PRINTABLE,
160 "suffix.example", "res_mailok", res_mailok);
161 one_char
162 ("mailbox.middle",
163 LETTERSDIGITS ".-_\\",
164 "suffix.example", "res_mailok", res_mailok);
165
166 return 0;
167 }
168
169 #include <support/test-driver.c>
170