2011-08-05 14 views
5

Estoy trabajando en un sistema que se comunica con procesos secundarios usando pipes para stdin y stdout. Los procesos secundarios usan una biblioteca api para facilitar esta comunicación y necesito escribir pruebas unitarias para la biblioteca. La única forma en que pude descubrir cómo probar adecuadamente estas funciones es reemplazar stdin/stdout con tuberías para que las pruebas puedan pretender ser el sistema principal al llamar a las funciones.Reemplazando y luego abriendo stdin/stdout sobre ssh

/* 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]); 
} 

He tratado simplemente ahorro de entrada y salida estándar de temperaturas y el uso de fdopen() sobre ellos (debería funcionar porque son ARCHIVO *), pero esto no da lugar a las cosas que se escriben correctamente a la tubería. Este código funciona perfectamente cuando se ejecuta directamente desde el shell del host. El problema ocurre cuando se ejecuta sobre ssh. Las pruebas unitarias se ejecutan perfectamente, pero cuando voy a escribir algo para stdout después de este banco de pruebas, recibo un error de tubería rota.

¿Qué puedo hacer para evitar el uso de dup2 para que stdin y stdout nunca se cierren, o cómo puedo volver a abrir stdin y stdout para que funcionen correctamente en el shell y en ssh?

Respuesta

3

stdin, stdout es simplemente FILE * que apunta a una estructura (objeto) que internamente tienen su fd configurado en 0 (y 1). Por lo tanto, cuando haces el dup2, el archivo 0 y 1 ya no funcionan. Lo que debe hacer es crear un nuevo objeto de archivo desde cero antes de haciendo el dup2, por lo que esta puede ser toda la modificación que necesita;

void setup(void) { 
    int dupin, dupout; 

    dupin = dup(0); // Create an extra fd to stdin 
    dupout = dup(1); // create an extra fd to stdout 

    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 = fdopen(dupout, "wb"); 
    stdin_t = fdopen(dupin, "rb"); 
}