2016-09-06 11 views
0

端末出力機能をユニットテストしようとしています。この関数はstdoutにデータを流すので、私の考えはstdoutバッファの制御を取得し、関数が正しいデータをバッファに正しく書き込むかどうかをチェックすることでした。標準出力のバッファ処理

setvbufはこれを達成するのに理想的なようでした。

setvbufを使用してstdoutをリダイレクトして、自分で指定したバッファを使用しました。

ストリーミングモード_IOFBFを使用しました。理論的には、バッファがいっぱいになった場合に内部フラッシュが行われるだけです。私のシステム上のBUFSIZは、8192バイトのサイズを持っています...呼び出し中に内部フラッシュなしで、テスト中の関数の出力に十分な大きさ以上です。

マイソースが現在のように見える:このコードをデバッグ

char buffer [BUFSIZ] = {0}; 

/* any outputs before redirecting */ 
printf("0\n"); 

/* output any remaining data */ 
fflush(stdout); 
/* redirect to my buffer with full buffering */ 
setvbuf(stdout,buffer,_IOFBF,BUFSIZ); 

/* testcode ... output of the function under test */ 
printf("1\n"); 
printf("2\n"); 

/* output any remaining data */ 
fflush(stdout); 
/* restore internal buffering with line buffering */ 
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); 

/* let us see what is in our buffer */ 
printf("%s",buffer); 

"は2 \ n" はtestcode部(GCC 5.4.0 x64のGNU libcのバージョンの間の "1 \ n" バッファ内を上書きすることを示します2.23)

出力は次のとおりです。

0 
1 
2 
2 

しかし、私は予想:

0 
1 
2 
1 
2 

私はどんなヒントでも喜ばれます。

+0

私は目を再現することはできませんeエラー。私は期待される出力を得る。 – Beta

+0

確認していただきありがとうございます。これが私のシステムでのclibバッファ処理のバグであるかどうかは不明です。確認するためにどのコンパイラ+バージョンを使用しましたか? – marcas756

+0

おそらく 'setvbuf()'を使っているのでしょうか? C11dr 7.21.5.6 2 "setvbuf関数は、ストリームが指すストリームがオープンファイル**に関連付けられた後で、他の操作**(setvbufへの不成功呼び出しを除く)がストリームに対して実行される前にのみ使用できます" – chux

答えて

0

私は自分のニーズに合ったものを見つけましたが、ポータブルではありませんが別のファイルは必要ありませんが、stdout、 "dup"オープンする:

How to buffer stdout in memory and write it from a dedicated thread

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define MAX_LEN 40 

int main(int argc, char *argv[]) { 
    char buffer[MAX_LEN+1] = {0}; 
    int out_pipe[2]; 
    int saved_stdout; 

    saved_stdout = dup(STDOUT_FILENO); /* save stdout for display later */ 

    if(pipe(out_pipe) != 0) {   /* make a pipe */ 
    exit(1); 
    } 

    dup2(out_pipe[1], STDOUT_FILENO); /* redirect stdout to the pipe */ 
    close(out_pipe[1]); 

    /* anything sent to printf should now go down the pipe */ 
    printf("ceci n'est pas une pipe"); 
    fflush(stdout); 

    read(out_pipe[0], buffer, MAX_LEN); /* read from pipe into buffer */ 

    dup2(saved_stdout, STDOUT_FILENO); /* reconnect stdout for testing */ 
    printf("read: %s\n", buffer); 

    return 0; 
} 

自身のモジュール "stdout_redirect.c" を作ってそれを書き換えた後に、これは、その結果:

#define BIGENOUGH 1000 
#define PIPE_READ 0 
#define PIPE_WRITE 1 

char stdout_buffer [BIGENOUGH]; 
static int stdout_save; 
static int stdout_pipe[2]; 

bool stdout_redirect() 
{ 
    stdout_save = dup(STDOUT_FILENO); /* save stdout for display later */ 

    if(pipe(stdout_pipe) != 0) {   /* make a pipe */ 
     return false; 
    } 

    dup2(stdout_pipe[PIPE_WRITE], STDOUT_FILENO); /* redirect stdout to the pipe */ 
    close(stdout_pipe[PIPE_WRITE]); 

    return true; 
} 

ssize_t stdout_restore() 
{ 
    ssize_t size; 
    fflush(stdout); /* flush if not flushed before */ 
    size = read(stdout_pipe[PIPE_READ], stdout_buffer, sizeof(stdout_buffer)); /* read from pipe into buffer */ 
    close(stdout_pipe[PIPE_READ]); 
    dup2(stdout_save, STDOUT_FILENO); /* reconnect stdout */ 
    return size; 
} 
関連する問題