Остановка Poco :: Thread для модульных тестов - PullRequest
3 голосов
/ 28 марта 2012

Проблема

У меня есть приложение UDPlistener, для которого мне нужно написать модульный тест.Этот слушатель постоянно прослушивает порт и должен всегда работать на продукте.Мы используем библиотеки poco для каркасов, не входящих в стандартную библиотеку.

Теперь мне нужно добавить его в приложение для модульного тестирования.

Curent Solution

Я подумал, что проще всего реализовать Poco::Runnable в классе RunApp, который запускает приложение.Затем я могу создать новый Poco::Thread в своем модульном тесте для запуска класса RunApp.

Это работает;мой слушатель работает, и я могу отправлять тестовые сообщения в теле модульного теста после создания потока.НО, мне нужно остановить слушателя, чтобы могли выполняться другие модульные тесты.Я добавил UDP-сообщение, сообщающее слушателю, что нужно убить себя, но оно используется только модульным тестом и потенциальной проблемой безопасности.

Вопрос

Есть ли способ заставить Poco::Threadпрекратить?Или я неправильно структурировал этот юнит-тест?Я не хочу, чтобы слушатель работал во время всех остальных модульных тестов.

1 Ответ

7 голосов
/ 21 июня 2012

Если вместо Poco::Thread вы используете Poco::Task, вы получите поток, который можно отменить. Следующий пример кода (готовый к запуску как есть) должен дать вам представление:

#include <Poco/Task.h>
#include <Poco/TaskManager.h>
#include <Poco/Thread.h>

#include <string>
#include <iostream>
using namespace std;

class UdpListenerTask : public Poco::Task {
public:
    UdpListenerTask(const string& name) : Task(name) { }

    void runTask() {
        cout << name() << ": starting" << endl;
        while (! isCancelled()) {
            // Do some work. Cannot block indefinitely, otherwise it
            // will never test the isCancelled() condition.
            doSomeWork();
        }
        cout << endl << name() << ": cancelled " << endl;
    }
private:
    int doSomeWork() {
        cout << "*" << flush;
        // Simulate some time spent doing work
        int i;
        for (i = 0; i < INT32_MAX/1000; i++) { }
        return i;
    }
};

void runUdpProbe() {
    // Simulate some time spent running the probe.
    Poco::Thread::sleep(1000);
}

int main() {
    Poco::TaskManager tm;
    UdpListenerTask* st = new UdpListenerTask("task1");
    tm.start(st); // tm takes ownership

    // Run test 1.
    runUdpProbe();
    // Test 1 done. Cancel the UDP listener
    st->cancel();

    // Run all the other tests

    // cleanup
    tm.joinAll();
    return 0;
}

Слайды POCO Многопоточность дают примеры использования как Poco :: Thread, так и Poco :: Task.

Кроме того, модульный тест должен обходить связь UDP через абстрактные классы и фиктивные объекты; Я думаю, что этот тест должен называться функциональным тестом: -)

...