替换然后在ssh上打开stdin / stdout

时间:2011-08-05 19:02:47

标签: c linux unit-testing ssh pipe

我正在开发一个使用管道连接到stdin和stdout的子进程通信的系统。子进程使用api库来促进这种通信,我需要为库编写单元测试。我能弄清楚如何正确测试这些函数的唯一方法是用管道替换stdin / stdout,以便测试在调用函数时可以伪装成父系统。

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

我试过在temps中保存stdin和stdout并在它们上使用fdopen()(应该可以工作,因为它们是FILE *)但是这不会导致正确写入管道。直接从主机shell运行时,此代码可以正常工作。在ssh上运行时会出现问题。单元测试执行得很完美,但是当我在这个测试套件之后向stdout写任何内容时,我收到一个管道错误。

我能做些什么来避免使用dup2以便stdin和stdout永远不会被关闭,或者我如何重新打开stdin和stdout以便它们能够在shell中正确地工作并通过ssh?

1 个答案:

答案 0 :(得分:3)

stdin,stdout只是FILE *指向一个struct(object),它在内部将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");
}