pipecmd: add stderr fd arg.
[ccan] / ccan / pipecmd / test / run.c
index 425e7d00bbd79729d5897a6161550bbb0bab2a61..45b96ab2f03b2d5d2145f9cdc6a3ae990778b528 100644 (file)
@@ -9,7 +9,7 @@
 int main(int argc, char *argv[])
 {
        pid_t child;
-       int infd, outfd, status;
+       int infd, outfd, errfd, status;
        char buf[5] = "test";
 
        /* We call ourselves, to test pipe. */
@@ -28,43 +28,94 @@ int main(int argc, char *argv[])
                        buf[0]++;
                        if (write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf))
                                exit(1);
+               } else if (strcmp(argv[1], "err") == 0) {
+                       if (write(STDERR_FILENO, buf, sizeof(buf)) != sizeof(buf))
+                               exit(1);
                } else
                        abort();
                exit(0);
        }
 
+       /* We assume no fd leaks, so close them now. */
+       close(3);
+       close(4);
+       close(5);
+       close(6);
+       close(7);
+       close(8);
+       close(9);
+       close(10);
+       
        /* This is how many tests you plan to run */
-       plan_tests(28);
-       child = pipecmd(&outfd, &infd, argv[0], "inout", NULL);
+       plan_tests(67);
+       child = pipecmd(&outfd, &infd, &errfd, argv[0], "inout", NULL);
        if (!ok1(child > 0))
                exit(1);
        ok1(write(infd, buf, sizeof(buf)) == sizeof(buf));
        ok1(read(outfd, buf, sizeof(buf)) == sizeof(buf));
+       ok1(read(errfd, buf, sizeof(buf)) == 0);
+       ok1(close(infd) == 0);
+       ok1(close(outfd) == 0);
+       ok1(close(errfd) == 0);
        buf[0]--;
        ok1(memcmp(buf, "test", sizeof(buf)) == 0);
        ok1(waitpid(child, &status, 0) == child);
        ok1(WIFEXITED(status));
        ok1(WEXITSTATUS(status) == 0);
 
-       child = pipecmd(NULL, &infd, argv[0], "in", NULL);
+       child = pipecmd(NULL, &infd, NULL, argv[0], "in", NULL);
        if (!ok1(child > 0))
                exit(1);
        ok1(write(infd, buf, sizeof(buf)) == sizeof(buf));
+       ok1(close(infd) == 0);
+       ok1(waitpid(child, &status, 0) == child);
+       ok1(WIFEXITED(status));
+       ok1(WEXITSTATUS(status) == 0);
+
+       child = pipecmd(&outfd, NULL, NULL, argv[0], "out", NULL);
+       if (!ok1(child > 0))
+               exit(1);
+       ok1(read(outfd, buf, sizeof(buf)) == sizeof(buf));
+       ok1(close(outfd) == 0);
+       ok1(memcmp(buf, "test", sizeof(buf)) == 0);
+       ok1(waitpid(child, &status, 0) == child);
+       ok1(WIFEXITED(status));
+       ok1(WEXITSTATUS(status) == 0);
+
+       /* Errfd only should be fine. */
+       child = pipecmd(NULL, NULL, &errfd, argv[0], "err", NULL);
+       if (!ok1(child > 0))
+               exit(1);
+       ok1(read(errfd, buf, sizeof(buf)) == sizeof(buf));
+       ok1(close(errfd) == 0);
+       ok1(memcmp(buf, "test", sizeof(buf)) == 0);
+       ok1(waitpid(child, &status, 0) == child);
+       ok1(WIFEXITED(status));
+       ok1(WEXITSTATUS(status) == 0);
+
+       /* errfd == outfd should work with both. */
+       child = pipecmd(&errfd, NULL, &errfd, argv[0], "err", NULL);
+       if (!ok1(child > 0))
+               exit(1);
+       ok1(read(errfd, buf, sizeof(buf)) == sizeof(buf));
+       ok1(close(errfd) == 0);
+       ok1(memcmp(buf, "test", sizeof(buf)) == 0);
        ok1(waitpid(child, &status, 0) == child);
        ok1(WIFEXITED(status));
        ok1(WEXITSTATUS(status) == 0);
 
-       child = pipecmd(&outfd, NULL, argv[0], "out", NULL);
+       child = pipecmd(&outfd, NULL, &outfd, argv[0], "out", NULL);
        if (!ok1(child > 0))
                exit(1);
        ok1(read(outfd, buf, sizeof(buf)) == sizeof(buf));
+       ok1(close(outfd) == 0);
        ok1(memcmp(buf, "test", sizeof(buf)) == 0);
        ok1(waitpid(child, &status, 0) == child);
        ok1(WIFEXITED(status));
        ok1(WEXITSTATUS(status) == 0);
 
        // Writing to /dev/null should be fine.
-       child = pipecmd(NULL, NULL, argv[0], "out", NULL);
+       child = pipecmd(NULL, NULL, NULL, argv[0], "out", NULL);
        if (!ok1(child > 0))
                exit(1);
        ok1(waitpid(child, &status, 0) == child);
@@ -72,18 +123,35 @@ int main(int argc, char *argv[])
        ok1(WEXITSTATUS(status) == 0);
 
        // Reading should fail.
-       child = pipecmd(NULL, NULL, argv[0], "in", NULL);
+       child = pipecmd(NULL, NULL, NULL, argv[0], "in", NULL);
        if (!ok1(child > 0))
                exit(1);
        ok1(waitpid(child, &status, 0) == child);
        ok1(WIFEXITED(status));
        ok1(WEXITSTATUS(status) == 1);
 
+       child = pipecmd(NULL, NULL, NULL, argv[0], "err", NULL);
+       if (!ok1(child > 0))
+               exit(1);
+       ok1(waitpid(child, &status, 0) == child);
+       ok1(WIFEXITED(status));
+       ok1(WEXITSTATUS(status) == 0);
+
        // Can't run non-existent file, but errno set correctly.
-       child = pipecmd(NULL, NULL, "/doesnotexist", "in", NULL);
+       child = pipecmd(NULL, NULL, NULL, "/doesnotexist", "in", NULL);
        ok1(errno == ENOENT);
        ok1(child < 0);
 
+       /* No fd leaks! */
+       ok1(close(3) == -1 && errno == EBADF);
+       ok1(close(4) == -1 && errno == EBADF);
+       ok1(close(5) == -1 && errno == EBADF);
+       ok1(close(6) == -1 && errno == EBADF);
+       ok1(close(7) == -1 && errno == EBADF);
+       ok1(close(8) == -1 && errno == EBADF);
+       ok1(close(9) == -1 && errno == EBADF);
+       ok1(close(10) == -1 && errno == EBADF);
+
        /* This exits depending on whether all tests passed */
        return exit_status();
 }