TEST(MyTest, test_async_connect) { boost::io_service client_io, server_io; my_client client(client_io); my_server server(server_io); EXPECT_FALSE(client.connected());//connected возвращает false, если клиент не подключен к серверу EXPECT_EQ(server.clients_count(), 0);//к серверу не подключен ни один клиент server.start_accept();//начинаем принимать подключения client.async_connect("localhost", my_port);//метод async_connect, //начинает асинхронную операцию подключения к серверу, //в коде my_client, это может быть реализовано примерно так: // boost::asio::async_connect(thsi->socket_, &my_client::on_connect); //естественно, метод on_connect, должен изменить состояние клиента server_io.run_one();//во время этого вызова, сервер дожен принять подключение, //обработать сообветствующее событие и изменить свое состояние EXPECT_EQ(server.clients_count(), 1);//теперь клиент подключен к серверу EXPECT_FALSE(client.connected());//но сам еще не знает об этом client_io.run_one();//что-бы он об этом узнал, нужно что-бы выполнился обработчик собыитя on_connect EXPECT_TRUE(client.connected());//done }
вторник, 24 марта 2009 г.
Unit тестирование и boost::asio
Как известно, одно из главных требований к модульным тестам, это повторяемость. Очень сложно искать ошибку, которая воспроизводится через раз. А с кодом, использующим асинхронный ввод вывод, все обычно так и обстоит, как как обработчики различных событий, обычно, выполняются в неопределенном порядке, к тому-же из разных потоков. Но, если вы используете boost::asio, то все не так плохо. Эта библиотека спроектирована так, что-бы её можно было легко испоьзовать в модульных тестах.
Представим, что у нас есть два класса, клиент и сервер, оба используют boost::asio для асинхронного IO. Для того, что-бы написать для них тест, нам нужно создать два io_service-a, так-как в они будут работать независимо. Далее, мы можем вызывать различные функции, которые начинают асинхронные операции, например запись данных в сокет, или ожидание подключения клиента. Но, вместо того, что-бы вызывать метод io_service::run, мы можем вызвать метод io_service::run_one, который выполняет обработчик только одного события. Благодаря этому, асинхронный код можно превратить в линейный и протестировать таким образом логику наших классов.
Подписаться на:
Комментарии к сообщению (Atom)
5 комментариев:
Это я удачно зашел. Может книгу все же писать начнешь? ;)
Кстати сейчас встал вопрос ребром - думаю начать поднимать boost но ряд товарищей настаивают на ace. Ты можешь что нибудь сказать по этому вопросу?
ACE я не использовал, когда я делал свой выбор, для меня решающим фактором оказалась простота Asio, по сравнению с ACE. Начать очень просто, особенно если есть опыт работы с библиотекой boost. С ACE framework можно делать более продвинутые вещи, к примеру управлять скоростью работы producer-a в зависимости от скорости работы consumer-a. В Asio это нужно делать вручную.
выложи плиз код метода my_client::connected()... или ткни носом где в хелпе к boost.asio написано как узнать подключен клиент к серверу...
Покажи, плиз, код метода my_client::connected(). а то я никак в хелпе к boost.asio не могу найти как узнать подключен клиент к серверу или нет...
Покажи, плиз, код метода my_client::connected(). а то я никак в хелпе к boost.asio не могу найти как узнать подключен клиент к серверу или нет...
Отправить комментарий