io_fetch_unittest.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  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 <algorithm>
  15. #include <cstdlib>
  16. #include <string>
  17. #include <iostream>
  18. #include <iomanip>
  19. #include <iterator>
  20. #include <vector>
  21. #include <gtest/gtest.h>
  22. #include <boost/bind.hpp>
  23. #include <boost/date_time/posix_time/posix_time_types.hpp>
  24. #include <asio.hpp>
  25. #include <util/buffer.h>
  26. #include <util/io_utilities.h>
  27. #include <dns/question.h>
  28. #include <dns/message.h>
  29. #include <dns/messagerenderer.h>
  30. #include <dns/opcode.h>
  31. #include <dns/name.h>
  32. #include <dns/rcode.h>
  33. #include <asiolink/io_address.h>
  34. #include <asiolink/io_endpoint.h>
  35. #include <asiolink/io_service.h>
  36. #include <asiodns/io_fetch.h>
  37. using namespace asio;
  38. using namespace isc::dns;
  39. using namespace isc::util;
  40. using namespace asio::ip;
  41. using namespace std;
  42. using namespace isc::asiolink;
  43. namespace isc {
  44. namespace asiodns {
  45. const asio::ip::address TEST_HOST(asio::ip::address::from_string("127.0.0.1"));
  46. const uint16_t TEST_PORT(5301);
  47. const int SEND_INTERVAL = 250; // Interval in ms between TCP sends
  48. const size_t MAX_SIZE = 64 * 1024; // Should be able to take 64kB
  49. // The tests are complex, so debug output has been left in (although disabled).
  50. // Set this to true to enable it.
  51. const bool DEBUG = false;
  52. /// \brief Test fixture for the asiolink::IOFetch.
  53. class IOFetchTest : public virtual ::testing::Test, public virtual IOFetch::Callback
  54. {
  55. public:
  56. IOService service_; ///< Service to run the query
  57. IOFetch::Result expected_; ///< Expected result of the callback
  58. bool run_; ///< Did the callback run already?
  59. Question question_; ///< What to ask
  60. OutputBufferPtr result_buff_; ///< Buffer to hold result of fetch
  61. OutputBufferPtr msgbuf_; ///< Buffer corresponding to known question
  62. IOFetch udp_fetch_; ///< For UDP query test
  63. IOFetch tcp_fetch_; ///< For TCP query test
  64. IOFetch::Protocol protocol_; ///< Protocol being tested
  65. size_t cumulative_; ///< Cumulative data received by "server".
  66. deadline_timer timer_; ///< Timer to measure timeouts
  67. // The next member is the buffer in which the "server" (implemented by the
  68. // response handler methods in this class) receives the question sent by the
  69. // fetch object.
  70. uint8_t receive_buffer_[MAX_SIZE]; ///< Server receive buffer
  71. OutputBufferPtr expected_buffer_; ///< Data we expect to receive
  72. vector<uint8_t> send_buffer_; ///< Server send buffer
  73. uint16_t send_cumulative_; ///< Data sent so far
  74. // Other data.
  75. string return_data_; ///< Data returned by server
  76. string test_data_; ///< Large string - here for convenience
  77. bool debug_; ///< true to enable debug output
  78. size_t tcp_send_size_; ///< Max size of TCP send
  79. uint8_t qid_0; ///< First octet of qid
  80. uint8_t qid_1; ///< Second octet of qid
  81. bool tcp_short_send_; ///< If set to true, we do not send
  82. /// all data in the tcp response
  83. /// \brief Constructor
  84. IOFetchTest() :
  85. service_(),
  86. expected_(IOFetch::NOTSET),
  87. run_(false),
  88. question_(Name("example.net"), RRClass::IN(), RRType::A()),
  89. result_buff_(new OutputBuffer(512)),
  90. msgbuf_(new OutputBuffer(512)),
  91. udp_fetch_(IOFetch::UDP, service_, question_, IOAddress(TEST_HOST),
  92. TEST_PORT, result_buff_, this, 100),
  93. tcp_fetch_(IOFetch::TCP, service_, question_, IOAddress(TEST_HOST),
  94. TEST_PORT, result_buff_, this, (16 * SEND_INTERVAL)),
  95. // Timeout interval chosen to ensure no timeout
  96. protocol_(IOFetch::TCP), // for initialization - will be changed
  97. cumulative_(0),
  98. timer_(service_.get_io_service()),
  99. receive_buffer_(),
  100. expected_buffer_(new OutputBuffer(512)),
  101. send_buffer_(),
  102. send_cumulative_(0),
  103. return_data_(""),
  104. test_data_(""),
  105. debug_(DEBUG),
  106. tcp_send_size_(0),
  107. qid_0(0),
  108. qid_1(0),
  109. tcp_short_send_(false)
  110. {
  111. // Construct the data buffer for question we expect to receive.
  112. Message msg(Message::RENDER);
  113. msg.setQid(0);
  114. msg.setOpcode(Opcode::QUERY());
  115. msg.setRcode(Rcode::NOERROR());
  116. msg.setHeaderFlag(Message::HEADERFLAG_RD);
  117. msg.addQuestion(question_);
  118. EDNSPtr msg_edns(new EDNS());
  119. msg_edns->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
  120. msg.setEDNS(msg_edns);
  121. MessageRenderer renderer(*msgbuf_);
  122. msg.toWire(renderer);
  123. MessageRenderer renderer2(*expected_buffer_);
  124. msg.toWire(renderer2);
  125. // Initialize the test data to be returned: tests will return a
  126. // substring of this data. (It's convenient to have this as a member of
  127. // the class.)
  128. //
  129. // We could initialize the data with a single character, but as an added
  130. // check we'll make ssre that it has some structure.
  131. test_data_.clear();
  132. test_data_.reserve(MAX_SIZE);
  133. while (test_data_.size() < MAX_SIZE) {
  134. test_data_ += "A message to be returned to the client that has "
  135. "some sort of structure.";
  136. }
  137. }
  138. /// \brief UDP Response handler (the "remote UDP DNS server")
  139. ///
  140. /// When IOFetch is sending data, this response handler emulates the remote
  141. /// DNS server. It checks that the data sent by the IOFetch object is what
  142. /// was expected to have been sent, then sends back a known buffer of data.
  143. ///
  144. /// \param remote Endpoint to which to send the answer
  145. /// \param socket Socket to use to send the answer
  146. /// \param ec ASIO error code, completion code of asynchronous I/O issued
  147. /// by the "server" to receive data.
  148. /// \param bad_qid If set to true, the QID in the response will be mangled
  149. /// \param second_send If set to true, (and bad_qid is too), after the
  150. /// mangled qid response has been sent, a second packet will be
  151. /// sent with the correct QID.
  152. /// \param length Amount of data received.
  153. void udpReceiveHandler(udp::endpoint* remote, udp::socket* socket,
  154. error_code ec = error_code(), size_t length = 0,
  155. bool bad_qid = false, bool second_send = false) {
  156. if (debug_) {
  157. cout << "udpReceiveHandler(): error = " << ec.value() <<
  158. ", length = " << length << endl;
  159. }
  160. // The QID in the incoming data is random so set it to 0 for the
  161. // data comparison check. (It is set to 0 in the buffer containing
  162. // the expected data.)
  163. qid_0 = receive_buffer_[0];
  164. qid_1 = receive_buffer_[1];
  165. receive_buffer_[0] = receive_buffer_[1] = 0;
  166. // Check that length of the received data and the expected data are
  167. // identical, then check that the data is identical as well.
  168. EXPECT_EQ(msgbuf_->getLength(), length);
  169. EXPECT_TRUE(equal(receive_buffer_, (receive_buffer_ + length - 1),
  170. static_cast<const uint8_t*>(msgbuf_->getData())));
  171. // Return a message back to the IOFetch object.
  172. if (!bad_qid) {
  173. expected_buffer_->writeUint8At(qid_0, 0);
  174. expected_buffer_->writeUint8At(qid_1, 1);
  175. } else {
  176. expected_buffer_->writeUint8At(qid_0 + 1, 0);
  177. expected_buffer_->writeUint8At(qid_1 + 1, 1);
  178. }
  179. socket->send_to(asio::buffer(expected_buffer_->getData(), length), *remote);
  180. if (bad_qid && second_send) {
  181. expected_buffer_->writeUint8At(qid_0, 0);
  182. expected_buffer_->writeUint8At(qid_1, 1);
  183. socket->send_to(asio::buffer(expected_buffer_->getData(),
  184. expected_buffer_->getLength()), *remote);
  185. }
  186. if (debug_) {
  187. cout << "udpReceiveHandler(): returned " << expected_buffer_->getLength() <<
  188. " bytes to the client" << endl;
  189. }
  190. }
  191. /// \brief Completion Handler for accepting TCP data
  192. ///
  193. /// Called when the remote system connects to the "server". It issues
  194. /// an asynchronous read on the socket to read data.
  195. ///
  196. /// \param socket Socket on which data will be received
  197. /// \param ec Boost error code, value should be zero.
  198. void tcpAcceptHandler(tcp::socket* socket, error_code ec = error_code())
  199. {
  200. if (debug_) {
  201. cout << "tcpAcceptHandler(): error = " << ec.value() << endl;
  202. }
  203. // Expect that the accept completed without a problem.
  204. EXPECT_EQ(0, ec.value());
  205. // Work out the maximum size of data we can send over it when we
  206. // respond, then subtract 1kB or so for safety.
  207. tcp::socket::send_buffer_size send_size;
  208. socket->get_option(send_size);
  209. if (send_size.value() < (2 * 1024)) {
  210. FAIL() << "TCP send size is less than 2kB";
  211. } else {
  212. tcp_send_size_ = send_size.value() - 1024;
  213. if (debug_) {
  214. cout << "tcpacceptHandler(): will use send size = " << tcp_send_size_ << endl;
  215. }
  216. }
  217. // Initiate a read on the socket.
  218. cumulative_ = 0;
  219. socket->async_receive(asio::buffer(receive_buffer_, sizeof(receive_buffer_)),
  220. boost::bind(&IOFetchTest::tcpReceiveHandler, this, socket, _1, _2));
  221. }
  222. /// \brief Completion handler for receiving TCP data
  223. ///
  224. /// When IOFetch is sending data, this response handler emulates the remote
  225. /// DNS server. It that all the data sent by the IOFetch object has been
  226. /// received, issuing another read if not. If the data is complete, it is
  227. /// compared to what is expected and a reply sent back to the IOFetch.
  228. ///
  229. /// \param socket Socket to use to send the answer
  230. /// \param ec ASIO error code, completion code of asynchronous I/O issued
  231. /// by the "server" to receive data.
  232. /// \param length Amount of data received.
  233. void tcpReceiveHandler(tcp::socket* socket, error_code ec = error_code(),
  234. size_t length = 0)
  235. {
  236. if (debug_) {
  237. cout << "tcpReceiveHandler(): error = " << ec.value() <<
  238. ", length = " << length << endl;
  239. }
  240. // Expect that the receive completed without a problem.
  241. EXPECT_EQ(0, ec.value());
  242. // If we haven't received all the data, issue another read.
  243. cumulative_ += length;
  244. bool complete = false;
  245. if (cumulative_ > 2) {
  246. uint16_t dns_length = readUint16(receive_buffer_);
  247. complete = ((dns_length + 2) == cumulative_);
  248. }
  249. if (!complete) {
  250. socket->async_receive(asio::buffer((receive_buffer_ + cumulative_),
  251. (sizeof(receive_buffer_) - cumulative_)),
  252. boost::bind(&IOFetchTest::tcpReceiveHandler, this, socket, _1, _2));
  253. return;
  254. }
  255. // Check that length of the DNS message received is that expected, then
  256. // compare buffers, zeroing the QID in the received buffer to match
  257. // that set in our expected question. Note that due to the length
  258. // field the QID in the received buffer is in the third and fourth
  259. // bytes.
  260. EXPECT_EQ(msgbuf_->getLength() + 2, cumulative_);
  261. qid_0 = receive_buffer_[2];
  262. qid_1 = receive_buffer_[3];
  263. receive_buffer_[2] = receive_buffer_[3] = 0;
  264. EXPECT_TRUE(equal((receive_buffer_ + 2), (receive_buffer_ + cumulative_ - 2),
  265. static_cast<const uint8_t*>(msgbuf_->getData())));
  266. // ... and return a message back. This has to be preceded by a two-byte
  267. // count field.
  268. send_buffer_.clear();
  269. send_buffer_.push_back(0);
  270. send_buffer_.push_back(0);
  271. writeUint16(return_data_.size(), &send_buffer_[0]);
  272. copy(return_data_.begin(), return_data_.end(), back_inserter(send_buffer_));
  273. if (return_data_.size() >= 2) {
  274. send_buffer_[2] = qid_0;
  275. send_buffer_[3] = qid_1;
  276. }
  277. // Send the data. This is done in multiple writes with a delay between
  278. // each to check that the reassembly of TCP packets from fragments works.
  279. send_cumulative_ = 0;
  280. tcpSendData(socket);
  281. }
  282. /// \brief Sent Data Over TCP
  283. ///
  284. /// Send the TCP data back to the IOFetch object. The data is sent in
  285. /// three chunks - two of 16 bytes and the remainder, with a 250ms gap
  286. /// between each. (Amounts of data smaller than one 32 bytes are sent in
  287. /// one or two packets.)
  288. ///
  289. /// \param socket Socket over which send should take place
  290. void tcpSendData(tcp::socket* socket) {
  291. if (debug_) {
  292. cout << "tcpSendData()" << endl;
  293. }
  294. // Decide what to send based on the cumulative count. At most we'll do
  295. // two chunks of 16 bytes (with a 250ms gap between) and then the
  296. // remainder.
  297. uint8_t* send_ptr = &send_buffer_[send_cumulative_];
  298. // Pointer to data to send
  299. size_t amount = 16; // Amount of data to send
  300. if (send_cumulative_ < (2 * amount)) {
  301. // First or second time through, send at most 16 bytes
  302. amount = min(amount, (send_buffer_.size() - send_cumulative_));
  303. } else {
  304. // For all subsequent times, send the remainder, maximised to
  305. // whatever we have chosen for the maximum send size.
  306. amount = min(tcp_send_size_,
  307. (send_buffer_.size() - send_cumulative_));
  308. }
  309. // This is for the short send test; reduce the actual amount of
  310. // data we send
  311. if (tcp_short_send_) {
  312. if (debug_) {
  313. cout << "tcpSendData(): sending incomplete data (" <<
  314. (amount - 1) << " of " << amount << " bytes)" <<
  315. endl;
  316. }
  317. --amount;
  318. } else {
  319. if (debug_) {
  320. cout << "tcpSendData(): sending " << amount << " bytes" << endl;
  321. }
  322. }
  323. // ... and send it. The amount sent is also passed as the first
  324. // argument of the send callback, as a check.
  325. socket->async_send(asio::buffer(send_ptr, amount),
  326. boost::bind(&IOFetchTest::tcpSendHandler, this,
  327. amount, socket, _1, _2));
  328. }
  329. /// \brief Completion Handler for Sending TCP data
  330. ///
  331. /// Called when the asynchronous send of data back to the IOFetch object
  332. /// by the TCP "server" in this class has completed. (This send has to
  333. /// be asynchronous because control needs to return to the caller in order
  334. /// for the IOService "run()" method to be called to run the handlers.)
  335. ///
  336. /// If not all the data has been sent, a short delay is instigated (during
  337. /// which control returns to the IOService). This should force the queued
  338. /// data to actually be sent and the IOFetch receive handler to be triggered.
  339. /// In this way, the ability of IOFetch to handle fragmented TCP packets
  340. /// should be checked.
  341. ///
  342. /// \param expected Number of bytes that were expected to have been sent.
  343. /// \param socket Socket over which the send took place. Only used to
  344. /// pass back to the send method.
  345. /// \param ec Boost error code, value should be zero.
  346. /// \param length Number of bytes sent.
  347. void tcpSendHandler(size_t expected, tcp::socket* socket,
  348. error_code ec = error_code(), size_t length = 0)
  349. {
  350. if (debug_) {
  351. cout << "tcpSendHandler(): error = " << ec.value() <<
  352. ", length = " << length << endl;
  353. }
  354. EXPECT_EQ(0, ec.value()); // Expect no error
  355. EXPECT_EQ(expected, length); // And that amount sent is as expected
  356. // Do we need to send more?
  357. send_cumulative_ += length;
  358. if (send_cumulative_ < send_buffer_.size()) {
  359. // Yes - set up a timer: the callback handler for the timer is
  360. // tcpSendData, which will then send the next chunk. We pass the
  361. // socket over which data should be sent as an argument to that
  362. // function.
  363. timer_.expires_from_now(boost::posix_time::milliseconds(SEND_INTERVAL));
  364. timer_.async_wait(boost::bind(&IOFetchTest::tcpSendData, this,
  365. socket));
  366. }
  367. }
  368. /// \brief Fetch completion callback
  369. ///
  370. /// This is the callback's operator() method which is called when the fetch
  371. /// is complete. It checks that the data received is the wire format of the
  372. /// data sent back by the server.
  373. ///
  374. /// \param result Result indicated by the callback
  375. void operator()(IOFetch::Result result) {
  376. if (debug_) {
  377. cout << "operator()(): result = " << result << endl;
  378. }
  379. EXPECT_EQ(expected_, result); // Check correct result returned
  380. EXPECT_FALSE(run_); // Check it is run only once
  381. run_ = true; // Note success
  382. // If the expected result for SUCCESS, then this should have been called
  383. // when one of the "servers" in this class has sent back return_data_.
  384. // Check the data is as expected/
  385. if (expected_ == IOFetch::SUCCESS) {
  386. // In the case of UDP, we actually send back a real looking packet
  387. // in the case of TCP, we send back a 'random' string
  388. if (protocol_ == IOFetch::UDP) {
  389. EXPECT_EQ(expected_buffer_->getLength(), result_buff_->getLength());
  390. EXPECT_EQ(0, memcmp(expected_buffer_->getData(), result_buff_->getData(),
  391. expected_buffer_->getLength()));
  392. } else {
  393. EXPECT_EQ(return_data_.size(), result_buff_->getLength());
  394. // Overwrite the random qid with our own data for the
  395. // comparison to succeed
  396. if (result_buff_->getLength() >= 2) {
  397. result_buff_->writeUint8At(return_data_[0], 0);
  398. result_buff_->writeUint8At(return_data_[1], 1);
  399. }
  400. const uint8_t* start = static_cast<const uint8_t*>(result_buff_->getData());
  401. EXPECT_TRUE(equal(return_data_.begin(), return_data_.end(), start));
  402. }
  403. }
  404. // ... and cause the run loop to exit.
  405. service_.stop();
  406. }
  407. // The next set of methods are the tests themselves. A number of the TCP
  408. // and UDP tests are very similar.
  409. /// \brief Check for stop()
  410. ///
  411. /// Test that when we run the query and stop it after it was run, it returns
  412. /// "stopped" correctly. (That is why stop() is posted to the service_ as
  413. /// well instead of calling it.)
  414. ///
  415. /// \param protocol Test protocol
  416. /// \param fetch Fetch object being tested
  417. void stopTest(IOFetch::Protocol protocol, IOFetch& fetch) {
  418. protocol_ = protocol;
  419. expected_ = IOFetch::STOPPED;
  420. // Post the query
  421. service_.get_io_service().post(fetch);
  422. // Post query_.stop() (yes, the boost::bind thing is just
  423. // query_.stop()).
  424. service_.get_io_service().post(
  425. boost::bind(&IOFetch::stop, fetch, IOFetch::STOPPED));
  426. // Run both of them. run() returns when everything in the I/O service
  427. // queue has completed.
  428. service_.run();
  429. EXPECT_TRUE(run_);
  430. }
  431. /// \brief Premature stop test
  432. ///
  433. /// Test that when we queue the query to service_ and call stop() before it
  434. /// gets executed, it acts sanely as well (eg. has the same result as
  435. /// running stop() after - calls the callback).
  436. ///
  437. /// \param protocol Test protocol
  438. /// \param fetch Fetch object being tested
  439. void prematureStopTest(IOFetch::Protocol protocol, IOFetch& fetch) {
  440. protocol_ = protocol;
  441. expected_ = IOFetch::STOPPED;
  442. // Stop before it is started
  443. fetch.stop();
  444. service_.get_io_service().post(fetch);
  445. service_.run();
  446. EXPECT_TRUE(run_);
  447. }
  448. /// \brief Timeout test
  449. ///
  450. /// Test that fetch times out when no answer arrives.
  451. ///
  452. /// \param protocol Test protocol
  453. /// \param fetch Fetch object being tested
  454. void timeoutTest(IOFetch::Protocol protocol, IOFetch& fetch) {
  455. protocol_ = protocol;
  456. expected_ = IOFetch::TIME_OUT;
  457. service_.get_io_service().post(fetch);
  458. service_.run();
  459. EXPECT_TRUE(run_);
  460. }
  461. /// \brief Send/Receive Test
  462. ///
  463. /// Send a query to the server then receives a response.
  464. ///
  465. /// \param Test data to return to client
  466. /// \param short_send If true, do not send all data
  467. /// (should result in timeout)
  468. void tcpSendReturnTest(const std::string& return_data, bool short_send = false) {
  469. if (debug_) {
  470. cout << "tcpSendReturnTest(): data size = " << return_data.size() << endl;
  471. }
  472. return_data_ = return_data;
  473. protocol_ = IOFetch::TCP;
  474. if (short_send) {
  475. tcp_short_send_ = true;
  476. expected_ = IOFetch::TIME_OUT;
  477. } else {
  478. expected_ = IOFetch::SUCCESS;
  479. }
  480. // Socket into which the connection will be accepted.
  481. tcp::socket socket(service_.get_io_service());
  482. // Acceptor object - called when the connection is made, the handler
  483. // will initiate a read on the socket.
  484. tcp::acceptor acceptor(service_.get_io_service(),
  485. tcp::endpoint(tcp::v4(), TEST_PORT));
  486. acceptor.async_accept(socket,
  487. boost::bind(&IOFetchTest::tcpAcceptHandler, this, &socket, _1));
  488. // Post the TCP fetch object to send the query and receive the response.
  489. service_.get_io_service().post(tcp_fetch_);
  490. // ... and execute all the callbacks. This exits when the fetch
  491. // completes.
  492. service_.run();
  493. EXPECT_TRUE(run_); // Make sure the callback did execute
  494. // Tidy up
  495. socket.close();
  496. }
  497. /// Perform a send/receive test over UDP
  498. ///
  499. /// \param bad_qid If true, do the test where the QID is mangled
  500. /// in the response
  501. /// \param second_send If true, do the test where the QID is
  502. /// mangled in the response, but a second
  503. /// (correct) packet is used
  504. void udpSendReturnTest(bool bad_qid, bool second_send) {
  505. protocol_ = IOFetch::UDP;
  506. // Set up the server.
  507. udp::socket socket(service_.get_io_service(), udp::v4());
  508. socket.set_option(socket_base::reuse_address(true));
  509. socket.bind(udp::endpoint(TEST_HOST, TEST_PORT));
  510. return_data_ = "Message returned to the client";
  511. udp::endpoint remote;
  512. socket.async_receive_from(asio::buffer(receive_buffer_, sizeof(receive_buffer_)),
  513. remote,
  514. boost::bind(&IOFetchTest::udpReceiveHandler, this, &remote, &socket,
  515. _1, _2, bad_qid, second_send));
  516. service_.get_io_service().post(udp_fetch_);
  517. if (debug_) {
  518. cout << "udpSendReceive: async_receive_from posted, waiting for callback" <<
  519. endl;
  520. }
  521. service_.run();
  522. socket.close();
  523. EXPECT_TRUE(run_);;
  524. }
  525. };
  526. // Check the protocol
  527. TEST_F(IOFetchTest, Protocol) {
  528. EXPECT_EQ(IOFetch::UDP, udp_fetch_.getProtocol());
  529. EXPECT_EQ(IOFetch::TCP, tcp_fetch_.getProtocol());
  530. }
  531. // UDP Stop test - see IOFetchTest::stopTest() header.
  532. TEST_F(IOFetchTest, UdpStop) {
  533. stopTest(IOFetch::UDP, udp_fetch_);
  534. }
  535. // UDP premature stop test - see IOFetchTest::prematureStopTest() header.
  536. TEST_F(IOFetchTest, UdpPrematureStop) {
  537. prematureStopTest(IOFetch::UDP, udp_fetch_);
  538. }
  539. // UDP premature stop test - see IOFetchTest::timeoutTest() header.
  540. TEST_F(IOFetchTest, UdpTimeout) {
  541. timeoutTest(IOFetch::UDP, udp_fetch_);
  542. }
  543. // UDP SendReceive test. Set up a UDP server then ports a UDP fetch object.
  544. // This will send question_ to the server and receive the answer back from it.
  545. TEST_F(IOFetchTest, UdpSendReceive) {
  546. expected_ = IOFetch::SUCCESS;
  547. udpSendReturnTest(false, false);
  548. EXPECT_TRUE(run_);;
  549. }
  550. TEST_F(IOFetchTest, UdpSendReceiveBadQid) {
  551. expected_ = IOFetch::TIME_OUT;
  552. udpSendReturnTest(true, false);
  553. EXPECT_TRUE(run_);;
  554. }
  555. TEST_F(IOFetchTest, UdpSendReceiveBadQidResend) {
  556. expected_ = IOFetch::SUCCESS;
  557. udpSendReturnTest(true, true);
  558. EXPECT_TRUE(run_);;
  559. }
  560. // Do the same tests for TCP transport
  561. TEST_F(IOFetchTest, TcpStop) {
  562. stopTest(IOFetch::TCP, tcp_fetch_);
  563. }
  564. TEST_F(IOFetchTest, TcpPrematureStop) {
  565. prematureStopTest(IOFetch::TCP, tcp_fetch_);
  566. }
  567. TEST_F(IOFetchTest, TcpTimeout) {
  568. timeoutTest(IOFetch::TCP, tcp_fetch_);
  569. }
  570. // Test with values at or near 2, then at or near the chunk size (16 and 32
  571. // bytes, the sizes of the first two packets) then up to 65535. These are done
  572. // in separate tests because in practice a new IOFetch is created for each
  573. // query/response exchange and we don't want to confuse matters in the test
  574. // by running the test with an IOFetch that has already done one exchange.
  575. //
  576. // Don't do 0 or 1; the server would not accept the packet
  577. // (since the length is too short to check the qid)
  578. TEST_F(IOFetchTest, TcpSendReceive2) {
  579. tcpSendReturnTest(test_data_.substr(0, 2));
  580. }
  581. TEST_F(IOFetchTest, TcpSendReceive3) {
  582. tcpSendReturnTest(test_data_.substr(0, 3));
  583. }
  584. TEST_F(IOFetchTest, TcpSendReceive15) {
  585. tcpSendReturnTest(test_data_.substr(0, 15));
  586. }
  587. TEST_F(IOFetchTest, TcpSendReceive16) {
  588. tcpSendReturnTest(test_data_.substr(0, 16));
  589. }
  590. TEST_F(IOFetchTest, TcpSendReceive17) {
  591. tcpSendReturnTest(test_data_.substr(0, 17));
  592. }
  593. TEST_F(IOFetchTest, TcpSendReceive31) {
  594. tcpSendReturnTest(test_data_.substr(0, 31));
  595. }
  596. TEST_F(IOFetchTest, TcpSendReceive32) {
  597. tcpSendReturnTest(test_data_.substr(0, 32));
  598. }
  599. TEST_F(IOFetchTest, TcpSendReceive33) {
  600. tcpSendReturnTest(test_data_.substr(0, 33));
  601. }
  602. TEST_F(IOFetchTest, TcpSendReceive4096) {
  603. tcpSendReturnTest(test_data_.substr(0, 4096));
  604. }
  605. TEST_F(IOFetchTest, TcpSendReceive8192) {
  606. tcpSendReturnTest(test_data_.substr(0, 8192));
  607. }
  608. TEST_F(IOFetchTest, TcpSendReceive16384) {
  609. tcpSendReturnTest(test_data_.substr(0, 16384));
  610. }
  611. TEST_F(IOFetchTest, TcpSendReceive32768) {
  612. tcpSendReturnTest(test_data_.substr(0, 32768));
  613. }
  614. TEST_F(IOFetchTest, TcpSendReceive65535) {
  615. tcpSendReturnTest(test_data_.substr(0, 65535));
  616. }
  617. TEST_F(IOFetchTest, TcpSendReceive2ShortSend) {
  618. tcpSendReturnTest(test_data_.substr(0, 2), true);
  619. }
  620. TEST_F(IOFetchTest, TcpSendReceive15ShortSend) {
  621. tcpSendReturnTest(test_data_.substr(0, 15), true);
  622. }
  623. TEST_F(IOFetchTest, TcpSendReceive8192ShortSend) {
  624. tcpSendReturnTest(test_data_.substr(0, 8192), true);
  625. }
  626. } // namespace asiodns
  627. } // namespace isc