I'm working on a system that communicates with child processes using pipes to stdin and stdout. The child processes use a api library to facilitate this communication and I need to write unit tests for the library. The only way that I could figure out how to properly test these functions is to replace stdin/stdout with pipes so that the tests can pretend to be the parent system when calling the functions.
/* replace stdin and stdout with pipes */
void setup(void) {
pipe(in_sub);
pipe(out_sub);
dup2(out_sub[1], fileno(stdout));
dup2( in_sub[0], fileno(stdin));
read_from = fdopen(out_sub[0], "rb");
write_to = fdopen( in_sub[1], "wb");
stdout_t = fopen("/dev/tty", "wb");
stdin_t = fopen("/dev/tty", "rb");
}
/* reopen stdin and stdout for future test suites */
void teardown(void) {
fclose(read_from);
fclose(write_to);
stdout = stdout_t;
stdin = stdin_t;
close(in_sub[0]);
close(in_sub[1]);
close(out_sub[0]);
close(out_sub[1]);
}
I have tried just saving stdin and stdout in temps and using fdopen() on them (should work because they are FILE*) but this doesn't result in things being correctly written to the pipe. This code does work perfectly when being run directly from the host's shell. The problem occurs when running over ssh. The unit tests execute perfectly, but when I go to write anything to stdout after this test suite, I receive a broken pipe error.
What can I do that avoids using the dup2 so that stdin and stdout never get closed, or how can I reopen stdin and stdout such that they will correctly work in the shell and over ssh?