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