dns_server_unittest.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <gtest/gtest.h>
  16. #include <asio.hpp>
  17. #include <asiolink/io_endpoint.h>
  18. #include <asiolink/io_error.h>
  19. #include <asiodns/udp_server.h>
  20. #include <asiodns/sync_udp_server.h>
  21. #include <asiodns/tcp_server.h>
  22. #include <asiodns/dns_answer.h>
  23. #include <asiodns/dns_lookup.h>
  24. #include <string>
  25. #include <cstring>
  26. #include <cerrno>
  27. #include <csignal>
  28. #include <unistd.h> //for alarm
  29. #include <boost/shared_ptr.hpp>
  30. #include <boost/bind.hpp>
  31. #include <boost/function.hpp>
  32. #include <sys/types.h>
  33. #include <sys/socket.h>
  34. /// The following tests focus on stop interface for udp and
  35. /// tcp server, there are lots of things can be shared to test
  36. /// both tcp and udp server, so they are in the same unittest
  37. /// The general work flow for dns server, is that wait for user
  38. /// query, once get one query, we will check the data is valid or
  39. /// not, if it passed, we will try to loop up the question, then
  40. /// compose the answer and finally send it back to user. The server
  41. /// may be stopped at any point during this porcess, so the test strategy
  42. /// is that we define 5 stop point and stop the server at these
  43. /// 5 points, to check whether stop is successful
  44. /// The 5 test points are :
  45. /// Before the server start to run
  46. /// After we get the query and check whether it's valid
  47. /// After we lookup the query
  48. /// After we compose the answer
  49. /// After user gets the final result.
  50. /// The standard about whether we stop the server successfully or not
  51. /// is based on the fact that if the server is still running, the io
  52. /// service won't quit since it will wait for some asynchronized event for
  53. /// server. So if the io service block function run returns we assume
  54. /// that the server is stopped. To avoid stop interface failure which
  55. /// will block followed tests, using alarm signal to stop the blocking
  56. /// io service
  57. ///
  58. /// The whole test context including one server and one client, and
  59. /// five stop checkpoints, we call them ServerStopper exclude the first
  60. /// stop point. Once the unittest fired, the client will send message
  61. /// to server, and the stopper may stop the server at the checkpoint, then
  62. /// we check the client get feedback or not. Since there is no DNS logic
  63. /// involved so the message sending between client and server is plain text
  64. /// And the valid checker, question lookup and answer composition are dummy.
  65. using namespace isc::asiolink;
  66. using namespace isc::asiodns;
  67. using namespace asio;
  68. namespace {
  69. const char* const server_ip = "::1";
  70. const int server_port = 5553;
  71. const char* const server_port_str = "5553";
  72. //message client send to udp server, which isn't dns package
  73. //just for simple testing
  74. const char* const query_message = "BIND10 is awesome";
  75. // \brief provide capacity to derived class the ability
  76. // to stop DNSServer at certain point
  77. class ServerStopper {
  78. public:
  79. ServerStopper() : server_to_stop_(NULL) {}
  80. virtual ~ServerStopper(){}
  81. void setServerToStop(DNSServer& server) {
  82. server_to_stop_ = &server;
  83. }
  84. void stopServer() const {
  85. if (server_to_stop_) {
  86. server_to_stop_->stop();
  87. }
  88. }
  89. private:
  90. DNSServer* server_to_stop_;
  91. };
  92. // \brief no lookup logic at all,just provide a checkpoint to stop the server
  93. class DummyLookup : public DNSLookup, public ServerStopper {
  94. public:
  95. DummyLookup() :
  96. allow_resume_(true)
  97. { }
  98. virtual void operator()(const IOMessage& io_message,
  99. isc::dns::MessagePtr message,
  100. isc::dns::MessagePtr answer_message,
  101. isc::util::OutputBufferPtr buffer,
  102. DNSServer* server) const {
  103. stopServer();
  104. if (allow_resume_) {
  105. server->resume(true);
  106. }
  107. }
  108. // If you want it not to call resume, set this to false
  109. bool allow_resume_;
  110. };
  111. // \brief copy the data received from user to the answer part
  112. // provide checkpoint to stop server
  113. class SimpleAnswer : public DNSAnswer, public ServerStopper {
  114. public:
  115. void operator()(const IOMessage& message,
  116. isc::dns::MessagePtr query_message,
  117. isc::dns::MessagePtr answer_message,
  118. isc::util::OutputBufferPtr buffer) const
  119. {
  120. //copy what we get from user
  121. buffer->writeData(message.getData(), message.getDataSize());
  122. stopServer();
  123. }
  124. };
  125. /// \brief Mixture of DummyLookup and SimpleAnswer: build the answer in the
  126. /// lookup callback. Used with SyncUDPServer.
  127. class SyncDummyLookup : public DummyLookup {
  128. public:
  129. virtual void operator()(const IOMessage& io_message,
  130. isc::dns::MessagePtr message,
  131. isc::dns::MessagePtr answer_message,
  132. isc::util::OutputBufferPtr buffer,
  133. DNSServer* server) const
  134. {
  135. buffer->writeData(io_message.getData(), io_message.getDataSize());
  136. stopServer();
  137. if (allow_resume_) {
  138. server->resume(true);
  139. }
  140. }
  141. };
  142. // \brief simple client, send one string to server and wait for response
  143. // in case, server stopped and client can't get response, there is a timer wait
  144. // for specified seconds (the value is just a estimate since server process logic is quite
  145. // simple, and all the intercommunication is local) then cancel the waiting.
  146. class SimpleClient : public ServerStopper {
  147. public:
  148. static const size_t MAX_DATA_LEN = 256;
  149. SimpleClient(asio::io_service& service,
  150. unsigned int wait_server_time_out)
  151. {
  152. wait_for_response_timer_.reset(new deadline_timer(service));
  153. received_data_ = new char[MAX_DATA_LEN];
  154. received_data_len_ = 0;
  155. wait_server_time_out_ = wait_server_time_out;
  156. }
  157. virtual ~SimpleClient() {
  158. delete [] received_data_;
  159. }
  160. void setGetFeedbackCallback(boost::function<void()>& func) {
  161. get_response_call_back_ = func;
  162. }
  163. virtual void sendDataThenWaitForFeedback(const std::string& data) = 0;
  164. virtual std::string getReceivedData() const = 0;
  165. void startTimer() {
  166. wait_for_response_timer_->cancel();
  167. wait_for_response_timer_->
  168. expires_from_now(boost::posix_time::
  169. seconds(wait_server_time_out_));
  170. wait_for_response_timer_->
  171. async_wait(boost::bind(&SimpleClient::stopWaitingforResponse,
  172. this));
  173. }
  174. void cancelTimer() { wait_for_response_timer_->cancel(); }
  175. void getResponseCallBack(const asio::error_code& error, size_t
  176. received_bytes)
  177. {
  178. cancelTimer();
  179. if (!error)
  180. received_data_len_ = received_bytes;
  181. if (!get_response_call_back_.empty()) {
  182. get_response_call_back_();
  183. }
  184. stopServer();
  185. }
  186. protected:
  187. virtual void stopWaitingforResponse() = 0;
  188. boost::shared_ptr<deadline_timer> wait_for_response_timer_;
  189. char* received_data_;
  190. size_t received_data_len_;
  191. boost::function<void()> get_response_call_back_;
  192. unsigned int wait_server_time_out_;
  193. };
  194. class UDPClient : public SimpleClient {
  195. public:
  196. //After 1 second without feedback client will stop wait
  197. static const unsigned int SERVER_TIME_OUT = 1;
  198. UDPClient(asio::io_service& service, const ip::udp::endpoint& server) :
  199. SimpleClient(service, SERVER_TIME_OUT)
  200. {
  201. server_ = server;
  202. socket_.reset(new ip::udp::socket(service));
  203. socket_->open(ip::udp::v6());
  204. }
  205. void sendDataThenWaitForFeedback(const std::string& data) {
  206. received_data_len_ = 0;
  207. socket_->send_to(buffer(data.c_str(), data.size() + 1), server_);
  208. socket_->async_receive_from(buffer(received_data_, MAX_DATA_LEN),
  209. received_from_,
  210. boost::bind(&SimpleClient::
  211. getResponseCallBack, this, _1,
  212. _2));
  213. startTimer();
  214. }
  215. virtual std::string getReceivedData() const {
  216. return (received_data_len_ == 0 ? std::string("") :
  217. std::string(received_data_));
  218. }
  219. private:
  220. void stopWaitingforResponse() {
  221. socket_->close();
  222. }
  223. boost::shared_ptr<ip::udp::socket> socket_;
  224. ip::udp::endpoint server_;
  225. ip::udp::endpoint received_from_;
  226. };
  227. class TCPClient : public SimpleClient {
  228. public:
  229. // after 2 seconds without feedback client will stop wait,
  230. // this includes connect, send message and recevice message
  231. static const unsigned int SERVER_TIME_OUT = 2;
  232. TCPClient(asio::io_service& service, const ip::tcp::endpoint& server)
  233. : SimpleClient(service, SERVER_TIME_OUT),
  234. send_data_delay_(0), send_data_len_delay_(0)
  235. {
  236. server_ = server;
  237. socket_.reset(new ip::tcp::socket(service));
  238. socket_->open(ip::tcp::v6());
  239. }
  240. virtual void sendDataThenWaitForFeedback(const std::string &data) {
  241. received_data_len_ = 0;
  242. data_to_send_ = data;
  243. data_to_send_len_ = data.size() + 1;
  244. socket_->async_connect(server_, boost::bind(&TCPClient::connectHandler,
  245. this, _1));
  246. startTimer();
  247. }
  248. virtual std::string getReceivedData() const {
  249. return (received_data_len_ == 0 ? std::string("") :
  250. std::string(received_data_ + 2));
  251. }
  252. /// Set the delay before the data len is sent (in seconds)
  253. /// If this is non-zero, the actual data is never sent
  254. /// (it is used to test timeout, in which case the connection
  255. /// should have been closed by the other side anyway)
  256. void setSendDataLenDelay(size_t send_data_len_delay) {
  257. send_data_len_delay_ = send_data_len_delay;
  258. }
  259. /// Set the delay before the packet data itself is sent
  260. /// (in seconds)
  261. void setSendDataDelay(size_t send_data_delay) {
  262. send_data_delay_ = send_data_delay;
  263. }
  264. private:
  265. void stopWaitingforResponse() {
  266. socket_->close();
  267. }
  268. void connectHandler(const asio::error_code& error) {
  269. if (!error) {
  270. data_to_send_len_ = htons(data_to_send_len_);
  271. sleep(send_data_len_delay_);
  272. socket_->async_send(buffer(&data_to_send_len_, 2),
  273. boost::bind(&TCPClient::sendMessageBodyHandler,
  274. this, _1, _2));
  275. }
  276. }
  277. void sendMessageBodyHandler(const asio::error_code& error,
  278. size_t send_bytes)
  279. {
  280. if (!error && send_bytes == 2 && send_data_len_delay_ == 0) {
  281. sleep(send_data_delay_);
  282. socket_->async_send(buffer(data_to_send_.c_str(),
  283. data_to_send_.size() + 1),
  284. boost::bind(&TCPClient::finishSendHandler, this, _1, _2));
  285. }
  286. }
  287. void finishSendHandler(const asio::error_code& error, size_t send_bytes) {
  288. if (!error && send_bytes == data_to_send_.size() + 1) {
  289. socket_->async_receive(buffer(received_data_, MAX_DATA_LEN),
  290. boost::bind(&SimpleClient::getResponseCallBack, this, _1,
  291. _2));
  292. }
  293. }
  294. boost::shared_ptr<ip::tcp::socket> socket_;
  295. ip::tcp::endpoint server_;
  296. std::string data_to_send_;
  297. uint16_t data_to_send_len_;
  298. size_t send_data_delay_;
  299. size_t send_data_len_delay_;
  300. };
  301. // \brief provide the context which including two clients and
  302. // two servers, UDP client will only communicate with UDP server, same for TCP
  303. // client
  304. //
  305. // This is only the active part of the test. We run the test case four times, once
  306. // for each type of initialization (once when giving it the address and port,
  307. // once when giving the file descriptor) multiplied by once for each type of UDP
  308. // server (UDPServer and SyncUDPServer), to ensure it works exactly the same.
  309. template<class UDPServerClass>
  310. class DNSServerTestBase : public::testing::Test {
  311. protected:
  312. DNSServerTestBase() :
  313. server_address_(ip::address::from_string(server_ip)),
  314. lookup_(new DummyLookup()),
  315. sync_lookup_(new SyncDummyLookup()),
  316. answer_(new SimpleAnswer()),
  317. udp_client_(new UDPClient(service,
  318. ip::udp::endpoint(server_address_,
  319. server_port))),
  320. tcp_client_(new TCPClient(service,
  321. ip::tcp::endpoint(server_address_,
  322. server_port)))
  323. {
  324. current_service = &service;
  325. }
  326. ~ DNSServerTestBase() {
  327. if (udp_server_) {
  328. udp_server_->stop();
  329. }
  330. if (tcp_server_) {
  331. tcp_server_->stop();
  332. }
  333. delete lookup_;
  334. delete sync_lookup_;
  335. delete answer_;
  336. delete udp_client_;
  337. delete tcp_client_;
  338. // No delete here. The service is not allocated by new, but as our
  339. // member. This only references it, so just cleaning the pointer.
  340. current_service = NULL;
  341. }
  342. void testStopServerByStopper(DNSServer& server, SimpleClient* client,
  343. ServerStopper* stopper)
  344. {
  345. static const unsigned int IO_SERVICE_TIME_OUT = 5;
  346. io_service_is_time_out = false;
  347. stopper->setServerToStop(server);
  348. server();
  349. client->sendDataThenWaitForFeedback(query_message);
  350. // Since thread hasn't been introduced into the tool box, using
  351. // signal to make sure run function will eventually return even
  352. // server stop failed
  353. void (*prev_handler)(int) =
  354. std::signal(SIGALRM, DNSServerTestBase::stopIOService);
  355. current_service = &service;
  356. alarm(IO_SERVICE_TIME_OUT);
  357. service.run();
  358. service.reset();
  359. //cancel scheduled alarm
  360. alarm(0);
  361. std::signal(SIGALRM, prev_handler);
  362. }
  363. static void stopIOService(int _no_use_parameter) {
  364. io_service_is_time_out = true;
  365. if (current_service != NULL) {
  366. current_service->stop();
  367. }
  368. }
  369. bool serverStopSucceed() const {
  370. return (!io_service_is_time_out);
  371. }
  372. asio::io_service service;
  373. const ip::address server_address_;
  374. DummyLookup* lookup_; // we need to replace it in some cases
  375. SyncDummyLookup* const sync_lookup_;
  376. SimpleAnswer* const answer_;
  377. UDPClient* const udp_client_;
  378. TCPClient* const tcp_client_;
  379. boost::shared_ptr<UDPServerClass> udp_server_;
  380. boost::shared_ptr<TCPServer> tcp_server_;
  381. // To access them in signal handle function, the following
  382. // variables have to be static.
  383. static asio::io_service* current_service;
  384. static bool io_service_is_time_out;
  385. };
  386. // Initialization (by the file descriptor)
  387. template<class UDPServerClass>
  388. class FdInit : public DNSServerTestBase<UDPServerClass> {
  389. private:
  390. // Opens the file descriptor for us
  391. // It uses the low-level C api, as it seems to be the easiest way to get
  392. // a raw file descriptor. It also is what the socket creator does and this
  393. // API is aimed to it.
  394. int getFd(int type) {
  395. struct addrinfo hints;
  396. memset(&hints, 0, sizeof(hints));
  397. hints.ai_family = AF_UNSPEC;
  398. hints.ai_socktype = type;
  399. hints.ai_protocol = (type == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP;
  400. hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST;
  401. struct addrinfo* res;
  402. const int error = getaddrinfo(server_ip, server_port_str,
  403. &hints, &res);
  404. if (error != 0) {
  405. isc_throw(IOError, "getaddrinfo failed: " << gai_strerror(error));
  406. }
  407. int sock;
  408. const int on(1);
  409. // Go as far as you can and stop on failure
  410. // Create the socket
  411. // set the options
  412. // and bind it
  413. const bool failed((sock = socket(res->ai_family, res->ai_socktype,
  414. res->ai_protocol)) == -1 ||
  415. setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
  416. sizeof(on)) == -1 ||
  417. bind(sock, res->ai_addr, res->ai_addrlen) == -1);
  418. // No matter if it succeeded or not, free the address info
  419. freeaddrinfo(res);
  420. if (failed) {
  421. if (sock != -1) {
  422. close(sock);
  423. }
  424. return (-1);
  425. } else {
  426. return (sock);
  427. }
  428. }
  429. protected:
  430. // Using SetUp here so we can ASSERT_*
  431. void SetUp() {
  432. const int fd_udp(getFd(SOCK_DGRAM));
  433. ASSERT_NE(-1, fd_udp) << strerror(errno);
  434. this->udp_server_ = createServer(fd_udp, AF_INET6);
  435. const int fd_tcp(getFd(SOCK_STREAM));
  436. ASSERT_NE(-1, fd_tcp) << strerror(errno);
  437. this->tcp_server_ =
  438. boost::shared_ptr<TCPServer>(new TCPServer(
  439. this->service, fd_tcp, AF_INET6,
  440. this->lookup_,
  441. this->answer_));
  442. }
  443. // A helper factory of the tested UDP server class: allow customization
  444. // by template specialization.
  445. boost::shared_ptr<UDPServerClass> createServer(int fd, int af) {
  446. return (boost::shared_ptr<UDPServerClass>(
  447. new UDPServerClass(this->service, fd, af,
  448. this->lookup_,
  449. this->answer_)));
  450. }
  451. };
  452. // Specialization for SyncUDPServer. It needs to use SyncDummyLookup.
  453. template<>
  454. boost::shared_ptr<SyncUDPServer>
  455. FdInit<SyncUDPServer>::createServer(int fd, int af) {
  456. delete this->lookup_;
  457. this->lookup_ = new SyncDummyLookup;
  458. return (SyncUDPServer::create(this->service, fd, af, this->lookup_));
  459. }
  460. // This makes it the template as gtest wants it.
  461. template<class Parent>
  462. class DNSServerTest : public Parent { };
  463. typedef ::testing::Types<FdInit<UDPServer>, FdInit<SyncUDPServer> >
  464. ServerTypes;
  465. TYPED_TEST_CASE(DNSServerTest, ServerTypes);
  466. // Some tests work only for SyncUDPServer, some others work only for
  467. // (non Sync)UDPServer. We specialize these tests.
  468. typedef FdInit<UDPServer> AsyncServerTest;
  469. typedef FdInit<SyncUDPServer> SyncServerTest;
  470. typedef ::testing::Types<UDPServer, SyncUDPServer> UDPServerTypes;
  471. TYPED_TEST_CASE(DNSServerTestBase, UDPServerTypes);
  472. template<class UDPServerClass>
  473. bool DNSServerTestBase<UDPServerClass>::io_service_is_time_out = false;
  474. template<class UDPServerClass>
  475. asio::io_service* DNSServerTestBase<UDPServerClass>::current_service(NULL);
  476. // Test whether server stopped successfully after client get response
  477. // client will send query and start to wait for response, once client
  478. // get response, UDP server will be stopped, the io service won't quit
  479. // if udp server doesn't stop successfully.
  480. TYPED_TEST(DNSServerTest, stopUDPServerAfterOneQuery) {
  481. this->testStopServerByStopper(*this->udp_server_, this->udp_client_,
  482. this->udp_client_);
  483. EXPECT_EQ(query_message, this->udp_client_->getReceivedData());
  484. EXPECT_TRUE(this->serverStopSucceed());
  485. }
  486. // Test whether udp server stopped successfully before server start to serve
  487. TYPED_TEST(DNSServerTest, stopUDPServerBeforeItStartServing) {
  488. this->udp_server_->stop();
  489. this->testStopServerByStopper(*this->udp_server_, this->udp_client_,
  490. this->udp_client_);
  491. EXPECT_EQ(std::string(""), this->udp_client_->getReceivedData());
  492. EXPECT_TRUE(this->serverStopSucceed());
  493. }
  494. // Test whether udp server stopped successfully during query lookup
  495. TYPED_TEST(DNSServerTest, stopUDPServerDuringQueryLookup) {
  496. this->testStopServerByStopper(*this->udp_server_, this->udp_client_,
  497. this->lookup_);
  498. EXPECT_EQ(std::string(""), this->udp_client_->getReceivedData());
  499. EXPECT_TRUE(this->serverStopSucceed());
  500. }
  501. // Test whether UDP server stopped successfully during composing answer.
  502. // Only works for (non-sync) server because SyncUDPServer doesn't use answer
  503. // callback.
  504. TEST_F(AsyncServerTest, stopUDPServerDuringPrepareAnswer) {
  505. testStopServerByStopper(*udp_server_, udp_client_, answer_);
  506. EXPECT_EQ(std::string(""), udp_client_->getReceivedData());
  507. EXPECT_TRUE(serverStopSucceed());
  508. }
  509. void
  510. stopServerManyTimes(DNSServer *server, unsigned int times) {
  511. for (unsigned int i = 0; i < times; ++i) {
  512. server->stop();
  513. }
  514. }
  515. // Test whether udp server stop interface can be invoked several times without
  516. // throw any exception
  517. TYPED_TEST(DNSServerTest, stopUDPServerMoreThanOnce) {
  518. ASSERT_NO_THROW({
  519. boost::function<void()> stop_server_3_times
  520. = boost::bind(stopServerManyTimes, this->udp_server_.get(), 3);
  521. this->udp_client_->setGetFeedbackCallback(stop_server_3_times);
  522. this->testStopServerByStopper(*this->udp_server_,
  523. this->udp_client_, this->udp_client_);
  524. EXPECT_EQ(query_message, this->udp_client_->getReceivedData());
  525. });
  526. EXPECT_TRUE(this->serverStopSucceed());
  527. }
  528. TYPED_TEST(DNSServerTest, stopTCPServerAfterOneQuery) {
  529. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  530. this->tcp_client_);
  531. EXPECT_EQ(query_message, this->tcp_client_->getReceivedData());
  532. EXPECT_TRUE(this->serverStopSucceed());
  533. }
  534. TYPED_TEST(DNSServerTest, TCPTimeoutOnLen) {
  535. this->tcp_server_->setTCPRecvTimeout(100);
  536. this->tcp_client_->setSendDataLenDelay(2);
  537. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  538. this->tcp_client_);
  539. EXPECT_EQ("", this->tcp_client_->getReceivedData());
  540. EXPECT_FALSE(this->serverStopSucceed());
  541. }
  542. TYPED_TEST(DNSServerTest, TCPTimeout) {
  543. // set delay higher than timeout
  544. this->tcp_server_->setTCPRecvTimeout(100);
  545. this->tcp_client_->setSendDataDelay(2);
  546. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  547. this->tcp_client_);
  548. EXPECT_EQ("", this->tcp_client_->getReceivedData());
  549. EXPECT_TRUE(this->serverStopSucceed());
  550. }
  551. TYPED_TEST(DNSServerTest, TCPNoTimeout) {
  552. // set delay lower than timeout
  553. this->tcp_server_->setTCPRecvTimeout(3000);
  554. this->tcp_client_->setSendDataDelay(1);
  555. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  556. this->tcp_client_);
  557. EXPECT_EQ("BIND10 is awesome", this->tcp_client_->getReceivedData());
  558. EXPECT_TRUE(this->serverStopSucceed());
  559. }
  560. // Test whether tcp server stopped successfully before server start to serve
  561. TYPED_TEST(DNSServerTest, stopTCPServerBeforeItStartServing) {
  562. this->tcp_server_->stop();
  563. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  564. this->tcp_client_);
  565. EXPECT_EQ(std::string(""), this->tcp_client_->getReceivedData());
  566. EXPECT_TRUE(this->serverStopSucceed());
  567. }
  568. // Test whether tcp server stopped successfully during query lookup
  569. TYPED_TEST(DNSServerTest, stopTCPServerDuringQueryLookup) {
  570. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  571. this->lookup_);
  572. EXPECT_EQ(std::string(""), this->tcp_client_->getReceivedData());
  573. EXPECT_TRUE(this->serverStopSucceed());
  574. }
  575. // Test whether tcp server stopped successfully during composing answer
  576. TYPED_TEST(DNSServerTest, stopTCPServerDuringPrepareAnswer) {
  577. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  578. this->answer_);
  579. EXPECT_EQ(std::string(""), this->tcp_client_->getReceivedData());
  580. EXPECT_TRUE(this->serverStopSucceed());
  581. }
  582. // Test whether tcp server stop interface can be invoked several times without
  583. // throw any exception
  584. TYPED_TEST(DNSServerTest, stopTCPServeMoreThanOnce) {
  585. ASSERT_NO_THROW({
  586. boost::function<void()> stop_server_3_times
  587. = boost::bind(stopServerManyTimes, this->tcp_server_.get(), 3);
  588. this->tcp_client_->setGetFeedbackCallback(stop_server_3_times);
  589. this->testStopServerByStopper(*this->tcp_server_, this->tcp_client_,
  590. this->tcp_client_);
  591. EXPECT_EQ(query_message, this->tcp_client_->getReceivedData());
  592. });
  593. EXPECT_TRUE(this->serverStopSucceed());
  594. }
  595. // It raises an exception when invalid address family is passed
  596. // The parameter here doesn't mean anything
  597. TYPED_TEST(DNSServerTestBase, invalidFamily) {
  598. // We abuse DNSServerTestBase for this test, as we don't need the
  599. // initialization.
  600. EXPECT_THROW(TCPServer(this->service, 0, AF_UNIX,
  601. this->lookup_, this->answer_),
  602. isc::InvalidParameter);
  603. }
  604. TYPED_TEST(DNSServerTest, invalidFamilyUDP) {
  605. EXPECT_THROW(this->createServer(0, AF_UNIX), isc::InvalidParameter);
  606. }
  607. // It raises an exception when invalid address family is passed
  608. TYPED_TEST(DNSServerTestBase, invalidTCPFD) {
  609. // We abuse DNSServerTestBase for this test, as we don't need the
  610. // initialization.
  611. /*
  612. FIXME: The UDP server doesn't fail reliably with an invalid FD.
  613. We need to find a way to trigger it reliably (it seems epoll
  614. asio backend does fail as it tries to insert it right away, but
  615. not the others, maybe we could make it run this at last on epoll-based
  616. systems).
  617. EXPECT_THROW(UDPServer(service, -1, AF_INET, lookup_,
  618. answer_), isc::asiolink::IOError);
  619. */
  620. EXPECT_THROW(TCPServer(this->service, -1, AF_INET,
  621. this->lookup_, this->answer_),
  622. isc::asiolink::IOError);
  623. }
  624. TYPED_TEST(DNSServerTest, DISABLED_invalidUDPFD) {
  625. /*
  626. FIXME: The UDP server doesn't fail reliably with an invalid FD.
  627. We need to find a way to trigger it reliably (it seems epoll
  628. asio backend does fail as it tries to insert it right away, but
  629. not the others, maybe we could make it run this at least on epoll-based
  630. systems).
  631. */
  632. EXPECT_THROW(this->createServer(-1, AF_INET), isc::asiolink::IOError);
  633. }
  634. // Check it rejects some of the unsupported operations
  635. TEST_F(SyncServerTest, unsupportedOps) {
  636. EXPECT_THROW(udp_server_->clone(), isc::Unexpected);
  637. EXPECT_THROW(udp_server_->asyncLookup(), isc::Unexpected);
  638. }
  639. // Check it rejects forgotten resume (eg. insists that it is synchronous)
  640. TEST_F(SyncServerTest, mustResume) {
  641. lookup_->allow_resume_ = false;
  642. ASSERT_THROW(testStopServerByStopper(*udp_server_, udp_client_, lookup_),
  643. isc::Unexpected);
  644. }
  645. // SyncUDPServer doesn't allow NULL lookup callback.
  646. TEST_F(SyncServerTest, nullLookupCallback) {
  647. EXPECT_THROW(SyncUDPServer::create(service, 0, AF_INET, NULL),
  648. isc::InvalidParameter);
  649. }
  650. TEST_F(SyncServerTest, resetUDPServerBeforeEvent) {
  651. // Reset the UDP server object after starting and before it would get
  652. // an event from io_service (in this case abort event). The following
  653. // sequence confirms it's shut down immediately, and without any
  654. // disruption.
  655. // Since we'll stop the server run() should immediately return, and
  656. // it's very unlikely to cause hangup. But we'll make very sure it
  657. // doesn't happen.
  658. const unsigned int IO_SERVICE_TIME_OUT = 5;
  659. (*udp_server_)();
  660. udp_server_->stop();
  661. udp_server_.reset();
  662. void (*prev_handler)(int) = std::signal(SIGALRM, stopIOService);
  663. current_service = &service;
  664. alarm(IO_SERVICE_TIME_OUT);
  665. service.run();
  666. alarm(0);
  667. std::signal(SIGALRM, prev_handler);
  668. EXPECT_FALSE(io_service_is_time_out);
  669. }
  670. }