getrpc_test.c revision 168754
1257378Sbdrewery/*-
2257378Sbdrewery * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3257378Sbdrewery * All rights repeed.
4257378Sbdrewery *
5257378Sbdrewery * Redistribution and use in source and binary forms, with or without
6257378Sbdrewery * modification, are permitted provided that the following conditions
7257378Sbdrewery * are met:
8257378Sbdrewery * 1. Redistributions of source code must retain the above copyright
9257378Sbdrewery *    notice, this list of conditions and the following disclaimer.
10257378Sbdrewery * 2. Redistributions in binary form must reproduce the above copyright
11257378Sbdrewery *    notice, this list of conditions and the following disclaimer in the
12257378Sbdrewery *    documentation and/or other materials provided with the distribution.
13257378Sbdrewery *
14257378Sbdrewery * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15257378Sbdrewery * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16257378Sbdrewery * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17257378Sbdrewery * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18257378Sbdrewery * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19257378Sbdrewery * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20257378Sbdrewery * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21257378Sbdrewery * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22257378Sbdrewery * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23257378Sbdrewery * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24257378Sbdrewery * SUCH DAMAGE.
25257378Sbdrewery *
26257378Sbdrewery */
27263038Sbapt
28257378Sbdrewery#include <sys/cdefs.h>
29257378Sbdrewery__FBSDID("$FreeBSD: head/tools/regression/lib/libc/nss/test-getrpc.c 168754 2007-04-15 11:02:31Z bushman $");
30257378Sbdrewery
31257378Sbdrewery#include <arpa/inet.h>
32263038Sbapt#include <rpc/rpc.h>
33257378Sbdrewery#include <assert.h>
34257378Sbdrewery#include <errno.h>
35257378Sbdrewery#include <stdio.h>
36257378Sbdrewery#include <stdlib.h>
37257378Sbdrewery#include <string.h>
38263038Sbapt#include <stringlist.h>
39257378Sbdrewery#include <unistd.h>
40257378Sbdrewery#include "testutil.h"
41257378Sbdrewery
42257378Sbdreweryenum test_methods {
43257378Sbdrewery	TEST_GETRPCENT,
44263038Sbapt	TEST_GETRPCBYNAME,
45257378Sbdrewery	TEST_GETRPCBYNUMBER,
46257378Sbdrewery	TEST_GETRPCENT_2PASS,
47257378Sbdrewery	TEST_BUILD_SNAPSHOT
48257378Sbdrewery};
49257378Sbdrewery
50257378Sbdrewerystatic int debug = 0;
51257378Sbdrewerystatic enum test_methods method = TEST_BUILD_SNAPSHOT;
52257378Sbdrewery
53257378SbdreweryDECLARE_TEST_DATA(rpcent)
54257378SbdreweryDECLARE_TEST_FILE_SNAPSHOT(rpcent)
55257378SbdreweryDECLARE_1PASS_TEST(rpcent)
56257378SbdreweryDECLARE_2PASS_TEST(rpcent)
57257378Sbdrewery
58257378Sbdrewerystatic void clone_rpcent(struct rpcent *, struct rpcent const *);
59257378Sbdrewerystatic int compare_rpcent(struct rpcent *, struct rpcent *, void *);
60263038Sbaptstatic void dump_rpcent(struct rpcent *);
61257378Sbdrewerystatic void free_rpcent(struct rpcent *);
62257378Sbdrewery
63257378Sbdrewerystatic void sdump_rpcent(struct rpcent *, char *, size_t);
64257378Sbdrewerystatic int rpcent_read_snapshot_func(struct rpcent *, char *);
65257378Sbdrewery
66257378Sbdrewerystatic int rpcent_check_ambiguity(struct rpcent_test_data *,
67257378Sbdrewery	struct rpcent *);
68263038Sbaptstatic int rpcent_fill_test_data(struct rpcent_test_data *);
69257378Sbdrewerystatic int rpcent_test_correctness(struct rpcent *, void *);
70257378Sbdrewerystatic int rpcent_test_getrpcbyname(struct rpcent *, void *);
71257378Sbdrewerystatic int rpcent_test_getrpcbynumber(struct rpcent *, void *);
72257378Sbdrewerystatic int rpcent_test_getrpcent(struct rpcent *, void *);
73257378Sbdrewery
74257378Sbdrewerystatic void usage(void)  __attribute__((__noreturn__));
75257378Sbdrewery
76257378SbdreweryIMPLEMENT_TEST_DATA(rpcent)
77263038SbaptIMPLEMENT_TEST_FILE_SNAPSHOT(rpcent)
78263038SbaptIMPLEMENT_1PASS_TEST(rpcent)
79263038SbaptIMPLEMENT_2PASS_TEST(rpcent)
80263038Sbapt
81263038Sbaptstatic void
82257378Sbdreweryclone_rpcent(struct rpcent *dest, struct rpcent const *src)
83257378Sbdrewery{
84257378Sbdrewery	assert(dest != NULL);
85257378Sbdrewery	assert(src != NULL);
86257378Sbdrewery
87257378Sbdrewery	char **cp;
88263038Sbapt	int aliases_num;
89257378Sbdrewery
90257378Sbdrewery	memset(dest, 0, sizeof(struct rpcent));
91257378Sbdrewery
92263038Sbapt	if (src->r_name != NULL) {
93263038Sbapt		dest->r_name = strdup(src->r_name);
94263038Sbapt		assert(dest->r_name != NULL);
95263038Sbapt	}
96263038Sbapt
97257378Sbdrewery	dest->r_number = src->r_number;
98257378Sbdrewery
99257378Sbdrewery	if (src->r_aliases != NULL) {
100257378Sbdrewery		aliases_num = 0;
101257378Sbdrewery		for (cp = src->r_aliases; *cp; ++cp)
102257378Sbdrewery			++aliases_num;
103257378Sbdrewery
104257378Sbdrewery		dest->r_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
105257378Sbdrewery		assert(dest->r_aliases != NULL);
106257378Sbdrewery		memset(dest->r_aliases, 0, (aliases_num+1) * (sizeof(char *)));
107257378Sbdrewery
108257378Sbdrewery		for (cp = src->r_aliases; *cp; ++cp) {
109257378Sbdrewery			dest->r_aliases[cp - src->r_aliases] = strdup(*cp);
110257378Sbdrewery			assert(dest->r_aliases[cp - src->r_aliases] != NULL);
111263038Sbapt		}
112257378Sbdrewery	}
113257378Sbdrewery}
114257378Sbdrewery
115257378Sbdrewerystatic void
116257378Sbdreweryfree_rpcent(struct rpcent *rpc)
117257378Sbdrewery{
118257378Sbdrewery	char **cp;
119257378Sbdrewery
120257378Sbdrewery	assert(rpc != NULL);
121257378Sbdrewery
122257378Sbdrewery	free(rpc->r_name);
123257378Sbdrewery
124257378Sbdrewery	for (cp = rpc->r_aliases; *cp; ++cp)
125257378Sbdrewery		free(*cp);
126257378Sbdrewery	free(rpc->r_aliases);
127257378Sbdrewery}
128257378Sbdrewery
129257378Sbdrewerystatic  int
130257378Sbdrewerycompare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata)
131257378Sbdrewery{
132257378Sbdrewery	char **c1, **c2;
133257378Sbdrewery
134257378Sbdrewery	if (rpc1 == rpc2)
135257378Sbdrewery		return 0;
136257378Sbdrewery
137257378Sbdrewery	if ((rpc1 == NULL) || (rpc2 == NULL))
138257378Sbdrewery		goto errfin;
139257378Sbdrewery
140257378Sbdrewery	if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) ||
141257378Sbdrewery		(rpc1->r_number != rpc2->r_number))
142257378Sbdrewery			goto errfin;
143257378Sbdrewery
144257378Sbdrewery	c1 = rpc1->r_aliases;
145257378Sbdrewery	c2 = rpc2->r_aliases;
146257378Sbdrewery
147257378Sbdrewery	if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == NULL))
148257378Sbdrewery		goto errfin;
149257378Sbdrewery
150263038Sbapt	for (;*c1 && *c2; ++c1, ++c2)
151257378Sbdrewery		if (strcmp(*c1, *c2) != 0)
152257378Sbdrewery			goto errfin;
153257378Sbdrewery
154257378Sbdrewery	if ((*c1 != '\0') || (*c2 != '\0'))
155263038Sbapt		goto errfin;
156257378Sbdrewery
157263038Sbapt	return 0;
158257378Sbdrewery
159257378Sbdreweryerrfin:
160257378Sbdrewery	if ((debug) && (mdata == NULL)) {
161257378Sbdrewery		printf("following structures are not equal:\n");
162257378Sbdrewery		dump_rpcent(rpc1);
163257378Sbdrewery		dump_rpcent(rpc2);
164257378Sbdrewery	}
165257378Sbdrewery
166257378Sbdrewery	return (-1);
167257378Sbdrewery}
168257378Sbdrewery
169257378Sbdrewerystatic void
170257378Sbdrewerysdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen)
171257378Sbdrewery{
172257378Sbdrewery	char **cp;
173257378Sbdrewery	int written;
174257378Sbdrewery
175257378Sbdrewery	written = snprintf(buffer, buflen, "%s %d",
176257378Sbdrewery		rpc->r_name, rpc->r_number);
177257378Sbdrewery	buffer += written;
178257378Sbdrewery	if (written > buflen)
179257378Sbdrewery		return;
180257378Sbdrewery	buflen -= written;
181257378Sbdrewery
182257378Sbdrewery	if (rpc->r_aliases != NULL) {
183257378Sbdrewery		if (*(rpc->r_aliases) != '\0') {
184257378Sbdrewery			for (cp = rpc->r_aliases; *cp; ++cp) {
185257378Sbdrewery				written = snprintf(buffer, buflen, " %s",*cp);
186257378Sbdrewery				buffer += written;
187257378Sbdrewery				if (written > buflen)
188257378Sbdrewery					return;
189257378Sbdrewery				buflen -= written;
190257378Sbdrewery
191257378Sbdrewery				if (buflen == 0)
192257378Sbdrewery					return;
193257378Sbdrewery			}
194257378Sbdrewery		} else
195257378Sbdrewery			snprintf(buffer, buflen, " noaliases");
196257378Sbdrewery	} else
197257378Sbdrewery		snprintf(buffer, buflen, " (null)");
198263038Sbapt}
199263038Sbapt
200263038Sbaptstatic int
201257378Sbdreweryrpcent_read_snapshot_func(struct rpcent *rpc, char *line)
202257378Sbdrewery{
203257378Sbdrewery	StringList *sl;
204263038Sbapt	char *s, *ps, *ts;
205263038Sbapt	int i;
206263038Sbapt
207257378Sbdrewery	if (debug)
208257378Sbdrewery		printf("1 line read from snapshot:\n%s\n", line);
209257378Sbdrewery
210257378Sbdrewery	i = 0;
211263038Sbapt	sl = NULL;
212257378Sbdrewery	ps = line;
213257378Sbdrewery	memset(rpc, 0, sizeof(struct rpcent));
214257378Sbdrewery	while ( (s = strsep(&ps, " ")) != NULL) {
215257378Sbdrewery		switch (i) {
216257378Sbdrewery			case 0:
217257378Sbdrewery				rpc->r_name = strdup(s);
218257378Sbdrewery				assert(rpc->r_name != NULL);
219257378Sbdrewery			break;
220257378Sbdrewery
221257378Sbdrewery			case 1:
222257378Sbdrewery				rpc->r_number = (int)strtol(s, &ts, 10);
223257378Sbdrewery				if (*ts != '\0') {
224257378Sbdrewery					free(rpc->r_name);
225257378Sbdrewery					return (-1);
226257378Sbdrewery				}
227257378Sbdrewery			break;
228257378Sbdrewery
229257378Sbdrewery			default:
230257378Sbdrewery				if (sl == NULL) {
231257378Sbdrewery					if (strcmp(s, "(null)") == 0)
232257378Sbdrewery						return (0);
233257378Sbdrewery
234257378Sbdrewery					sl = sl_init();
235257378Sbdrewery					assert(sl != NULL);
236257378Sbdrewery
237257378Sbdrewery					if (strcmp(s, "noaliases") != 0) {
238257378Sbdrewery						ts = strdup(s);
239257378Sbdrewery						assert(ts != NULL);
240257378Sbdrewery						sl_add(sl, ts);
241257378Sbdrewery					}
242257378Sbdrewery				} else {
243257378Sbdrewery					ts = strdup(s);
244257378Sbdrewery					assert(ts != NULL);
245257378Sbdrewery					sl_add(sl, ts);
246257378Sbdrewery				}
247257378Sbdrewery			break;
248257378Sbdrewery		};
249257378Sbdrewery		++i;
250257378Sbdrewery	}
251257378Sbdrewery
252257378Sbdrewery	if (i < 3) {
253257378Sbdrewery		free(rpc->r_name);
254257378Sbdrewery		memset(rpc, 0, sizeof(struct rpcent));
255257378Sbdrewery		return (-1);
256257378Sbdrewery	}
257257378Sbdrewery
258257378Sbdrewery	sl_add(sl, NULL);
259257378Sbdrewery	rpc->r_aliases = sl->sl_str;
260257378Sbdrewery
261257378Sbdrewery	/* NOTE: is it a dirty hack or not? */
262257378Sbdrewery	free(sl);
263257378Sbdrewery	return (0);
264257378Sbdrewery}
265257378Sbdrewery
266257378Sbdrewerystatic void
267257378Sbdrewerydump_rpcent(struct rpcent *result)
268263038Sbapt{
269263038Sbapt	if (result != NULL) {
270257378Sbdrewery		char buffer[1024];
271257378Sbdrewery		sdump_rpcent(result, buffer, sizeof(buffer));
272257378Sbdrewery		printf("%s\n", buffer);
273257378Sbdrewery	} else
274257378Sbdrewery		printf("(null)\n");
275257378Sbdrewery}
276257378Sbdrewery
277257378Sbdrewerystatic int
278257378Sbdreweryrpcent_fill_test_data(struct rpcent_test_data *td)
279257378Sbdrewery{
280257378Sbdrewery	struct rpcent *rpc;
281257378Sbdrewery
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
294static int
295rpcent_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);
318errfin:
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 */
330static int
331rpcent_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
338static int
339rpcent_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
374errfin:
375	if (debug)
376		printf("not ok\n");
377
378	return (-1);
379}
380
381static int
382rpcent_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
406static int
407rpcent_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
414static void
415usage(void)
416{
417	(void)fprintf(stderr,
418	    "Usage: %s -nve2 [-d] [-s <file>]\n",
419	    getprogname());
420	exit(1);
421}
422
423int
424main(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
530fin:
531	TEST_DATA_DESTROY(rpcent, &td_snap);
532	TEST_DATA_DESTROY(rpcent, &td);
533	free(snapshot_file);
534	return (rv);
535}
536