asiolink_unittest.cc 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  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. #include <config.h>
  15. #include <sys/socket.h>
  16. #include <sys/time.h>
  17. #include <string.h>
  18. #include <boost/lexical_cast.hpp>
  19. #include <boost/bind.hpp>
  20. #include <boost/date_time/posix_time/posix_time_types.hpp>
  21. #include <gtest/gtest.h>
  22. #include <exceptions/exceptions.h>
  23. #include <dns/tests/unittest_util.h>
  24. #include <dns/rcode.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(IOAddressTest, Equality) {
  68. EXPECT_TRUE(IOAddress("192.0.2.1") == IOAddress("192.0.2.1"));
  69. EXPECT_FALSE(IOAddress("192.0.2.1") != IOAddress("192.0.2.1"));
  70. EXPECT_TRUE(IOAddress("192.0.2.1") != IOAddress("192.0.2.2"));
  71. EXPECT_FALSE(IOAddress("192.0.2.1") == IOAddress("192.0.2.2"));
  72. EXPECT_TRUE(IOAddress("2001:db8::12") == IOAddress("2001:0DB8:0:0::0012"));
  73. EXPECT_FALSE(IOAddress("2001:db8::12") != IOAddress("2001:0DB8:0:0::0012"));
  74. EXPECT_TRUE(IOAddress("2001:db8::1234") != IOAddress("2001:db8::1235"));
  75. EXPECT_FALSE(IOAddress("2001:db8::1234") == IOAddress("2001:db8::1235"));
  76. EXPECT_TRUE(IOAddress("2001:db8::1234") != IOAddress("192.0.2.3"));
  77. EXPECT_FALSE(IOAddress("2001:db8::1234") == IOAddress("192.0.2.3"));
  78. }
  79. TEST(IOEndpointTest, createUDPv4) {
  80. const IOEndpoint* ep;
  81. ep = IOEndpoint::create(IPPROTO_UDP, IOAddress("192.0.2.1"), 5300);
  82. EXPECT_EQ("192.0.2.1", ep->getAddress().toText());
  83. EXPECT_EQ(5300, ep->getPort());
  84. EXPECT_EQ(AF_INET, ep->getFamily());
  85. EXPECT_EQ(AF_INET, ep->getAddress().getFamily());
  86. EXPECT_EQ(IPPROTO_UDP, ep->getProtocol());
  87. }
  88. TEST(IOEndpointTest, createTCPv4) {
  89. const IOEndpoint* ep;
  90. ep = IOEndpoint::create(IPPROTO_TCP, IOAddress("192.0.2.1"), 5301);
  91. EXPECT_EQ("192.0.2.1", ep->getAddress().toText());
  92. EXPECT_EQ(5301, ep->getPort());
  93. EXPECT_EQ(AF_INET, ep->getFamily());
  94. EXPECT_EQ(AF_INET, ep->getAddress().getFamily());
  95. EXPECT_EQ(IPPROTO_TCP, ep->getProtocol());
  96. }
  97. TEST(IOEndpointTest, createUDPv6) {
  98. const IOEndpoint* ep;
  99. ep = IOEndpoint::create(IPPROTO_UDP, IOAddress("2001:db8::1234"), 5302);
  100. EXPECT_EQ("2001:db8::1234", ep->getAddress().toText());
  101. EXPECT_EQ(5302, ep->getPort());
  102. EXPECT_EQ(AF_INET6, ep->getFamily());
  103. EXPECT_EQ(AF_INET6, ep->getAddress().getFamily());
  104. EXPECT_EQ(IPPROTO_UDP, ep->getProtocol());
  105. }
  106. TEST(IOEndpointTest, createTCPv6) {
  107. const IOEndpoint* ep;
  108. ep = IOEndpoint::create(IPPROTO_TCP, IOAddress("2001:db8::1234"), 5303);
  109. EXPECT_EQ("2001:db8::1234", ep->getAddress().toText());
  110. EXPECT_EQ(5303, ep->getPort());
  111. EXPECT_EQ(AF_INET6, ep->getFamily());
  112. EXPECT_EQ(AF_INET6, ep->getAddress().getFamily());
  113. EXPECT_EQ(IPPROTO_TCP, ep->getProtocol());
  114. }
  115. TEST(IOEndpointTest, createIPProto) {
  116. EXPECT_THROW(IOEndpoint::create(IPPROTO_IP, IOAddress("192.0.2.1"),
  117. 5300)->getAddress().toText(),
  118. IOError);
  119. }
  120. TEST(IOSocketTest, dummySockets) {
  121. EXPECT_EQ(IPPROTO_UDP, IOSocket::getDummyUDPSocket().getProtocol());
  122. EXPECT_EQ(IPPROTO_TCP, IOSocket::getDummyTCPSocket().getProtocol());
  123. EXPECT_EQ(-1, IOSocket::getDummyUDPSocket().getNative());
  124. EXPECT_EQ(-1, IOSocket::getDummyTCPSocket().getNative());
  125. }
  126. TEST(IOServiceTest, badPort) {
  127. IOService io_service;
  128. EXPECT_THROW(DNSService(io_service, *"65536", true, false, NULL, NULL, NULL), IOError);
  129. EXPECT_THROW(DNSService(io_service, *"5300.0", true, false, NULL, NULL, NULL), IOError);
  130. EXPECT_THROW(DNSService(io_service, *"-1", true, false, NULL, NULL, NULL), IOError);
  131. EXPECT_THROW(DNSService(io_service, *"domain", true, false, NULL, NULL, NULL), IOError);
  132. }
  133. TEST(IOServiceTest, badAddress) {
  134. IOService io_service;
  135. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"192.0.2.1.1", NULL, NULL, NULL), IOError);
  136. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"2001:db8:::1", NULL, NULL, NULL), IOError);
  137. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"localhost", NULL, NULL, NULL), IOError);
  138. }
  139. TEST(IOServiceTest, unavailableAddress) {
  140. IOService io_service;
  141. // These addresses should generally be unavailable as a valid local
  142. // address, although there's no guarantee in theory.
  143. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"192.0.2.0", NULL, NULL, NULL), IOError);
  144. // Some OSes would simply reject binding attempt for an AF_INET6 socket
  145. // to an IPv4-mapped IPv6 address. Even if those that allow it, since
  146. // the corresponding IPv4 address is the same as the one used in the
  147. // AF_INET socket case above, it should at least show the same result
  148. // as the previous one.
  149. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:192.0.2.0", NULL, NULL, NULL), IOError);
  150. }
  151. TEST(IOServiceTest, duplicateBind_v6) {
  152. // In each sub test case, second attempt should fail due to duplicate bind
  153. IOService io_service;
  154. // IPv6, "any" address
  155. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, false, true, NULL, NULL, NULL);
  156. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, false, true, NULL, NULL, NULL), IOError);
  157. delete dns_service;
  158. }
  159. TEST(IOServiceTest, duplicateBind_v6_address) {
  160. // In each sub test case, second attempt should fail due to duplicate bind
  161. IOService io_service;
  162. // IPv6, specific address
  163. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL);
  164. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV6_ADDR, NULL, NULL, NULL), IOError);
  165. delete dns_service;
  166. }
  167. TEST(IOServiceTest, duplicateBind_v4) {
  168. // In each sub test case, second attempt should fail due to duplicate bind
  169. IOService io_service;
  170. // IPv4, "any" address
  171. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, true, false, NULL, NULL, NULL);
  172. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, true, false, NULL, NULL, NULL), IOError);
  173. delete dns_service;
  174. }
  175. TEST(IOServiceTest, duplicateBind_v4_address) {
  176. // In each sub test case, second attempt should fail due to duplicate bind
  177. IOService io_service;
  178. // IPv4, specific address
  179. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL);
  180. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *TEST_IPV4_ADDR, NULL, NULL, NULL), IOError);
  181. delete dns_service;
  182. }
  183. // Disabled because IPv4-mapped addresses don't seem to be working with
  184. // the IOService constructor
  185. TEST(IOServiceTest, DISABLED_IPv4MappedDuplicateBind) {
  186. IOService io_service;
  187. // Duplicate bind on IPv4-mapped IPv6 address
  188. DNSService* dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *"127.0.0.1", NULL, NULL, NULL);
  189. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:127.0.0.1", NULL, NULL, NULL), IOError);
  190. delete dns_service;
  191. // XXX:
  192. // Currently, this throws an "invalid argument" exception. I have
  193. // not been able to get IPv4-mapped addresses to work.
  194. dns_service = new DNSService(io_service, *TEST_SERVER_PORT, *"::ffff:127.0.0.1", NULL, NULL, NULL);
  195. EXPECT_THROW(DNSService(io_service, *TEST_SERVER_PORT, *"127.0.0.1", NULL, NULL, NULL), IOError);
  196. delete dns_service;
  197. }
  198. // This function returns an addrinfo structure for use by tests, using
  199. // different addresses and ports depending on whether we're testing
  200. // IPv4 or v6, TCP or UDP, and client or server operation.
  201. struct addrinfo*
  202. resolveAddress(const int family, const int protocol, const bool client) {
  203. const char* const addr = (family == AF_INET6) ?
  204. TEST_IPV6_ADDR : TEST_IPV4_ADDR;
  205. const char* const port = client ? TEST_CLIENT_PORT : TEST_SERVER_PORT;
  206. struct addrinfo hints;
  207. memset(&hints, 0, sizeof(hints));
  208. hints.ai_family = family;
  209. hints.ai_socktype = (protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
  210. hints.ai_protocol = protocol;
  211. hints.ai_flags = AI_NUMERICSERV;
  212. struct addrinfo* res;
  213. const int error = getaddrinfo(addr, port, &hints, &res);
  214. if (error != 0) {
  215. isc_throw(IOError, "getaddrinfo failed: " << gai_strerror(error));
  216. }
  217. return (res);
  218. }
  219. // This fixture is a framework for various types of network operations
  220. // using the ASIO interfaces. Each test case creates an IOService object,
  221. // opens a local "client" socket for testing, sends data via the local socket
  222. // to the service that would run in the IOService object.
  223. // A mock callback function (an ASIOCallBack object) is registered with the
  224. // IOService object, so the test code should be able to examine the data
  225. // received on the server side. It then checks the received data matches
  226. // expected parameters.
  227. // If initialization parameters of the IOService should be modified, the test
  228. // case can do it using the setDNSService() method.
  229. // Note: the set of tests in ASIOLinkTest use actual network services and may
  230. // involve undesirable side effects such as blocking.
  231. class ASIOLinkTest : public ::testing::Test {
  232. protected:
  233. ASIOLinkTest();
  234. ~ASIOLinkTest() {
  235. if (res_ != NULL) {
  236. freeaddrinfo(res_);
  237. }
  238. if (sock_ != -1) {
  239. close(sock_);
  240. }
  241. delete dns_service_;
  242. delete callback_;
  243. delete io_service_;
  244. }
  245. // Send a test UDP packet to a mock server
  246. void sendUDP(const int family) {
  247. res_ = resolveAddress(family, IPPROTO_UDP, false);
  248. sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  249. if (sock_ < 0) {
  250. isc_throw(IOError, "failed to open test socket");
  251. }
  252. const int cc = sendto(sock_, test_data, sizeof(test_data), 0,
  253. res_->ai_addr, res_->ai_addrlen);
  254. if (cc != sizeof(test_data)) {
  255. isc_throw(IOError, "unexpected sendto result: " << cc);
  256. }
  257. io_service_->run();
  258. }
  259. // Send a test TCP packet to a mock server
  260. void sendTCP(const int family) {
  261. res_ = resolveAddress(family, IPPROTO_TCP, false);
  262. sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  263. if (sock_ < 0) {
  264. isc_throw(IOError, "failed to open test socket");
  265. }
  266. if (connect(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
  267. isc_throw(IOError, "failed to connect to the test server");
  268. }
  269. const int cc = send(sock_, test_data, sizeof(test_data), 0);
  270. if (cc != sizeof(test_data)) {
  271. isc_throw(IOError, "unexpected send result: " << cc);
  272. }
  273. io_service_->run();
  274. }
  275. // Receive a UDP packet from a mock server; used for testing
  276. // recursive lookup. The caller must place a RecursiveQuery
  277. // on the IO Service queue before running this routine.
  278. void recvUDP(const int family, void* buffer, size_t& size) {
  279. res_ = resolveAddress(family, IPPROTO_UDP, true);
  280. sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  281. if (sock_ < 0) {
  282. isc_throw(IOError, "failed to open test socket");
  283. }
  284. if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
  285. isc_throw(IOError, "bind failed: " << strerror(errno));
  286. }
  287. // The IO service queue should have a RecursiveQuery object scheduled
  288. // to run at this point. This call will cause it to begin an
  289. // async send, then return.
  290. io_service_->run_one();
  291. // ... and this one will block until the send has completed
  292. io_service_->run_one();
  293. // Now we attempt to recv() whatever was sent.
  294. // XXX: there's no guarantee the receiving socket can immediately get
  295. // the packet. Normally we can perform blocking recv to wait for it,
  296. // but in theory it's even possible that the packet is lost.
  297. // In order to prevent the test from hanging in such a worst case
  298. // we add an ad hoc timeout.
  299. const struct timeval timeo = { 10, 0 };
  300. int recv_options = 0;
  301. if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo,
  302. sizeof(timeo))) {
  303. if (errno == ENOPROTOOPT) {
  304. // Workaround for Solaris: it doesn't accept SO_RCVTIMEO
  305. // with the error of ENOPROTOOPT. Since this is a workaround
  306. // for rare error cases anyway, we simply switch to the
  307. // "don't wait" mode. If we still find an error in recv()
  308. // can happen often we'll consider a more complete solution.
  309. recv_options = MSG_DONTWAIT;
  310. } else {
  311. isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
  312. }
  313. }
  314. const int ret = recv(sock_, buffer, size, recv_options);
  315. if (ret < 0) {
  316. isc_throw(IOError, "recvfrom failed: " << strerror(errno));
  317. }
  318. // Pass the message size back via the size parameter
  319. size = ret;
  320. }
  321. // Set up an IO Service queue using the specified address
  322. void setDNSService(const char& address) {
  323. delete dns_service_;
  324. dns_service_ = NULL;
  325. delete io_service_;
  326. io_service_ = new IOService();
  327. callback_ = new ASIOCallBack(this);
  328. dns_service_ = new DNSService(*io_service_, *TEST_SERVER_PORT, address, callback_, NULL, NULL);
  329. }
  330. // Set up an IO Service queue using the "any" address, on IPv4 if
  331. // 'use_ipv4' is true and on IPv6 if 'use_ipv6' is true.
  332. void setDNSService(const bool use_ipv4, const bool use_ipv6) {
  333. delete dns_service_;
  334. dns_service_ = NULL;
  335. delete io_service_;
  336. io_service_ = new IOService();
  337. callback_ = new ASIOCallBack(this);
  338. dns_service_ = new DNSService(*io_service_, *TEST_SERVER_PORT, use_ipv4, use_ipv6, callback_,
  339. NULL, NULL);
  340. }
  341. // Set up empty DNS Service
  342. // Set up an IO Service queue without any addresses
  343. void setDNSService() {
  344. delete dns_service_;
  345. dns_service_ = NULL;
  346. delete io_service_;
  347. io_service_ = new IOService();
  348. callback_ = new ASIOCallBack(this);
  349. dns_service_ = new DNSService(*io_service_, callback_, NULL, NULL);
  350. }
  351. // Run a simple server test, on either IPv4 or IPv6, and over either
  352. // UDP or TCP. Calls the sendUDP() or sendTCP() methods, which will
  353. // start the IO Service queue. The UDPServer or TCPServer that was
  354. // created by setIOService() will receive the test packet and issue a
  355. // callback, which enables us to check that the data it received
  356. // matches what we sent.
  357. void doTest(const int family, const int protocol) {
  358. if (protocol == IPPROTO_UDP) {
  359. sendUDP(family);
  360. } else {
  361. sendTCP(family);
  362. }
  363. // There doesn't seem to be an effective test for the validity of
  364. // 'native'.
  365. // One thing we are sure is it must be different from our local socket.
  366. EXPECT_NE(sock_, callback_native_);
  367. EXPECT_EQ(protocol, callback_protocol_);
  368. EXPECT_EQ(family == AF_INET6 ? TEST_IPV6_ADDR : TEST_IPV4_ADDR,
  369. callback_address_);
  370. const uint8_t* expected_data =
  371. protocol == IPPROTO_UDP ? test_data : test_data + 2;
  372. const size_t expected_datasize =
  373. protocol == IPPROTO_UDP ? sizeof(test_data) :
  374. sizeof(test_data) - 2;
  375. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
  376. callback_data_.size(),
  377. expected_data, expected_datasize);
  378. }
  379. protected:
  380. // This is a nonfunctional mockup of a DNSServer object. Its purpose
  381. // is to resume after a recursive query or other asynchronous call
  382. // has completed.
  383. class MockServer : public DNSServer {
  384. public:
  385. explicit MockServer(IOService& io_service,
  386. SimpleCallback* checkin = NULL,
  387. DNSLookup* lookup = NULL,
  388. DNSAnswer* answer = NULL) :
  389. io_(io_service),
  390. message_(new Message(Message::PARSE)),
  391. answer_message_(new Message(Message::RENDER)),
  392. respbuf_(new OutputBuffer(0)),
  393. checkin_(checkin), lookup_(lookup), answer_(answer)
  394. {}
  395. void operator()(asio::error_code ec = asio::error_code(),
  396. size_t length = 0)
  397. {}
  398. void resume(const bool) {
  399. // should never be called in our tests
  400. }
  401. DNSServer* clone() {
  402. MockServer* s = new MockServer(*this);
  403. return (s);
  404. }
  405. inline void asyncLookup() {
  406. if (lookup_) {
  407. (*lookup_)(*io_message_, message_, answer_message_,
  408. respbuf_, this);
  409. }
  410. }
  411. protected:
  412. IOService& io_;
  413. bool done_;
  414. private:
  415. // Currently unused; these will be used for testing
  416. // asynchronous lookup calls via the asyncLookup() method
  417. boost::shared_ptr<asiolink::IOMessage> io_message_;
  418. isc::dns::MessagePtr message_;
  419. isc::dns::MessagePtr answer_message_;
  420. isc::dns::OutputBufferPtr respbuf_;
  421. // Callback functions provided by the caller
  422. const SimpleCallback* checkin_;
  423. const DNSLookup* lookup_;
  424. const DNSAnswer* answer_;
  425. };
  426. // This version of mock server just stops the io_service when it is resumed
  427. class MockServerStop : public MockServer {
  428. public:
  429. explicit MockServerStop(IOService& io_service, bool* done) :
  430. MockServer(io_service),
  431. done_(done)
  432. {}
  433. void resume(const bool done) {
  434. *done_ = done;
  435. io_.stop();
  436. }
  437. DNSServer* clone() {
  438. return (new MockServerStop(*this));
  439. }
  440. private:
  441. bool* done_;
  442. };
  443. private:
  444. class ASIOCallBack : public SimpleCallback {
  445. public:
  446. ASIOCallBack(ASIOLinkTest* test_obj) : test_obj_(test_obj) {}
  447. void operator()(const IOMessage& io_message) const {
  448. test_obj_->callBack(io_message);
  449. }
  450. private:
  451. ASIOLinkTest* test_obj_;
  452. };
  453. void callBack(const IOMessage& io_message) {
  454. callback_protocol_ = io_message.getSocket().getProtocol();
  455. callback_native_ = io_message.getSocket().getNative();
  456. callback_address_ =
  457. io_message.getRemoteEndpoint().getAddress().toText();
  458. callback_data_.assign(
  459. static_cast<const uint8_t*>(io_message.getData()),
  460. static_cast<const uint8_t*>(io_message.getData()) +
  461. io_message.getDataSize());
  462. io_service_->stop();
  463. }
  464. protected:
  465. // We use a pointer for io_service_, because for some tests we
  466. // need to recreate a new one within one onstance of this class
  467. IOService* io_service_;
  468. DNSService* dns_service_;
  469. ASIOCallBack* callback_;
  470. int callback_protocol_;
  471. int callback_native_;
  472. string callback_address_;
  473. vector<uint8_t> callback_data_;
  474. int sock_;
  475. struct addrinfo* res_;
  476. };
  477. ASIOLinkTest::ASIOLinkTest() :
  478. dns_service_(NULL), callback_(NULL), sock_(-1), res_(NULL)
  479. {
  480. io_service_ = new IOService();
  481. setDNSService(true, true);
  482. }
  483. TEST_F(ASIOLinkTest, v6UDPSend) {
  484. doTest(AF_INET6, IPPROTO_UDP);
  485. }
  486. TEST_F(ASIOLinkTest, v6TCPSend) {
  487. doTest(AF_INET6, IPPROTO_TCP);
  488. }
  489. TEST_F(ASIOLinkTest, v4UDPSend) {
  490. doTest(AF_INET, IPPROTO_UDP);
  491. }
  492. TEST_F(ASIOLinkTest, v4TCPSend) {
  493. doTest(AF_INET, IPPROTO_TCP);
  494. }
  495. TEST_F(ASIOLinkTest, v6UDPSendSpecific) {
  496. // Explicitly set a specific address to be bound to the socket.
  497. // The subsequent test does not directly ensures the underlying socket
  498. // is bound to the expected address, but the success of the tests should
  499. // reasonably suggest it works as intended.
  500. // Specifying an address also implicitly means the service runs in a
  501. // single address-family mode. In tests using TCP we can confirm that
  502. // by trying to make a connection and seeing a failure. In UDP, it'd be
  503. // more complicated because we need to use a connected socket and catch
  504. // an error on a subsequent read operation. We could do it, but for
  505. // simplicity we only tests the easier cases for now.
  506. setDNSService(*TEST_IPV6_ADDR);
  507. doTest(AF_INET6, IPPROTO_UDP);
  508. }
  509. TEST_F(ASIOLinkTest, v6TCPSendSpecific) {
  510. setDNSService(*TEST_IPV6_ADDR);
  511. doTest(AF_INET6, IPPROTO_TCP);
  512. EXPECT_THROW(sendTCP(AF_INET), IOError);
  513. }
  514. TEST_F(ASIOLinkTest, v4UDPSendSpecific) {
  515. setDNSService(*TEST_IPV4_ADDR);
  516. doTest(AF_INET, IPPROTO_UDP);
  517. }
  518. TEST_F(ASIOLinkTest, v4TCPSendSpecific) {
  519. setDNSService(*TEST_IPV4_ADDR);
  520. doTest(AF_INET, IPPROTO_TCP);
  521. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  522. }
  523. TEST_F(ASIOLinkTest, v6AddServer) {
  524. setDNSService();
  525. dns_service_->addServer(*TEST_SERVER_PORT, TEST_IPV6_ADDR);
  526. doTest(AF_INET6, IPPROTO_TCP);
  527. EXPECT_THROW(sendTCP(AF_INET), IOError);
  528. }
  529. TEST_F(ASIOLinkTest, v4AddServer) {
  530. setDNSService();
  531. dns_service_->addServer(*TEST_SERVER_PORT, TEST_IPV4_ADDR);
  532. doTest(AF_INET, IPPROTO_TCP);
  533. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  534. }
  535. TEST_F(ASIOLinkTest, DISABLED_clearServers) {
  536. // FIXME: Enable when clearServers actually close the sockets
  537. // See #388
  538. setDNSService();
  539. dns_service_->clearServers();
  540. EXPECT_THROW(sendTCP(AF_INET), IOError);
  541. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  542. }
  543. TEST_F(ASIOLinkTest, v6TCPOnly) {
  544. // Open only IPv6 TCP socket. A subsequent attempt of establishing an
  545. // IPv4/TCP connection should fail. See above for why we only test this
  546. // for TCP.
  547. setDNSService(false, true);
  548. EXPECT_THROW(sendTCP(AF_INET), IOError);
  549. }
  550. TEST_F(ASIOLinkTest, v4TCPOnly) {
  551. setDNSService(true, false);
  552. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  553. }
  554. vector<pair<string, uint16_t> >
  555. singleAddress(const string &address, uint16_t port) {
  556. vector<pair<string, uint16_t> > result;
  557. result.push_back(pair<string, uint16_t>(address, port));
  558. return (result);
  559. }
  560. TEST_F(ASIOLinkTest, recursiveSetupV4) {
  561. setDNSService(true, false);
  562. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  563. EXPECT_NO_THROW(RecursiveQuery(*dns_service_,
  564. singleAddress(TEST_IPV4_ADDR, port),
  565. singleAddress(TEST_IPV4_ADDR, port)));
  566. }
  567. TEST_F(ASIOLinkTest, recursiveSetupV6) {
  568. setDNSService(false, true);
  569. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  570. EXPECT_NO_THROW(RecursiveQuery(*dns_service_,
  571. singleAddress(TEST_IPV6_ADDR, port),
  572. singleAddress(TEST_IPV6_ADDR,port)));
  573. }
  574. // XXX:
  575. // This is very inadequate unit testing. It should be generalized into
  576. // a routine that can do this with variable address family, address, and
  577. // port, and with the various callbacks defined in such a way as to ensure
  578. // full code coverage including error cases.
  579. TEST_F(ASIOLinkTest, forwarderSend) {
  580. setDNSService(true, false);
  581. // Note: We use the test prot plus one to ensure we aren't binding
  582. // to the same port as the actual server
  583. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  584. MockServer server(*io_service_);
  585. RecursiveQuery rq(*dns_service_,
  586. singleAddress(TEST_IPV4_ADDR, port),
  587. singleAddress(TEST_IPV4_ADDR, port));
  588. Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
  589. OutputBufferPtr buffer(new OutputBuffer(0));
  590. MessagePtr answer(new Message(Message::RENDER));
  591. rq.resolve(q, answer, buffer, &server);
  592. char data[4096];
  593. size_t size = sizeof(data);
  594. ASSERT_NO_THROW(recvUDP(AF_INET, data, size));
  595. Message m(Message::PARSE);
  596. InputBuffer ibuf(data, size);
  597. // Make sure we can parse the message that was sent
  598. EXPECT_NO_THROW(m.parseHeader(ibuf));
  599. EXPECT_NO_THROW(m.fromWire(ibuf));
  600. // Check that the question sent matches the one we wanted
  601. QuestionPtr q2 = *m.beginQuestion();
  602. EXPECT_EQ(q.getName(), q2->getName());
  603. EXPECT_EQ(q.getType(), q2->getType());
  604. EXPECT_EQ(q.getClass(), q2->getClass());
  605. }
  606. int
  607. createTestSocket()
  608. {
  609. struct addrinfo* res_ = resolveAddress(AF_INET, IPPROTO_UDP, true);
  610. int sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
  611. if (sock_ < 0) {
  612. isc_throw(IOError, "failed to open test socket");
  613. }
  614. if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
  615. isc_throw(IOError, "failed to bind test socket");
  616. }
  617. return sock_;
  618. }
  619. int
  620. setSocketTimeout(int sock_, size_t tv_sec, size_t tv_usec) {
  621. const struct timeval timeo = { tv_sec, tv_usec };
  622. int recv_options = 0;
  623. if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo))) {
  624. if (errno == ENOPROTOOPT) { // see ASIOLinkTest::recvUDP()
  625. recv_options = MSG_DONTWAIT;
  626. } else {
  627. isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
  628. }
  629. }
  630. return recv_options;
  631. }
  632. // try to read from the socket max time
  633. // *num is incremented for every succesfull read
  634. // returns true if it can read max times, false otherwise
  635. bool tryRead(int sock_, int recv_options, size_t max, int* num) {
  636. size_t i = 0;
  637. do {
  638. char inbuff[512];
  639. if (recv(sock_, inbuff, sizeof(inbuff), recv_options) < 0) {
  640. return false;
  641. } else {
  642. ++i;
  643. ++*num;
  644. }
  645. } while (i < max);
  646. return true;
  647. }
  648. // Test it tries the correct amount of times before giving up
  649. TEST_F(ASIOLinkTest, forwardQueryTimeout) {
  650. // Prepare the service (we do not use the common setup, we do not answer
  651. setDNSService();
  652. // Prepare the socket
  653. sock_ = createTestSocket();
  654. // Prepare the server
  655. bool done(true);
  656. MockServerStop server(*io_service_, &done);
  657. // Do the answer
  658. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  659. RecursiveQuery query(*dns_service_,
  660. singleAddress(TEST_IPV4_ADDR, port),
  661. singleAddress(TEST_IPV4_ADDR, port),
  662. 10, 4000, 3000, 2);
  663. Question question(Name("example.net"), RRClass::IN(), RRType::A());
  664. OutputBufferPtr buffer(new OutputBuffer(0));
  665. MessagePtr answer(new Message(Message::RENDER));
  666. query.resolve(question, answer, buffer, &server);
  667. // Run the test
  668. io_service_->run();
  669. // Read up to 3 packets. Use some ad hoc timeout to prevent an infinite
  670. // block (see also recvUDP()).
  671. int recv_options = setSocketTimeout(sock_, 10, 0);
  672. int num = 0;
  673. bool read_success = tryRead(sock_, recv_options, 3, &num);
  674. // The query should fail
  675. EXPECT_FALSE(done);
  676. EXPECT_EQ(3, num);
  677. EXPECT_TRUE(read_success);
  678. }
  679. // If we set client timeout to lower than querytimeout, we should
  680. // get a failure answer, but still see retries
  681. // (no actual answer is given here yet)
  682. TEST_F(ASIOLinkTest, forwardClientTimeout) {
  683. // Prepare the service (we do not use the common setup, we do not answer
  684. setDNSService();
  685. sock_ = createTestSocket();
  686. // Prepare the server
  687. bool done(true);
  688. MockServerStop server(*io_service_, &done);
  689. MessagePtr answer(new Message(Message::RENDER));
  690. // Do the answer
  691. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  692. // Set it up to retry twice before client timeout fires
  693. // Since the lookup timer has not fired, it should retry
  694. // a third time
  695. RecursiveQuery query(*dns_service_,
  696. singleAddress(TEST_IPV4_ADDR, port),
  697. singleAddress(TEST_IPV4_ADDR, port),
  698. 50, 120, 1000, 3);
  699. Question question(Name("example.net"), RRClass::IN(), RRType::A());
  700. OutputBufferPtr buffer(new OutputBuffer(0));
  701. query.resolve(question, answer, buffer, &server);
  702. // Run the test
  703. io_service_->run();
  704. // we know it'll fail, so make it a shorter timeout
  705. int recv_options = setSocketTimeout(sock_, 1, 0);
  706. // Try to read 5 times, should stop after 3 reads
  707. int num = 0;
  708. bool read_success = tryRead(sock_, recv_options, 5, &num);
  709. // The query should fail (for resolver it should send back servfail,
  710. // but currently, and perhaps for forwarder in general, the effect
  711. // will be the same as on a lookup timeout, i.e. no answer is sent
  712. // back)
  713. EXPECT_FALSE(done);
  714. EXPECT_EQ(3, num);
  715. EXPECT_FALSE(read_success);
  716. }
  717. // If we set lookup timeout to lower than querytimeout*retries, we should
  718. // fail before the full amount of retries
  719. TEST_F(ASIOLinkTest, forwardLookupTimeout) {
  720. // Prepare the service (we do not use the common setup, we do not answer
  721. setDNSService();
  722. // Prepare the socket
  723. sock_ = createTestSocket();
  724. // Prepare the server
  725. bool done(true);
  726. MockServerStop server(*io_service_, &done);
  727. MessagePtr answer(new Message(Message::RENDER));
  728. // Do the answer
  729. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  730. // Set up the test so that it will retry 5 times, but the lookup
  731. // timeout will fire after only 3 normal timeouts
  732. RecursiveQuery query(*dns_service_,
  733. singleAddress(TEST_IPV4_ADDR, port),
  734. singleAddress(TEST_IPV4_ADDR, port),
  735. 50, 4000, 120, 5);
  736. Question question(Name("example.net"), RRClass::IN(), RRType::A());
  737. OutputBufferPtr buffer(new OutputBuffer(0));
  738. query.resolve(question, answer, buffer, &server);
  739. // Run the test
  740. io_service_->run();
  741. int recv_options = setSocketTimeout(sock_, 1, 0);
  742. // Try to read 5 times, should stop after 3 reads
  743. int num = 0;
  744. bool read_success = tryRead(sock_, recv_options, 5, &num);
  745. // The query should fail
  746. EXPECT_FALSE(done);
  747. EXPECT_EQ(3, num);
  748. EXPECT_FALSE(read_success);
  749. }
  750. // as mentioned above, we need a more better framework for this,
  751. // in addition to that, this sends out queries into the world
  752. // (which we should catch somehow and fake replies for)
  753. // for the skeleton code, it shouldn't be too much of a problem
  754. // Ok so even we don't all have access to the DNS world right now,
  755. // so disabling these tests too.
  756. TEST_F(ASIOLinkTest, DISABLED_recursiveSendOk) {
  757. setDNSService(true, false);
  758. bool done;
  759. MockServerStop server(*io_service_, &done);
  760. vector<pair<string, uint16_t> > empty_vector;
  761. RecursiveQuery rq(*dns_service_, empty_vector, empty_vector, 10000, 0);
  762. Question q(Name("www.isc.org"), RRClass::IN(), RRType::A());
  763. OutputBufferPtr buffer(new OutputBuffer(0));
  764. MessagePtr answer(new Message(Message::RENDER));
  765. rq.resolve(q, answer, buffer, &server);
  766. io_service_->run();
  767. // Check that the answer we got matches the one we wanted
  768. EXPECT_EQ(Rcode::NOERROR(), answer->getRcode());
  769. ASSERT_EQ(1, answer->getRRCount(Message::SECTION_ANSWER));
  770. RRsetPtr a = *answer->beginSection(Message::SECTION_ANSWER);
  771. EXPECT_EQ(q.getName(), a->getName());
  772. EXPECT_EQ(q.getType(), a->getType());
  773. EXPECT_EQ(q.getClass(), a->getClass());
  774. EXPECT_EQ(1, a->getRdataCount());
  775. }
  776. // see comments at previous test
  777. TEST_F(ASIOLinkTest, DISABLED_recursiveSendNXDOMAIN) {
  778. setDNSService(true, false);
  779. bool done;
  780. MockServerStop server(*io_service_, &done);
  781. vector<pair<string, uint16_t> > empty_vector;
  782. RecursiveQuery rq(*dns_service_, empty_vector, empty_vector, 10000, 0);
  783. Question q(Name("wwwdoesnotexist.isc.org"), RRClass::IN(), RRType::A());
  784. OutputBufferPtr buffer(new OutputBuffer(0));
  785. MessagePtr answer(new Message(Message::RENDER));
  786. rq.resolve(q, answer, buffer, &server);
  787. io_service_->run();
  788. // Check that the answer we got matches the one we wanted
  789. EXPECT_EQ(Rcode::NXDOMAIN(), answer->getRcode());
  790. EXPECT_EQ(0, answer->getRRCount(Message::SECTION_ANSWER));
  791. }
  792. // This fixture is for testing IntervalTimer. Some callback functors are
  793. // registered as callback function of the timer to test if they are called
  794. // or not.
  795. class IntervalTimerTest : public ::testing::Test {
  796. protected:
  797. IntervalTimerTest() : io_service_() {}
  798. ~IntervalTimerTest() {}
  799. class TimerCallBack : public std::unary_function<void, void> {
  800. public:
  801. TimerCallBack(IntervalTimerTest* test_obj) : test_obj_(test_obj) {}
  802. void operator()() const {
  803. test_obj_->timer_called_ = true;
  804. test_obj_->io_service_.stop();
  805. return;
  806. }
  807. private:
  808. IntervalTimerTest* test_obj_;
  809. };
  810. class TimerCallBackCounter : public std::unary_function<void, void> {
  811. public:
  812. TimerCallBackCounter(IntervalTimerTest* test_obj) : test_obj_(test_obj) {
  813. counter_ = 0;
  814. }
  815. void operator()() {
  816. ++counter_;
  817. return;
  818. }
  819. int counter_;
  820. private:
  821. IntervalTimerTest* test_obj_;
  822. };
  823. class TimerCallBackCancelDeleter : public std::unary_function<void, void> {
  824. public:
  825. TimerCallBackCancelDeleter(IntervalTimerTest* test_obj,
  826. IntervalTimer* timer,
  827. TimerCallBackCounter& counter)
  828. : test_obj_(test_obj), timer_(timer), counter_(counter), count_(0)
  829. {}
  830. void operator()() {
  831. ++count_;
  832. if (count_ == 1) {
  833. // First time of call back.
  834. // Store the value of counter_.counter_.
  835. prev_counter_ = counter_.counter_;
  836. delete timer_;
  837. } else if (count_ == 2) {
  838. // Second time of call back.
  839. // Stop io_service to stop all timers.
  840. test_obj_->io_service_.stop();
  841. // Compare the value of counter_.counter_ with stored one.
  842. // If TimerCallBackCounter was not called (expected behavior),
  843. // they are same.
  844. if (counter_.counter_ == prev_counter_) {
  845. test_obj_->timer_cancel_success_ = true;
  846. }
  847. }
  848. return;
  849. }
  850. private:
  851. IntervalTimerTest* test_obj_;
  852. IntervalTimer* timer_;
  853. TimerCallBackCounter& counter_;
  854. int count_;
  855. int prev_counter_;
  856. };
  857. class TimerCallBackCanceller {
  858. public:
  859. TimerCallBackCanceller(unsigned int& counter, IntervalTimer& itimer) :
  860. counter_(counter), itimer_(itimer)
  861. {}
  862. void operator()() {
  863. ++counter_;
  864. itimer_.cancel();
  865. }
  866. private:
  867. unsigned int& counter_;
  868. IntervalTimer& itimer_;
  869. };
  870. class TimerCallBackOverwriter : public std::unary_function<void, void> {
  871. public:
  872. TimerCallBackOverwriter(IntervalTimerTest* test_obj,
  873. IntervalTimer& timer)
  874. : test_obj_(test_obj), timer_(timer), count_(0)
  875. {}
  876. void operator()() {
  877. ++count_;
  878. if (count_ == 1) {
  879. // First time of call back.
  880. // Call setup() to update callback function to TimerCallBack.
  881. test_obj_->timer_called_ = false;
  882. timer_.setup(TimerCallBack(test_obj_), 100);
  883. } else if (count_ == 2) {
  884. // Second time of call back.
  885. // If it reaches here, re-setup() is failed (unexpected).
  886. // We should stop here.
  887. test_obj_->io_service_.stop();
  888. }
  889. return;
  890. }
  891. private:
  892. IntervalTimerTest* test_obj_;
  893. IntervalTimer& timer_;
  894. int count_;
  895. };
  896. protected:
  897. IOService io_service_;
  898. bool timer_called_;
  899. bool timer_cancel_success_;
  900. };
  901. TEST_F(IntervalTimerTest, invalidArgumentToIntervalTimer) {
  902. // Create asio_link::IntervalTimer and setup.
  903. IntervalTimer itimer(io_service_);
  904. // expect throw if call back function is empty
  905. EXPECT_THROW(itimer.setup(IntervalTimer::Callback(), 1),
  906. isc::InvalidParameter);
  907. // expect throw if interval is not greater than 0
  908. EXPECT_THROW(itimer.setup(TimerCallBack(this), 0), isc::BadValue);
  909. EXPECT_THROW(itimer.setup(TimerCallBack(this), -1), isc::BadValue);
  910. }
  911. TEST_F(IntervalTimerTest, startIntervalTimer) {
  912. // Create asio_link::IntervalTimer and setup.
  913. // Then run IOService and test if the callback function is called.
  914. IntervalTimer itimer(io_service_);
  915. timer_called_ = false;
  916. // store start time
  917. boost::posix_time::ptime start;
  918. start = boost::posix_time::microsec_clock::universal_time();
  919. // setup timer
  920. itimer.setup(TimerCallBack(this), 100);
  921. EXPECT_EQ(100, itimer.getInterval());
  922. io_service_.run();
  923. // reaches here after timer expired
  924. // delta: difference between elapsed time and 100 milliseconds.
  925. boost::posix_time::time_duration delta =
  926. (boost::posix_time::microsec_clock::universal_time() - start)
  927. - boost::posix_time::millisec(100);
  928. if (delta.is_negative()) {
  929. delta.invert_sign();
  930. }
  931. // expect TimerCallBack is called; timer_called_ is true
  932. EXPECT_TRUE(timer_called_);
  933. // expect interval is 100 milliseconds +/- TIMER_MARGIN_MSEC.
  934. EXPECT_TRUE(delta < TIMER_MARGIN_MSEC);
  935. }
  936. TEST_F(IntervalTimerTest, destructIntervalTimer) {
  937. // This code isn't exception safe, but we'd rather keep the code
  938. // simpler and more readable as this is only for tests and if it throws
  939. // the program would immediately terminate anyway.
  940. // The call back function will not be called after the timer is
  941. // destroyed.
  942. //
  943. // There are two timers:
  944. // itimer_counter (A)
  945. // (Calls TimerCallBackCounter)
  946. // - increments internal counter in callback function
  947. // itimer_canceller (B)
  948. // (Calls TimerCallBackCancelDeleter)
  949. // - first time of callback, it stores the counter value of
  950. // callback_canceller and destroys itimer_counter
  951. // - second time of callback, it compares the counter value of
  952. // callback_canceller with stored value
  953. // if they are same the timer was not called; expected result
  954. // if they are different the timer was called after destroyed
  955. //
  956. // 0 100 200 300 400 500 600 (ms)
  957. // (A) i--------+----x
  958. // ^
  959. // |destroy itimer_counter
  960. // (B) i-------------+--------------s
  961. // ^stop io_service
  962. // and check if itimer_counter have been
  963. // stopped
  964. // itimer_counter will be deleted in TimerCallBackCancelDeleter
  965. IntervalTimer* itimer_counter = new IntervalTimer(io_service_);
  966. IntervalTimer itimer_canceller(io_service_);
  967. timer_cancel_success_ = false;
  968. TimerCallBackCounter callback_canceller(this);
  969. itimer_counter->setup(callback_canceller, 200);
  970. itimer_canceller.setup(
  971. TimerCallBackCancelDeleter(this, itimer_counter, callback_canceller),
  972. 300);
  973. io_service_.run();
  974. EXPECT_TRUE(timer_cancel_success_);
  975. }
  976. TEST_F(IntervalTimerTest, cancel) {
  977. // Similar to destructIntervalTimer test, but the first timer explicitly
  978. // cancels itself on first callback.
  979. IntervalTimer itimer_counter(io_service_);
  980. IntervalTimer itimer_watcher(io_service_);
  981. unsigned int counter = 0;
  982. itimer_counter.setup(TimerCallBackCanceller(counter, itimer_counter), 100);
  983. itimer_watcher.setup(TimerCallBack(this), 200);
  984. io_service_.run();
  985. EXPECT_EQ(1, counter);
  986. EXPECT_EQ(0, itimer_counter.getInterval());
  987. // canceling an already canceled timer shouldn't cause any surprise.
  988. EXPECT_NO_THROW(itimer_counter.cancel());
  989. }
  990. TEST_F(IntervalTimerTest, overwriteIntervalTimer) {
  991. // Calling setup() multiple times updates call back function and interval.
  992. //
  993. // There are two timers:
  994. // itimer (A)
  995. // (Calls TimerCallBackCounter / TimerCallBack)
  996. // - increments internal counter in callback function
  997. // (TimerCallBackCounter)
  998. // interval: 300 milliseconds
  999. // - io_service_.stop() (TimerCallBack)
  1000. // interval: 100 milliseconds
  1001. // itimer_overwriter (B)
  1002. // (Calls TimerCallBackOverwriter)
  1003. // - first time of callback, it calls setup() to change call back
  1004. // function to TimerCallBack and interval of itimer to 100
  1005. // milliseconds
  1006. // after 300 + 100 milliseconds from the beginning of this test,
  1007. // TimerCallBack() will be called and io_service_ stops.
  1008. // - second time of callback, it means the test fails.
  1009. //
  1010. // 0 100 200 300 400 500 600 700 800 (ms)
  1011. // (A) i-------------+----C----s
  1012. // ^ ^stop io_service
  1013. // |change call back function
  1014. // (B) i------------------+-------------------S
  1015. // ^(stop io_service on fail)
  1016. //
  1017. IntervalTimer itimer(io_service_);
  1018. IntervalTimer itimer_overwriter(io_service_);
  1019. // store start time
  1020. boost::posix_time::ptime start;
  1021. start = boost::posix_time::microsec_clock::universal_time();
  1022. itimer.setup(TimerCallBackCounter(this), 300);
  1023. itimer_overwriter.setup(TimerCallBackOverwriter(this, itimer), 400);
  1024. io_service_.run();
  1025. // reaches here after timer expired
  1026. // if interval is updated, it takes
  1027. // 400 milliseconds for TimerCallBackOverwriter
  1028. // + 100 milliseconds for TimerCallBack (stop)
  1029. // = 500 milliseconds.
  1030. // otherwise (test fails), it takes
  1031. // 400 milliseconds for TimerCallBackOverwriter
  1032. // + 400 milliseconds for TimerCallBackOverwriter (stop)
  1033. // = 800 milliseconds.
  1034. // delta: difference between elapsed time and 400 + 100 milliseconds
  1035. boost::posix_time::time_duration delta =
  1036. (boost::posix_time::microsec_clock::universal_time() - start)
  1037. - boost::posix_time::millisec(400 + 100);
  1038. if (delta.is_negative()) {
  1039. delta.invert_sign();
  1040. }
  1041. // expect callback function is updated: TimerCallBack is called
  1042. EXPECT_TRUE(timer_called_);
  1043. // expect interval is updated
  1044. EXPECT_TRUE(delta < TIMER_MARGIN_MSEC);
  1045. }
  1046. }