]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - lib/libc/tests/nss/getrpc_test.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / lib / libc / tests / nss / getrpc_test.c
1 /*-
2  * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <arpa/inet.h>
32 #include <rpc/rpc.h>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stringlist.h>
38 #include <unistd.h>
39
40 #include <atf-c.h>
41
42 #include "testutil.h"
43
44 enum test_methods {
45         TEST_GETRPCENT,
46         TEST_GETRPCBYNAME,
47         TEST_GETRPCBYNUMBER,
48         TEST_GETRPCENT_2PASS,
49         TEST_BUILD_SNAPSHOT
50 };
51
52 DECLARE_TEST_DATA(rpcent)
53 DECLARE_TEST_FILE_SNAPSHOT(rpcent)
54 DECLARE_1PASS_TEST(rpcent)
55 DECLARE_2PASS_TEST(rpcent)
56
57 static void clone_rpcent(struct rpcent *, struct rpcent const *);
58 static int compare_rpcent(struct rpcent *, struct rpcent *, void *);
59 static void dump_rpcent(struct rpcent *);
60 static void free_rpcent(struct rpcent *);
61
62 static void sdump_rpcent(struct rpcent *, char *, size_t);
63 static int rpcent_read_snapshot_func(struct rpcent *, char *);
64
65 static int rpcent_check_ambiguity(struct rpcent_test_data *,
66         struct rpcent *);
67 static int rpcent_fill_test_data(struct rpcent_test_data *);
68 static int rpcent_test_correctness(struct rpcent *, void *);
69 static int rpcent_test_getrpcbyname(struct rpcent *, void *);
70 static int rpcent_test_getrpcbynumber(struct rpcent *, void *);
71 static int rpcent_test_getrpcent(struct rpcent *, void *);
72
73 static void usage(void)  __attribute__((__noreturn__));
74
75 IMPLEMENT_TEST_DATA(rpcent)
76 IMPLEMENT_TEST_FILE_SNAPSHOT(rpcent)
77 IMPLEMENT_1PASS_TEST(rpcent)
78 IMPLEMENT_2PASS_TEST(rpcent)
79
80 static void
81 clone_rpcent(struct rpcent *dest, struct rpcent const *src)
82 {
83         ATF_REQUIRE(dest != NULL);
84         ATF_REQUIRE(src != NULL);
85
86         char **cp;
87         int aliases_num;
88
89         memset(dest, 0, sizeof(struct rpcent));
90
91         if (src->r_name != NULL) {
92                 dest->r_name = strdup(src->r_name);
93                 ATF_REQUIRE(dest->r_name != NULL);
94         }
95
96         dest->r_number = src->r_number;
97
98         if (src->r_aliases != NULL) {
99                 aliases_num = 0;
100                 for (cp = src->r_aliases; *cp; ++cp)
101                         ++aliases_num;
102
103                 dest->r_aliases = calloc(1, (aliases_num + 1) * sizeof(char *));
104                 ATF_REQUIRE(dest->r_aliases != NULL);
105
106                 for (cp = src->r_aliases; *cp; ++cp) {
107                         dest->r_aliases[cp - src->r_aliases] = strdup(*cp);
108                         ATF_REQUIRE(dest->r_aliases[cp - src->r_aliases] != NULL);
109                 }
110         }
111 }
112
113 static void
114 free_rpcent(struct rpcent *rpc)
115 {
116         char **cp;
117
118         ATF_REQUIRE(rpc != NULL);
119
120         free(rpc->r_name);
121
122         for (cp = rpc->r_aliases; *cp; ++cp)
123                 free(*cp);
124         free(rpc->r_aliases);
125 }
126
127 static  int
128 compare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata)
129 {
130         char **c1, **c2;
131
132         if (rpc1 == rpc2)
133                 return 0;
134
135         if ((rpc1 == NULL) || (rpc2 == NULL))
136                 goto errfin;
137
138         if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) ||
139                 (rpc1->r_number != rpc2->r_number))
140                         goto errfin;
141
142         c1 = rpc1->r_aliases;
143         c2 = rpc2->r_aliases;
144
145         if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == NULL))
146                 goto errfin;
147
148         for (;*c1 && *c2; ++c1, ++c2)
149                 if (strcmp(*c1, *c2) != 0)
150                         goto errfin;
151
152         if ((*c1 != '\0') || (*c2 != '\0'))
153                 goto errfin;
154
155         return 0;
156
157 errfin:
158         if (mdata == NULL) {
159                 printf("following structures are not equal:\n");
160                 dump_rpcent(rpc1);
161                 dump_rpcent(rpc2);
162         }
163
164         return (-1);
165 }
166
167 static void
168 sdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen)
169 {
170         char **cp;
171         int written;
172
173         written = snprintf(buffer, buflen, "%s %d",
174                 rpc->r_name, rpc->r_number);
175         buffer += written;
176         if (written > buflen)
177                 return;
178         buflen -= written;
179
180         if (rpc->r_aliases != NULL) {
181                 if (*(rpc->r_aliases) != '\0') {
182                         for (cp = rpc->r_aliases; *cp; ++cp) {
183                                 written = snprintf(buffer, buflen, " %s",*cp);
184                                 buffer += written;
185                                 if (written > buflen)
186                                         return;
187                                 buflen -= written;
188
189                                 if (buflen == 0)
190                                         return;
191                         }
192                 } else
193                         snprintf(buffer, buflen, " noaliases");
194         } else
195                 snprintf(buffer, buflen, " (null)");
196 }
197
198 static int
199 rpcent_read_snapshot_func(struct rpcent *rpc, char *line)
200 {
201         StringList *sl;
202         char *s, *ps, *ts;
203         int i;
204
205         printf("1 line read from snapshot:\n%s\n", line);
206
207         i = 0;
208         sl = NULL;
209         ps = line;
210         memset(rpc, 0, sizeof(struct rpcent));
211         while ((s = strsep(&ps, " ")) != NULL) {
212                 switch (i) {
213                 case 0:
214                                 rpc->r_name = strdup(s);
215                                 ATF_REQUIRE(rpc->r_name != NULL);
216                         break;
217
218                 case 1:
219                         rpc->r_number = (int)strtol(s, &ts, 10);
220                         if (*ts != '\0') {
221                                 free(rpc->r_name);
222                                 return (-1);
223                         }
224                         break;
225
226                 default:
227                         if (sl == NULL) {
228                                 if (strcmp(s, "(null)") == 0)
229                                         return (0);
230
231                                 sl = sl_init();
232                                 ATF_REQUIRE(sl != NULL);
233
234                                 if (strcmp(s, "noaliases") != 0) {
235                                         ts = strdup(s);
236                                         ATF_REQUIRE(ts != NULL);
237                                         sl_add(sl, ts);
238                                 }
239                         } else {
240                                 ts = strdup(s);
241                                 ATF_REQUIRE(ts != NULL);
242                                 sl_add(sl, ts);
243                         }
244                         break;
245                 }
246                 i++;
247         }
248
249         if (i < 3) {
250                 free(rpc->r_name);
251                 memset(rpc, 0, sizeof(struct rpcent));
252                 return (-1);
253         }
254
255         sl_add(sl, NULL);
256         rpc->r_aliases = sl->sl_str;
257
258         /* NOTE: is it a dirty hack or not? */
259         free(sl);
260         return (0);
261 }
262
263 static void
264 dump_rpcent(struct rpcent *result)
265 {
266         if (result != NULL) {
267                 char buffer[1024];
268                 sdump_rpcent(result, buffer, sizeof(buffer));
269                 printf("%s\n", buffer);
270         } else
271                 printf("(null)\n");
272 }
273
274 static int
275 rpcent_fill_test_data(struct rpcent_test_data *td)
276 {
277         struct rpcent *rpc;
278
279         setrpcent(1);
280         while ((rpc = getrpcent()) != NULL) {
281                 if (rpcent_test_correctness(rpc, NULL) == 0)
282                         TEST_DATA_APPEND(rpcent, td, rpc);
283                 else
284                         return (-1);
285         }
286         endrpcent();
287
288         return (0);
289 }
290
291 static int
292 rpcent_test_correctness(struct rpcent *rpc, void *mdata)
293 {
294
295         printf("testing correctness with the following data:\n");
296         dump_rpcent(rpc);
297
298         if (rpc == NULL)
299                 goto errfin;
300
301         if (rpc->r_name == NULL)
302                 goto errfin;
303
304         if (rpc->r_number < 0)
305                 goto errfin;
306
307         if (rpc->r_aliases == NULL)
308                 goto errfin;
309
310         printf("correct\n");
311
312         return (0);
313 errfin:
314         printf("incorrect\n");
315
316         return (-1);
317 }
318
319 /* rpcent_check_ambiguity() is needed when one port+rpc is associated with
320  * more than one peice (these cases are usually marked as PROBLEM in
321  * /etc/peices. This functions is needed also when one peice+rpc is
322  * associated with several ports. We have to check all the rpcent structures
323  * to make sure that rpc really exists and correct */
324 static int
325 rpcent_check_ambiguity(struct rpcent_test_data *td, struct rpcent *rpc)
326 {
327
328         return (TEST_DATA_FIND(rpcent, td, rpc, compare_rpcent,
329                 NULL) != NULL ? 0 : -1);
330 }
331
332 static int
333 rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata)
334 {
335         char **alias;
336         struct rpcent *rpc;
337
338         printf("testing getrpcbyname() with the following data:\n");
339         dump_rpcent(rpc_model);
340
341         rpc = getrpcbyname(rpc_model->r_name);
342         if (rpcent_test_correctness(rpc, NULL) != 0)
343                 goto errfin;
344
345         if ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
346             (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc)
347             !=0))
348             goto errfin;
349
350         for (alias = rpc_model->r_aliases; *alias; ++alias) {
351                 rpc = getrpcbyname(*alias);
352
353                 if (rpcent_test_correctness(rpc, NULL) != 0)
354                         goto errfin;
355
356                 if ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
357                     (rpcent_check_ambiguity(
358                     (struct rpcent_test_data *)mdata, rpc) != 0))
359                     goto errfin;
360         }
361
362         printf("ok\n");
363         return (0);
364
365 errfin:
366         printf("not ok\n");
367
368         return (-1);
369 }
370
371 static int
372 rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata)
373 {
374         struct rpcent *rpc;
375
376         printf("testing getrpcbyport() with the following data...\n");
377         dump_rpcent(rpc_model);
378
379         rpc = getrpcbynumber(rpc_model->r_number);
380         if (rpcent_test_correctness(rpc, NULL) != 0 ||
381             (compare_rpcent(rpc, rpc_model, NULL) != 0 &&
382              rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc)
383             != 0)) {
384                 printf("not ok\n");
385                 return (-1);
386         } else {
387                 printf("ok\n");
388                 return (0);
389         }
390 }
391
392 static int
393 rpcent_test_getrpcent(struct rpcent *rpc, void *mdata)
394 {
395
396         /*
397          * Only correctness can be checked when doing 1-pass test for
398          * getrpcent().
399          */
400         return (rpcent_test_correctness(rpc, NULL));
401 }
402
403 int
404 run_tests(const char *snapshot_file, enum test_methods method)
405 {
406         struct rpcent_test_data td, td_snap, td_2pass;
407         int rv;
408
409         TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent);
410         TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent);
411         if (snapshot_file != NULL) {
412                 if (access(snapshot_file, W_OK | R_OK) != 0) {
413                         if (errno == ENOENT)
414                                 method = TEST_BUILD_SNAPSHOT;
415                         else {
416                                 printf("can't access the file %s\n",
417                                     snapshot_file);
418
419                                 rv = -1;
420                                 goto fin;
421                         }
422                 } else {
423                         if (method == TEST_BUILD_SNAPSHOT) {
424                                 rv = 0;
425                                 goto fin;
426                         }
427
428                         TEST_SNAPSHOT_FILE_READ(rpcent, snapshot_file,
429                                 &td_snap, rpcent_read_snapshot_func);
430                 }
431         }
432
433         rv = rpcent_fill_test_data(&td);
434         if (rv == -1)
435                 return (-1);
436         switch (method) {
437         case TEST_GETRPCBYNAME:
438                 if (snapshot_file == NULL)
439                         rv = DO_1PASS_TEST(rpcent, &td,
440                                 rpcent_test_getrpcbyname, (void *)&td);
441                 else
442                         rv = DO_1PASS_TEST(rpcent, &td_snap,
443                                 rpcent_test_getrpcbyname, (void *)&td_snap);
444                 break;
445         case TEST_GETRPCBYNUMBER:
446                 if (snapshot_file == NULL)
447                         rv = DO_1PASS_TEST(rpcent, &td,
448                                 rpcent_test_getrpcbynumber, (void *)&td);
449                 else
450                         rv = DO_1PASS_TEST(rpcent, &td_snap,
451                                 rpcent_test_getrpcbynumber, (void *)&td_snap);
452                 break;
453         case TEST_GETRPCENT:
454                 if (snapshot_file == NULL)
455                         rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcent,
456                                 (void *)&td);
457                 else
458                         rv = DO_2PASS_TEST(rpcent, &td, &td_snap,
459                                 compare_rpcent, NULL);
460                 break;
461         case TEST_GETRPCENT_2PASS:
462                         TEST_DATA_INIT(rpcent, &td_2pass, clone_rpcent, free_rpcent);
463                         rv = rpcent_fill_test_data(&td_2pass);
464                         if (rv != -1)
465                                 rv = DO_2PASS_TEST(rpcent, &td, &td_2pass,
466                                         compare_rpcent, NULL);
467                         TEST_DATA_DESTROY(rpcent, &td_2pass);
468                 break;
469         case TEST_BUILD_SNAPSHOT:
470                 if (snapshot_file != NULL)
471                     rv = TEST_SNAPSHOT_FILE_WRITE(rpcent, snapshot_file, &td,
472                         sdump_rpcent);
473                 break;
474         default:
475                 rv = 0;
476                 break;
477         }
478
479 fin:
480         TEST_DATA_DESTROY(rpcent, &td_snap);
481         TEST_DATA_DESTROY(rpcent, &td);
482
483         return (rv);
484 }
485
486 #define SNAPSHOT_FILE   "snapshot_rpc"
487
488 ATF_TC_WITHOUT_HEAD(build_snapshot);
489 ATF_TC_BODY(build_snapshot, tc)
490 {
491
492         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
493 }
494
495 ATF_TC_WITHOUT_HEAD(getrpcbyname);
496 ATF_TC_BODY(getrpcbyname, tc)
497 {
498
499         ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNAME) == 0);
500 }
501
502 ATF_TC_WITHOUT_HEAD(getrpcbyname_with_snapshot);
503 ATF_TC_BODY(getrpcbyname_with_snapshot, tc)
504 {
505
506         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
507         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNAME) == 0);
508 }
509
510 ATF_TC_WITHOUT_HEAD(getrpcbynumber);
511 ATF_TC_BODY(getrpcbynumber, tc)
512 {
513
514         ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNUMBER) == 0);
515 }
516
517 ATF_TC_WITHOUT_HEAD(getrpcbynumber_with_snapshot);
518 ATF_TC_BODY(getrpcbynumber_with_snapshot, tc)
519 {
520
521         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
522         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNUMBER) == 0);
523 }
524
525 ATF_TC_WITHOUT_HEAD(getrpcbyent);
526 ATF_TC_BODY(getrpcbyent, tc)
527 {
528
529         ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT) == 0);
530 }
531
532 ATF_TC_WITHOUT_HEAD(getrpcbyent_with_snapshot);
533 ATF_TC_BODY(getrpcbyent_with_snapshot, tc)
534 {
535
536         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
537         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCENT) == 0);
538 }
539
540 ATF_TC_WITHOUT_HEAD(getrpcbyent_with_two_pass);
541 ATF_TC_BODY(getrpcbyent_with_two_pass, tc)
542 {
543
544         ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT_2PASS) == 0);
545 }
546
547 ATF_TP_ADD_TCS(tp)
548 {
549
550         ATF_TP_ADD_TC(tp, build_snapshot);
551         ATF_TP_ADD_TC(tp, getrpcbyname);
552         ATF_TP_ADD_TC(tp, getrpcbyname_with_snapshot);
553         ATF_TP_ADD_TC(tp, getrpcbynumber);
554         ATF_TP_ADD_TC(tp, getrpcbynumber_with_snapshot);
555         ATF_TP_ADD_TC(tp, getrpcbyent);
556         ATF_TP_ADD_TC(tp, getrpcbyent_with_snapshot);
557         ATF_TP_ADD_TC(tp, getrpcbyent_with_two_pass);
558
559         return (atf_no_error());
560 }