Commit de6b350f authored by Michal Vaner's avatar Michal Vaner
Browse files

Some tests for the UDPQuery

It does not link, unresolved UDPQuery.stop.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/vorner-recursor-timeouts@3398 e5f2f494-b856-4b98-b285-d166d9295462
parent 3c7604d4
......@@ -231,10 +231,17 @@ namespace {
// This is just temporary so the interface change does not propagate too far
struct ServerNotify : public UDPQuery::Callback {
DNSServer *server;
virtual void operator()(UDPQuery::Result result) {
server->resume(result == UDPQuery::SUCCESS);
}
ServerNotify(DNSServer *server) :
server_(server)
{ }
virtual void operator()(UDPQuery::Result result) {
server_->resume(result == UDPQuery::SUCCESS);
delete this;
}
private:
// FIXME This is said it does problems when it is shared pointer, as
// it is destroyed too soon. But who deletes it now?
DNSServer *server_;
};
}
......@@ -249,11 +256,8 @@ RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
// UDP and then fall back to TCP on failure, but for the moment
// we're only going to handle UDP.
asio::io_service& io = dns_service_.get_io_service();
boost::shared_ptr<ServerNotify> callback(new ServerNotify);
// FIXME This is said it does problems when it is shared pointer, as
// it is destroyed too soon. But who deletes it now?
callback->server = server->clone();
UDPQuery q(io, question, ns_addr_, port_, buffer, callback);
UDPQuery q(io, question, ns_addr_, port_, buffer,
new ServerNotify(server->clone()));
io.post(q);
}
......
......@@ -198,13 +198,21 @@ public:
/// This will be called when the UDPQuery is completed
virtual void operator()(Result result) = 0;
};
/**
* \short Constructor.
*
* It creates the query.
* @param callback will be called when we terminate. It is your task to
* delete it if allocated on heap.
* @param timeout in ms.
*/
explicit UDPQuery(asio::io_service& io_service,
const isc::dns::Question& q,
const IOAddress& addr, uint16_t port,
isc::dns::OutputBufferPtr buffer,
boost::shared_ptr<Callback> callback, int timeout = -1);
Callback *callback, int timeout = -1);
void operator()(asio::error_code ec = asio::error_code(),
size_t length = 0);
size_t length = 0);
/// Terminate the query.
void stop(Result reason = STOPPED);
private:
......@@ -239,7 +247,7 @@ private:
boost::shared_array<char> data_;
// This will be called when we are done.
boost::shared_ptr<Callback> callback_;
Callback *callback_;
};
}
......
......@@ -17,6 +17,7 @@ TESTS += run_unittests
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
run_unittests_SOURCES += asiolink_unittest.cc
run_unittests_SOURCES += udpdns_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
......
// Copyright (C) 2010 CZ.NIC
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <gtest/gtest.h>
#include <asio.hpp>
#include <boost/bind.hpp>
#include <cstdlib>
#include <dns/question.h>
#include <asiolink/internal/udpdns.h>
using namespace asio;
using namespace isc::dns;
using asio::ip::udp;
namespace {
const asio::ip::address TEST_HOST(asio::ip::address::from_string("127.0.0.1"));
const uint16_t TEST_PORT(5301);
// FIXME Shouldn't we send something that is real message?
const char TEST_DATA[] = "TEST DATA";
class UDPQuery : public ::testing::Test, public asiolink::UDPQuery::Callback {
public:
asiolink::UDPQuery::Result expected;
bool run;
io_service service;
Question question;
// To keep a reference so noone calls delete this;
OutputBufferPtr buffer;
asiolink::UDPQuery query;
UDPQuery() :
run(false),
question(Name("example.net"), RRClass::IN(), RRType::A()),
buffer(new OutputBuffer(512)),
query(service, question, asiolink::IOAddress(TEST_HOST), TEST_PORT,
buffer, this, 100)
{ }
void operator()(asiolink::UDPQuery::Result result) {
EXPECT_EQ(expected, result);
run = true;
}
void respond(udp::endpoint& remote, udp::socket* socket) {
// Some data came, just send something back.
socket->send_to(asio::buffer(TEST_DATA, sizeof TEST_DATA), remote);
socket->close();
}
};
TEST_F(UDPQuery, stop) {
expected = asiolink::UDPQuery::STOPPED;
service.post(query);
// Make sure stop is called after executing () of the query
// Why doesn't boost::bind support default parameters?
service.post(boost::bind(&asiolink::UDPQuery::stop, query,
asiolink::UDPQuery::STOPPED));
service.run();
EXPECT_TRUE(run);
}
TEST_F(UDPQuery, prematureStop) {
expected = asiolink::UDPQuery::STOPPED;
// Stop before it is started
query.stop();
service.post(query);
service.run();
EXPECT_TRUE(run);
}
TEST_F(UDPQuery, timeout) {
expected = asiolink::UDPQuery::TIME_OUT;
service.post(query);
service.run();
EXPECT_TRUE(run);
}
TEST_F(UDPQuery, receive) {
expected = asiolink::UDPQuery::SUCCESS;
udp::socket socket(service, udp::v4());
socket.set_option(socket_base::reuse_address(true));
socket.bind(udp::endpoint(TEST_HOST, TEST_PORT));
char inbuff[512];
udp::endpoint remote;
socket.async_receive_from(asio::buffer(inbuff, 512), remote, boost::bind(
&UDPQuery::respond, this, remote, &socket));
service.post(query);
service.run();
EXPECT_TRUE(run);
ASSERT_EQ(sizeof TEST_DATA, buffer->getLength());
EXPECT_EQ(0, memcmp(TEST_DATA, buffer->getData(), sizeof TEST_DATA));
}
}
......@@ -176,8 +176,7 @@ UDPServer::resume(const bool done) {
/// The constructor
UDPQuery::UDPQuery(io_service& io_service,
const Question& q, const IOAddress& addr, uint16_t port,
OutputBufferPtr buffer,
boost::shared_ptr<Callback> callback, int timeout) :
OutputBufferPtr buffer, Callback *callback, int timeout) :
question_(q), buffer_(buffer), callback_(callback)
{
udp proto = (addr.getFamily() == AF_INET) ? udp::v4() : udp::v6();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment