2011-08-05 10 views
5

stdinとstdoutへのパイプを使って子プロセスと通信するシステムで作業しています。子プロセスはこの通信を容易にするためにapiライブラリを使用し、ライブラリの単体テストを書く必要があります。これらの関数を適切にテストする方法を理解する唯一の方法は、stdin/stdoutをパイプで置き換えて、関数を呼び出すときにテストが親システムのふりをすることができるようにすることです。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]); 
} 

私は(彼らはFILEの*であるため、動作するはずです)その上)(ちょうどタンで標準入出力を保存してのfdopenを使用して試してみましたが、これは正しくパイプに書き込まれているものにはなりません。このコードは、ホストのシェルから直接実行されたときに完全に機能します。この問題は、sshで実行しているときに発生します。ユニットテストは完全に実行されますが、このテストスイートの後にstdoutに何かを書き込むと、パイプエラーが発生します。

stdinとstdoutが決して閉じられないようにするためにdup2を使用しないようにするにはどうすればよいでしょうか、またはstdinとstdoutをシェルやsshで正しく動作させる方法を教えてください。

答えて

3

stdin、stdoutは、内部的にfdが0(および1)に設定されているstruct(オブジェクト)を指すFILE *です。したがって、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"); 
} 
関連する問題