return -1;
}
-static inline bool test_run_parent_check_outputs(const struct test *t,
- int fdout, int fderr, int fdmonitor, pid_t child)
+#define BUFSZ 4096
+struct buffer {
+ char buf[BUFSZ];
+};
+
+/* read fd and fd_match, checking they match exactly */
+static bool cmpbuf_exact(const struct test *t, const char *prefix,
+ int fd, int fd_match, struct buffer *buf,
+ struct buffer *buf_match)
+{
+ int r, rmatch, done = 0;
+
+ r = read(fd, buf->buf, sizeof(buf->buf) - 1);
+ if (r <= 0)
+ /* try again later */
+ return true;
+
+ /* read as much data from fd_match as we read from fd */
+ for (;;) {
+ rmatch = read(fd_match, buf_match->buf + done, r - done);
+ if (rmatch == 0)
+ break;
+
+ if (rmatch < 0) {
+ if (errno == EINTR)
+ continue;
+ ERR("could not read match fd %d\n", fd_match);
+ return false;
+ }
+
+ done += rmatch;
+ }
+
+ buf->buf[r] = '\0';
+ buf_match->buf[r] = '\0';
+
+ if (t->print_outputs)
+ printf("%s: %s\n", prefix, buf->buf);
+
+ if (!streq(buf->buf, buf_match->buf)) {
+ ERR("Outputs do not match on %s:\n", prefix);
+ ERR("correct:\n%s\n", buf_match->buf);
+ ERR("wrong:\n%s\n", buf->buf);
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_run_parent_check_outputs(const struct test *t,
+ int fdout, int fderr, int fdmonitor,
+ pid_t child)
{
struct epoll_event ep_outpipe, ep_errpipe, ep_monitor;
int err, fd_ep, fd_matchout = -1, fd_matcherr = -1;
bool fd_activityout = false, fd_activityerr = false;
unsigned long long end_usec, start_usec;
+ _cleanup_free_ struct buffer *buf_out = NULL, *buf_err = NULL;
fd_ep = epoll_create1(EPOLL_CLOEXEC);
if (fd_ep < 0) {
ERR("could not add fd to epoll: %m\n");
goto out;
}
+ buf_out = calloc(2, sizeof(*buf_out));
} else
fdout = -1;
ERR("could not add fd to epoll: %m\n");
goto out;
}
+ buf_err = calloc(2, sizeof(*buf_err));
} else
fderr = -1;
}
for (i = 0; i < fdcount; i++) {
- int *fd = ev[i].data.ptr;
+ int fd = *(int *)ev[i].data.ptr;
if (ev[i].events & EPOLLIN) {
- ssize_t r, done = 0;
- char buf[4096];
- char bufmatch[4096];
int fd_match;
+ struct buffer *buf, *buf_match;
+ const char *prefix;
- /*
- * compare the output from child with the one
- * saved as correct
- */
-
- r = read(*fd, buf, sizeof(buf) - 1);
- if (r <= 0)
- continue;
-
- if (*fd == fdout) {
+ if (fd == fdout) {
fd_match = fd_matchout;
+ buf = buf_out;
fd_activityout = true;
- } else if (*fd == fderr) {
+ prefix = "STDOUT";
+ } else if (fd == fderr) {
fd_match = fd_matcherr;
+ buf = buf_err;
fd_activityerr = true;
+ prefix = "STDERR";
} else {
ERR("Unexpected activity on monitor pipe\n");
err = -EINVAL;
goto out;
}
- for (;;) {
- int rmatch = read(fd_match,
- bufmatch + done, r - done);
- if (rmatch == 0)
- break;
-
- if (rmatch < 0) {
- if (errno == EINTR)
- continue;
- err = -errno;
- ERR("could not read match fd %d\n",
- fd_match);
- goto out;
- }
-
- done += rmatch;
- }
+ buf_match = buf + 1;
- buf[r] = '\0';
- bufmatch[r] = '\0';
-
- if (t->print_outputs)
- printf("%s: %s\n",
- fd_match == fd_matchout ? "STDOUT:" : "STDERR:",
- buf);
-
- if (!streq(buf, bufmatch)) {
- ERR("Outputs do not match on %s:\n",
- fd_match == fd_matchout ? "STDOUT" : "STDERR");
- ERR("correct:\n%s\n", bufmatch);
- ERR("wrong:\n%s\n", buf);
- err = -1;
+ if (!cmpbuf_exact(t, prefix, fd, fd_match,
+ buf, buf_match))
goto out;
- }
} else if (ev[i].events & EPOLLHUP) {
- if (epoll_ctl(fd_ep, EPOLL_CTL_DEL,
- *fd, NULL) < 0) {
- ERR("could not remove fd %d from epoll: %m\n",
- *fd);
+ if (epoll_ctl(fd_ep, EPOLL_CTL_DEL, fd, NULL) < 0) {
+ ERR("could not remove fd %d from epoll: %m\n", fd);
}
- *fd = -1;
+ *(int *)ev[i].data.ptr = -1;
}
}
}