2011-08-05 101 views
5

我正在使用管道到標準輸入和標準輸出與子進程進行通信的系統上工作。子進程使用api庫來促進這種通信,我需要爲圖書館編寫單元測試。我可以想出如何正確測試這些函數的唯一方法是用管道替換stdin/stdout,以便在調用函數時測試可以假裝爲父系統。替換,然後通過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]); 
} 

我已經嘗試過節省臨時工stdin和stdout和使用fdopen()對他們(應該工作,因爲他們是FILE *),但是這不會導致事情都是正確寫入到管道。當直接從主機的shell運行時,此代碼完美工作。在ssh上運行時會出現問題。單元測試執行完美,但是當我在這個測試套件之後寫入任何標準輸出時,我收到了一個損壞的管道錯誤。

我該怎麼辦,避免使用dup2,以便stdin和stdout永遠不會關閉,或者我如何重新打開stdin和stdout,以便它們能夠正確地在shell和ssh中工作?

回答

3

標準輸入,標準輸出只是文件*指向一個結構(對象),它的內部fd設置爲0(和1)。因此,當您執行dup2時,文件0和1不再起作用。你需要做的是在做dup2之前從零開始創建一個新的文件對象,所以這可能是你需要的所有修改;

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"); 
} 
相關問題