在eof上的std :: stringstream块上创建std :: getline()(或者找到替代流类)

时间:2015-06-30 22:29:02

标签: c++ c++11 iostream c++14 stringstream

我在寻找什么

像stream一样的管道,用std :: ostream连接std :: istream。我应该能够写一些东西到std :: ostream部分,然后从std :: istream部分读取它。在istream部分调用std :: getline()时,它应该阻塞,直到来自std :: ostream部分的数据可用。

std :: stringstream完全符合我的要求,除非它没有阻止。在空的std :: stringstream上调用std :: getline()时,它只返回并设置eof()标志。

为什么我需要这个

为了测试使用流进行输入/输出的Console类,我需要对应的对象来读取Console类的输出并为其生成输入。 std :: cin上的std :: getline()是阻塞的,所以如果管道流为空,管道流也应该阻塞。

详情

我有一个 Console 类,用于处理控制台输入和输出。简化版本就像

class Console {
public:
  Console(): Console(std::cin, std::cout) {}
  Console(istream &istr, ostream &ostr): _istr(istr), _ostr(ostr) {}

  string ask(const string &question) {
    _ostr << question << "\n";
    string answer;
    std::getline(_istr, answer);
    return answer;
  }
private:
  istream &_istr;
  ostream &_ostr;
};

在生产中,_istr将设置为std :: cin,_ostr将设置为std :: cout。 在测试用例中,我将它们设置为拥有内存中的流类。

为此,我想使用std :: stringstream,因为我可以用

测试输出
void EXPECT_OUTPUT_LINE(const string &expected) {
  string actual;
  std::getline(ostr, actual);
  EXPECT_EQ(expected, actual);
}

并使用

发送输入
void sendInputLine(const string &line) {
  istr << line << "\n";
}

在这种情况下, Console 类在不同的线程中运行,因为它在尝试从_istr读取时应该阻塞其线程。 一般的测试用例看起来像

TEST(ConsoleTest, MyTest) {
  stringstream istr, ostr;
  future<string> answer = std::async(std::launch::async, [&] () {
    Console(ostr, istr).ask("Question?");
  });
  EXPECT_OUTPUT_LINE("Question?");
  sendInputLine("Answer");
  EXPECT_EQ("Answer", answer.get());
}

然而,结果是std :: getline()没有阻塞。当与std :: cin一起使用时,它会阻塞。当与空的std :: stringstream一起使用时,std :: getline会立即返回并设置eof标志。

因此,即使我的测试用例说明了sendInputLine(“bla”),这也没有任何效果,因为Console类不会等待它,并且它的std :: getline()调用可能已经返回了过去的空串流。

同样的问题出在EXPECT_OUTPUT_LINE中。它调用std :: getline来获取Console类的输出,但它不会等待它。如果在Console类实际产生任何输出之前发生这种情况,那么它只返回并设置字符串流的eof标志。

0 个答案:

没有答案