]> granicus.if.org Git - sudo/blob - lib/util/regress/getdelim/getdelim_test.c
Add SPDX-License-Identifier to files.
[sudo] / lib / util / regress / getdelim / getdelim_test.c
1 /*
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2019 Todd C. Miller <Todd.Miller@sudo.ws>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include <config.h>
20
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/wait.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #ifdef HAVE_STRING_H
27 # include <string.h>
28 #endif /* HAVE_STRING_H */
29 #ifdef HAVE_STRINGS_H
30 # include <strings.h>
31 #endif /* HAVE_STRINGS_H */
32 #ifdef HAVE_STDBOOL_H
33 # include <stdbool.h>
34 #else
35 # include "compat/stdbool.h"
36 #endif
37 #include <unistd.h>
38
39 #include "sudo_compat.h"
40 #include "sudo_fatal.h"
41 #include "sudo_util.h"
42
43 __dso_public int main(int argc, char *argv[]);
44
45 /*
46  * Test that sudo_getdelim() works as expected.
47  */
48
49 struct getdelim_test {
50     const char *input;
51     const char *output[4];
52     int delim;
53 };
54
55 /*
56  * TODO: test error case.
57  *       test realloc case (buf > LINE_MAX)
58  */
59 static struct getdelim_test test_data[] = {
60     { "a\nb\nc\n", { "a\n", "b\n", "c\n", NULL }, '\n' },
61     { "a\nb\nc", { "a\n", "b\n", "c", NULL }, '\n' },
62     { "a\tb\tc\t", { "a\t", "b\t", "c\t", NULL }, '\t' },
63     { "a\tb\tc", { "a\t", "b\t", "c", NULL }, '\t' },
64     { NULL, { NULL }, '\0' }
65 };
66
67 static int errors = 0, ntests = 0;
68
69 static void
70 runtests(char **buf, size_t *buflen)
71 {
72     int i, j, sv[2];
73     pid_t pid;
74     FILE *fp;
75
76     for (i = 0; test_data[i].input != NULL; i++) {
77         if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
78             sudo_fatal_nodebug("socketpair");
79
80         switch ((pid = fork())) {
81         case -1:
82             sudo_fatal_nodebug("fork");
83         case 0:
84             /* child */
85             close(sv[0]);
86             if (send(sv[1], test_data[i].input, strlen(test_data[i].input), 0) == -1) {
87                 sudo_warn_nodebug("send");
88                 _exit(127);
89             }
90             _exit(0);
91             break;
92         default:
93             /* parent */
94             break;
95         }
96
97         close(sv[1]);
98         if ((fp = fdopen(sv[0], "r")) == NULL)
99             sudo_fatal_nodebug("fdopen");
100
101         for (j = 0; test_data[i].output[j] != NULL; j++) {
102             ntests++;
103             alarm(10);
104             if (getdelim(buf, buflen, test_data[i].delim, fp) == -1)
105                 sudo_fatal_nodebug("getdelim");
106             alarm(0);
107             if (strcmp(*buf, test_data[i].output[j]) != 0) {
108                 sudo_warnx_nodebug("failed test #%d: expected %s, got %s",
109                     ntests, test_data[i].output[j], *buf);
110                 errors++;
111             }
112         }
113         /* test EOF */
114         ntests++;
115         alarm(30);
116         if (getdelim(buf, buflen, test_data[i].delim, fp) != -1) {
117             sudo_warnx_nodebug("failed test #%d: expected EOF, got %s",
118                 ntests, *buf);
119             errors++;
120         } else {
121             if (!feof(fp)) {
122                 sudo_warn_nodebug("failed test #%d: expected EOF, got error",
123                     ntests);
124                 errors++;
125             }
126         }
127         fclose(fp);
128         waitpid(pid, NULL, 0);
129         alarm(0);
130     }
131 }
132
133 int
134 main(int argc, char *argv[])
135 {
136     size_t buflen = 0;
137     char *buf = NULL;
138
139     initprogname(argc > 0 ? argv[0] : "getdelim_test");
140
141     runtests(&buf, &buflen);
142
143     /* XXX - redo tests with preallocated buffer filled with junk */
144     if (ntests != 0) {
145         printf("%s: %d tests run, %d errors, %d%% success rate\n",
146             getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
147     }
148     exit(errors);
149 }