Модульный тест для протокола через cin / cout - как заблокировать потоки для ожидания контента? - PullRequest
1 голос
/ 28 марта 2019

Я пытаюсь написать модульный тест для программы, которая должна взаимодействовать с другим процессом по протоколу через канал cin / cout.Он хорошо работает при выделении и тестировании с клавиатуры или другой программы, отправляющей и получающей команды и ответы.

В модульном тесте мне, очевидно, потребуется заменить cin / cout другими потоками, из которых я могу отправлять и получать данные.(Через другой поток и запись во входной поток обработчика протокола)

К сожалению, я не могу найти метод для получения блокирующего метода чтения, который ожидает, пока поток не получит больше контента.

Приведенный ниже код работает нормально при использовании cin.

void Handler::loop() {
  string cmd, token;
  do {
    cout << "HANDLER WAIT FOR COMMAND:" << endl;

    // Block here waiting for input or EOF
    // only blocks on cin!!
    if (!getline(*pInputStream, cmd)) cmd = "quit";

    //  create the stream object
    istringstream inStream(cmd);

    inStream >> skipws >> token;
    cout << "HANDLER RECEIVED: " << token << endl;

    if (token == "quit") break;
    // handle commands...
    else if (token == "noop") /* noop */;
    else cerr << "Unknown command: " << token << endl;
    cout << "HANDLER COMMAND PROCESSED: " << token << endl;

  } while (token != "quit");
}

При использовании

istringstream is;

вместо cin, тогда getline (* pInputStream, cmd) 'не работаетблокировать больше и немедленно возвращает -1.Я не могу найти другой mothed, который бы выполнил то, что мне нужно (если бы я провел какое-то исследование в течение некоторого времени).

В Java я реализовал это с помощью:

final BufferedReader in = 
    new BufferedReader(newnputStreamReader(inputStream));

while (running) {
  try {
    // wait until a line is ready to be read
    final String readLine = in.readLine();
...

Это прекрасно работает с System.in или другими потоками.in.readline () всегда блокируется, пока содержимое не станет доступным.Идеально для модульного тестирования.

Так как конкретно это можно сделать в C ++ или, в более общем смысле, как выполнить модульное тестирование протоколов по межпроцессным каналам?

Заранее спасибо за любые идеи.

1 Ответ

0 голосов
/ 28 марта 2019

std:::getline возвращает объект входного потока, который вы указали в качестве аргумента.Сам поток будет иметь состояние, которое используется для определения того, должен ли он оцениваться как true или false в логическом контексте.Я сделал ваш цикл способным принимать общий std::istream, чтобы он мог быть протестирован как с std::cin, так и с другими потоками.Первый запуск usues std::cin, а второй запуск us std::istringstream, чтобы показать, что он работает.

#include <iostream>
#include <sstream>
#include <iomanip>

void loop(std::istream& is) {
    std::cout << "-----------------------------\n";
    std::string cmd, token;
    do {
        std::cout << "HANDLER WAIT FOR COMMAND:\n";

        // Block here waiting for input or EOF
        // only blocks on cin!!
        if(!getline(is, cmd)) cmd = "quit";

        //  create the stream object
        std::istringstream inStream(cmd);

        inStream >> std::skipws >> token;
        std::cout << "HANDLER RECEIVED: " << token << "\n";

        if(token == "quit") break;
        // handle commands...
        else if(token == "noop") /* noop */
            ;
        else
            std::cerr << "Unknown command: " << token << "\n";
        std::cout << "HANDLER COMMAND PROCESSED: " << token << "\n";

    } while(token != "quit");
}

int main() {
    loop(std::cin);
    std::istringstream ss("unknown\nnoop\nquit\nafter quit\n");
    loop(ss);
}
...