]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - lib/libc/tests/nss/getproto_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 / getproto_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 <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
45 enum test_methods {
46         TEST_GETPROTOENT,
47         TEST_GETPROTOBYNAME,
48         TEST_GETPROTOBYNUMBER,
49         TEST_GETPROTOENT_2PASS,
50         TEST_BUILD_SNAPSHOT
51 };
52
53 DECLARE_TEST_DATA(protoent)
54 DECLARE_TEST_FILE_SNAPSHOT(protoent)
55 DECLARE_1PASS_TEST(protoent)
56 DECLARE_2PASS_TEST(protoent)
57
58 static void clone_protoent(struct protoent *, struct protoent const *);
59 static int compare_protoent(struct protoent *, struct protoent *, void *);
60 static void dump_protoent(struct protoent *);
61 static void free_protoent(struct protoent *);
62
63 static void sdump_protoent(struct protoent *, char *, size_t);
64 static int protoent_read_snapshot_func(struct protoent *, char *);
65
66 static int protoent_check_ambiguity(struct protoent_test_data *,
67         struct protoent *);
68 static int protoent_fill_test_data(struct protoent_test_data *);
69 static int protoent_test_correctness(struct protoent *, void *);
70 static int protoent_test_getprotobyname(struct protoent *, void *);
71 static int protoent_test_getprotobynumber(struct protoent *, void *);
72 static int protoent_test_getprotoent(struct protoent *, void *);
73
74 IMPLEMENT_TEST_DATA(protoent)
75 IMPLEMENT_TEST_FILE_SNAPSHOT(protoent)
76 IMPLEMENT_1PASS_TEST(protoent)
77 IMPLEMENT_2PASS_TEST(protoent)
78
79 static void
80 clone_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(1, (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
112 static void
113 free_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
126 static  int
127 compare_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
156 errfin:
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
166 static void
167 sdump_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 > 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 > 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
197 static int
198 protoent_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
262 static void
263 dump_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
273 static int
274 protoent_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
290 static int
291 protoent_test_correctness(struct protoent *pe, void *mdata)
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);
311 errfin:
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 peice (these cases are usually marked as PROBLEM in
319  * /etc/peices. This functions is needed also when one peice+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 */
322 static int
323 protoent_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
330 static int
331 protoent_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
363 errfin:
364         printf("not ok\n");
365
366         return (-1);
367 }
368
369 static int
370 protoent_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
390 static int
391 protoent_test_getprotoent(struct protoent *pe, void *mdata)
392 {
393         /* Only correctness can be checked when doing 1-pass test for
394          * getprotoent(). */
395         return (protoent_test_correctness(pe, NULL));
396 }
397
398 int
399 run_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
475 fin:
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
484 ATF_TC_WITHOUT_HEAD(build_snapshot);
485 ATF_TC_BODY(build_snapshot, tc)
486 {
487
488         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
489 }
490
491 ATF_TC_WITHOUT_HEAD(getprotoent);
492 ATF_TC_BODY(getprotoent, tc)
493 {
494
495         ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT) == 0);
496 }
497
498 ATF_TC_WITHOUT_HEAD(getprotoent_with_snapshot);
499 ATF_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
506 ATF_TC_WITHOUT_HEAD(getprotoent_with_two_pass);
507 ATF_TC_BODY(getprotoent_with_two_pass, tc)
508 {
509
510         ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT_2PASS) == 0);
511 }
512
513 ATF_TC_WITHOUT_HEAD(getprotobyname);
514 ATF_TC_BODY(getprotobyname, tc)
515 {
516
517         ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNAME) == 0);
518 }
519
520 ATF_TC_WITHOUT_HEAD(getprotobyname_with_snapshot);
521 ATF_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
528 ATF_TC_WITHOUT_HEAD(getprotobynumber);
529 ATF_TC_BODY(getprotobynumber, tc)
530 {
531
532         ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNUMBER) == 0);
533 }
534
535 ATF_TC_WITHOUT_HEAD(getprotobynumber_with_snapshot);
536 ATF_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
543 ATF_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 }