io_fetch_unittest.cc 28 KB

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