我尝试对终端输出功能进行单元测试。该函数将数据流式传输到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"覆盖" 1 \ n"在testcode部分的缓冲区中(gcc 5.4.0 x64 GNU libc version:2.23)
输出是:
0
1
2
2
但我期待:
0
1
2
1
2
我会感激任何提示。
答案 0 :(得分:1)
在关闭和打开stdout,“dup”-ing,写入文件和从文件和其他奇怪的解决方案中读取后,我找到了一个符合我需要的解决方案,但不是那么便携但是不需要另外的文件来打开:
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;
}