1 /* Common code for NSS test cases.
2 Copyright (C) 2017-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
20 /* There are two (or more) NSS test modules named nss_test1,
21 nss_test2, etc. Each one will call a function IN THE TEST CASE
22 called _nss_test1_init_hook(test_tables *) (or _nss_test2_*, etc).
24 In your copy of the hook function, you may change the *_table
25 pointers in the passed struct to point to static tables in your
26 test case, and the test modules will use that table instead.
28 Your tables MUST end with an entry that has a *_LAST() macro.
29 Use the *_ISLAST() macro to test for end of list.
31 Use __nss_configure_lookup("passwd", "test1 test2") (for example) to
32 configure NSS to use the test modules. */
39 typedef struct test_tables
{
40 struct passwd
*pwd_table
;
41 struct group
*grp_table
;
42 struct spwd
*spwd_table
;
43 struct hostent
*host_table
;
46 extern void _nss_test1_init_hook (test_tables
*) __attribute__((weak
));
47 extern void _nss_test2_init_hook (test_tables
*) __attribute__((weak
));
49 #define PWD_LAST() { .pw_name = NULL, .pw_uid = 0 }
50 #define GRP_LAST() { .gr_name = NULL, .gr_gid = 0 }
51 #define SPWD_LAST() { .sp_namp = NULL, .sp_pwdp = NULL }
52 #define HOST_LAST() { .h_name = NULL, .h_aliases = NULL, .h_length = 0, .h_addr_list = NULL }
54 #define PWD_ISLAST(p) ((p)->pw_name == NULL && (p)->pw_uid == 0)
55 #define GRP_ISLAST(g) ((g)->gr_name == NULL && (g)->gr_gid == 0)
56 #define SPWD_ISLAST(s) ((s)->sp_namp == NULL && (s)->sp_pwdp == 0)
57 #define HOST_ISLAST(h) ((h)->h_name == NULL && (h)->h_length == 0)
59 /* Macros to fill in the tables easily. */
61 /* Note that the "unparameterized" fields are not magic; they're just
62 arbitrary values. Tests which need to verify those fields should
63 fill them in explicitly. */
66 { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \
67 .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \
68 .pw_shell = (char *) "*" }
71 { .pw_name = (char *) n, .pw_passwd = (char *) "*", .pw_uid = u, \
72 .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \
73 .pw_shell = (char *) "*" }
76 { .gr_name = (char *) "name" #u, .gr_passwd = (char *) "*", .gr_gid = u, \
77 .gr_mem = (char **) group_##u }
79 #define GRP_N(u,n,m) \
80 { .gr_name = (char *) n, .gr_passwd = (char *) "*", .gr_gid = u, \
81 .gr_mem = (char **) m }
84 { .sp_namp = (char *) "name" #u, .sp_pwdp = (char *) "passwd" #u }
87 { .h_name = (char *) "name" #u, .h_aliases = NULL, .h_addrtype = u, \
89 .h_addr_list = (char **) hostaddr_##u }
91 /*------------------------------------------------------------*/
93 /* Helper functions for testing passwd entries. Call
94 compare_passwds() passing a test index, the passwd entry you got,
95 and the expected passwd entry. The function will return the number
96 of mismatches, or zero of the two records are the same. */
98 static void __attribute__((used
))
99 print_passwd (struct passwd
*p
)
101 printf (" passwd %u.%s (%s) :", p
->pw_uid
, p
->pw_name
, p
->pw_passwd
);
102 printf (" %u, %s, %s, %s\n", p
->pw_gid
, p
->pw_gecos
, p
->pw_dir
, p
->pw_shell
);
106 static int __attribute__((used
))
107 compare_passwd_field (int i
, struct passwd
*p
, const char *got
,
108 const char *exp
, const char *name
)
110 /* Does the entry have a value? */
113 printf ("[%d] passwd %s for %u.%s was (null)\n",
115 p
->pw_uid
, p
->pw_name
);
118 /* Does the entry have an unexpected name? */
119 else if (exp
== NULL
)
121 printf ("[%d] passwd %s for %u.(null) was %s\n",
126 /* And is it correct? */
127 else if (got
&& strcmp (got
, exp
) != 0)
129 printf("[%d] passwd entry %u.%s had %s \"%s\" (expected \"%s\") \n",
131 p
->pw_uid
, p
->pw_name
, name
,
138 #define COMPARE_PWD_FIELD(f) \
139 retval += compare_passwd_field (i, e, p->f, e->f, #f)
141 /* Compare passwd to expected passwd, return number of "problems".
142 "I" is the index into the testcase data. */
143 static int __attribute__((used
))
144 compare_passwds (int i
, struct passwd
*p
, struct passwd
*e
)
148 /* Did we get the expected uid? */
149 if (p
->pw_uid
!= e
->pw_uid
)
151 printf("[%d] passwd entry %u.%s had uid %u\n", i
,
152 e
->pw_uid
, e
->pw_name
,
157 /* Did we get the expected gid? */
158 if (p
->pw_gid
!= e
->pw_gid
)
160 printf("[%d] passwd entry %u.%s had gid %u (expected %u)\n", i
,
161 e
->pw_uid
, e
->pw_name
,
162 p
->pw_gid
, e
->pw_gid
);
166 COMPARE_PWD_FIELD (pw_name
);
167 COMPARE_PWD_FIELD (pw_passwd
);
168 COMPARE_PWD_FIELD (pw_gecos
);
169 COMPARE_PWD_FIELD (pw_dir
);
170 COMPARE_PWD_FIELD (pw_shell
);
174 /* Left in for debugging later, if needed. */
182 /*------------------------------------------------------------*/
184 /* Helpers for checking group entries. See passwd helper comment
185 above for details. */
187 static void __attribute__((used
))
188 print_group (struct group
*g
)
192 printf (" group %u.%s (%s) :", g
->gr_gid
, g
->gr_name
, g
->gr_passwd
);
194 for (j
=0; g
->gr_mem
[j
]; j
++)
195 printf ("%s%s", j
==0 ? " " : ", ", g
->gr_mem
[j
]);
199 /* Compare group to expected group, return number of "problems". "I"
200 is the index into the testcase data. */
201 static int __attribute__((used
))
202 compare_groups (int i
, struct group
*g
, struct group
*e
)
207 /* Did we get the expected gid? */
208 if (g
->gr_gid
!= e
->gr_gid
)
210 printf("[%d] group entry %u.%s had gid %u\n", i
,
211 e
->gr_gid
, e
->gr_name
,
216 /* Does the entry have a name? */
217 if (g
->gr_name
== NULL
)
219 printf ("[%d] group name for %u.%s was (null)\n", i
,
220 e
->gr_gid
, e
->gr_name
);
223 /* Does the entry have an unexpected name? */
224 else if (e
->gr_name
== NULL
)
226 printf ("[%d] group name for %u.(null) was %s\n", i
,
227 e
->gr_gid
, g
->gr_name
);
230 /* And is it correct? */
231 else if (strcmp (g
->gr_name
, e
->gr_name
) != 0)
233 printf("[%d] group entry %u.%s had name \"%s\"\n", i
,
234 e
->gr_gid
, e
->gr_name
,
239 /* Does the entry have a password? */
240 if (g
->gr_passwd
== NULL
&& e
->gr_passwd
!= NULL
)
242 printf ("[%d] group password for %u.%s was NULL\n", i
,
243 e
->gr_gid
, e
->gr_name
);
246 else if (g
->gr_passwd
!= NULL
&& e
->gr_passwd
== NULL
)
248 printf ("[%d] group password for %u.%s was not NULL\n", i
,
249 e
->gr_gid
, e
->gr_name
);
252 /* And is it correct? */
253 else if (g
->gr_passwd
&& strcmp (g
->gr_passwd
, e
->gr_passwd
) != 0)
255 printf("[%d] group entry %u.%s had password \"%s\" (not \"%s\")\n", i
,
256 e
->gr_gid
, e
->gr_name
,
257 g
->gr_passwd
, e
->gr_passwd
);
261 /* Now compare group members... */
263 if (e
->gr_mem
!= NULL
&& g
->gr_mem
== NULL
)
265 printf("[%d] group entry %u.%s missing member list\n", i
,
266 e
->gr_gid
, e
->gr_name
);
269 else if (e
->gr_mem
== NULL
&& g
->gr_mem
!= NULL
)
271 printf("[%d] group entry %u.%s has unexpected member list\n", i
,
272 e
->gr_gid
, e
->gr_name
);
275 else if (e
->gr_mem
== NULL
&& g
->gr_mem
== NULL
)
277 /* This case is OK. */
281 /* Compare two existing lists. */
285 if (g
->gr_mem
[j
] == NULL
&& e
->gr_mem
[j
] == NULL
)
287 /* Matching end-of-lists. */
290 if (g
->gr_mem
[j
] == NULL
)
292 printf ("[%d] group member list for %u.%s is too short.\n", i
,
293 e
->gr_gid
, e
->gr_name
);
297 if (e
->gr_mem
[j
] == NULL
)
299 printf ("[%d] group member list for %u.%s is too long.\n", i
,
300 e
->gr_gid
, e
->gr_name
);
304 if (strcmp (g
->gr_mem
[j
], e
->gr_mem
[j
]) != 0)
306 printf ("[%d] group member list for %u.%s differs: %s vs %s.\n", i
,
307 e
->gr_gid
, e
->gr_name
,
308 e
->gr_mem
[j
], g
->gr_mem
[j
]);
318 /* Left in for debugging later, if needed. */