]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/regression/lib/libc/nss/test-getrpc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / regression / lib / libc / nss / test-getrpc.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 <assert.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stringlist.h>
39 #include <unistd.h>
40 #include "testutil.h"
41
42 enum test_methods {
43         TEST_GETRPCENT,
44         TEST_GETRPCBYNAME,
45         TEST_GETRPCBYNUMBER,
46         TEST_GETRPCENT_2PASS,
47         TEST_BUILD_SNAPSHOT
48 };
49
50 static int debug = 0;
51 static enum test_methods method = TEST_BUILD_SNAPSHOT;
52
53 DECLARE_TEST_DATA(rpcent)
54 DECLARE_TEST_FILE_SNAPSHOT(rpcent)
55 DECLARE_1PASS_TEST(rpcent)
56 DECLARE_2PASS_TEST(rpcent)
57
58 static void clone_rpcent(struct rpcent *, struct rpcent const *);
59 static int compare_rpcent(struct rpcent *, struct rpcent *, void *);
60 static void dump_rpcent(struct rpcent *);
61 static void free_rpcent(struct rpcent *);
62
63 static void sdump_rpcent(struct rpcent *, char *, size_t);
64 static int rpcent_read_snapshot_func(struct rpcent *, char *);
65
66 static int rpcent_check_ambiguity(struct rpcent_test_data *, 
67         struct rpcent *);
68 static int rpcent_fill_test_data(struct rpcent_test_data *);
69 static int rpcent_test_correctness(struct rpcent *, void *);
70 static int rpcent_test_getrpcbyname(struct rpcent *, void *);
71 static int rpcent_test_getrpcbynumber(struct rpcent *, void *);
72 static int rpcent_test_getrpcent(struct rpcent *, void *);
73         
74 static void usage(void)  __attribute__((__noreturn__));
75
76 IMPLEMENT_TEST_DATA(rpcent)
77 IMPLEMENT_TEST_FILE_SNAPSHOT(rpcent)
78 IMPLEMENT_1PASS_TEST(rpcent)
79 IMPLEMENT_2PASS_TEST(rpcent)
80
81 static void
82 clone_rpcent(struct rpcent *dest, struct rpcent const *src)
83 {
84         assert(dest != NULL);
85         assert(src != NULL);
86         
87         char **cp;
88         int aliases_num;
89                 
90         memset(dest, 0, sizeof(struct rpcent));
91         
92         if (src->r_name != NULL) {
93                 dest->r_name = strdup(src->r_name);
94                 assert(dest->r_name != NULL);
95         }
96         
97         dest->r_number = src->r_number;
98         
99         if (src->r_aliases != NULL) {
100                 aliases_num = 0;
101                 for (cp = src->r_aliases; *cp; ++cp)
102                         ++aliases_num;
103         
104                 dest->r_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
105                 assert(dest->r_aliases != NULL);
106                 memset(dest->r_aliases, 0, (aliases_num+1) * (sizeof(char *)));
107         
108                 for (cp = src->r_aliases; *cp; ++cp) {
109                         dest->r_aliases[cp - src->r_aliases] = strdup(*cp);
110                         assert(dest->r_aliases[cp - src->r_aliases] != NULL);
111                 }
112         }
113 }
114
115 static void 
116 free_rpcent(struct rpcent *rpc)
117 {
118         char **cp;
119         
120         assert(rpc != NULL);
121         
122         free(rpc->r_name);
123         
124         for (cp = rpc->r_aliases; *cp; ++cp)
125                 free(*cp);
126         free(rpc->r_aliases);
127 }
128
129 static  int 
130 compare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata)
131 {
132         char **c1, **c2;
133         
134         if (rpc1 == rpc2)
135                 return 0;
136         
137         if ((rpc1 == NULL) || (rpc2 == NULL))
138                 goto errfin;
139         
140         if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) ||
141                 (rpc1->r_number != rpc2->r_number))
142                         goto errfin;
143         
144         c1 = rpc1->r_aliases;
145         c2 = rpc2->r_aliases;
146         
147         if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == NULL))
148                 goto errfin;
149         
150         for (;*c1 && *c2; ++c1, ++c2)
151                 if (strcmp(*c1, *c2) != 0)
152                         goto errfin;
153                 
154         if ((*c1 != '\0') || (*c2 != '\0'))
155                 goto errfin;
156         
157         return 0;
158         
159 errfin:
160         if ((debug) && (mdata == NULL)) {
161                 printf("following structures are not equal:\n");
162                 dump_rpcent(rpc1);
163                 dump_rpcent(rpc2);
164         }
165
166         return (-1);
167 }
168
169 static void
170 sdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen)
171 {
172         char **cp;
173         int written;
174         
175         written = snprintf(buffer, buflen, "%s %d",
176                 rpc->r_name, rpc->r_number);    
177         buffer += written;
178         if (written > buflen)
179                 return;
180         buflen -= written;
181                         
182         if (rpc->r_aliases != NULL) {
183                 if (*(rpc->r_aliases) != '\0') {
184                         for (cp = rpc->r_aliases; *cp; ++cp) {
185                                 written = snprintf(buffer, buflen, " %s",*cp);
186                                 buffer += written;
187                                 if (written > buflen)
188                                         return;
189                                 buflen -= written;
190                                 
191                                 if (buflen == 0)
192                                         return;                         
193                         }
194                 } else
195                         snprintf(buffer, buflen, " noaliases");
196         } else
197                 snprintf(buffer, buflen, " (null)");
198 }
199
200 static int
201 rpcent_read_snapshot_func(struct rpcent *rpc, char *line)
202 {
203         StringList *sl;
204         char *s, *ps, *ts;
205         int i;
206
207         if (debug)
208                 printf("1 line read from snapshot:\n%s\n", line);
209         
210         i = 0;
211         sl = NULL;
212         ps = line;
213         memset(rpc, 0, sizeof(struct rpcent));
214         while ( (s = strsep(&ps, " ")) != NULL) {
215                 switch (i) {
216                         case 0:
217                                 rpc->r_name = strdup(s);
218                                 assert(rpc->r_name != NULL);
219                         break;
220
221                         case 1:
222                                 rpc->r_number = (int)strtol(s, &ts, 10);
223                                 if (*ts != '\0') {
224                                         free(rpc->r_name);
225                                         return (-1);
226                                 }
227                         break;
228
229                         default:
230                                 if (sl == NULL) {
231                                         if (strcmp(s, "(null)") == 0)
232                                                 return (0);
233                                                                                 
234                                         sl = sl_init();
235                                         assert(sl != NULL);
236                                         
237                                         if (strcmp(s, "noaliases") != 0) {
238                                                 ts = strdup(s);
239                                                 assert(ts != NULL);
240                                                 sl_add(sl, ts);
241                                         }
242                                 } else {
243                                         ts = strdup(s);
244                                         assert(ts != NULL);
245                                         sl_add(sl, ts);
246                                 }
247                         break;                  
248                 };
249                 ++i;
250         }
251
252         if (i < 3) {
253                 free(rpc->r_name);
254                 memset(rpc, 0, sizeof(struct rpcent));
255                 return (-1);
256         }
257         
258         sl_add(sl, NULL);
259         rpc->r_aliases = sl->sl_str;
260
261         /* NOTE: is it a dirty hack or not? */
262         free(sl);       
263         return (0);
264 }
265
266 static void 
267 dump_rpcent(struct rpcent *result)
268 {
269         if (result != NULL) {
270                 char buffer[1024];
271                 sdump_rpcent(result, buffer, sizeof(buffer));
272                 printf("%s\n", buffer);
273         } else
274                 printf("(null)\n");
275 }
276
277 static int
278 rpcent_fill_test_data(struct rpcent_test_data *td)
279 {
280         struct rpcent *rpc;
281                 
282         setrpcent(1);
283         while ((rpc = getrpcent()) != NULL) {
284                 if (rpcent_test_correctness(rpc, NULL) == 0)
285                         TEST_DATA_APPEND(rpcent, td, rpc);
286                 else
287                         return (-1);
288         }
289         endrpcent();
290         
291         return (0);
292 }
293
294 static int
295 rpcent_test_correctness(struct rpcent *rpc, void *mdata)
296 {
297         if (debug) {
298                 printf("testing correctness with the following data:\n");
299                 dump_rpcent(rpc);
300         }
301         
302         if (rpc == NULL)
303                 goto errfin;
304         
305         if (rpc->r_name == NULL)
306                 goto errfin;
307         
308         if (rpc->r_number < 0)
309                 goto errfin;
310         
311         if (rpc->r_aliases == NULL)
312                 goto errfin;
313         
314         if (debug)
315                 printf("correct\n");
316         
317         return (0);     
318 errfin:
319         if (debug)
320                 printf("incorrect\n");
321         
322         return (-1);
323 }
324
325 /* rpcent_check_ambiguity() is needed when one port+rpc is associated with
326  * more than one peice (these cases are usually marked as PROBLEM in
327  * /etc/peices. This functions is needed also when one peice+rpc is 
328  * associated with several ports. We have to check all the rpcent structures
329  * to make sure that rpc really exists and correct */
330 static int
331 rpcent_check_ambiguity(struct rpcent_test_data *td, struct rpcent *rpc)
332 {
333         
334         return (TEST_DATA_FIND(rpcent, td, rpc, compare_rpcent,
335                 NULL) != NULL ? 0 : -1);
336 }
337
338 static int
339 rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata)
340 {
341         char **alias;
342         struct rpcent *rpc;
343                 
344         if (debug) {
345                 printf("testing getrpcbyname() with the following data:\n");
346                 dump_rpcent(rpc_model);
347         }
348
349         rpc = getrpcbyname(rpc_model->r_name);
350         if (rpcent_test_correctness(rpc, NULL) != 0)
351                 goto errfin;
352         
353         if ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
354             (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) 
355             !=0))
356             goto errfin;
357         
358         for (alias = rpc_model->r_aliases; *alias; ++alias) {
359                 rpc = getrpcbyname(*alias);
360                 
361                 if (rpcent_test_correctness(rpc, NULL) != 0)
362                         goto errfin;
363                 
364                 if ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
365                     (rpcent_check_ambiguity(
366                     (struct rpcent_test_data *)mdata, rpc) != 0))
367                     goto errfin;
368         }
369         
370         if (debug)
371                 printf("ok\n");
372         return (0);
373         
374 errfin:
375         if (debug)
376                 printf("not ok\n");
377         
378         return (-1);
379 }
380
381 static int
382 rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata)
383 {
384         struct rpcent *rpc;
385                 
386         if (debug) {
387                 printf("testing getrpcbyport() with the following data...\n");
388                 dump_rpcent(rpc_model);
389         }       
390         
391         rpc = getrpcbynumber(rpc_model->r_number);
392         if ((rpcent_test_correctness(rpc, NULL) != 0) || 
393             ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
394             (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc)
395             != 0))) {
396             if (debug)
397                 printf("not ok\n");
398             return (-1);
399         } else {
400             if (debug)
401                 printf("ok\n");
402             return (0);
403         }
404 }
405
406 static int 
407 rpcent_test_getrpcent(struct rpcent *rpc, void *mdata)
408 {
409         /* Only correctness can be checked when doing 1-pass test for
410          * getrpcent(). */
411         return (rpcent_test_correctness(rpc, NULL));
412 }
413
414 static void
415 usage(void)
416 {
417         (void)fprintf(stderr,
418             "Usage: %s -nve2 [-d] [-s <file>]\n",
419             getprogname());
420         exit(1);
421 }
422
423 int
424 main(int argc, char **argv)
425 {
426         struct rpcent_test_data td, td_snap, td_2pass;
427         char *snapshot_file;
428         int rv;
429         int c;
430         
431         if (argc < 2)
432                 usage();
433                 
434         snapshot_file = NULL;
435         while ((c = getopt(argc, argv, "nve2ds:")) != -1)
436                 switch (c) {
437                 case 'd':
438                         debug++;
439                         break;
440                 case 'n':
441                         method = TEST_GETRPCBYNAME;
442                         break;
443                 case 'v':
444                         method = TEST_GETRPCBYNUMBER;
445                         break;
446                 case 'e':
447                         method = TEST_GETRPCENT;
448                         break;
449                 case '2':
450                         method = TEST_GETRPCENT_2PASS;
451                         break;
452                 case 's':
453                         snapshot_file = strdup(optarg);
454                         break;
455                 default:
456                         usage();
457                 }
458         
459         TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent);
460         TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent);
461         if (snapshot_file != NULL) {
462                 if (access(snapshot_file, W_OK | R_OK) != 0) {          
463                         if (errno == ENOENT)
464                                 method = TEST_BUILD_SNAPSHOT;
465                         else {
466                                 if (debug)
467                                         printf("can't access the file %s\n",
468                                 snapshot_file);
469                         
470                                 rv = -1;
471                                 goto fin;
472                         }
473                 } else {
474                         if (method == TEST_BUILD_SNAPSHOT) {
475                                 rv = 0;
476                                 goto fin;
477                         }
478                         
479                         TEST_SNAPSHOT_FILE_READ(rpcent, snapshot_file,
480                                 &td_snap, rpcent_read_snapshot_func);
481                 }
482         }
483                 
484         rv = rpcent_fill_test_data(&td);
485         if (rv == -1)
486                 return (-1);
487         switch (method) {
488         case TEST_GETRPCBYNAME:
489                 if (snapshot_file == NULL)
490                         rv = DO_1PASS_TEST(rpcent, &td,
491                                 rpcent_test_getrpcbyname, (void *)&td);
492                 else
493                         rv = DO_1PASS_TEST(rpcent, &td_snap, 
494                                 rpcent_test_getrpcbyname, (void *)&td_snap);
495                 break;
496         case TEST_GETRPCBYNUMBER:
497                 if (snapshot_file == NULL)
498                         rv = DO_1PASS_TEST(rpcent, &td,
499                                 rpcent_test_getrpcbynumber, (void *)&td);
500                 else
501                         rv = DO_1PASS_TEST(rpcent, &td_snap, 
502                                 rpcent_test_getrpcbynumber, (void *)&td_snap);
503                 break;
504         case TEST_GETRPCENT:
505                 if (snapshot_file == NULL)
506                         rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcent,
507                                 (void *)&td);
508                 else
509                         rv = DO_2PASS_TEST(rpcent, &td, &td_snap,
510                                 compare_rpcent, NULL);
511                 break;
512         case TEST_GETRPCENT_2PASS:
513                         TEST_DATA_INIT(rpcent, &td_2pass, clone_rpcent, free_rpcent);
514                         rv = rpcent_fill_test_data(&td_2pass);                  
515                         if (rv != -1)
516                                 rv = DO_2PASS_TEST(rpcent, &td, &td_2pass,
517                                         compare_rpcent, NULL);
518                         TEST_DATA_DESTROY(rpcent, &td_2pass);
519                 break;
520         case TEST_BUILD_SNAPSHOT:
521                 if (snapshot_file != NULL)
522                     rv = TEST_SNAPSHOT_FILE_WRITE(rpcent, snapshot_file, &td, 
523                         sdump_rpcent);
524                 break;
525         default:
526                 rv = 0;
527                 break;
528         };
529
530 fin:
531         TEST_DATA_DESTROY(rpcent, &td_snap);
532         TEST_DATA_DESTROY(rpcent, &td);
533         free(snapshot_file);    
534         return (rv);
535 }