1 /* Common code for NSS test cases.
2 Copyright (C) 2017-2019 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 <http://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. */
37 typedef struct test_tables
{
38 struct passwd
*pwd_table
;
39 struct group
*grp_table
;
42 extern void _nss_test1_init_hook (test_tables
*) __attribute__((weak
));
43 extern void _nss_test2_init_hook (test_tables
*) __attribute__((weak
));
45 #define PWD_LAST() { .pw_name = NULL, .pw_uid = 0 }
46 #define GRP_LAST() { .gr_name = NULL, .gr_gid = 0 }
48 #define PWD_ISLAST(p) ((p)->pw_name == NULL && (p)->pw_uid == 0)
49 #define GRP_ISLAST(g) ((g)->gr_name == NULL && (g)->gr_gid == 0)
51 /* Macros to fill in the tables easily. */
53 /* Note that the "unparameterized" fields are not magic; they're just
54 arbitrary values. Tests which need to verify those fields should
55 fill them in explicitly. */
58 { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \
59 .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \
60 .pw_shell = (char *) "*" }
63 { .pw_name = (char *) n, .pw_passwd = (char *) "*", .pw_uid = u, \
64 .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \
65 .pw_shell = (char *) "*" }
68 { .gr_name = (char *) "name" #u, .gr_passwd = (char *) "*", .gr_gid = u, \
69 .gr_mem = (char **) group_##u }
71 #define GRP_N(u,n,m) \
72 { .gr_name = (char *) n, .gr_passwd = (char *) "*", .gr_gid = u, \
73 .gr_mem = (char **) m }
75 /*------------------------------------------------------------*/
77 /* Helper functions for testing passwd entries. Call
78 compare_passwds() passing a test index, the passwd entry you got,
79 and the expected passwd entry. The function will return the number
80 of mismatches, or zero of the two records are the same. */
82 static void __attribute__((used
))
83 print_passwd (struct passwd
*p
)
85 printf (" passwd %u.%s (%s) :", p
->pw_uid
, p
->pw_name
, p
->pw_passwd
);
86 printf (" %u, %s, %s, %s\n", p
->pw_gid
, p
->pw_gecos
, p
->pw_dir
, p
->pw_shell
);
90 static int __attribute__((used
))
91 compare_passwd_field (int i
, struct passwd
*p
, const char *got
,
92 const char *exp
, const char *name
)
94 /* Does the entry have a value? */
97 printf ("[%d] passwd %s for %u.%s was (null)\n",
99 p
->pw_uid
, p
->pw_name
);
102 /* Does the entry have an unexpected name? */
103 else if (exp
== NULL
)
105 printf ("[%d] passwd %s for %u.(null) was %s\n",
110 /* And is it correct? */
111 else if (got
&& strcmp (got
, exp
) != 0)
113 printf("[%d] passwd entry %u.%s had %s \"%s\" (expected \"%s\") \n",
115 p
->pw_uid
, p
->pw_name
, name
,
122 #define COMPARE_PWD_FIELD(f) \
123 retval += compare_passwd_field (i, e, p->f, e->f, #f)
125 /* Compare passwd to expected passwd, return number of "problems".
126 "I" is the index into the testcase data. */
127 static int __attribute__((used
))
128 compare_passwds (int i
, struct passwd
*p
, struct passwd
*e
)
132 /* Did we get the expected uid? */
133 if (p
->pw_uid
!= e
->pw_uid
)
135 printf("[%d] passwd entry %u.%s had uid %u\n", i
,
136 e
->pw_uid
, e
->pw_name
,
141 /* Did we get the expected gid? */
142 if (p
->pw_gid
!= e
->pw_gid
)
144 printf("[%d] passwd entry %u.%s had gid %u (expected %u)\n", i
,
145 e
->pw_uid
, e
->pw_name
,
146 p
->pw_gid
, e
->pw_gid
);
150 COMPARE_PWD_FIELD (pw_name
);
151 COMPARE_PWD_FIELD (pw_passwd
);
152 COMPARE_PWD_FIELD (pw_gecos
);
153 COMPARE_PWD_FIELD (pw_dir
);
154 COMPARE_PWD_FIELD (pw_shell
);
158 /* Left in for debugging later, if needed. */
166 /*------------------------------------------------------------*/
168 /* Helpers for checking group entries. See passwd helper comment
169 above for details. */
171 static void __attribute__((used
))
172 print_group (struct group
*g
)
176 printf (" group %u.%s (%s) :", g
->gr_gid
, g
->gr_name
, g
->gr_passwd
);
178 for (j
=0; g
->gr_mem
[j
]; j
++)
179 printf ("%s%s", j
==0 ? " " : ", ", g
->gr_mem
[j
]);
183 /* Compare group to expected group, return number of "problems". "I"
184 is the index into the testcase data. */
185 static int __attribute__((used
))
186 compare_groups (int i
, struct group
*g
, struct group
*e
)
191 /* Did we get the expected gid? */
192 if (g
->gr_gid
!= e
->gr_gid
)
194 printf("[%d] group entry %u.%s had gid %u\n", i
,
195 e
->gr_gid
, e
->gr_name
,
200 /* Does the entry have a name? */
201 if (g
->gr_name
== NULL
)
203 printf ("[%d] group name for %u.%s was (null)\n", i
,
204 e
->gr_gid
, e
->gr_name
);
207 /* Does the entry have an unexpected name? */
208 else if (e
->gr_name
== NULL
)
210 printf ("[%d] group name for %u.(null) was %s\n", i
,
211 e
->gr_gid
, g
->gr_name
);
214 /* And is it correct? */
215 else if (strcmp (g
->gr_name
, e
->gr_name
) != 0)
217 printf("[%d] group entry %u.%s had name \"%s\"\n", i
,
218 e
->gr_gid
, e
->gr_name
,
223 /* Does the entry have a password? */
224 if (g
->gr_passwd
== NULL
&& e
->gr_passwd
!= NULL
)
226 printf ("[%d] group password for %u.%s was NULL\n", i
,
227 e
->gr_gid
, e
->gr_name
);
230 else if (g
->gr_passwd
!= NULL
&& e
->gr_passwd
== NULL
)
232 printf ("[%d] group password for %u.%s was not NULL\n", i
,
233 e
->gr_gid
, e
->gr_name
);
236 /* And is it correct? */
237 else if (g
->gr_passwd
&& strcmp (g
->gr_passwd
, e
->gr_passwd
) != 0)
239 printf("[%d] group entry %u.%s had password \"%s\" (not \"%s\")\n", i
,
240 e
->gr_gid
, e
->gr_name
,
241 g
->gr_passwd
, e
->gr_passwd
);
245 /* Now compare group members... */
247 if (e
->gr_mem
!= NULL
&& g
->gr_mem
== NULL
)
249 printf("[%d] group entry %u.%s missing member list\n", i
,
250 e
->gr_gid
, e
->gr_name
);
253 else if (e
->gr_mem
== NULL
&& g
->gr_mem
!= NULL
)
255 printf("[%d] group entry %u.%s has unexpected member list\n", i
,
256 e
->gr_gid
, e
->gr_name
);
259 else if (e
->gr_mem
== NULL
&& g
->gr_mem
== NULL
)
261 /* This case is OK. */
265 /* Compare two existing lists. */
269 if (g
->gr_mem
[j
] == NULL
&& e
->gr_mem
[j
] == NULL
)
271 /* Matching end-of-lists. */
274 if (g
->gr_mem
[j
] == NULL
)
276 printf ("[%d] group member list for %u.%s is too short.\n", i
,
277 e
->gr_gid
, e
->gr_name
);
281 if (e
->gr_mem
[j
] == NULL
)
283 printf ("[%d] group member list for %u.%s is too long.\n", i
,
284 e
->gr_gid
, e
->gr_name
);
288 if (strcmp (g
->gr_mem
[j
], e
->gr_mem
[j
]) != 0)
290 printf ("[%d] group member list for %u.%s differs: %s vs %s.\n", i
,
291 e
->gr_gid
, e
->gr_name
,
292 e
->gr_mem
[j
], g
->gr_mem
[j
]);
302 /* Left in for debugging later, if needed. */