1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker * Copyright (C) 2012-2013 ProFUSION embedded systems
3*cc4ad7daSAndroid Build Coastguard Worker *
4*cc4ad7daSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*cc4ad7daSAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
6*cc4ad7daSAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
7*cc4ad7daSAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
8*cc4ad7daSAndroid Build Coastguard Worker *
9*cc4ad7daSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
10*cc4ad7daSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*cc4ad7daSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12*cc4ad7daSAndroid Build Coastguard Worker * Lesser General Public License for more details.
13*cc4ad7daSAndroid Build Coastguard Worker *
14*cc4ad7daSAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
15*cc4ad7daSAndroid Build Coastguard Worker * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16*cc4ad7daSAndroid Build Coastguard Worker */
17*cc4ad7daSAndroid Build Coastguard Worker
18*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
19*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
20*cc4ad7daSAndroid Build Coastguard Worker #include <fcntl.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <getopt.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <regex.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <time.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <sys/epoll.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <sys/prctl.h>
32*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
33*cc4ad7daSAndroid Build Coastguard Worker #include <sys/wait.h>
34*cc4ad7daSAndroid Build Coastguard Worker
35*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
36*cc4ad7daSAndroid Build Coastguard Worker
37*cc4ad7daSAndroid Build Coastguard Worker #include "testsuite.h"
38*cc4ad7daSAndroid Build Coastguard Worker
39*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_GREEN_ON = "\x1B[1;32m";
40*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_YELLOW_ON = "\x1B[1;33m";
41*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_RED_ON = "\x1B[1;31m";
42*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_OFF = "\x1B[0m";
43*cc4ad7daSAndroid Build Coastguard Worker
44*cc4ad7daSAndroid Build Coastguard Worker static const char *progname;
45*cc4ad7daSAndroid Build Coastguard Worker static int oneshot = 0;
46*cc4ad7daSAndroid Build Coastguard Worker static const char options_short[] = "lhn";
47*cc4ad7daSAndroid Build Coastguard Worker static const struct option options[] = {
48*cc4ad7daSAndroid Build Coastguard Worker { "list", no_argument, 0, 'l' },
49*cc4ad7daSAndroid Build Coastguard Worker { "help", no_argument, 0, 'h' },
50*cc4ad7daSAndroid Build Coastguard Worker { NULL, 0, 0, 0 }
51*cc4ad7daSAndroid Build Coastguard Worker };
52*cc4ad7daSAndroid Build Coastguard Worker
53*cc4ad7daSAndroid Build Coastguard Worker #define OVERRIDE_LIBDIR ABS_TOP_BUILDDIR "/testsuite/.libs/"
54*cc4ad7daSAndroid Build Coastguard Worker #define TEST_TIMEOUT_USEC 2 * USEC_PER_SEC
55*cc4ad7daSAndroid Build Coastguard Worker
56*cc4ad7daSAndroid Build Coastguard Worker static const struct {
57*cc4ad7daSAndroid Build Coastguard Worker const char *key;
58*cc4ad7daSAndroid Build Coastguard Worker const char *ldpreload;
59*cc4ad7daSAndroid Build Coastguard Worker } env_config[_TC_LAST] = {
60*cc4ad7daSAndroid Build Coastguard Worker [TC_UNAME_R] = { S_TC_UNAME_R, OVERRIDE_LIBDIR "uname.so" },
61*cc4ad7daSAndroid Build Coastguard Worker [TC_ROOTFS] = { S_TC_ROOTFS, OVERRIDE_LIBDIR "path.so" },
62*cc4ad7daSAndroid Build Coastguard Worker [TC_INIT_MODULE_RETCODES] = { S_TC_INIT_MODULE_RETCODES, OVERRIDE_LIBDIR "init_module.so" },
63*cc4ad7daSAndroid Build Coastguard Worker [TC_DELETE_MODULE_RETCODES] = { S_TC_DELETE_MODULE_RETCODES, OVERRIDE_LIBDIR "delete_module.so" },
64*cc4ad7daSAndroid Build Coastguard Worker };
65*cc4ad7daSAndroid Build Coastguard Worker
help(void)66*cc4ad7daSAndroid Build Coastguard Worker static void help(void)
67*cc4ad7daSAndroid Build Coastguard Worker {
68*cc4ad7daSAndroid Build Coastguard Worker const struct option *itr;
69*cc4ad7daSAndroid Build Coastguard Worker const char *itr_short;
70*cc4ad7daSAndroid Build Coastguard Worker
71*cc4ad7daSAndroid Build Coastguard Worker printf("Usage:\n"
72*cc4ad7daSAndroid Build Coastguard Worker "\t%s [options] <test>\n"
73*cc4ad7daSAndroid Build Coastguard Worker "Options:\n", basename(progname));
74*cc4ad7daSAndroid Build Coastguard Worker
75*cc4ad7daSAndroid Build Coastguard Worker for (itr = options, itr_short = options_short;
76*cc4ad7daSAndroid Build Coastguard Worker itr->name != NULL; itr++, itr_short++)
77*cc4ad7daSAndroid Build Coastguard Worker printf("\t-%c, --%s\n", *itr_short, itr->name);
78*cc4ad7daSAndroid Build Coastguard Worker }
79*cc4ad7daSAndroid Build Coastguard Worker
test_list(const struct test * start,const struct test * stop)80*cc4ad7daSAndroid Build Coastguard Worker static void test_list(const struct test *start, const struct test *stop)
81*cc4ad7daSAndroid Build Coastguard Worker {
82*cc4ad7daSAndroid Build Coastguard Worker const struct test *t;
83*cc4ad7daSAndroid Build Coastguard Worker
84*cc4ad7daSAndroid Build Coastguard Worker printf("Available tests:\n");
85*cc4ad7daSAndroid Build Coastguard Worker for (t = start; t < stop; t++)
86*cc4ad7daSAndroid Build Coastguard Worker printf("\t%s, %s\n", t->name, t->description);
87*cc4ad7daSAndroid Build Coastguard Worker }
88*cc4ad7daSAndroid Build Coastguard Worker
test_init(const struct test * start,const struct test * stop,int argc,char * const argv[])89*cc4ad7daSAndroid Build Coastguard Worker int test_init(const struct test *start, const struct test *stop,
90*cc4ad7daSAndroid Build Coastguard Worker int argc, char *const argv[])
91*cc4ad7daSAndroid Build Coastguard Worker {
92*cc4ad7daSAndroid Build Coastguard Worker progname = argv[0];
93*cc4ad7daSAndroid Build Coastguard Worker
94*cc4ad7daSAndroid Build Coastguard Worker for (;;) {
95*cc4ad7daSAndroid Build Coastguard Worker int c, idx = 0;
96*cc4ad7daSAndroid Build Coastguard Worker c = getopt_long(argc, argv, options_short, options, &idx);
97*cc4ad7daSAndroid Build Coastguard Worker if (c == -1)
98*cc4ad7daSAndroid Build Coastguard Worker break;
99*cc4ad7daSAndroid Build Coastguard Worker switch (c) {
100*cc4ad7daSAndroid Build Coastguard Worker case 'l':
101*cc4ad7daSAndroid Build Coastguard Worker test_list(start, stop);
102*cc4ad7daSAndroid Build Coastguard Worker return 0;
103*cc4ad7daSAndroid Build Coastguard Worker case 'h':
104*cc4ad7daSAndroid Build Coastguard Worker help();
105*cc4ad7daSAndroid Build Coastguard Worker return 0;
106*cc4ad7daSAndroid Build Coastguard Worker case 'n':
107*cc4ad7daSAndroid Build Coastguard Worker oneshot = 1;
108*cc4ad7daSAndroid Build Coastguard Worker break;
109*cc4ad7daSAndroid Build Coastguard Worker case '?':
110*cc4ad7daSAndroid Build Coastguard Worker return -1;
111*cc4ad7daSAndroid Build Coastguard Worker default:
112*cc4ad7daSAndroid Build Coastguard Worker ERR("unexpected getopt_long() value %c\n", c);
113*cc4ad7daSAndroid Build Coastguard Worker return -1;
114*cc4ad7daSAndroid Build Coastguard Worker }
115*cc4ad7daSAndroid Build Coastguard Worker }
116*cc4ad7daSAndroid Build Coastguard Worker
117*cc4ad7daSAndroid Build Coastguard Worker if (isatty(STDOUT_FILENO) == 0) {
118*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_OFF = "";
119*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_RED_ON = "";
120*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_GREEN_ON = "";
121*cc4ad7daSAndroid Build Coastguard Worker }
122*cc4ad7daSAndroid Build Coastguard Worker
123*cc4ad7daSAndroid Build Coastguard Worker return optind;
124*cc4ad7daSAndroid Build Coastguard Worker }
125*cc4ad7daSAndroid Build Coastguard Worker
test_find(const struct test * start,const struct test * stop,const char * name)126*cc4ad7daSAndroid Build Coastguard Worker const struct test *test_find(const struct test *start,
127*cc4ad7daSAndroid Build Coastguard Worker const struct test *stop, const char *name)
128*cc4ad7daSAndroid Build Coastguard Worker {
129*cc4ad7daSAndroid Build Coastguard Worker const struct test *t;
130*cc4ad7daSAndroid Build Coastguard Worker
131*cc4ad7daSAndroid Build Coastguard Worker for (t = start; t < stop; t++) {
132*cc4ad7daSAndroid Build Coastguard Worker if (streq(t->name, name))
133*cc4ad7daSAndroid Build Coastguard Worker return t;
134*cc4ad7daSAndroid Build Coastguard Worker }
135*cc4ad7daSAndroid Build Coastguard Worker
136*cc4ad7daSAndroid Build Coastguard Worker return NULL;
137*cc4ad7daSAndroid Build Coastguard Worker }
138*cc4ad7daSAndroid Build Coastguard Worker
test_spawn_test(const struct test * t)139*cc4ad7daSAndroid Build Coastguard Worker static int test_spawn_test(const struct test *t)
140*cc4ad7daSAndroid Build Coastguard Worker {
141*cc4ad7daSAndroid Build Coastguard Worker const char *const args[] = { progname, "-n", t->name, NULL };
142*cc4ad7daSAndroid Build Coastguard Worker
143*cc4ad7daSAndroid Build Coastguard Worker execv(progname, (char *const *) args);
144*cc4ad7daSAndroid Build Coastguard Worker
145*cc4ad7daSAndroid Build Coastguard Worker ERR("failed to spawn %s for %s: %m\n", progname, t->name);
146*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
147*cc4ad7daSAndroid Build Coastguard Worker }
148*cc4ad7daSAndroid Build Coastguard Worker
test_run_spawned(const struct test * t)149*cc4ad7daSAndroid Build Coastguard Worker static int test_run_spawned(const struct test *t)
150*cc4ad7daSAndroid Build Coastguard Worker {
151*cc4ad7daSAndroid Build Coastguard Worker int err = t->func(t);
152*cc4ad7daSAndroid Build Coastguard Worker exit(err);
153*cc4ad7daSAndroid Build Coastguard Worker
154*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
155*cc4ad7daSAndroid Build Coastguard Worker }
156*cc4ad7daSAndroid Build Coastguard Worker
test_spawn_prog(const char * prog,const char * const args[])157*cc4ad7daSAndroid Build Coastguard Worker int test_spawn_prog(const char *prog, const char *const args[])
158*cc4ad7daSAndroid Build Coastguard Worker {
159*cc4ad7daSAndroid Build Coastguard Worker execv(prog, (char *const *) args);
160*cc4ad7daSAndroid Build Coastguard Worker
161*cc4ad7daSAndroid Build Coastguard Worker ERR("failed to spawn %s\n", prog);
162*cc4ad7daSAndroid Build Coastguard Worker ERR("did you forget to build tools?\n");
163*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
164*cc4ad7daSAndroid Build Coastguard Worker }
165*cc4ad7daSAndroid Build Coastguard Worker
test_export_environ(const struct test * t)166*cc4ad7daSAndroid Build Coastguard Worker static void test_export_environ(const struct test *t)
167*cc4ad7daSAndroid Build Coastguard Worker {
168*cc4ad7daSAndroid Build Coastguard Worker char *preload = NULL;
169*cc4ad7daSAndroid Build Coastguard Worker size_t preloadlen = 0;
170*cc4ad7daSAndroid Build Coastguard Worker size_t i;
171*cc4ad7daSAndroid Build Coastguard Worker const struct keyval *env;
172*cc4ad7daSAndroid Build Coastguard Worker
173*cc4ad7daSAndroid Build Coastguard Worker unsetenv("LD_PRELOAD");
174*cc4ad7daSAndroid Build Coastguard Worker
175*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < _TC_LAST; i++) {
176*cc4ad7daSAndroid Build Coastguard Worker const char *ldpreload;
177*cc4ad7daSAndroid Build Coastguard Worker size_t ldpreloadlen;
178*cc4ad7daSAndroid Build Coastguard Worker char *tmp;
179*cc4ad7daSAndroid Build Coastguard Worker
180*cc4ad7daSAndroid Build Coastguard Worker if (t->config[i] == NULL)
181*cc4ad7daSAndroid Build Coastguard Worker continue;
182*cc4ad7daSAndroid Build Coastguard Worker
183*cc4ad7daSAndroid Build Coastguard Worker setenv(env_config[i].key, t->config[i], 1);
184*cc4ad7daSAndroid Build Coastguard Worker
185*cc4ad7daSAndroid Build Coastguard Worker ldpreload = env_config[i].ldpreload;
186*cc4ad7daSAndroid Build Coastguard Worker ldpreloadlen = strlen(ldpreload);
187*cc4ad7daSAndroid Build Coastguard Worker tmp = realloc(preload, preloadlen + 2 + ldpreloadlen);
188*cc4ad7daSAndroid Build Coastguard Worker if (tmp == NULL) {
189*cc4ad7daSAndroid Build Coastguard Worker ERR("oom: test_export_environ()\n");
190*cc4ad7daSAndroid Build Coastguard Worker return;
191*cc4ad7daSAndroid Build Coastguard Worker }
192*cc4ad7daSAndroid Build Coastguard Worker preload = tmp;
193*cc4ad7daSAndroid Build Coastguard Worker
194*cc4ad7daSAndroid Build Coastguard Worker if (preloadlen > 0)
195*cc4ad7daSAndroid Build Coastguard Worker preload[preloadlen++] = ' ';
196*cc4ad7daSAndroid Build Coastguard Worker memcpy(preload + preloadlen, ldpreload, ldpreloadlen);
197*cc4ad7daSAndroid Build Coastguard Worker preloadlen += ldpreloadlen;
198*cc4ad7daSAndroid Build Coastguard Worker preload[preloadlen] = '\0';
199*cc4ad7daSAndroid Build Coastguard Worker }
200*cc4ad7daSAndroid Build Coastguard Worker
201*cc4ad7daSAndroid Build Coastguard Worker if (preload != NULL)
202*cc4ad7daSAndroid Build Coastguard Worker setenv("LD_PRELOAD", preload, 1);
203*cc4ad7daSAndroid Build Coastguard Worker
204*cc4ad7daSAndroid Build Coastguard Worker free(preload);
205*cc4ad7daSAndroid Build Coastguard Worker
206*cc4ad7daSAndroid Build Coastguard Worker for (env = t->env_vars; env && env->key; env++)
207*cc4ad7daSAndroid Build Coastguard Worker setenv(env->key, env->val, 1);
208*cc4ad7daSAndroid Build Coastguard Worker }
209*cc4ad7daSAndroid Build Coastguard Worker
test_run_child(const struct test * t,int fdout[2],int fderr[2],int fdmonitor[2])210*cc4ad7daSAndroid Build Coastguard Worker static inline int test_run_child(const struct test *t, int fdout[2],
211*cc4ad7daSAndroid Build Coastguard Worker int fderr[2], int fdmonitor[2])
212*cc4ad7daSAndroid Build Coastguard Worker {
213*cc4ad7daSAndroid Build Coastguard Worker /* kill child if parent dies */
214*cc4ad7daSAndroid Build Coastguard Worker prctl(PR_SET_PDEATHSIG, SIGTERM);
215*cc4ad7daSAndroid Build Coastguard Worker
216*cc4ad7daSAndroid Build Coastguard Worker test_export_environ(t);
217*cc4ad7daSAndroid Build Coastguard Worker
218*cc4ad7daSAndroid Build Coastguard Worker /* Close read-fds and redirect std{out,err} to the write-fds */
219*cc4ad7daSAndroid Build Coastguard Worker if (t->output.out != NULL) {
220*cc4ad7daSAndroid Build Coastguard Worker close(fdout[0]);
221*cc4ad7daSAndroid Build Coastguard Worker if (dup2(fdout[1], STDOUT_FILENO) < 0) {
222*cc4ad7daSAndroid Build Coastguard Worker ERR("could not redirect stdout to pipe: %m\n");
223*cc4ad7daSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
224*cc4ad7daSAndroid Build Coastguard Worker }
225*cc4ad7daSAndroid Build Coastguard Worker }
226*cc4ad7daSAndroid Build Coastguard Worker
227*cc4ad7daSAndroid Build Coastguard Worker if (t->output.err != NULL) {
228*cc4ad7daSAndroid Build Coastguard Worker close(fderr[0]);
229*cc4ad7daSAndroid Build Coastguard Worker if (dup2(fderr[1], STDERR_FILENO) < 0) {
230*cc4ad7daSAndroid Build Coastguard Worker ERR("could not redirect stderr to pipe: %m\n");
231*cc4ad7daSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
232*cc4ad7daSAndroid Build Coastguard Worker }
233*cc4ad7daSAndroid Build Coastguard Worker }
234*cc4ad7daSAndroid Build Coastguard Worker
235*cc4ad7daSAndroid Build Coastguard Worker close(fdmonitor[0]);
236*cc4ad7daSAndroid Build Coastguard Worker
237*cc4ad7daSAndroid Build Coastguard Worker if (t->config[TC_ROOTFS] != NULL) {
238*cc4ad7daSAndroid Build Coastguard Worker const char *stamp = TESTSUITE_ROOTFS "../stamp-rootfs";
239*cc4ad7daSAndroid Build Coastguard Worker const char *rootfs = t->config[TC_ROOTFS];
240*cc4ad7daSAndroid Build Coastguard Worker struct stat rootfsst, stampst;
241*cc4ad7daSAndroid Build Coastguard Worker
242*cc4ad7daSAndroid Build Coastguard Worker if (stat(stamp, &stampst) != 0) {
243*cc4ad7daSAndroid Build Coastguard Worker ERR("could not stat %s\n - %m", stamp);
244*cc4ad7daSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
245*cc4ad7daSAndroid Build Coastguard Worker }
246*cc4ad7daSAndroid Build Coastguard Worker
247*cc4ad7daSAndroid Build Coastguard Worker if (stat(rootfs, &rootfsst) != 0) {
248*cc4ad7daSAndroid Build Coastguard Worker ERR("could not stat %s\n - %m", rootfs);
249*cc4ad7daSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
250*cc4ad7daSAndroid Build Coastguard Worker }
251*cc4ad7daSAndroid Build Coastguard Worker
252*cc4ad7daSAndroid Build Coastguard Worker if (stat_mstamp(&rootfsst) > stat_mstamp(&stampst)) {
253*cc4ad7daSAndroid Build Coastguard Worker ERR("rootfs %s is dirty, please run 'make rootfs' before runnning this test\n",
254*cc4ad7daSAndroid Build Coastguard Worker rootfs);
255*cc4ad7daSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
256*cc4ad7daSAndroid Build Coastguard Worker }
257*cc4ad7daSAndroid Build Coastguard Worker }
258*cc4ad7daSAndroid Build Coastguard Worker
259*cc4ad7daSAndroid Build Coastguard Worker if (t->need_spawn)
260*cc4ad7daSAndroid Build Coastguard Worker return test_spawn_test(t);
261*cc4ad7daSAndroid Build Coastguard Worker else
262*cc4ad7daSAndroid Build Coastguard Worker return test_run_spawned(t);
263*cc4ad7daSAndroid Build Coastguard Worker }
264*cc4ad7daSAndroid Build Coastguard Worker
265*cc4ad7daSAndroid Build Coastguard Worker #define BUFSZ 4096
266*cc4ad7daSAndroid Build Coastguard Worker
267*cc4ad7daSAndroid Build Coastguard Worker enum fd_cmp_type {
268*cc4ad7daSAndroid Build Coastguard Worker FD_CMP_MONITOR,
269*cc4ad7daSAndroid Build Coastguard Worker FD_CMP_OUT,
270*cc4ad7daSAndroid Build Coastguard Worker FD_CMP_ERR,
271*cc4ad7daSAndroid Build Coastguard Worker FD_CMP_MAX = FD_CMP_ERR,
272*cc4ad7daSAndroid Build Coastguard Worker };
273*cc4ad7daSAndroid Build Coastguard Worker
274*cc4ad7daSAndroid Build Coastguard Worker struct fd_cmp {
275*cc4ad7daSAndroid Build Coastguard Worker enum fd_cmp_type type;
276*cc4ad7daSAndroid Build Coastguard Worker int fd;
277*cc4ad7daSAndroid Build Coastguard Worker int fd_match;
278*cc4ad7daSAndroid Build Coastguard Worker bool activity;
279*cc4ad7daSAndroid Build Coastguard Worker const char *path;
280*cc4ad7daSAndroid Build Coastguard Worker const char *name;
281*cc4ad7daSAndroid Build Coastguard Worker char buf[BUFSZ];
282*cc4ad7daSAndroid Build Coastguard Worker char buf_match[BUFSZ];
283*cc4ad7daSAndroid Build Coastguard Worker unsigned int head;
284*cc4ad7daSAndroid Build Coastguard Worker unsigned int head_match;
285*cc4ad7daSAndroid Build Coastguard Worker };
286*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_check_activity(struct fd_cmp * fd_cmp)287*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_check_activity(struct fd_cmp *fd_cmp)
288*cc4ad7daSAndroid Build Coastguard Worker {
289*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
290*cc4ad7daSAndroid Build Coastguard Worker
291*cc4ad7daSAndroid Build Coastguard Worker /* not monitoring or monitoring and it has activity */
292*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp == NULL || fd_cmp->fd < 0 || fd_cmp->activity)
293*cc4ad7daSAndroid Build Coastguard Worker return 0;
294*cc4ad7daSAndroid Build Coastguard Worker
295*cc4ad7daSAndroid Build Coastguard Worker /* monitoring, there was no activity and size matches */
296*cc4ad7daSAndroid Build Coastguard Worker if (stat(fd_cmp->path, &st) == 0 && st.st_size == 0)
297*cc4ad7daSAndroid Build Coastguard Worker return 0;
298*cc4ad7daSAndroid Build Coastguard Worker
299*cc4ad7daSAndroid Build Coastguard Worker ERR("Expecting output on %s, but test didn't produce any\n",
300*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->name);
301*cc4ad7daSAndroid Build Coastguard Worker
302*cc4ad7daSAndroid Build Coastguard Worker return -1;
303*cc4ad7daSAndroid Build Coastguard Worker }
304*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_is_active(struct fd_cmp * fd_cmp)305*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_is_active(struct fd_cmp *fd_cmp)
306*cc4ad7daSAndroid Build Coastguard Worker {
307*cc4ad7daSAndroid Build Coastguard Worker return fd_cmp->fd != -1;
308*cc4ad7daSAndroid Build Coastguard Worker }
309*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_open_monitor(struct fd_cmp * fd_cmp,int fd,int fd_ep)310*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_open_monitor(struct fd_cmp *fd_cmp, int fd, int fd_ep)
311*cc4ad7daSAndroid Build Coastguard Worker {
312*cc4ad7daSAndroid Build Coastguard Worker struct epoll_event ep = {};
313*cc4ad7daSAndroid Build Coastguard Worker
314*cc4ad7daSAndroid Build Coastguard Worker ep.events = EPOLLHUP;
315*cc4ad7daSAndroid Build Coastguard Worker ep.data.ptr = fd_cmp;
316*cc4ad7daSAndroid Build Coastguard Worker if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd, &ep) < 0) {
317*cc4ad7daSAndroid Build Coastguard Worker ERR("could not add monitor fd to epoll: %m\n");
318*cc4ad7daSAndroid Build Coastguard Worker return -errno;
319*cc4ad7daSAndroid Build Coastguard Worker }
320*cc4ad7daSAndroid Build Coastguard Worker
321*cc4ad7daSAndroid Build Coastguard Worker return 0;
322*cc4ad7daSAndroid Build Coastguard Worker }
323*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_open_std(struct fd_cmp * fd_cmp,const char * fn,int fd,int fd_ep)324*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_open_std(struct fd_cmp *fd_cmp,
325*cc4ad7daSAndroid Build Coastguard Worker const char *fn, int fd, int fd_ep)
326*cc4ad7daSAndroid Build Coastguard Worker {
327*cc4ad7daSAndroid Build Coastguard Worker struct epoll_event ep = {};
328*cc4ad7daSAndroid Build Coastguard Worker int fd_match;
329*cc4ad7daSAndroid Build Coastguard Worker
330*cc4ad7daSAndroid Build Coastguard Worker fd_match = open(fn, O_RDONLY);
331*cc4ad7daSAndroid Build Coastguard Worker if (fd_match < 0) {
332*cc4ad7daSAndroid Build Coastguard Worker ERR("could not open %s for read: %m\n", fn);
333*cc4ad7daSAndroid Build Coastguard Worker return -errno;
334*cc4ad7daSAndroid Build Coastguard Worker }
335*cc4ad7daSAndroid Build Coastguard Worker ep.events = EPOLLIN;
336*cc4ad7daSAndroid Build Coastguard Worker ep.data.ptr = fd_cmp;
337*cc4ad7daSAndroid Build Coastguard Worker if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd, &ep) < 0) {
338*cc4ad7daSAndroid Build Coastguard Worker ERR("could not add fd to epoll: %m\n");
339*cc4ad7daSAndroid Build Coastguard Worker close(fd_match);
340*cc4ad7daSAndroid Build Coastguard Worker return -errno;
341*cc4ad7daSAndroid Build Coastguard Worker }
342*cc4ad7daSAndroid Build Coastguard Worker
343*cc4ad7daSAndroid Build Coastguard Worker return fd_match;
344*cc4ad7daSAndroid Build Coastguard Worker }
345*cc4ad7daSAndroid Build Coastguard Worker
346*cc4ad7daSAndroid Build Coastguard Worker /* opens output file AND adds descriptor to epoll */
fd_cmp_open(struct fd_cmp ** fd_cmp_out,enum fd_cmp_type type,const char * fn,int fd,int fd_ep)347*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_open(struct fd_cmp **fd_cmp_out,
348*cc4ad7daSAndroid Build Coastguard Worker enum fd_cmp_type type, const char *fn, int fd,
349*cc4ad7daSAndroid Build Coastguard Worker int fd_ep)
350*cc4ad7daSAndroid Build Coastguard Worker {
351*cc4ad7daSAndroid Build Coastguard Worker int err = 0;
352*cc4ad7daSAndroid Build Coastguard Worker struct fd_cmp *fd_cmp;
353*cc4ad7daSAndroid Build Coastguard Worker
354*cc4ad7daSAndroid Build Coastguard Worker fd_cmp = calloc(1, sizeof(*fd_cmp));
355*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp == NULL) {
356*cc4ad7daSAndroid Build Coastguard Worker ERR("could not allocate fd_cmp\n");
357*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
358*cc4ad7daSAndroid Build Coastguard Worker }
359*cc4ad7daSAndroid Build Coastguard Worker
360*cc4ad7daSAndroid Build Coastguard Worker switch (type) {
361*cc4ad7daSAndroid Build Coastguard Worker case FD_CMP_MONITOR:
362*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_open_monitor(fd_cmp, fd, fd_ep);
363*cc4ad7daSAndroid Build Coastguard Worker break;
364*cc4ad7daSAndroid Build Coastguard Worker case FD_CMP_OUT:
365*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->name = "STDOUT";
366*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_open_std(fd_cmp, fn, fd, fd_ep);
367*cc4ad7daSAndroid Build Coastguard Worker break;
368*cc4ad7daSAndroid Build Coastguard Worker case FD_CMP_ERR:
369*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->name = "STDERR";
370*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_open_std(fd_cmp, fn, fd, fd_ep);
371*cc4ad7daSAndroid Build Coastguard Worker break;
372*cc4ad7daSAndroid Build Coastguard Worker default:
373*cc4ad7daSAndroid Build Coastguard Worker ERR("unknown fd type %d\n", type);
374*cc4ad7daSAndroid Build Coastguard Worker err = -1;
375*cc4ad7daSAndroid Build Coastguard Worker }
376*cc4ad7daSAndroid Build Coastguard Worker
377*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
378*cc4ad7daSAndroid Build Coastguard Worker free(fd_cmp);
379*cc4ad7daSAndroid Build Coastguard Worker return err;
380*cc4ad7daSAndroid Build Coastguard Worker }
381*cc4ad7daSAndroid Build Coastguard Worker
382*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->fd_match = err;
383*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->fd = fd;
384*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->type = type;
385*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->path = fn;
386*cc4ad7daSAndroid Build Coastguard Worker
387*cc4ad7daSAndroid Build Coastguard Worker *fd_cmp_out = fd_cmp;
388*cc4ad7daSAndroid Build Coastguard Worker return 0;
389*cc4ad7daSAndroid Build Coastguard Worker }
390*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_check_ev_in(struct fd_cmp * fd_cmp)391*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_check_ev_in(struct fd_cmp *fd_cmp)
392*cc4ad7daSAndroid Build Coastguard Worker {
393*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp->type == FD_CMP_MONITOR) {
394*cc4ad7daSAndroid Build Coastguard Worker ERR("Unexpected activity on monitor pipe\n");
395*cc4ad7daSAndroid Build Coastguard Worker return -EINVAL;
396*cc4ad7daSAndroid Build Coastguard Worker }
397*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->activity = true;
398*cc4ad7daSAndroid Build Coastguard Worker
399*cc4ad7daSAndroid Build Coastguard Worker return 0;
400*cc4ad7daSAndroid Build Coastguard Worker }
401*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_delete_ep(struct fd_cmp * fd_cmp,int fd_ep)402*cc4ad7daSAndroid Build Coastguard Worker static void fd_cmp_delete_ep(struct fd_cmp *fd_cmp, int fd_ep)
403*cc4ad7daSAndroid Build Coastguard Worker {
404*cc4ad7daSAndroid Build Coastguard Worker if (epoll_ctl(fd_ep, EPOLL_CTL_DEL, fd_cmp->fd, NULL) < 0) {
405*cc4ad7daSAndroid Build Coastguard Worker ERR("could not remove fd %d from epoll: %m\n", fd_cmp->fd);
406*cc4ad7daSAndroid Build Coastguard Worker }
407*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->fd = -1;
408*cc4ad7daSAndroid Build Coastguard Worker }
409*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_close(struct fd_cmp * fd_cmp)410*cc4ad7daSAndroid Build Coastguard Worker static void fd_cmp_close(struct fd_cmp *fd_cmp)
411*cc4ad7daSAndroid Build Coastguard Worker {
412*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp == NULL)
413*cc4ad7daSAndroid Build Coastguard Worker return;
414*cc4ad7daSAndroid Build Coastguard Worker
415*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp->fd >= 0)
416*cc4ad7daSAndroid Build Coastguard Worker close(fd_cmp->fd);
417*cc4ad7daSAndroid Build Coastguard Worker free(fd_cmp);
418*cc4ad7daSAndroid Build Coastguard Worker }
419*cc4ad7daSAndroid Build Coastguard Worker
fd_cmp_regex_one(const char * pattern,const char * s)420*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_regex_one(const char *pattern, const char *s)
421*cc4ad7daSAndroid Build Coastguard Worker {
422*cc4ad7daSAndroid Build Coastguard Worker _cleanup_(regfree) regex_t re = { };
423*cc4ad7daSAndroid Build Coastguard Worker
424*cc4ad7daSAndroid Build Coastguard Worker return !regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) &&
425*cc4ad7daSAndroid Build Coastguard Worker !regexec(&re, s, 0, NULL, 0);
426*cc4ad7daSAndroid Build Coastguard Worker }
427*cc4ad7daSAndroid Build Coastguard Worker
428*cc4ad7daSAndroid Build Coastguard Worker /*
429*cc4ad7daSAndroid Build Coastguard Worker * read fd and fd_match, checking the first matches the regex of the second,
430*cc4ad7daSAndroid Build Coastguard Worker * line by line
431*cc4ad7daSAndroid Build Coastguard Worker */
fd_cmp_regex(struct fd_cmp * fd_cmp,const struct test * t)432*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_regex(struct fd_cmp *fd_cmp, const struct test *t)
433*cc4ad7daSAndroid Build Coastguard Worker {
434*cc4ad7daSAndroid Build Coastguard Worker char *p, *p_match;
435*cc4ad7daSAndroid Build Coastguard Worker int done = 0, done_match = 0, r;
436*cc4ad7daSAndroid Build Coastguard Worker
437*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp->head >= sizeof(fd_cmp->buf)) {
438*cc4ad7daSAndroid Build Coastguard Worker ERR("Read %zu bytes without a newline\n", sizeof(fd_cmp->buf));
439*cc4ad7daSAndroid Build Coastguard Worker ERR("output: %.*s", (int)sizeof(fd_cmp->buf), fd_cmp->buf);
440*cc4ad7daSAndroid Build Coastguard Worker return false;
441*cc4ad7daSAndroid Build Coastguard Worker }
442*cc4ad7daSAndroid Build Coastguard Worker
443*cc4ad7daSAndroid Build Coastguard Worker r = read(fd_cmp->fd, fd_cmp->buf + fd_cmp->head,
444*cc4ad7daSAndroid Build Coastguard Worker sizeof(fd_cmp->buf) - fd_cmp->head);
445*cc4ad7daSAndroid Build Coastguard Worker if (r <= 0)
446*cc4ad7daSAndroid Build Coastguard Worker return true;
447*cc4ad7daSAndroid Build Coastguard Worker
448*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->head += r;
449*cc4ad7daSAndroid Build Coastguard Worker
450*cc4ad7daSAndroid Build Coastguard Worker /*
451*cc4ad7daSAndroid Build Coastguard Worker * Process as many lines as read from fd and that fits in the buffer -
452*cc4ad7daSAndroid Build Coastguard Worker * it's assumed that if we get N lines from fd, we should be able to
453*cc4ad7daSAndroid Build Coastguard Worker * get the same amount from fd_match
454*cc4ad7daSAndroid Build Coastguard Worker */
455*cc4ad7daSAndroid Build Coastguard Worker for (;;) {
456*cc4ad7daSAndroid Build Coastguard Worker p = memchr(fd_cmp->buf + done, '\n', fd_cmp->head - done);
457*cc4ad7daSAndroid Build Coastguard Worker if (!p)
458*cc4ad7daSAndroid Build Coastguard Worker break;
459*cc4ad7daSAndroid Build Coastguard Worker *p = '\0';
460*cc4ad7daSAndroid Build Coastguard Worker
461*cc4ad7daSAndroid Build Coastguard Worker p_match = memchr(fd_cmp->buf_match + done_match, '\n',
462*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->head_match - done_match);
463*cc4ad7daSAndroid Build Coastguard Worker if (!p_match) {
464*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp->head_match >= sizeof(fd_cmp->buf_match)) {
465*cc4ad7daSAndroid Build Coastguard Worker ERR("Read %zu bytes without a match\n", sizeof(fd_cmp->buf_match));
466*cc4ad7daSAndroid Build Coastguard Worker ERR("output: %.*s", (int)sizeof(fd_cmp->buf_match), fd_cmp->buf_match);
467*cc4ad7daSAndroid Build Coastguard Worker return false;
468*cc4ad7daSAndroid Build Coastguard Worker }
469*cc4ad7daSAndroid Build Coastguard Worker
470*cc4ad7daSAndroid Build Coastguard Worker /* pump more data from file */
471*cc4ad7daSAndroid Build Coastguard Worker r = read(fd_cmp->fd_match, fd_cmp->buf_match + fd_cmp->head_match,
472*cc4ad7daSAndroid Build Coastguard Worker sizeof(fd_cmp->buf_match) - fd_cmp->head_match);
473*cc4ad7daSAndroid Build Coastguard Worker if (r <= 0) {
474*cc4ad7daSAndroid Build Coastguard Worker ERR("could not read match fd %d\n", fd_cmp->fd_match);
475*cc4ad7daSAndroid Build Coastguard Worker return false;
476*cc4ad7daSAndroid Build Coastguard Worker }
477*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->head_match += r;
478*cc4ad7daSAndroid Build Coastguard Worker p_match = memchr(fd_cmp->buf_match + done_match, '\n',
479*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->head_match - done_match);
480*cc4ad7daSAndroid Build Coastguard Worker if (!p_match) {
481*cc4ad7daSAndroid Build Coastguard Worker ERR("could not find match line from fd %d\n", fd_cmp->fd_match);
482*cc4ad7daSAndroid Build Coastguard Worker return false;
483*cc4ad7daSAndroid Build Coastguard Worker }
484*cc4ad7daSAndroid Build Coastguard Worker }
485*cc4ad7daSAndroid Build Coastguard Worker *p_match = '\0';
486*cc4ad7daSAndroid Build Coastguard Worker
487*cc4ad7daSAndroid Build Coastguard Worker if (!fd_cmp_regex_one(fd_cmp->buf_match + done_match, fd_cmp->buf + done)) {
488*cc4ad7daSAndroid Build Coastguard Worker ERR("Output does not match pattern on %s:\n", fd_cmp->name);
489*cc4ad7daSAndroid Build Coastguard Worker ERR("pattern: %s\n", fd_cmp->buf_match + done_match);
490*cc4ad7daSAndroid Build Coastguard Worker ERR("output : %s\n", fd_cmp->buf + done);
491*cc4ad7daSAndroid Build Coastguard Worker return false;
492*cc4ad7daSAndroid Build Coastguard Worker }
493*cc4ad7daSAndroid Build Coastguard Worker
494*cc4ad7daSAndroid Build Coastguard Worker done = p - fd_cmp->buf + 1;
495*cc4ad7daSAndroid Build Coastguard Worker done_match = p_match - fd_cmp->buf_match + 1;
496*cc4ad7daSAndroid Build Coastguard Worker }
497*cc4ad7daSAndroid Build Coastguard Worker
498*cc4ad7daSAndroid Build Coastguard Worker /*
499*cc4ad7daSAndroid Build Coastguard Worker * Prepare for the next call: anything we processed we remove from the
500*cc4ad7daSAndroid Build Coastguard Worker * buffer by memmoving the remaining bytes up to the beginning
501*cc4ad7daSAndroid Build Coastguard Worker */
502*cc4ad7daSAndroid Build Coastguard Worker if (done) {
503*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp->head - done)
504*cc4ad7daSAndroid Build Coastguard Worker memmove(fd_cmp->buf, fd_cmp->buf + done, fd_cmp->head - done);
505*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->head -= done;
506*cc4ad7daSAndroid Build Coastguard Worker }
507*cc4ad7daSAndroid Build Coastguard Worker
508*cc4ad7daSAndroid Build Coastguard Worker if (done_match) {
509*cc4ad7daSAndroid Build Coastguard Worker if (fd_cmp->head_match - done_match)
510*cc4ad7daSAndroid Build Coastguard Worker memmove(fd_cmp->buf_match, fd_cmp->buf_match + done_match,
511*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->head_match - done_match);
512*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->head_match -= done_match;
513*cc4ad7daSAndroid Build Coastguard Worker }
514*cc4ad7daSAndroid Build Coastguard Worker
515*cc4ad7daSAndroid Build Coastguard Worker return true;
516*cc4ad7daSAndroid Build Coastguard Worker }
517*cc4ad7daSAndroid Build Coastguard Worker
518*cc4ad7daSAndroid Build Coastguard Worker /* read fd and fd_match, checking they match exactly */
fd_cmp_exact(struct fd_cmp * fd_cmp,const struct test * t)519*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_exact(struct fd_cmp *fd_cmp, const struct test *t)
520*cc4ad7daSAndroid Build Coastguard Worker {
521*cc4ad7daSAndroid Build Coastguard Worker int r, rmatch, done = 0;
522*cc4ad7daSAndroid Build Coastguard Worker
523*cc4ad7daSAndroid Build Coastguard Worker r = read(fd_cmp->fd, fd_cmp->buf, sizeof(fd_cmp->buf) - 1);
524*cc4ad7daSAndroid Build Coastguard Worker if (r <= 0)
525*cc4ad7daSAndroid Build Coastguard Worker /* try again later */
526*cc4ad7daSAndroid Build Coastguard Worker return true;
527*cc4ad7daSAndroid Build Coastguard Worker
528*cc4ad7daSAndroid Build Coastguard Worker /* read as much data from fd_match as we read from fd */
529*cc4ad7daSAndroid Build Coastguard Worker for (;;) {
530*cc4ad7daSAndroid Build Coastguard Worker rmatch = read(fd_cmp->fd_match, fd_cmp->buf_match + done, r - done);
531*cc4ad7daSAndroid Build Coastguard Worker if (rmatch == 0)
532*cc4ad7daSAndroid Build Coastguard Worker break;
533*cc4ad7daSAndroid Build Coastguard Worker
534*cc4ad7daSAndroid Build Coastguard Worker if (rmatch < 0) {
535*cc4ad7daSAndroid Build Coastguard Worker if (errno == EINTR)
536*cc4ad7daSAndroid Build Coastguard Worker continue;
537*cc4ad7daSAndroid Build Coastguard Worker ERR("could not read match fd %d\n", fd_cmp->fd_match);
538*cc4ad7daSAndroid Build Coastguard Worker return false;
539*cc4ad7daSAndroid Build Coastguard Worker }
540*cc4ad7daSAndroid Build Coastguard Worker
541*cc4ad7daSAndroid Build Coastguard Worker done += rmatch;
542*cc4ad7daSAndroid Build Coastguard Worker }
543*cc4ad7daSAndroid Build Coastguard Worker
544*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->buf[r] = '\0';
545*cc4ad7daSAndroid Build Coastguard Worker fd_cmp->buf_match[r] = '\0';
546*cc4ad7daSAndroid Build Coastguard Worker
547*cc4ad7daSAndroid Build Coastguard Worker if (t->print_outputs)
548*cc4ad7daSAndroid Build Coastguard Worker printf("%s: %s\n", fd_cmp->name, fd_cmp->buf);
549*cc4ad7daSAndroid Build Coastguard Worker
550*cc4ad7daSAndroid Build Coastguard Worker if (!streq(fd_cmp->buf, fd_cmp->buf_match)) {
551*cc4ad7daSAndroid Build Coastguard Worker ERR("Outputs do not match on %s:\n", fd_cmp->name);
552*cc4ad7daSAndroid Build Coastguard Worker ERR("correct:\n%s\n", fd_cmp->buf_match);
553*cc4ad7daSAndroid Build Coastguard Worker ERR("wrong:\n%s\n", fd_cmp->buf);
554*cc4ad7daSAndroid Build Coastguard Worker return false;
555*cc4ad7daSAndroid Build Coastguard Worker }
556*cc4ad7daSAndroid Build Coastguard Worker
557*cc4ad7daSAndroid Build Coastguard Worker return true;
558*cc4ad7daSAndroid Build Coastguard Worker }
559*cc4ad7daSAndroid Build Coastguard Worker
test_run_parent_check_outputs(const struct test * t,int fdout,int fderr,int fdmonitor,pid_t child)560*cc4ad7daSAndroid Build Coastguard Worker static bool test_run_parent_check_outputs(const struct test *t,
561*cc4ad7daSAndroid Build Coastguard Worker int fdout, int fderr, int fdmonitor,
562*cc4ad7daSAndroid Build Coastguard Worker pid_t child)
563*cc4ad7daSAndroid Build Coastguard Worker {
564*cc4ad7daSAndroid Build Coastguard Worker int err, fd_ep;
565*cc4ad7daSAndroid Build Coastguard Worker unsigned long long end_usec, start_usec;
566*cc4ad7daSAndroid Build Coastguard Worker struct fd_cmp *fd_cmp_out = NULL;
567*cc4ad7daSAndroid Build Coastguard Worker struct fd_cmp *fd_cmp_err = NULL;
568*cc4ad7daSAndroid Build Coastguard Worker struct fd_cmp *fd_cmp_monitor = NULL;
569*cc4ad7daSAndroid Build Coastguard Worker int n_fd = 0;
570*cc4ad7daSAndroid Build Coastguard Worker
571*cc4ad7daSAndroid Build Coastguard Worker fd_ep = epoll_create1(EPOLL_CLOEXEC);
572*cc4ad7daSAndroid Build Coastguard Worker if (fd_ep < 0) {
573*cc4ad7daSAndroid Build Coastguard Worker ERR("could not create epoll fd: %m\n");
574*cc4ad7daSAndroid Build Coastguard Worker return false;
575*cc4ad7daSAndroid Build Coastguard Worker }
576*cc4ad7daSAndroid Build Coastguard Worker
577*cc4ad7daSAndroid Build Coastguard Worker if (t->output.out != NULL) {
578*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_open(&fd_cmp_out,
579*cc4ad7daSAndroid Build Coastguard Worker FD_CMP_OUT, t->output.out, fdout, fd_ep);
580*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
581*cc4ad7daSAndroid Build Coastguard Worker goto out;
582*cc4ad7daSAndroid Build Coastguard Worker n_fd++;
583*cc4ad7daSAndroid Build Coastguard Worker }
584*cc4ad7daSAndroid Build Coastguard Worker
585*cc4ad7daSAndroid Build Coastguard Worker if (t->output.err != NULL) {
586*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_open(&fd_cmp_err,
587*cc4ad7daSAndroid Build Coastguard Worker FD_CMP_ERR, t->output.err, fderr, fd_ep);
588*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
589*cc4ad7daSAndroid Build Coastguard Worker goto out;
590*cc4ad7daSAndroid Build Coastguard Worker n_fd++;
591*cc4ad7daSAndroid Build Coastguard Worker }
592*cc4ad7daSAndroid Build Coastguard Worker
593*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_open(&fd_cmp_monitor, FD_CMP_MONITOR, NULL, fdmonitor, fd_ep);
594*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
595*cc4ad7daSAndroid Build Coastguard Worker goto out;
596*cc4ad7daSAndroid Build Coastguard Worker n_fd++;
597*cc4ad7daSAndroid Build Coastguard Worker
598*cc4ad7daSAndroid Build Coastguard Worker start_usec = now_usec();
599*cc4ad7daSAndroid Build Coastguard Worker end_usec = start_usec + TEST_TIMEOUT_USEC;
600*cc4ad7daSAndroid Build Coastguard Worker
601*cc4ad7daSAndroid Build Coastguard Worker for (err = 0; n_fd > 0;) {
602*cc4ad7daSAndroid Build Coastguard Worker int fdcount, i, timeout;
603*cc4ad7daSAndroid Build Coastguard Worker struct epoll_event ev[4];
604*cc4ad7daSAndroid Build Coastguard Worker unsigned long long curr_usec = now_usec();
605*cc4ad7daSAndroid Build Coastguard Worker
606*cc4ad7daSAndroid Build Coastguard Worker if (curr_usec > end_usec)
607*cc4ad7daSAndroid Build Coastguard Worker break;
608*cc4ad7daSAndroid Build Coastguard Worker
609*cc4ad7daSAndroid Build Coastguard Worker timeout = (end_usec - curr_usec) / USEC_PER_MSEC;
610*cc4ad7daSAndroid Build Coastguard Worker fdcount = epoll_wait(fd_ep, ev, 4, timeout);
611*cc4ad7daSAndroid Build Coastguard Worker if (fdcount < 0) {
612*cc4ad7daSAndroid Build Coastguard Worker if (errno == EINTR)
613*cc4ad7daSAndroid Build Coastguard Worker continue;
614*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
615*cc4ad7daSAndroid Build Coastguard Worker ERR("could not poll: %m\n");
616*cc4ad7daSAndroid Build Coastguard Worker goto out;
617*cc4ad7daSAndroid Build Coastguard Worker }
618*cc4ad7daSAndroid Build Coastguard Worker
619*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < fdcount; i++) {
620*cc4ad7daSAndroid Build Coastguard Worker struct fd_cmp *fd_cmp = ev[i].data.ptr;
621*cc4ad7daSAndroid Build Coastguard Worker bool ret;
622*cc4ad7daSAndroid Build Coastguard Worker
623*cc4ad7daSAndroid Build Coastguard Worker if (ev[i].events & EPOLLIN) {
624*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_check_ev_in(fd_cmp);
625*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
626*cc4ad7daSAndroid Build Coastguard Worker goto out;
627*cc4ad7daSAndroid Build Coastguard Worker
628*cc4ad7daSAndroid Build Coastguard Worker if (t->output.regex)
629*cc4ad7daSAndroid Build Coastguard Worker ret = fd_cmp_regex(fd_cmp, t);
630*cc4ad7daSAndroid Build Coastguard Worker else
631*cc4ad7daSAndroid Build Coastguard Worker ret = fd_cmp_exact(fd_cmp, t);
632*cc4ad7daSAndroid Build Coastguard Worker
633*cc4ad7daSAndroid Build Coastguard Worker if (!ret) {
634*cc4ad7daSAndroid Build Coastguard Worker err = -1;
635*cc4ad7daSAndroid Build Coastguard Worker goto out;
636*cc4ad7daSAndroid Build Coastguard Worker }
637*cc4ad7daSAndroid Build Coastguard Worker } else if (ev[i].events & EPOLLHUP) {
638*cc4ad7daSAndroid Build Coastguard Worker fd_cmp_delete_ep(fd_cmp, fd_ep);
639*cc4ad7daSAndroid Build Coastguard Worker n_fd--;
640*cc4ad7daSAndroid Build Coastguard Worker }
641*cc4ad7daSAndroid Build Coastguard Worker }
642*cc4ad7daSAndroid Build Coastguard Worker }
643*cc4ad7daSAndroid Build Coastguard Worker
644*cc4ad7daSAndroid Build Coastguard Worker err = fd_cmp_check_activity(fd_cmp_out);
645*cc4ad7daSAndroid Build Coastguard Worker err |= fd_cmp_check_activity(fd_cmp_err);
646*cc4ad7daSAndroid Build Coastguard Worker
647*cc4ad7daSAndroid Build Coastguard Worker if (err == 0 && fd_cmp_is_active(fd_cmp_monitor)) {
648*cc4ad7daSAndroid Build Coastguard Worker err = -EINVAL;
649*cc4ad7daSAndroid Build Coastguard Worker ERR("Test '%s' timed out, killing %d\n", t->name, child);
650*cc4ad7daSAndroid Build Coastguard Worker kill(child, SIGKILL);
651*cc4ad7daSAndroid Build Coastguard Worker }
652*cc4ad7daSAndroid Build Coastguard Worker
653*cc4ad7daSAndroid Build Coastguard Worker out:
654*cc4ad7daSAndroid Build Coastguard Worker fd_cmp_close(fd_cmp_out);
655*cc4ad7daSAndroid Build Coastguard Worker fd_cmp_close(fd_cmp_err);
656*cc4ad7daSAndroid Build Coastguard Worker fd_cmp_close(fd_cmp_monitor);
657*cc4ad7daSAndroid Build Coastguard Worker close(fd_ep);
658*cc4ad7daSAndroid Build Coastguard Worker
659*cc4ad7daSAndroid Build Coastguard Worker return err == 0;
660*cc4ad7daSAndroid Build Coastguard Worker }
661*cc4ad7daSAndroid Build Coastguard Worker
safe_read(int fd,void * buf,size_t count)662*cc4ad7daSAndroid Build Coastguard Worker static inline int safe_read(int fd, void *buf, size_t count)
663*cc4ad7daSAndroid Build Coastguard Worker {
664*cc4ad7daSAndroid Build Coastguard Worker int r;
665*cc4ad7daSAndroid Build Coastguard Worker
666*cc4ad7daSAndroid Build Coastguard Worker while (1) {
667*cc4ad7daSAndroid Build Coastguard Worker r = read(fd, buf, count);
668*cc4ad7daSAndroid Build Coastguard Worker if (r == -1 && errno == EINTR)
669*cc4ad7daSAndroid Build Coastguard Worker continue;
670*cc4ad7daSAndroid Build Coastguard Worker break;
671*cc4ad7daSAndroid Build Coastguard Worker }
672*cc4ad7daSAndroid Build Coastguard Worker
673*cc4ad7daSAndroid Build Coastguard Worker return r;
674*cc4ad7daSAndroid Build Coastguard Worker }
675*cc4ad7daSAndroid Build Coastguard Worker
check_generated_files(const struct test * t)676*cc4ad7daSAndroid Build Coastguard Worker static bool check_generated_files(const struct test *t)
677*cc4ad7daSAndroid Build Coastguard Worker {
678*cc4ad7daSAndroid Build Coastguard Worker const struct keyval *k;
679*cc4ad7daSAndroid Build Coastguard Worker
680*cc4ad7daSAndroid Build Coastguard Worker /* This is not meant to be a diff replacement, just stupidly check if
681*cc4ad7daSAndroid Build Coastguard Worker * the files match. Bear in mind they can be binary files */
682*cc4ad7daSAndroid Build Coastguard Worker for (k = t->output.files; k && k->key; k++) {
683*cc4ad7daSAndroid Build Coastguard Worker struct stat sta, stb;
684*cc4ad7daSAndroid Build Coastguard Worker int fda = -1, fdb = -1;
685*cc4ad7daSAndroid Build Coastguard Worker char bufa[4096];
686*cc4ad7daSAndroid Build Coastguard Worker char bufb[4096];
687*cc4ad7daSAndroid Build Coastguard Worker
688*cc4ad7daSAndroid Build Coastguard Worker fda = open(k->key, O_RDONLY);
689*cc4ad7daSAndroid Build Coastguard Worker if (fda < 0) {
690*cc4ad7daSAndroid Build Coastguard Worker ERR("could not open %s\n - %m\n", k->key);
691*cc4ad7daSAndroid Build Coastguard Worker goto fail;
692*cc4ad7daSAndroid Build Coastguard Worker }
693*cc4ad7daSAndroid Build Coastguard Worker
694*cc4ad7daSAndroid Build Coastguard Worker fdb = open(k->val, O_RDONLY);
695*cc4ad7daSAndroid Build Coastguard Worker if (fdb < 0) {
696*cc4ad7daSAndroid Build Coastguard Worker ERR("could not open %s\n - %m\n", k->val);
697*cc4ad7daSAndroid Build Coastguard Worker goto fail;
698*cc4ad7daSAndroid Build Coastguard Worker }
699*cc4ad7daSAndroid Build Coastguard Worker
700*cc4ad7daSAndroid Build Coastguard Worker if (fstat(fda, &sta) != 0) {
701*cc4ad7daSAndroid Build Coastguard Worker ERR("could not fstat %d %s\n - %m\n", fda, k->key);
702*cc4ad7daSAndroid Build Coastguard Worker goto fail;
703*cc4ad7daSAndroid Build Coastguard Worker }
704*cc4ad7daSAndroid Build Coastguard Worker
705*cc4ad7daSAndroid Build Coastguard Worker if (fstat(fdb, &stb) != 0) {
706*cc4ad7daSAndroid Build Coastguard Worker ERR("could not fstat %d %s\n - %m\n", fdb, k->key);
707*cc4ad7daSAndroid Build Coastguard Worker goto fail;
708*cc4ad7daSAndroid Build Coastguard Worker }
709*cc4ad7daSAndroid Build Coastguard Worker
710*cc4ad7daSAndroid Build Coastguard Worker if (sta.st_size != stb.st_size) {
711*cc4ad7daSAndroid Build Coastguard Worker ERR("sizes do not match %s %s\n", k->key, k->val);
712*cc4ad7daSAndroid Build Coastguard Worker goto fail;
713*cc4ad7daSAndroid Build Coastguard Worker }
714*cc4ad7daSAndroid Build Coastguard Worker
715*cc4ad7daSAndroid Build Coastguard Worker for (;;) {
716*cc4ad7daSAndroid Build Coastguard Worker int r, done;
717*cc4ad7daSAndroid Build Coastguard Worker
718*cc4ad7daSAndroid Build Coastguard Worker r = safe_read(fda, bufa, sizeof(bufa));
719*cc4ad7daSAndroid Build Coastguard Worker if (r < 0)
720*cc4ad7daSAndroid Build Coastguard Worker goto fail;
721*cc4ad7daSAndroid Build Coastguard Worker
722*cc4ad7daSAndroid Build Coastguard Worker if (r == 0)
723*cc4ad7daSAndroid Build Coastguard Worker /* size is already checked, go to next file */
724*cc4ad7daSAndroid Build Coastguard Worker goto next;
725*cc4ad7daSAndroid Build Coastguard Worker
726*cc4ad7daSAndroid Build Coastguard Worker for (done = 0; done < r;) {
727*cc4ad7daSAndroid Build Coastguard Worker int r2 = safe_read(fdb, bufb + done, r - done);
728*cc4ad7daSAndroid Build Coastguard Worker
729*cc4ad7daSAndroid Build Coastguard Worker if (r2 <= 0)
730*cc4ad7daSAndroid Build Coastguard Worker goto fail;
731*cc4ad7daSAndroid Build Coastguard Worker
732*cc4ad7daSAndroid Build Coastguard Worker done += r2;
733*cc4ad7daSAndroid Build Coastguard Worker }
734*cc4ad7daSAndroid Build Coastguard Worker
735*cc4ad7daSAndroid Build Coastguard Worker if (memcmp(bufa, bufb, r) != 0)
736*cc4ad7daSAndroid Build Coastguard Worker goto fail;
737*cc4ad7daSAndroid Build Coastguard Worker }
738*cc4ad7daSAndroid Build Coastguard Worker
739*cc4ad7daSAndroid Build Coastguard Worker next:
740*cc4ad7daSAndroid Build Coastguard Worker close(fda);
741*cc4ad7daSAndroid Build Coastguard Worker close(fdb);
742*cc4ad7daSAndroid Build Coastguard Worker continue;
743*cc4ad7daSAndroid Build Coastguard Worker
744*cc4ad7daSAndroid Build Coastguard Worker fail:
745*cc4ad7daSAndroid Build Coastguard Worker if (fda >= 0)
746*cc4ad7daSAndroid Build Coastguard Worker close(fda);
747*cc4ad7daSAndroid Build Coastguard Worker if (fdb >= 0)
748*cc4ad7daSAndroid Build Coastguard Worker close(fdb);
749*cc4ad7daSAndroid Build Coastguard Worker
750*cc4ad7daSAndroid Build Coastguard Worker return false;
751*cc4ad7daSAndroid Build Coastguard Worker }
752*cc4ad7daSAndroid Build Coastguard Worker
753*cc4ad7daSAndroid Build Coastguard Worker return true;
754*cc4ad7daSAndroid Build Coastguard Worker }
755*cc4ad7daSAndroid Build Coastguard Worker
cmp_modnames(const void * m1,const void * m2)756*cc4ad7daSAndroid Build Coastguard Worker static int cmp_modnames(const void *m1, const void *m2)
757*cc4ad7daSAndroid Build Coastguard Worker {
758*cc4ad7daSAndroid Build Coastguard Worker const char *s1 = *(char *const *)m1;
759*cc4ad7daSAndroid Build Coastguard Worker const char *s2 = *(char *const *)m2;
760*cc4ad7daSAndroid Build Coastguard Worker int i;
761*cc4ad7daSAndroid Build Coastguard Worker
762*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; s1[i] || s2[i]; i++) {
763*cc4ad7daSAndroid Build Coastguard Worker char c1 = s1[i], c2 = s2[i];
764*cc4ad7daSAndroid Build Coastguard Worker if (c1 == '-')
765*cc4ad7daSAndroid Build Coastguard Worker c1 = '_';
766*cc4ad7daSAndroid Build Coastguard Worker if (c2 == '-')
767*cc4ad7daSAndroid Build Coastguard Worker c2 = '_';
768*cc4ad7daSAndroid Build Coastguard Worker if (c1 != c2)
769*cc4ad7daSAndroid Build Coastguard Worker return c1 - c2;
770*cc4ad7daSAndroid Build Coastguard Worker }
771*cc4ad7daSAndroid Build Coastguard Worker return 0;
772*cc4ad7daSAndroid Build Coastguard Worker }
773*cc4ad7daSAndroid Build Coastguard Worker
774*cc4ad7daSAndroid Build Coastguard Worker /*
775*cc4ad7daSAndroid Build Coastguard Worker * Store the expected module names in buf and return a list of pointers to
776*cc4ad7daSAndroid Build Coastguard Worker * them.
777*cc4ad7daSAndroid Build Coastguard Worker */
read_expected_modules(const struct test * t,char ** buf,int * count)778*cc4ad7daSAndroid Build Coastguard Worker static const char **read_expected_modules(const struct test *t,
779*cc4ad7daSAndroid Build Coastguard Worker char **buf, int *count)
780*cc4ad7daSAndroid Build Coastguard Worker {
781*cc4ad7daSAndroid Build Coastguard Worker const char **res;
782*cc4ad7daSAndroid Build Coastguard Worker int len;
783*cc4ad7daSAndroid Build Coastguard Worker int i;
784*cc4ad7daSAndroid Build Coastguard Worker char *p;
785*cc4ad7daSAndroid Build Coastguard Worker
786*cc4ad7daSAndroid Build Coastguard Worker if (t->modules_loaded[0] == '\0') {
787*cc4ad7daSAndroid Build Coastguard Worker *count = 0;
788*cc4ad7daSAndroid Build Coastguard Worker *buf = NULL;
789*cc4ad7daSAndroid Build Coastguard Worker return NULL;
790*cc4ad7daSAndroid Build Coastguard Worker }
791*cc4ad7daSAndroid Build Coastguard Worker *buf = strdup(t->modules_loaded);
792*cc4ad7daSAndroid Build Coastguard Worker if (!*buf) {
793*cc4ad7daSAndroid Build Coastguard Worker *count = -1;
794*cc4ad7daSAndroid Build Coastguard Worker return NULL;
795*cc4ad7daSAndroid Build Coastguard Worker }
796*cc4ad7daSAndroid Build Coastguard Worker len = 1;
797*cc4ad7daSAndroid Build Coastguard Worker for (p = *buf; *p; p++)
798*cc4ad7daSAndroid Build Coastguard Worker if (*p == ',')
799*cc4ad7daSAndroid Build Coastguard Worker len++;
800*cc4ad7daSAndroid Build Coastguard Worker res = malloc(sizeof(char *) * len);
801*cc4ad7daSAndroid Build Coastguard Worker if (!res) {
802*cc4ad7daSAndroid Build Coastguard Worker perror("malloc");
803*cc4ad7daSAndroid Build Coastguard Worker *count = -1;
804*cc4ad7daSAndroid Build Coastguard Worker free(*buf);
805*cc4ad7daSAndroid Build Coastguard Worker *buf = NULL;
806*cc4ad7daSAndroid Build Coastguard Worker return NULL;
807*cc4ad7daSAndroid Build Coastguard Worker }
808*cc4ad7daSAndroid Build Coastguard Worker i = 0;
809*cc4ad7daSAndroid Build Coastguard Worker res[i++] = *buf;
810*cc4ad7daSAndroid Build Coastguard Worker for (p = *buf; i < len; p++)
811*cc4ad7daSAndroid Build Coastguard Worker if (*p == ',') {
812*cc4ad7daSAndroid Build Coastguard Worker *p = '\0';
813*cc4ad7daSAndroid Build Coastguard Worker res[i++] = p + 1;
814*cc4ad7daSAndroid Build Coastguard Worker }
815*cc4ad7daSAndroid Build Coastguard Worker *count = len;
816*cc4ad7daSAndroid Build Coastguard Worker return res;
817*cc4ad7daSAndroid Build Coastguard Worker }
818*cc4ad7daSAndroid Build Coastguard Worker
read_loaded_modules(const struct test * t,char ** buf,int * count)819*cc4ad7daSAndroid Build Coastguard Worker static char **read_loaded_modules(const struct test *t, char **buf, int *count)
820*cc4ad7daSAndroid Build Coastguard Worker {
821*cc4ad7daSAndroid Build Coastguard Worker char dirname[PATH_MAX];
822*cc4ad7daSAndroid Build Coastguard Worker DIR *dir;
823*cc4ad7daSAndroid Build Coastguard Worker struct dirent *dirent;
824*cc4ad7daSAndroid Build Coastguard Worker int i;
825*cc4ad7daSAndroid Build Coastguard Worker int len = 0, bufsz;
826*cc4ad7daSAndroid Build Coastguard Worker char **res = NULL;
827*cc4ad7daSAndroid Build Coastguard Worker char *p;
828*cc4ad7daSAndroid Build Coastguard Worker const char *rootfs = t->config[TC_ROOTFS] ? t->config[TC_ROOTFS] : "";
829*cc4ad7daSAndroid Build Coastguard Worker
830*cc4ad7daSAndroid Build Coastguard Worker /* Store the entries in /sys/module to res */
831*cc4ad7daSAndroid Build Coastguard Worker if (snprintf(dirname, sizeof(dirname), "%s/sys/module", rootfs)
832*cc4ad7daSAndroid Build Coastguard Worker >= (int)sizeof(dirname)) {
833*cc4ad7daSAndroid Build Coastguard Worker ERR("rootfs path too long: %s\n", rootfs);
834*cc4ad7daSAndroid Build Coastguard Worker *buf = NULL;
835*cc4ad7daSAndroid Build Coastguard Worker len = -1;
836*cc4ad7daSAndroid Build Coastguard Worker goto out;
837*cc4ad7daSAndroid Build Coastguard Worker }
838*cc4ad7daSAndroid Build Coastguard Worker dir = opendir(dirname);
839*cc4ad7daSAndroid Build Coastguard Worker /* not an error, simply return empty list */
840*cc4ad7daSAndroid Build Coastguard Worker if (!dir) {
841*cc4ad7daSAndroid Build Coastguard Worker *buf = NULL;
842*cc4ad7daSAndroid Build Coastguard Worker goto out;
843*cc4ad7daSAndroid Build Coastguard Worker }
844*cc4ad7daSAndroid Build Coastguard Worker bufsz = 0;
845*cc4ad7daSAndroid Build Coastguard Worker while ((dirent = readdir(dir))) {
846*cc4ad7daSAndroid Build Coastguard Worker if (dirent->d_name[0] == '.')
847*cc4ad7daSAndroid Build Coastguard Worker continue;
848*cc4ad7daSAndroid Build Coastguard Worker len++;
849*cc4ad7daSAndroid Build Coastguard Worker bufsz += strlen(dirent->d_name) + 1;
850*cc4ad7daSAndroid Build Coastguard Worker }
851*cc4ad7daSAndroid Build Coastguard Worker res = malloc(sizeof(char *) * len);
852*cc4ad7daSAndroid Build Coastguard Worker if (!res) {
853*cc4ad7daSAndroid Build Coastguard Worker perror("malloc");
854*cc4ad7daSAndroid Build Coastguard Worker len = -1;
855*cc4ad7daSAndroid Build Coastguard Worker goto out_dir;
856*cc4ad7daSAndroid Build Coastguard Worker }
857*cc4ad7daSAndroid Build Coastguard Worker *buf = malloc(bufsz);
858*cc4ad7daSAndroid Build Coastguard Worker if (!*buf) {
859*cc4ad7daSAndroid Build Coastguard Worker perror("malloc");
860*cc4ad7daSAndroid Build Coastguard Worker free(res);
861*cc4ad7daSAndroid Build Coastguard Worker res = NULL;
862*cc4ad7daSAndroid Build Coastguard Worker len = -1;
863*cc4ad7daSAndroid Build Coastguard Worker goto out_dir;
864*cc4ad7daSAndroid Build Coastguard Worker }
865*cc4ad7daSAndroid Build Coastguard Worker rewinddir(dir);
866*cc4ad7daSAndroid Build Coastguard Worker i = 0;
867*cc4ad7daSAndroid Build Coastguard Worker p = *buf;
868*cc4ad7daSAndroid Build Coastguard Worker while ((dirent = readdir(dir))) {
869*cc4ad7daSAndroid Build Coastguard Worker int size;
870*cc4ad7daSAndroid Build Coastguard Worker
871*cc4ad7daSAndroid Build Coastguard Worker if (dirent->d_name[0] == '.')
872*cc4ad7daSAndroid Build Coastguard Worker continue;
873*cc4ad7daSAndroid Build Coastguard Worker size = strlen(dirent->d_name) + 1;
874*cc4ad7daSAndroid Build Coastguard Worker memcpy(p, dirent->d_name, size);
875*cc4ad7daSAndroid Build Coastguard Worker res[i++] = p;
876*cc4ad7daSAndroid Build Coastguard Worker p += size;
877*cc4ad7daSAndroid Build Coastguard Worker }
878*cc4ad7daSAndroid Build Coastguard Worker out_dir:
879*cc4ad7daSAndroid Build Coastguard Worker closedir(dir);
880*cc4ad7daSAndroid Build Coastguard Worker out:
881*cc4ad7daSAndroid Build Coastguard Worker *count = len;
882*cc4ad7daSAndroid Build Coastguard Worker return res;
883*cc4ad7daSAndroid Build Coastguard Worker }
884*cc4ad7daSAndroid Build Coastguard Worker
check_loaded_modules(const struct test * t)885*cc4ad7daSAndroid Build Coastguard Worker static int check_loaded_modules(const struct test *t)
886*cc4ad7daSAndroid Build Coastguard Worker {
887*cc4ad7daSAndroid Build Coastguard Worker int l1, l2, i1, i2;
888*cc4ad7daSAndroid Build Coastguard Worker const char **a1;
889*cc4ad7daSAndroid Build Coastguard Worker char **a2;
890*cc4ad7daSAndroid Build Coastguard Worker char *buf1, *buf2;
891*cc4ad7daSAndroid Build Coastguard Worker int err = false;
892*cc4ad7daSAndroid Build Coastguard Worker
893*cc4ad7daSAndroid Build Coastguard Worker a1 = read_expected_modules(t, &buf1, &l1);
894*cc4ad7daSAndroid Build Coastguard Worker if (l1 < 0)
895*cc4ad7daSAndroid Build Coastguard Worker return err;
896*cc4ad7daSAndroid Build Coastguard Worker a2 = read_loaded_modules(t, &buf2, &l2);
897*cc4ad7daSAndroid Build Coastguard Worker if (l2 < 0)
898*cc4ad7daSAndroid Build Coastguard Worker goto out_a1;
899*cc4ad7daSAndroid Build Coastguard Worker qsort(a1, l1, sizeof(char *), cmp_modnames);
900*cc4ad7daSAndroid Build Coastguard Worker qsort(a2, l2, sizeof(char *), cmp_modnames);
901*cc4ad7daSAndroid Build Coastguard Worker i1 = i2 = 0;
902*cc4ad7daSAndroid Build Coastguard Worker err = true;
903*cc4ad7daSAndroid Build Coastguard Worker while (i1 < l1 || i2 < l2) {
904*cc4ad7daSAndroid Build Coastguard Worker int cmp;
905*cc4ad7daSAndroid Build Coastguard Worker
906*cc4ad7daSAndroid Build Coastguard Worker if (i1 >= l1)
907*cc4ad7daSAndroid Build Coastguard Worker cmp = 1;
908*cc4ad7daSAndroid Build Coastguard Worker else if (i2 >= l2)
909*cc4ad7daSAndroid Build Coastguard Worker cmp = -1;
910*cc4ad7daSAndroid Build Coastguard Worker else
911*cc4ad7daSAndroid Build Coastguard Worker cmp = cmp_modnames(&a1[i1], &a2[i2]);
912*cc4ad7daSAndroid Build Coastguard Worker if (cmp == 0) {
913*cc4ad7daSAndroid Build Coastguard Worker i1++;
914*cc4ad7daSAndroid Build Coastguard Worker i2++;
915*cc4ad7daSAndroid Build Coastguard Worker } else if (cmp < 0) {
916*cc4ad7daSAndroid Build Coastguard Worker err = false;
917*cc4ad7daSAndroid Build Coastguard Worker ERR("module %s not loaded\n", a1[i1]);
918*cc4ad7daSAndroid Build Coastguard Worker i1++;
919*cc4ad7daSAndroid Build Coastguard Worker } else {
920*cc4ad7daSAndroid Build Coastguard Worker err = false;
921*cc4ad7daSAndroid Build Coastguard Worker ERR("module %s is loaded but should not be \n", a2[i2]);
922*cc4ad7daSAndroid Build Coastguard Worker i2++;
923*cc4ad7daSAndroid Build Coastguard Worker }
924*cc4ad7daSAndroid Build Coastguard Worker }
925*cc4ad7daSAndroid Build Coastguard Worker free(a2);
926*cc4ad7daSAndroid Build Coastguard Worker free(buf2);
927*cc4ad7daSAndroid Build Coastguard Worker out_a1:
928*cc4ad7daSAndroid Build Coastguard Worker free(a1);
929*cc4ad7daSAndroid Build Coastguard Worker free(buf1);
930*cc4ad7daSAndroid Build Coastguard Worker return err;
931*cc4ad7daSAndroid Build Coastguard Worker }
932*cc4ad7daSAndroid Build Coastguard Worker
test_run_parent(const struct test * t,int fdout[2],int fderr[2],int fdmonitor[2],pid_t child)933*cc4ad7daSAndroid Build Coastguard Worker static inline int test_run_parent(const struct test *t, int fdout[2],
934*cc4ad7daSAndroid Build Coastguard Worker int fderr[2], int fdmonitor[2], pid_t child)
935*cc4ad7daSAndroid Build Coastguard Worker {
936*cc4ad7daSAndroid Build Coastguard Worker pid_t pid;
937*cc4ad7daSAndroid Build Coastguard Worker int err;
938*cc4ad7daSAndroid Build Coastguard Worker bool matchout, match_modules;
939*cc4ad7daSAndroid Build Coastguard Worker
940*cc4ad7daSAndroid Build Coastguard Worker if (t->skip) {
941*cc4ad7daSAndroid Build Coastguard Worker LOG("%sSKIPPED%s: %s\n",
942*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_YELLOW_ON, ANSI_HIGHLIGHT_OFF,
943*cc4ad7daSAndroid Build Coastguard Worker t->name);
944*cc4ad7daSAndroid Build Coastguard Worker err = EXIT_SUCCESS;
945*cc4ad7daSAndroid Build Coastguard Worker goto exit;
946*cc4ad7daSAndroid Build Coastguard Worker }
947*cc4ad7daSAndroid Build Coastguard Worker
948*cc4ad7daSAndroid Build Coastguard Worker /* Close write-fds */
949*cc4ad7daSAndroid Build Coastguard Worker if (t->output.out != NULL)
950*cc4ad7daSAndroid Build Coastguard Worker close(fdout[1]);
951*cc4ad7daSAndroid Build Coastguard Worker if (t->output.err != NULL)
952*cc4ad7daSAndroid Build Coastguard Worker close(fderr[1]);
953*cc4ad7daSAndroid Build Coastguard Worker close(fdmonitor[1]);
954*cc4ad7daSAndroid Build Coastguard Worker
955*cc4ad7daSAndroid Build Coastguard Worker matchout = test_run_parent_check_outputs(t, fdout[0], fderr[0],
956*cc4ad7daSAndroid Build Coastguard Worker fdmonitor[0], child);
957*cc4ad7daSAndroid Build Coastguard Worker
958*cc4ad7daSAndroid Build Coastguard Worker /*
959*cc4ad7daSAndroid Build Coastguard Worker * break pipe on the other end: either child already closed or we want
960*cc4ad7daSAndroid Build Coastguard Worker * to stop it
961*cc4ad7daSAndroid Build Coastguard Worker */
962*cc4ad7daSAndroid Build Coastguard Worker if (t->output.out != NULL)
963*cc4ad7daSAndroid Build Coastguard Worker close(fdout[0]);
964*cc4ad7daSAndroid Build Coastguard Worker if (t->output.err != NULL)
965*cc4ad7daSAndroid Build Coastguard Worker close(fderr[0]);
966*cc4ad7daSAndroid Build Coastguard Worker close(fdmonitor[0]);
967*cc4ad7daSAndroid Build Coastguard Worker
968*cc4ad7daSAndroid Build Coastguard Worker do {
969*cc4ad7daSAndroid Build Coastguard Worker pid = wait(&err);
970*cc4ad7daSAndroid Build Coastguard Worker if (pid == -1) {
971*cc4ad7daSAndroid Build Coastguard Worker ERR("error waitpid(): %m\n");
972*cc4ad7daSAndroid Build Coastguard Worker err = EXIT_FAILURE;
973*cc4ad7daSAndroid Build Coastguard Worker goto exit;
974*cc4ad7daSAndroid Build Coastguard Worker }
975*cc4ad7daSAndroid Build Coastguard Worker } while (!WIFEXITED(err) && !WIFSIGNALED(err));
976*cc4ad7daSAndroid Build Coastguard Worker
977*cc4ad7daSAndroid Build Coastguard Worker if (WIFEXITED(err)) {
978*cc4ad7daSAndroid Build Coastguard Worker if (WEXITSTATUS(err) != 0)
979*cc4ad7daSAndroid Build Coastguard Worker ERR("'%s' [%u] exited with return code %d\n",
980*cc4ad7daSAndroid Build Coastguard Worker t->name, pid, WEXITSTATUS(err));
981*cc4ad7daSAndroid Build Coastguard Worker else
982*cc4ad7daSAndroid Build Coastguard Worker LOG("'%s' [%u] exited with return code %d\n",
983*cc4ad7daSAndroid Build Coastguard Worker t->name, pid, WEXITSTATUS(err));
984*cc4ad7daSAndroid Build Coastguard Worker } else if (WIFSIGNALED(err)) {
985*cc4ad7daSAndroid Build Coastguard Worker ERR("'%s' [%u] terminated by signal %d (%s)\n", t->name, pid,
986*cc4ad7daSAndroid Build Coastguard Worker WTERMSIG(err), strsignal(WTERMSIG(err)));
987*cc4ad7daSAndroid Build Coastguard Worker err = t->expected_fail ? EXIT_SUCCESS : EXIT_FAILURE;
988*cc4ad7daSAndroid Build Coastguard Worker goto exit;
989*cc4ad7daSAndroid Build Coastguard Worker }
990*cc4ad7daSAndroid Build Coastguard Worker
991*cc4ad7daSAndroid Build Coastguard Worker if (matchout)
992*cc4ad7daSAndroid Build Coastguard Worker matchout = check_generated_files(t);
993*cc4ad7daSAndroid Build Coastguard Worker if (t->modules_loaded)
994*cc4ad7daSAndroid Build Coastguard Worker match_modules = check_loaded_modules(t);
995*cc4ad7daSAndroid Build Coastguard Worker else
996*cc4ad7daSAndroid Build Coastguard Worker match_modules = true;
997*cc4ad7daSAndroid Build Coastguard Worker
998*cc4ad7daSAndroid Build Coastguard Worker if (t->expected_fail == false) {
999*cc4ad7daSAndroid Build Coastguard Worker if (err == 0) {
1000*cc4ad7daSAndroid Build Coastguard Worker if (matchout && match_modules)
1001*cc4ad7daSAndroid Build Coastguard Worker LOG("%sPASSED%s: %s\n",
1002*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
1003*cc4ad7daSAndroid Build Coastguard Worker t->name);
1004*cc4ad7daSAndroid Build Coastguard Worker else {
1005*cc4ad7daSAndroid Build Coastguard Worker ERR("%sFAILED%s: exit ok but %s do not match: %s\n",
1006*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1007*cc4ad7daSAndroid Build Coastguard Worker matchout ? "loaded modules" : "outputs",
1008*cc4ad7daSAndroid Build Coastguard Worker t->name);
1009*cc4ad7daSAndroid Build Coastguard Worker err = EXIT_FAILURE;
1010*cc4ad7daSAndroid Build Coastguard Worker }
1011*cc4ad7daSAndroid Build Coastguard Worker } else {
1012*cc4ad7daSAndroid Build Coastguard Worker ERR("%sFAILED%s: %s\n",
1013*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1014*cc4ad7daSAndroid Build Coastguard Worker t->name);
1015*cc4ad7daSAndroid Build Coastguard Worker }
1016*cc4ad7daSAndroid Build Coastguard Worker } else {
1017*cc4ad7daSAndroid Build Coastguard Worker if (err == 0) {
1018*cc4ad7daSAndroid Build Coastguard Worker if (matchout) {
1019*cc4ad7daSAndroid Build Coastguard Worker ERR("%sUNEXPECTED PASS%s: exit with 0: %s\n",
1020*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1021*cc4ad7daSAndroid Build Coastguard Worker t->name);
1022*cc4ad7daSAndroid Build Coastguard Worker err = EXIT_FAILURE;
1023*cc4ad7daSAndroid Build Coastguard Worker } else {
1024*cc4ad7daSAndroid Build Coastguard Worker ERR("%sUNEXPECTED PASS%s: exit with 0 and outputs do not match: %s\n",
1025*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1026*cc4ad7daSAndroid Build Coastguard Worker t->name);
1027*cc4ad7daSAndroid Build Coastguard Worker err = EXIT_FAILURE;
1028*cc4ad7daSAndroid Build Coastguard Worker }
1029*cc4ad7daSAndroid Build Coastguard Worker } else {
1030*cc4ad7daSAndroid Build Coastguard Worker if (matchout) {
1031*cc4ad7daSAndroid Build Coastguard Worker LOG("%sEXPECTED FAIL%s: %s\n",
1032*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
1033*cc4ad7daSAndroid Build Coastguard Worker t->name);
1034*cc4ad7daSAndroid Build Coastguard Worker err = EXIT_SUCCESS;
1035*cc4ad7daSAndroid Build Coastguard Worker } else {
1036*cc4ad7daSAndroid Build Coastguard Worker LOG("%sEXPECTED FAIL%s: exit with %d but outputs do not match: %s\n",
1037*cc4ad7daSAndroid Build Coastguard Worker ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
1038*cc4ad7daSAndroid Build Coastguard Worker WEXITSTATUS(err), t->name);
1039*cc4ad7daSAndroid Build Coastguard Worker err = EXIT_FAILURE;
1040*cc4ad7daSAndroid Build Coastguard Worker }
1041*cc4ad7daSAndroid Build Coastguard Worker }
1042*cc4ad7daSAndroid Build Coastguard Worker }
1043*cc4ad7daSAndroid Build Coastguard Worker
1044*cc4ad7daSAndroid Build Coastguard Worker exit:
1045*cc4ad7daSAndroid Build Coastguard Worker LOG("------\n");
1046*cc4ad7daSAndroid Build Coastguard Worker return err;
1047*cc4ad7daSAndroid Build Coastguard Worker }
1048*cc4ad7daSAndroid Build Coastguard Worker
prepend_path(const char * extra)1049*cc4ad7daSAndroid Build Coastguard Worker static int prepend_path(const char *extra)
1050*cc4ad7daSAndroid Build Coastguard Worker {
1051*cc4ad7daSAndroid Build Coastguard Worker char *oldpath, *newpath;
1052*cc4ad7daSAndroid Build Coastguard Worker int r;
1053*cc4ad7daSAndroid Build Coastguard Worker
1054*cc4ad7daSAndroid Build Coastguard Worker if (extra == NULL)
1055*cc4ad7daSAndroid Build Coastguard Worker return 0;
1056*cc4ad7daSAndroid Build Coastguard Worker
1057*cc4ad7daSAndroid Build Coastguard Worker oldpath = getenv("PATH");
1058*cc4ad7daSAndroid Build Coastguard Worker if (oldpath == NULL)
1059*cc4ad7daSAndroid Build Coastguard Worker return setenv("PATH", extra, 1);
1060*cc4ad7daSAndroid Build Coastguard Worker
1061*cc4ad7daSAndroid Build Coastguard Worker if (asprintf(&newpath, "%s:%s", extra, oldpath) < 0) {
1062*cc4ad7daSAndroid Build Coastguard Worker ERR("failed to allocate memory to new PATH\n");
1063*cc4ad7daSAndroid Build Coastguard Worker return -1;
1064*cc4ad7daSAndroid Build Coastguard Worker }
1065*cc4ad7daSAndroid Build Coastguard Worker
1066*cc4ad7daSAndroid Build Coastguard Worker r = setenv("PATH", newpath, 1);
1067*cc4ad7daSAndroid Build Coastguard Worker free(newpath);
1068*cc4ad7daSAndroid Build Coastguard Worker
1069*cc4ad7daSAndroid Build Coastguard Worker return r;
1070*cc4ad7daSAndroid Build Coastguard Worker }
1071*cc4ad7daSAndroid Build Coastguard Worker
test_run(const struct test * t)1072*cc4ad7daSAndroid Build Coastguard Worker int test_run(const struct test *t)
1073*cc4ad7daSAndroid Build Coastguard Worker {
1074*cc4ad7daSAndroid Build Coastguard Worker pid_t pid;
1075*cc4ad7daSAndroid Build Coastguard Worker int fdout[2];
1076*cc4ad7daSAndroid Build Coastguard Worker int fderr[2];
1077*cc4ad7daSAndroid Build Coastguard Worker int fdmonitor[2];
1078*cc4ad7daSAndroid Build Coastguard Worker
1079*cc4ad7daSAndroid Build Coastguard Worker if (t->need_spawn && oneshot)
1080*cc4ad7daSAndroid Build Coastguard Worker test_run_spawned(t);
1081*cc4ad7daSAndroid Build Coastguard Worker
1082*cc4ad7daSAndroid Build Coastguard Worker if (t->output.out != NULL) {
1083*cc4ad7daSAndroid Build Coastguard Worker if (pipe(fdout) != 0) {
1084*cc4ad7daSAndroid Build Coastguard Worker ERR("could not create out pipe for %s\n", t->name);
1085*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
1086*cc4ad7daSAndroid Build Coastguard Worker }
1087*cc4ad7daSAndroid Build Coastguard Worker }
1088*cc4ad7daSAndroid Build Coastguard Worker
1089*cc4ad7daSAndroid Build Coastguard Worker if (t->output.err != NULL) {
1090*cc4ad7daSAndroid Build Coastguard Worker if (pipe(fderr) != 0) {
1091*cc4ad7daSAndroid Build Coastguard Worker ERR("could not create err pipe for %s\n", t->name);
1092*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
1093*cc4ad7daSAndroid Build Coastguard Worker }
1094*cc4ad7daSAndroid Build Coastguard Worker }
1095*cc4ad7daSAndroid Build Coastguard Worker
1096*cc4ad7daSAndroid Build Coastguard Worker if (pipe(fdmonitor) != 0) {
1097*cc4ad7daSAndroid Build Coastguard Worker ERR("could not create monitor pipe for %s\n", t->name);
1098*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
1099*cc4ad7daSAndroid Build Coastguard Worker }
1100*cc4ad7daSAndroid Build Coastguard Worker
1101*cc4ad7daSAndroid Build Coastguard Worker if (prepend_path(t->path) < 0) {
1102*cc4ad7daSAndroid Build Coastguard Worker ERR("failed to prepend '%s' to PATH\n", t->path);
1103*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
1104*cc4ad7daSAndroid Build Coastguard Worker }
1105*cc4ad7daSAndroid Build Coastguard Worker
1106*cc4ad7daSAndroid Build Coastguard Worker LOG("running %s, in forked context\n", t->name);
1107*cc4ad7daSAndroid Build Coastguard Worker
1108*cc4ad7daSAndroid Build Coastguard Worker pid = fork();
1109*cc4ad7daSAndroid Build Coastguard Worker if (pid < 0) {
1110*cc4ad7daSAndroid Build Coastguard Worker ERR("could not fork(): %m\n");
1111*cc4ad7daSAndroid Build Coastguard Worker LOG("FAILED: %s\n", t->name);
1112*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
1113*cc4ad7daSAndroid Build Coastguard Worker }
1114*cc4ad7daSAndroid Build Coastguard Worker
1115*cc4ad7daSAndroid Build Coastguard Worker if (pid > 0)
1116*cc4ad7daSAndroid Build Coastguard Worker return test_run_parent(t, fdout, fderr, fdmonitor, pid);
1117*cc4ad7daSAndroid Build Coastguard Worker
1118*cc4ad7daSAndroid Build Coastguard Worker return test_run_child(t, fdout, fderr, fdmonitor);
1119*cc4ad7daSAndroid Build Coastguard Worker }
1120