1 /* Test continue and merge NSS actions for getaddrinfo.
2 Copyright The GNU Toolchain Authors.
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 <dlfcn.h>
20 #include <gnu/lib-names.h>
21 #include <nss.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <support/check.h>
27 #include <support/format_nss.h>
28 #include <support/support.h>
29 #include <support/xstdio.h>
30 #include <support/xunistd.h>
31
32 enum
33 {
34 ACTION_MERGE = 0,
35 ACTION_CONTINUE,
36 };
37
38 static const char *
family_str(int family)39 family_str (int family)
40 {
41 switch (family)
42 {
43 case AF_UNSPEC:
44 return "AF_UNSPEC";
45 case AF_INET:
46 return "AF_INET";
47 default:
48 __builtin_unreachable ();
49 }
50 }
51
52 static const char *
action_str(int action)53 action_str (int action)
54 {
55 switch (action)
56 {
57 case ACTION_MERGE:
58 return "merge";
59 case ACTION_CONTINUE:
60 return "continue";
61 default:
62 __builtin_unreachable ();
63 }
64 }
65
66 static void
do_one_test(int action,int family,bool canon)67 do_one_test (int action, int family, bool canon)
68 {
69 struct addrinfo hints =
70 {
71 .ai_family = family,
72 };
73
74 struct addrinfo *ai;
75
76 if (canon)
77 hints.ai_flags = AI_CANONNAME;
78
79 printf ("***** Testing \"files [SUCCESS=%s] files\" for family %s, %s\n",
80 action_str (action), family_str (family),
81 canon ? "AI_CANONNAME" : "");
82
83 int ret = getaddrinfo ("example.org", "80", &hints, &ai);
84
85 switch (action)
86 {
87 case ACTION_MERGE:
88 if (ret == 0)
89 {
90 char *formatted = support_format_addrinfo (ai, ret);
91
92 printf ("merge unexpectedly succeeded:\n %s\n", formatted);
93 support_record_failure ();
94 free (formatted);
95 }
96 else
97 return;
98 case ACTION_CONTINUE:
99 {
100 char *formatted = support_format_addrinfo (ai, ret);
101
102 /* Verify that the result appears exactly once. */
103 const char *expected = "address: STREAM/TCP 192.0.0.1 80\n"
104 "address: DGRAM/UDP 192.0.0.1 80\n"
105 "address: RAW/IP 192.0.0.1 80\n";
106
107 const char *contains = strstr (formatted, expected);
108 const char *contains2 = NULL;
109
110 if (contains != NULL)
111 contains2 = strstr (contains + strlen (expected), expected);
112
113 if (contains == NULL || contains2 != NULL)
114 {
115 printf ("continue failed:\n%s\n", formatted);
116 support_record_failure ();
117 }
118
119 free (formatted);
120 break;
121 }
122 default:
123 __builtin_unreachable ();
124 }
125 }
126
127 static void
do_one_test_set(int action)128 do_one_test_set (int action)
129 {
130 char buf[32];
131
132 snprintf (buf, sizeof (buf), "files [SUCCESS=%s] files",
133 action_str (action));
134 __nss_configure_lookup ("hosts", buf);
135
136 do_one_test (action, AF_UNSPEC, false);
137 do_one_test (action, AF_INET, false);
138 do_one_test (action, AF_INET, true);
139 }
140
141 static int
do_test(void)142 do_test (void)
143 {
144 do_one_test_set (ACTION_CONTINUE);
145 do_one_test_set (ACTION_MERGE);
146 return 0;
147 }
148
149 #include <support/test-driver.c>
150