asiolink_unittest.cc 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. // Copyright (C) 2010 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. // $Id$
  15. #include <config.h>
  16. #include <sys/socket.h>
  17. #include <sys/time.h>
  18. #include <string.h>
  19. #include <boost/lexical_cast.hpp>
  20. #include <boost/bind.hpp>
  21. #include <boost/date_time/posix_time/posix_time_types.hpp>
  22. #include <gtest/gtest.h>
  23. #include <exceptions/exceptions.h>
  24. #include <dns/tests/unittest_util.h>
  25. #include <dns/buffer.h>
  26. #include <dns/message.h>
  27. // IMPORTANT: We shouldn't directly use ASIO definitions in this test.
  28. // In particular, we must not include asio.hpp in this file.
  29. // The asiolink module is primarily intended to be a wrapper that hide the
  30. // details of the underlying implementations. We need to test the wrapper
  31. // level behaviors. In addition, some compilers reject to compile this file
  32. // if we include asio.hpp unless we specify a special compiler option.
  33. // If we need to test something at the level of underlying ASIO and need
  34. // their definition, that test should go to asiolink/internal/tests.
  35. #include <asiolink/asiolink.h>
  36. #include <asiolink/iosocket.h>
  37. using isc::UnitTestUtil;
  38. using namespace std;
  39. using namespace asiolink;
  40. using namespace isc::dns;
  41. namespace {
  42. const char* const TEST_SERVER_PORT = "53535";
  43. const char* const TEST_CLIENT_PORT = "53536";
  44. const char* const TEST_IPV6_ADDR = "::1";
  45. const char* const TEST_IPV4_ADDR = "127.0.0.1";
  46. // This data is intended to be valid as a DNS/TCP-like message: the first
  47. // two octets encode the length of the rest of the data. This is crucial
  48. // for the tests below.
  49. const uint8_t test_data[] = {0, 4, 1, 2, 3, 4};
  50. // TODO: Consider this margin
  51. const boost::posix_time::time_duration TIMER_MARGIN_MSEC =
  52. boost::posix_time::milliseconds(50);
  53. TEST(IOAddressTest, fromText) {
  54. IOAddress io_address_v4("192.0.2.1");
  55. EXPECT_EQ("192.0.2.1", io_address_v4.toText());
  56. IOAddress io_address_v6("2001:db8::1234");
  57. EXPECT_EQ("2001:db8::1234", io_address_v6.toText());
  58. // bogus IPv4 address-like input
  59. EXPECT_THROW(IOAddress("192.0.2.2.1"), IOError);
  60. // bogus IPv4 address-like input: out-of-range octet
  61. EXPECT_THROW(IOAddress("192.0.2.300"), IOError);
  62. // bogus IPv6 address-like input
  63. EXPECT_THROW(IOAddress("2001:db8:::1234"), IOError);
  64. // bogus IPv6 address-like input
  65. EXPECT_THROW(IOAddress("2001:db8::efgh"), IOError);
  66. }
  67. TEST(IOEndpointTest, createUDPv4) {
  68. const IOEndpoint* ep;
  69. ep = IOEndpoint::create(IPPROTO_UDP, IOAddress("192.0.2.1"), 5300);
  70. EXPECT_EQ("192.0.2.1", ep->getAddress().toText());
  71. EXPECT_EQ(5300, ep->getPort());
  72. EXPECT_EQ(AF_INET, ep->getFamily());
  73. EXPECT_EQ(AF_INET, ep->getAddress().getFamily());
  74. EXPECT_EQ(IPPROTO_UDP, ep->getProtocol());
  75. }
  76. TEST(IOEndpointTest, createTCPv4) {
  77. const IOEndpoint* ep;
  78. ep = IOEndpoint::create(IPPROTO_TCP, IOAddress("192.0.2.1"), 5301);
  79. EXPECT_EQ("192.0.2.1", ep->getAddress().toText());
  80. EXPECT_EQ(5301, ep->getPort());
  81. EXPECT_EQ(AF_INET, ep->getFamily());
  82. EXPECT_EQ(AF_INET, ep->getAddress().getFamily());
  83. EXPECT_EQ(IPPROTO_TCP, ep->getProtocol());
  84. }
  85. TEST(IOEndpointTest, createUDPv6) {
  86. const IOEndpoint* ep;
  87. ep = IOEndpoint::create(IPPROTO_UDP, IOAddress("2001:db8::1234"), 5302);
  88. EXPECT_EQ("2001:db8::1234", ep->getAddress().toText());
  89. EXPECT_EQ(5302, ep->getPort());
  90. EXPECT_EQ(AF_INET6, ep->getFamily());
  91. EXPECT_EQ(AF_INET6, ep->getAddress().getFamily());
  92. EXPECT_EQ(IPPROTO_UDP, ep->getProtocol());
  93. }
  94. TEST(IOEndpointTest, createTCPv6) {
  95. const IOEndpoint* ep;
  96. ep = IOEndpoint::create(IPPROTO_TCP, IOAddress("2001:db8::1234"), 5303);
  97. EXPECT_EQ("2001:db8::1234", ep->getAddress().toText());
  98. EXPECT_EQ(5303, ep->getPort());
  99. EXPECT_EQ(AF_INET6, ep->getFamily());
  100. EXPECT_EQ(AF_INET6, ep->getAddress().getFamily());
  101. EXPECT_EQ(IPPROTO_TCP, ep->getProtocol());
  102. }
  103. TEST(IOEndpointTest, createIPProto) {
  104. EXPECT_THROW(IOEndpoint::create(IPPROTO_IP, IOAddress("192.0.2.1"),
  105. 5300)->getAddress().toText(),
  106. IOError);
  107. }
  108. TEST(IOSocketTest, dummySockets) {
  109. EXPECT_EQ(IPPROTO_UDP, IOSocket::getDummyUDPSocket().getProtocol());
  110. EXPECT_EQ(IPPROTO_TCP, IOSocket::getDummyTCPSocket().getProtocol());
  111. EXPECT_EQ(-1, IOSocket::getDummyUDPSocket().getNative());
  112. EXPECT_EQ(-1, IOSocket::getDummyTCPSocket().getNative());
  113. }
  114. TEST(IOServiceTest, badPort) {
  115. IOService io_service;
  116. EXPECT_THROW(DNSService(io_service, *"65536", true, false, NULL, NULL, NULL), IOError);
  117. EXPECT_THROW(DNSService(io_service, *"5300.0", true, false, NULL, NULL, NULL), IOError);
  118. EXPECT_THROW(DNSService(io_service, *"-1", true, false, NULL, NULL, NULL), IOError);
  119. EXPECT_THROW(DNSService(io_service, *"domain", true, false, NULL, NULL, NULL), IOError);
  120. }
  121. TEST(IOServiceTest, badAddress) {
  122. IOService io_service;
  123. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"192.0.2.1.1", NULL, NULL, NULL), IOError);
  124. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"2001:db8:::1", NULL, NULL, NULL), IOError);
  125. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"localhost", NULL, NULL, NULL), IOError);
  126. }
  127. TEST(IOServiceTest, unavailableAddress) {
  128. IOService io_service;
  129. // These addresses should generally be unavailable as a valid local
  130. // address, although there's no guarantee in theory.
  131. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"255.255.0.0", NULL, NULL, NULL), IOError);
  132. // Some OSes would simply reject binding attempt for an AF_INET6 socket
  133. // to an IPv4-mapped IPv6 address. Even if those that allow it, since
  134. // the corresponding IPv4 address is the same as the one used in the
  135. // AF_INET socket case above, it should at least show the same result
  136. // as the previous one.
  137. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:255.255.0.0", NULL, NULL, NULL), IOError);
  138. }
  139. TEST(IOServiceTest, duplicateBind_v6) {
  140. // In each sub test case, second attempt should fail due to duplicate bind
  141. IOService io_service;
  142. // IPv6, "any" address
  143. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, false, true, NULL, NULL, NULL);
  144. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, false, true, NULL, NULL, NULL), IOError);
  145. delete dns_service;
  146. }
  147. TEST(IOServiceTest, duplicateBind_v6_address) {
  148. // In each sub test case, second attempt should fail due to duplicate bind
  149. IOService io_service;
  150. // IPv6, specific address
  151. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL);
  152. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL), IOError);
  153. delete dns_service;
  154. }
  155. TEST(IOServiceTest, duplicateBind_v4) {
  156. // In each sub test case, second attempt should fail due to duplicate bind
  157. IOService io_service;
  158. // IPv4, "any" address
  159. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, true, false, NULL, NULL, NULL);
  160. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, true, false, NULL, NULL, NULL), IOError);
  161. delete dns_service;
  162. }
  163. TEST(IOServiceTest, duplicateBind_v4_address) {
  164. // In each sub test case, second attempt should fail due to duplicate bind
  165. IOService io_service;
  166. // IPv4, specific address
  167. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL);
  168. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL), IOError);
  169. delete dns_service;
  170. }
  171. // Disabled because IPv4-mapped addresses don't seem to be working with
  172. // the IOService constructor
  173. TEST(IOServiceTest, DISABLED_IPv4MappedDuplicateBind) {
  174. IOService io_service;
  175. // Duplicate bind on IPv4-mapped IPv6 address
  176. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *"127.0.0.1", NULL, NULL, NULL);
  177. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:127.0.0.1", NULL, NULL, NULL), IOError);
  178. delete dns_service;
  179. // XXX:
  180. // Currently, this throws an "invalid argument" exception. I have
  181. // not been able to get IPv4-mapped addresses to work.
  182. dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:127.0.0.1", NULL, NULL, NULL);
  183. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"127.0.0.1", NULL, NULL, NULL), IOError);
  184. delete dns_service;
  185. }
  186. // This function returns an addrinfo structure for use by tests, using
  187. // different addresses and ports depending on whether we're testing
  188. // IPv4 or v6, TCP or UDP, and client or server operation.
  189. struct addrinfo*
  190. resolveAddress(const int family, const int protocol, const bool client) {
  191. const char* const addr = (family == AF_INET6) ?
  192. TEST_IPV6_ADDR : TEST_IPV4_ADDR;
  193. const char* const port = client ? TEST_CLIENT_PORT : TEST_SERVER_PORT;
  194. struct addrinfo hints;
  195. memset(&hints, 0, sizeof(hints));
  196. hints.ai_family = family;
  197. hints.ai_socktype = (protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
  198. hints.ai_protocol = protocol;
  199. hints.ai_flags = AI_NUMERICSERV;
  200. struct addrinfo* res;
  201. const int error = getaddrinfo(addr, port, &hints, &res);
  202. if (error != 0) {
  203. isc_throw(IOError, "getaddrinfo failed: " << gai_strerror(error));
  204. }
  205. return (res);
  206. }
  207. // This fixture is a framework for various types of network operations
  208. // using the ASIO interfaces. Each test case creates an IOService object,
  209. // opens a local "client" socket for testing, sends data via the local socket
  210. // to the service that would run in the IOService object.
  211. // A mock callback function (an ASIOCallBack object) is registered with the
  212. // IOService object, so the test code should be able to examine the data
  213. // received on the server side. It then checks the received data matches
  214. // expected parameters.
  215. // If initialization parameters of the IOService should be modified, the test
  216. // case can do it using the setDNSService() method.
  217. // Note: the set of tests in ASIOLinkTest use actual network services and may
  218. // involve undesirable side effects such as blocking.
  219. class ASIOLinkTest : public ::testing::Test {
  220. protected:
  221. ASIOLinkTest();
  222. ~ASIOLinkTest() {
  223. if (res_ != NULL) {
  224. freeaddrinfo(res_);
  225. }
  226. if (sock_ != -1) {
  227. close(sock_);
  228. }
  229. delete dns_service_;
  230. delete callback_;
  231. delete io_service_;
  232. }
  233. // Send a test UDP packet to a mock server
  234. void sendUDP(const int family) {
  235. res_ = resolveAddress(family, IPPROTO_UDP, false);
  236. sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  237. if (sock_ < 0) {
  238. isc_throw(IOError, "failed to open test socket");
  239. }
  240. const int cc = sendto(sock_, test_data, sizeof(test_data), 0,
  241. res_->ai_addr, res_->ai_addrlen);
  242. if (cc != sizeof(test_data)) {
  243. isc_throw(IOError, "unexpected sendto result: " << cc);
  244. }
  245. io_service_->run();
  246. }
  247. // Send a test TCP packet to a mock server
  248. void sendTCP(const int family) {
  249. res_ = resolveAddress(family, IPPROTO_TCP, false);
  250. sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  251. if (sock_ < 0) {
  252. isc_throw(IOError, "failed to open test socket");
  253. }
  254. if (connect(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
  255. isc_throw(IOError, "failed to connect to the test server");
  256. }
  257. const int cc = send(sock_, test_data, sizeof(test_data), 0);
  258. if (cc != sizeof(test_data)) {
  259. isc_throw(IOError, "unexpected send result: " << cc);
  260. }
  261. io_service_->run();
  262. }
  263. // Receive a UDP packet from a mock server; used for testing
  264. // recursive lookup. The caller must place a RecursiveQuery
  265. // on the IO Service queue before running this routine.
  266. void recvUDP(const int family, void* buffer, size_t& size) {
  267. res_ = resolveAddress(family, IPPROTO_UDP, true);
  268. sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  269. if (sock_ < 0) {
  270. isc_throw(IOError, "failed to open test socket");
  271. }
  272. if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
  273. isc_throw(IOError, "bind failed: " << strerror(errno));
  274. }
  275. // The IO service queue should have a RecursiveQuery object scheduled
  276. // to run at this point. This call will cause it to begin an
  277. // async send, then return.
  278. io_service_->run_one();
  279. // ... and this one will block until the send has completed
  280. io_service_->run_one();
  281. // Now we attempt to recv() whatever was sent.
  282. // XXX: there's no guarantee the receiving socket can immediately get
  283. // the packet. Normally we can perform blocking recv to wait for it,
  284. // but in theory it's even possible that the packet is lost.
  285. // In order to prevent the test from hanging in such a worst case
  286. // we add an ad hoc timeout.
  287. const struct timeval timeo = { 10, 0 };
  288. int recv_options = 0;
  289. if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo,
  290. sizeof(timeo))) {
  291. if (errno == ENOPROTOOPT) {
  292. // Workaround for Solaris: it doesn't accept SO_RCVTIMEO
  293. // with the error of ENOPROTOOPT. Since this is a workaround
  294. // for rare error cases anyway, we simply switch to the
  295. // "don't wait" mode. If we still find an error in recv()
  296. // can happen often we'll consider a more complete solution.
  297. recv_options = MSG_DONTWAIT;
  298. } else {
  299. isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
  300. }
  301. }
  302. const int ret = recv(sock_, buffer, size, recv_options);
  303. if (ret < 0) {
  304. isc_throw(IOError, "recvfrom failed: " << strerror(errno));
  305. }
  306. // Pass the message size back via the size parameter
  307. size = ret;
  308. }
  309. // Set up an IO Service queue using the specified address
  310. void setDNSService(const char& address) {
  311. delete dns_service_;
  312. dns_service_ = NULL;
  313. delete io_service_;
  314. io_service_ = new IOService();
  315. callback_ = new ASIOCallBack(this);
  316. dns_service_ = new DNSService(*io_service_, *TEST_SERVER_PORT, address, callback_, NULL, NULL);
  317. }
  318. // Set up an IO Service queue using the "any" address, on IPv4 if
  319. // 'use_ipv4' is true and on IPv6 if 'use_ipv6' is true.
  320. void setDNSService(const bool use_ipv4, const bool use_ipv6) {
  321. delete dns_service_;
  322. dns_service_ = NULL;
  323. delete io_service_;
  324. io_service_ = new IOService();
  325. callback_ = new ASIOCallBack(this);
  326. dns_service_ = new DNSService(*io_service_, *TEST_SERVER_PORT, use_ipv4, use_ipv6, callback_,
  327. NULL, NULL);
  328. }
  329. // Set up empty DNS Service
  330. // Set up an IO Service queue without any addresses
  331. void setDNSService() {
  332. delete dns_service_;
  333. dns_service_ = NULL;
  334. delete io_service_;
  335. io_service_ = new IOService();
  336. callback_ = new ASIOCallBack(this);
  337. dns_service_ = new DNSService(*io_service_, callback_, NULL, NULL);
  338. }
  339. // Run a simple server test, on either IPv4 or IPv6, and over either
  340. // UDP or TCP. Calls the sendUDP() or sendTCP() methods, which will
  341. // start the IO Service queue. The UDPServer or TCPServer that was
  342. // created by setIOService() will receive the test packet and issue a
  343. // callback, which enables us to check that the data it received
  344. // matches what we sent.
  345. void doTest(const int family, const int protocol) {
  346. if (protocol == IPPROTO_UDP) {
  347. sendUDP(family);
  348. } else {
  349. sendTCP(family);
  350. }
  351. // There doesn't seem to be an effective test for the validity of
  352. // 'native'.
  353. // One thing we are sure is it must be different from our local socket.
  354. EXPECT_NE(sock_, callback_native_);
  355. EXPECT_EQ(protocol, callback_protocol_);
  356. EXPECT_EQ(family == AF_INET6 ? TEST_IPV6_ADDR : TEST_IPV4_ADDR,
  357. callback_address_);
  358. const uint8_t* expected_data =
  359. protocol == IPPROTO_UDP ? test_data : test_data + 2;
  360. const size_t expected_datasize =
  361. protocol == IPPROTO_UDP ? sizeof(test_data) :
  362. sizeof(test_data) - 2;
  363. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
  364. callback_data_.size(),
  365. expected_data, expected_datasize);
  366. }
  367. protected:
  368. // This is a nonfunctional mockup of a DNSServer object. Its purpose
  369. // is to resume after a recursive query or other asynchronous call
  370. // has completed.
  371. class MockServer : public DNSServer {
  372. public:
  373. explicit MockServer(IOService& io_service,
  374. SimpleCallback* checkin = NULL,
  375. DNSLookup* lookup = NULL,
  376. DNSAnswer* answer = NULL) :
  377. io_(io_service),
  378. message_(new Message(Message::PARSE)),
  379. respbuf_(new OutputBuffer(0)),
  380. checkin_(checkin), lookup_(lookup), answer_(answer)
  381. {}
  382. void operator()(asio::error_code ec = asio::error_code(),
  383. size_t length = 0)
  384. {}
  385. void resume(const bool) { // in our test this shouldn't be called
  386. }
  387. DNSServer* clone() {
  388. MockServer* s = new MockServer(*this);
  389. return (s);
  390. }
  391. inline void asyncLookup() {
  392. if (lookup_) {
  393. (*lookup_)(*io_message_, message_, respbuf_, this);
  394. }
  395. }
  396. protected:
  397. IOService& io_;
  398. bool done_;
  399. private:
  400. // Currently unused; these will be used for testing
  401. // asynchronous lookup calls via the asyncLookup() method
  402. boost::shared_ptr<asiolink::IOMessage> io_message_;
  403. isc::dns::MessagePtr message_;
  404. isc::dns::OutputBufferPtr respbuf_;
  405. // Callback functions provided by the caller
  406. const SimpleCallback* checkin_;
  407. const DNSLookup* lookup_;
  408. const DNSAnswer* answer_;
  409. };
  410. // This version of mock server just stops the io_service when it is resumed
  411. class MockServerStop : public MockServer {
  412. public:
  413. explicit MockServerStop(IOService& io_service, bool* done) :
  414. MockServer(io_service),
  415. done_(done)
  416. {}
  417. void resume(const bool done) {
  418. *done_ = done;
  419. io_.stop();
  420. }
  421. DNSServer* clone() {
  422. return (new MockServerStop(*this));
  423. }
  424. private:
  425. bool* done_;
  426. };
  427. private:
  428. class ASIOCallBack : public SimpleCallback {
  429. public:
  430. ASIOCallBack(ASIOLinkTest* test_obj) : test_obj_(test_obj) {}
  431. void operator()(const IOMessage& io_message) const {
  432. test_obj_->callBack(io_message);
  433. }
  434. private:
  435. ASIOLinkTest* test_obj_;
  436. };
  437. void callBack(const IOMessage& io_message) {
  438. callback_protocol_ = io_message.getSocket().getProtocol();
  439. callback_native_ = io_message.getSocket().getNative();
  440. callback_address_ =
  441. io_message.getRemoteEndpoint().getAddress().toText();
  442. callback_data_.assign(
  443. static_cast<const uint8_t*>(io_message.getData()),
  444. static_cast<const uint8_t*>(io_message.getData()) +
  445. io_message.getDataSize());
  446. io_service_->stop();
  447. }
  448. protected:
  449. // We use a pointer for io_service_, because for some tests we
  450. // need to recreate a new one within one onstance of this class
  451. IOService* io_service_;
  452. DNSService* dns_service_;
  453. ASIOCallBack* callback_;
  454. int callback_protocol_;
  455. int callback_native_;
  456. string callback_address_;
  457. vector<uint8_t> callback_data_;
  458. int sock_;
  459. struct addrinfo* res_;
  460. };
  461. ASIOLinkTest::ASIOLinkTest() :
  462. dns_service_(NULL), callback_(NULL), sock_(-1), res_(NULL)
  463. {
  464. io_service_ = new IOService();
  465. setDNSService(true, true);
  466. }
  467. TEST_F(ASIOLinkTest, v6UDPSend) {
  468. doTest(AF_INET6, IPPROTO_UDP);
  469. }
  470. TEST_F(ASIOLinkTest, v6TCPSend) {
  471. doTest(AF_INET6, IPPROTO_TCP);
  472. }
  473. TEST_F(ASIOLinkTest, v4UDPSend) {
  474. doTest(AF_INET, IPPROTO_UDP);
  475. }
  476. TEST_F(ASIOLinkTest, v4TCPSend) {
  477. doTest(AF_INET, IPPROTO_TCP);
  478. }
  479. TEST_F(ASIOLinkTest, v6UDPSendSpecific) {
  480. // Explicitly set a specific address to be bound to the socket.
  481. // The subsequent test does not directly ensures the underlying socket
  482. // is bound to the expected address, but the success of the tests should
  483. // reasonably suggest it works as intended.
  484. // Specifying an address also implicitly means the service runs in a
  485. // single address-family mode. In tests using TCP we can confirm that
  486. // by trying to make a connection and seeing a failure. In UDP, it'd be
  487. // more complicated because we need to use a connected socket and catch
  488. // an error on a subsequent read operation. We could do it, but for
  489. // simplicity we only tests the easier cases for now.
  490. setDNSService(*TEST_IPV6_ADDR);
  491. doTest(AF_INET6, IPPROTO_UDP);
  492. }
  493. TEST_F(ASIOLinkTest, v6TCPSendSpecific) {
  494. setDNSService(*TEST_IPV6_ADDR);
  495. doTest(AF_INET6, IPPROTO_TCP);
  496. EXPECT_THROW(sendTCP(AF_INET), IOError);
  497. }
  498. TEST_F(ASIOLinkTest, v4UDPSendSpecific) {
  499. setDNSService(*TEST_IPV4_ADDR);
  500. doTest(AF_INET, IPPROTO_UDP);
  501. }
  502. TEST_F(ASIOLinkTest, v4TCPSendSpecific) {
  503. setDNSService(*TEST_IPV4_ADDR);
  504. doTest(AF_INET, IPPROTO_TCP);
  505. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  506. }
  507. TEST_F(ASIOLinkTest, v6AddServer) {
  508. setDNSService();
  509. dns_service_->addServer(*TEST_SERVER_PORT, TEST_IPV6_ADDR);
  510. doTest(AF_INET6, IPPROTO_TCP);
  511. EXPECT_THROW(sendTCP(AF_INET), IOError);
  512. }
  513. TEST_F(ASIOLinkTest, v4AddServer) {
  514. setDNSService();
  515. dns_service_->addServer(*TEST_SERVER_PORT, TEST_IPV4_ADDR);
  516. doTest(AF_INET, IPPROTO_TCP);
  517. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  518. }
  519. TEST_F(ASIOLinkTest, DISABLED_clearServers) {
  520. // FIXME: Enable when clearServers actually close the sockets
  521. // See #388
  522. setDNSService();
  523. dns_service_->clearServers();
  524. EXPECT_THROW(sendTCP(AF_INET), IOError);
  525. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  526. }
  527. TEST_F(ASIOLinkTest, v6TCPOnly) {
  528. // Open only IPv6 TCP socket. A subsequent attempt of establishing an
  529. // IPv4/TCP connection should fail. See above for why we only test this
  530. // for TCP.
  531. setDNSService(false, true);
  532. EXPECT_THROW(sendTCP(AF_INET), IOError);
  533. }
  534. TEST_F(ASIOLinkTest, v4TCPOnly) {
  535. setDNSService(true, false);
  536. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  537. }
  538. vector<pair<string, uint16_t> >
  539. singleAddress(const string &address, uint16_t port) {
  540. vector<pair<string, uint16_t> > result;
  541. result.push_back(pair<string, uint16_t>(address, port));
  542. return (result);
  543. }
  544. TEST_F(ASIOLinkTest, recursiveSetupV4) {
  545. setDNSService(true, false);
  546. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  547. EXPECT_NO_THROW(RecursiveQuery(*dns_service_, singleAddress(TEST_IPV6_ADDR,
  548. port)));
  549. }
  550. TEST_F(ASIOLinkTest, recursiveSetupV6) {
  551. setDNSService(false, true);
  552. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  553. EXPECT_NO_THROW(RecursiveQuery(*dns_service_, singleAddress(TEST_IPV6_ADDR,
  554. port)));
  555. }
  556. // XXX:
  557. // This is very inadequate unit testing. It should be generalized into
  558. // a routine that can do this with variable address family, address, and
  559. // port, and with the various callbacks defined in such a way as to ensure
  560. // full code coverage including error cases.
  561. TEST_F(ASIOLinkTest, recursiveSend) {
  562. setDNSService(true, false);
  563. // Note: We use the test prot plus one to ensure we aren't binding
  564. // to the same port as the actual server
  565. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  566. MockServer server(*io_service_);
  567. RecursiveQuery rq(*dns_service_, singleAddress(TEST_IPV4_ADDR, port));
  568. Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
  569. OutputBufferPtr buffer(new OutputBuffer(0));
  570. rq.sendQuery(q, buffer, &server);
  571. char data[4096];
  572. size_t size = sizeof(data);
  573. ASSERT_NO_THROW(recvUDP(AF_INET, data, size));
  574. Message m(Message::PARSE);
  575. InputBuffer ibuf(data, size);
  576. // Make sure we can parse the message that was sent
  577. EXPECT_NO_THROW(m.parseHeader(ibuf));
  578. EXPECT_NO_THROW(m.fromWire(ibuf));
  579. // Check that the question sent matches the one we wanted
  580. QuestionPtr q2 = *m.beginQuestion();
  581. EXPECT_EQ(q.getName(), q2->getName());
  582. EXPECT_EQ(q.getType(), q2->getType());
  583. EXPECT_EQ(q.getClass(), q2->getClass());
  584. }
  585. // Test it tries the correct amount of times before giving up
  586. TEST_F(ASIOLinkTest, recursiveTimeout) {
  587. // Prepare the service (we do not use the common setup, we do not answer
  588. setDNSService();
  589. // Prepare the socket
  590. res_ = resolveAddress(AF_INET, IPPROTO_UDP, true);
  591. sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  592. if (sock_ < 0) {
  593. isc_throw(IOError, "failed to open test socket");
  594. }
  595. if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
  596. isc_throw(IOError, "failed to bind test socket");
  597. }
  598. // Prepare the server
  599. bool done(true);
  600. MockServerStop server(*io_service_, &done);
  601. // Do the answer
  602. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  603. RecursiveQuery query(*dns_service_, singleAddress(TEST_IPV4_ADDR, port),
  604. 10, 2);
  605. Question question(Name("example.net"), RRClass::IN(), RRType::A());
  606. OutputBufferPtr buffer(new OutputBuffer(0));
  607. query.sendQuery(question, buffer, &server);
  608. // Run the test
  609. io_service_->run();
  610. // Read up to 3 packets. Use some ad hoc timeout to prevent an infinite
  611. // block (see also recvUDP()).
  612. const struct timeval timeo = { 10, 0 };
  613. int recv_options = 0;
  614. if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo))) {
  615. if (errno == ENOPROTOOPT) { // see ASIOLinkTest::recvUDP()
  616. recv_options = MSG_DONTWAIT;
  617. } else {
  618. isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
  619. }
  620. }
  621. int num = 0;
  622. do {
  623. char inbuff[512];
  624. if (recv(sock_, inbuff, sizeof(inbuff), recv_options) < 0) {
  625. num = -1;
  626. break;
  627. }
  628. } while (++num < 3);
  629. // The query should fail
  630. EXPECT_FALSE(done);
  631. EXPECT_EQ(3, num);
  632. }
  633. // This fixture is for testing IntervalTimer. Some callback functors are
  634. // registered as callback function of the timer to test if they are called
  635. // or not.
  636. class IntervalTimerTest : public ::testing::Test {
  637. protected:
  638. IntervalTimerTest() : io_service_() {};
  639. ~IntervalTimerTest() {}
  640. class TimerCallBack : public std::unary_function<void, void> {
  641. public:
  642. TimerCallBack(IntervalTimerTest* test_obj) : test_obj_(test_obj) {}
  643. void operator()() const {
  644. test_obj_->timer_called_ = true;
  645. test_obj_->io_service_.stop();
  646. return;
  647. }
  648. private:
  649. IntervalTimerTest* test_obj_;
  650. };
  651. class TimerCallBackCounter : public std::unary_function<void, void> {
  652. public:
  653. TimerCallBackCounter(IntervalTimerTest* test_obj) : test_obj_(test_obj) {
  654. counter_ = 0;
  655. }
  656. void operator()() {
  657. ++counter_;
  658. return;
  659. }
  660. int counter_;
  661. private:
  662. IntervalTimerTest* test_obj_;
  663. };
  664. class TimerCallBackCancelDeleter : public std::unary_function<void, void> {
  665. public:
  666. TimerCallBackCancelDeleter(IntervalTimerTest* test_obj,
  667. IntervalTimer* timer,
  668. TimerCallBackCounter& counter)
  669. : test_obj_(test_obj), timer_(timer), counter_(counter), count_(0)
  670. {}
  671. void operator()() {
  672. ++count_;
  673. if (count_ == 1) {
  674. // First time of call back.
  675. // Store the value of counter_.counter_.
  676. prev_counter_ = counter_.counter_;
  677. delete timer_;
  678. } else if (count_ == 2) {
  679. // Second time of call back.
  680. // Stop io_service to stop all timers.
  681. test_obj_->io_service_.stop();
  682. // Compare the value of counter_.counter_ with stored one.
  683. // If TimerCallBackCounter was not called (expected behavior),
  684. // they are same.
  685. if (counter_.counter_ == prev_counter_) {
  686. test_obj_->timer_cancel_success_ = true;
  687. }
  688. }
  689. return;
  690. }
  691. private:
  692. IntervalTimerTest* test_obj_;
  693. IntervalTimer* timer_;
  694. TimerCallBackCounter& counter_;
  695. int count_;
  696. int prev_counter_;
  697. };
  698. class TimerCallBackOverwriter : public std::unary_function<void, void> {
  699. public:
  700. TimerCallBackOverwriter(IntervalTimerTest* test_obj,
  701. IntervalTimer& timer)
  702. : test_obj_(test_obj), timer_(timer), count_(0)
  703. {}
  704. void operator()() {
  705. ++count_;
  706. if (count_ == 1) {
  707. // First time of call back.
  708. // Call setupTimer() to update callback function
  709. // to TimerCallBack.
  710. test_obj_->timer_called_ = false;
  711. timer_.setupTimer(TimerCallBack(test_obj_), 1);
  712. } else if (count_ == 2) {
  713. // Second time of call back.
  714. // If it reaches here, re-setupTimer() is failed (unexpected).
  715. // We should stop here.
  716. test_obj_->io_service_.stop();
  717. }
  718. return;
  719. }
  720. private:
  721. IntervalTimerTest* test_obj_;
  722. IntervalTimer& timer_;
  723. int count_;
  724. };
  725. protected:
  726. IOService io_service_;
  727. bool timer_called_;
  728. bool timer_cancel_success_;
  729. };
  730. TEST_F(IntervalTimerTest, invalidArgumentToIntervalTimer) {
  731. // Create asio_link::IntervalTimer and setup.
  732. IntervalTimer itimer(io_service_);
  733. // expect throw if call back function is empty
  734. EXPECT_THROW(itimer.setupTimer(IntervalTimer::Callback(), 1),
  735. isc::InvalidParameter);
  736. // expect throw if interval is 0
  737. EXPECT_THROW(itimer.setupTimer(TimerCallBack(this), 0), isc::BadValue);
  738. }
  739. TEST_F(IntervalTimerTest, startIntervalTimer) {
  740. // Create asio_link::IntervalTimer and setup.
  741. // Then run IOService and test if the callback function is called.
  742. IntervalTimer itimer(io_service_);
  743. timer_called_ = false;
  744. // store start time
  745. boost::posix_time::ptime start;
  746. start = boost::posix_time::microsec_clock::universal_time();
  747. // setup timer
  748. itimer.setupTimer(TimerCallBack(this), 1);
  749. io_service_.run();
  750. // reaches here after timer expired
  751. // delta: difference between elapsed time and 1 second
  752. boost::posix_time::time_duration delta =
  753. (boost::posix_time::microsec_clock::universal_time() - start)
  754. - boost::posix_time::seconds(1);
  755. if (delta.is_negative()) {
  756. delta.invert_sign();
  757. }
  758. // expect TimerCallBack is called; timer_called_ is true
  759. EXPECT_TRUE(timer_called_);
  760. // expect interval is 1 second +/- TIMER_MARGIN_MSEC.
  761. EXPECT_TRUE(delta < TIMER_MARGIN_MSEC);
  762. }
  763. TEST_F(IntervalTimerTest, destructIntervalTimer) {
  764. // Note: This test currently takes 6 seconds. The timer should have
  765. // finer granularity and timer periods in this test should be shorter
  766. // in the future.
  767. // This code isn't exception safe, but we'd rather keep the code
  768. // simpler and more readable as this is only for tests and if it throws
  769. // the program would immediately terminate anyway.
  770. // The call back function will not be called after the timer is
  771. // destructed.
  772. //
  773. // There are two timers:
  774. // itimer_counter (A)
  775. // (Calls TimerCallBackCounter)
  776. // - increments internal counter in callback function
  777. // itimer_canceller (B)
  778. // (Calls TimerCallBackCancelDeleter)
  779. // - first time of callback, it stores the counter value of
  780. // callback_canceller and destructs itimer_counter
  781. // - second time of callback, it compares the counter value of
  782. // callback_canceller with stored value
  783. // if they are same the timer was not called; expected result
  784. // if they are different the timer was called after destructed
  785. //
  786. // 0 1 2 3 4 5 6 (s)
  787. // (A) i-----+--x
  788. // ^
  789. // |destruct itimer_counter
  790. // (B) i--------+--------s
  791. // ^stop io_service
  792. // and test itimer_counter have been stopped
  793. //
  794. // itimer_counter will be deleted in TimerCallBackCancelDeleter
  795. IntervalTimer* itimer_counter = new IntervalTimer(io_service_);
  796. IntervalTimer itimer_canceller(io_service_);
  797. timer_cancel_success_ = false;
  798. TimerCallBackCounter callback_canceller(this);
  799. itimer_counter->setupTimer(callback_canceller, 2);
  800. itimer_canceller.setupTimer(
  801. TimerCallBackCancelDeleter(this, itimer_counter,
  802. callback_canceller),
  803. 3);
  804. io_service_.run();
  805. EXPECT_TRUE(timer_cancel_success_);
  806. }
  807. TEST_F(IntervalTimerTest, overwriteIntervalTimer) {
  808. // Note: This test currently takes 4 seconds. The timer should have
  809. // finer granularity and timer periods in this test should be shorter
  810. // in the future.
  811. // Calling setupTimer() multiple times updates call back function
  812. // and interval.
  813. //
  814. // There are two timers:
  815. // itimer (A)
  816. // (Calls TimerCallBackCounter / TimerCallBack)
  817. // - increments internal counter in callback function
  818. // (TimerCallBackCounter)
  819. // interval: 2 seconds
  820. // - io_service_.stop() (TimerCallBack)
  821. // interval: 1 second
  822. // itimer_overwriter (B)
  823. // (Calls TimerCallBackOverwriter)
  824. // - first time of callback, it calls setupTimer() to change
  825. // call back function and interval of itimer to
  826. // TimerCallBack / 1 second
  827. // after 3 + 1 seconds from the beginning of this test,
  828. // TimerCallBack() will be called and io_service_ stops.
  829. // - second time of callback, it means the test fails.
  830. //
  831. // 0 1 2 3 4 5 6 (s)
  832. // (A) i-----+--C--s
  833. // ^ ^stop io_service
  834. // |change call back function
  835. // (B) i--------+--------S
  836. // ^(stop io_service on fail)
  837. //
  838. IntervalTimer itimer(io_service_);
  839. IntervalTimer itimer_overwriter(io_service_);
  840. // store start time
  841. boost::posix_time::ptime start;
  842. start = boost::posix_time::microsec_clock::universal_time();
  843. itimer.setupTimer(TimerCallBackCounter(this), 2);
  844. itimer_overwriter.setupTimer(TimerCallBackOverwriter(this, itimer), 3);
  845. io_service_.run();
  846. // reaches here after timer expired
  847. // if interval is updated, it takes
  848. // 3 seconds for TimerCallBackOverwriter
  849. // + 1 second for TimerCallBack (stop)
  850. // = 4 seconds.
  851. // otherwise (test fails), it takes
  852. // 3 seconds for TimerCallBackOverwriter
  853. // + 3 seconds for TimerCallBackOverwriter (stop)
  854. // = 6 seconds.
  855. // delta: difference between elapsed time and 3 + 1 seconds
  856. boost::posix_time::time_duration delta =
  857. (boost::posix_time::microsec_clock::universal_time() - start)
  858. - boost::posix_time::seconds(3 + 1);
  859. if (delta.is_negative()) {
  860. delta.invert_sign();
  861. }
  862. // expect callback function is updated: TimerCallBack is called
  863. EXPECT_TRUE(timer_called_);
  864. // expect interval is updated
  865. EXPECT_TRUE(delta < TIMER_MARGIN_MSEC);
  866. }
  867. }