| 1 | /* |
| 2 | The software in this package is distributed under the GNU General |
| 3 | Public License version 2 (with a special exception described below). |
| 4 | |
| 5 | A copy of GNU General Public License (GPL) is included in this distribution, |
| 6 | in the file COPYING.GPL. |
| 7 | |
| 8 | As a special exception, if other files instantiate templates or use macros |
| 9 | or inline functions from this file, or you compile this file and link it |
| 10 | with other works to produce a work based on this file, this file |
| 11 | does not by itself cause the resulting work to be covered |
| 12 | by the GNU General Public License. |
| 13 | |
| 14 | However the source code for this file must still be made available |
| 15 | in accordance with section (3) of the GNU General Public License. |
| 16 | |
| 17 | This exception does not invalidate any other reasons why a work based |
| 18 | on this file might be covered by the GNU General Public License. |
| 19 | */ |
| 20 | |
| 21 | #define BOOST_TEST_MAIN |
| 22 | #define BOOST_TEST_DYN_LINK |
| 23 | |
| 24 | #include <algorithm> |
| 25 | |
| 26 | #include <boost/test/unit_test.hpp> |
| 27 | #include <boost/asio/io_service.hpp> |
| 28 | #include <boost/asio/ip/address.hpp> |
| 29 | #include <boost/bind.hpp> |
| 30 | |
| 31 | #include <logfunc.hpp> |
| 32 | #include <filefunc.hxx> |
| 33 | |
| 34 | #include "host/pingprotocol.h" |
| 35 | #include "dns/hostaddress.h" |
| 36 | #include "dns/dnsipprotocol.h" |
| 37 | #include "dns/dnsmaster.h" |
| 38 | #include "dns/dnscache.h" |
| 39 | #include "dns/resolverbase.h" |
| 40 | #include "dns/cname.h" |
| 41 | |
| 42 | using boost::asio::ip::address; |
| 43 | |
| 44 | // constants for master |
| 45 | address name_server = address::from_string("127.0.0.1"); |
| 46 | const int resolved_ip_ttl_threshold = 5; // this should be greater than... |
| 47 | const uint32_t min_time_between_resolves = 3; // ... this! |
| 48 | const int max_address_resolution_attempts = 2; |
| 49 | const int max_recursion_count = 10; |
| 50 | const std::string cache_file = DnsCache::DoNotUseCacheFile; |
| 51 | |
| 52 | //------------------------------------------------------------------------------ |
| 53 | // Global Test fixture (created once for test suite) |
| 54 | //------------------------------------------------------------------------------ |
| 55 | |
| 56 | // rely on boost that there will only be one instance |
| 57 | struct GlobalFixture; |
| 58 | GlobalFixture *global_fixture; |
| 59 | |
| 60 | |
| 61 | struct GlobalFixture |
| 62 | { |
| 63 | |
| 64 | GlobalFixture() |
| 65 | : IoService() |
| 66 | , Cache() |
| 67 | , Master() |
| 68 | { |
| 69 | BOOST_TEST_MESSAGE("Create global fixture"); |
| 70 | |
| 71 | // setup logging so we can see output from out code |
| 72 | I2n::Logger::enable_stderr_log( true ); |
| 73 | I2n::Logger::set_log_level( I2n::Logger::LogLevel::Debug ); |
| 74 | I2n::Logger::GlobalLogger.debug() << "Logging enabled for DnsTest"; |
| 75 | |
| 76 | // IoService |
| 77 | IoServiceItem io_service_temp( new boost::asio::io_service() ); |
| 78 | io_service_temp.swap( IoService ); |
| 79 | io_service_temp.reset(); |
| 80 | |
| 81 | // DNS Cache |
| 82 | DnsCacheItem cache_temp = DnsCacheItem( |
| 83 | new DnsCache(IoService, cache_file, min_time_between_resolves) ); |
| 84 | cache_temp.swap( Cache ); |
| 85 | cache_temp.reset(); |
| 86 | fill_cache(); |
| 87 | |
| 88 | // create master |
| 89 | DnsMaster::create_master(IoService, |
| 90 | name_server, |
| 91 | resolved_ip_ttl_threshold, |
| 92 | max_address_resolution_attempts, |
| 93 | max_recursion_count, |
| 94 | Cache); |
| 95 | Master = DnsMaster::get_instance(); |
| 96 | |
| 97 | // remember this instance, so we can later access all these variables |
| 98 | if (global_fixture == 0) |
| 99 | global_fixture = this; |
| 100 | } |
| 101 | |
| 102 | ~GlobalFixture() |
| 103 | { |
| 104 | BOOST_TEST_MESSAGE("Destructing global fixture"); |
| 105 | IoService->stop(); |
| 106 | IoService.reset(); |
| 107 | Master.reset(); |
| 108 | } |
| 109 | |
| 110 | void fill_cache() |
| 111 | { |
| 112 | BOOST_TEST_MESSAGE( "Filling cache..." ); |
| 113 | { |
| 114 | HostAddress ip(address::from_string("192.168.42.1"), 61); |
| 115 | HostAddressVec ips; |
| 116 | ips.push_back(ip); |
| 117 | Cache->update("host1.test", DNS_IPv4, ips); |
| 118 | } |
| 119 | |
| 120 | { |
| 121 | HostAddress ip1(address::from_string("192.168.42.2"), 92); |
| 122 | HostAddress ip2(address::from_string("192.168.42.3"), 93); |
| 123 | HostAddressVec ips; |
| 124 | ips.push_back(ip1); |
| 125 | ips.push_back(ip2); |
| 126 | Cache->update("host2_3.test", DNS_IPv4, ips); |
| 127 | } |
| 128 | |
| 129 | { |
| 130 | // cname.test --> host1.test |
| 131 | Cache->update("cname.test", Cname("host1.test", 35) ); |
| 132 | |
| 133 | // cname2.test --> cname.test --> host1.test |
| 134 | Cache->update("cname2.test", Cname("cname.test", 33) ); |
| 135 | |
| 136 | // cname3.test --> cname2.test --> cname.test --> host1.test |
| 137 | Cache->update("cname3.test", Cname("cname2.test", 37) ); |
| 138 | } |
| 139 | |
| 140 | { // for cache_outdated_test |
| 141 | HostAddressVec ips; |
| 142 | ips.push_back( HostAddress( address::from_string("192.168.42.4"), |
| 143 | 0 ) ); |
| 144 | ips.push_back( HostAddress( address::from_string("192.168.42.5"), |
| 145 | resolved_ip_ttl_threshold-1 ) ); |
| 146 | ips.push_back( HostAddress( address::from_string("192.168.42.6"), |
| 147 | resolved_ip_ttl_threshold ) ); |
| 148 | ips.push_back( HostAddress( address::from_string("192.168.42.7"), |
| 149 | resolved_ip_ttl_threshold+1 ) ); |
| 150 | Cache->update("host_outdated.test", DNS_IPv4, ips); |
| 151 | |
| 152 | Cache->update( "cname_outdated.test", |
| 153 | Cname("host_outdated.test", resolved_ip_ttl_threshold) ); |
| 154 | Cache->update( "cname_up_to_date.test", |
| 155 | Cname("host_outdated.test", resolved_ip_ttl_threshold+1)); |
| 156 | } |
| 157 | |
| 158 | { // for cache_ttl_below_thresh_test |
| 159 | // TTLs < min_time_between_resolves should be corrected |
| 160 | HostAddressVec ips; |
| 161 | ips.push_back( HostAddress( address::from_string("192.128.42.8"), |
| 162 | 1 ) ); |
| 163 | Cache->update("host_ttl_below_thresh.test", DNS_IPv4, ips); |
| 164 | |
| 165 | Cache->update( "cname_ttl_below_thresh.test", |
| 166 | Cname("host_ttl_below_thresh.test", 2) ); |
| 167 | } |
| 168 | |
| 169 | { // create a CNAME loop cname_loop1.test --> cname_loop2.test |
| 170 | // --> cname_loop3.test --> cname_loop1.test |
| 171 | Cache->update( "cname_loop1.test", Cname("cname_loop2.test", 60) ); |
| 172 | Cache->update( "cname_loop2.test", Cname("cname_loop3.test", 60) ); |
| 173 | Cache->update( "cname_loop3.test", Cname("cname_loop1.test", 60) ); |
| 174 | } |
| 175 | |
| 176 | { // create IPv4 and IPv6 for same host |
| 177 | HostAddressVec ips; |
| 178 | ips.push_back( HostAddress( address::from_string("192.168.42.8"), |
| 179 | 432 ) ); |
| 180 | Cache->update("host_v4_and_v6.test", DNS_IPv4, ips); |
| 181 | ips.clear(); |
| 182 | ips.push_back( HostAddress( |
| 183 | address::from_string("2a00:1450:4001:808::1004"), |
| 184 | 543 ) ); |
| 185 | Cache->update("host_v4_and_v6.test", DNS_IPv6, ips); |
| 186 | } |
| 187 | |
| 188 | BOOST_TEST_MESSAGE( "Done filling cache." ); |
| 189 | } |
| 190 | |
| 191 | // these variables will not be available in test cases: |
| 192 | IoServiceItem IoService; |
| 193 | DnsCacheItem Cache; |
| 194 | DnsMasterItem Master; |
| 195 | }; |
| 196 | |
| 197 | // this causes above fixture to be created only once before tests start and |
| 198 | // destructed after tests end; however, variables are not accessible in test |
| 199 | // cases |
| 200 | BOOST_GLOBAL_FIXTURE( GlobalFixture ) |
| 201 | |
| 202 | |
| 203 | // using this as suite-level fixture makes variable Master accessible in all |
| 204 | // test cases |
| 205 | struct TestFixture |
| 206 | { |
| 207 | IoServiceItem IoService; |
| 208 | DnsCacheItem Cache; |
| 209 | DnsMasterItem Master; |
| 210 | |
| 211 | TestFixture() |
| 212 | : IoService() |
| 213 | , Cache() |
| 214 | , Master() |
| 215 | { |
| 216 | BOOST_TEST_MESSAGE("Create test-level fixture"); |
| 217 | GlobalFixture *global = global_fixture; |
| 218 | IoService = global->IoService; |
| 219 | Cache = global->Cache; |
| 220 | Master = global->Master; |
| 221 | } |
| 222 | |
| 223 | virtual ~TestFixture() {} |
| 224 | }; |
| 225 | |
| 226 | //------------------------------------------------------------------------------ |
| 227 | // test suite |
| 228 | //------------------------------------------------------------------------------ |
| 229 | |
| 230 | BOOST_FIXTURE_TEST_SUITE( TestDns, TestFixture ) |
| 231 | |
| 232 | BOOST_AUTO_TEST_CASE( create_master ) |
| 233 | { |
| 234 | // simple checks |
| 235 | BOOST_CHECK_EQUAL( Master->get_resolved_ip_ttl_threshold(), |
| 236 | resolved_ip_ttl_threshold ); |
| 237 | BOOST_CHECK_EQUAL( Master->get_max_address_resolution_attempts(), |
| 238 | max_address_resolution_attempts ); |
| 239 | } |
| 240 | |
| 241 | //------------------------------------------------------------------------------ |
| 242 | // test Cache |
| 243 | //------------------------------------------------------------------------------ |
| 244 | BOOST_FIXTURE_TEST_SUITE( TestDnsCache, TestFixture ) |
| 245 | |
| 246 | BOOST_AUTO_TEST_CASE( cache_retrieve_ip1 ) |
| 247 | { |
| 248 | HostAddressVec ips = Cache->get_ips("host1.test", DNS_IPv4); |
| 249 | BOOST_REQUIRE_EQUAL( ips.size(), 1 ); |
| 250 | HostAddress ip = ips.front(); |
| 251 | BOOST_CHECK( ip.is_valid() ); |
| 252 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" ); |
| 253 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 61 ); |
| 254 | } |
| 255 | |
| 256 | |
| 257 | BOOST_AUTO_TEST_CASE( cache_retrieve_ip2 ) |
| 258 | { |
| 259 | HostAddressVec ips = Cache->get_ips("host2_3.test", DNS_IPv4); |
| 260 | BOOST_CHECK_EQUAL( ips.size(), 2 ); |
| 261 | HostAddress ip = ips[0]; |
| 262 | BOOST_CHECK( ip.is_valid() ); |
| 263 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.2" ); |
| 264 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 92 ); |
| 265 | ip = ips[1]; |
| 266 | BOOST_CHECK( ip.is_valid() ); |
| 267 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.3" ); |
| 268 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 93 ); |
| 269 | } |
| 270 | |
| 271 | BOOST_AUTO_TEST_CASE( cache_retrieve_cname ) |
| 272 | { |
| 273 | HostAddressVec ips = Cache->get_ips("cname.test", DNS_IPv4); |
| 274 | BOOST_CHECK( ips.empty() ); |
| 275 | |
| 276 | Cname cname = Cache->get_cname("cname.test"); |
| 277 | BOOST_CHECK_EQUAL( cname.Host, "host1.test" ); |
| 278 | BOOST_CHECK_EQUAL( cname.Ttl.get_value(), 35 ); |
| 279 | } |
| 280 | |
| 281 | BOOST_AUTO_TEST_CASE( cache_retrieve_recursive1 ) |
| 282 | { |
| 283 | // should get IP from host1 but ttl from cname since is smaller |
| 284 | HostAddressVec ips = Cache->get_ips_recursive("cname.test", DNS_IPv4); |
| 285 | BOOST_REQUIRE_EQUAL( ips.size(), 1 ); |
| 286 | HostAddress ip = ips.front(); |
| 287 | BOOST_CHECK( ip.is_valid() ); |
| 288 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" ); |
| 289 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 35 ); |
| 290 | } |
| 291 | |
| 292 | BOOST_AUTO_TEST_CASE( cache_retrieve_recursive2 ) |
| 293 | { |
| 294 | // should get IP from host1 but ttl from cname2 since is smaller |
| 295 | HostAddressVec ips = Cache->get_ips_recursive("cname3.test", DNS_IPv4); |
| 296 | BOOST_REQUIRE_EQUAL( ips.size(), 1 ); |
| 297 | HostAddress ip = ips.front(); |
| 298 | BOOST_CHECK( ip.is_valid() ); |
| 299 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" ); |
| 300 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 33 ); |
| 301 | } |
| 302 | |
| 303 | void cname_skip_test(const uint32_t ttl1, const uint32_t ttl2, |
| 304 | const uint32_t ttl3, const uint32_t ttl4, |
| 305 | const DnsCacheItem &cache, |
| 306 | const std::string &correct_host_after_skip) |
| 307 | { |
| 308 | { // create cname chain: |
| 309 | // skip_chain_first -(ttl1)-> skip_chain_second -(ttl2)-> |
| 310 | // skip_chain_third -(ttl3)-> skip_chain_fourth -(ttl4)-> IPs |
| 311 | cache->update( "skip_chain_first.test", |
| 312 | Cname("skip_chain_second.test", ttl1) ); |
| 313 | cache->update( "skip_chain_second.test", |
| 314 | Cname("skip_chain_third.test", ttl2) ); |
| 315 | cache->update( "skip_chain_third.test", |
| 316 | Cname("skip_chain_fourth.test", ttl3) ); |
| 317 | HostAddressVec ips; |
| 318 | ips.push_back( HostAddress( address::from_string("192.168.42.100"), |
| 319 | ttl4 ) ); |
| 320 | cache->update("skip_chain_fourth.test", DNS_IPv4, ips); |
| 321 | } |
| 322 | |
| 323 | // normal recursive call should give nothing since one cname is outdated |
| 324 | bool check_up_to_date = true; |
| 325 | HostAddressVec ips = cache->get_ips_recursive("skip_chain_first.test", |
| 326 | DNS_IPv4, |
| 327 | check_up_to_date); |
| 328 | bool one_is_out_of_date = (ttl1 < 5) || (ttl2 < 5) |
| 329 | || (ttl3 < 5) || (ttl4 < 5); |
| 330 | BOOST_CHECK_EQUAL( ips.empty(), one_is_out_of_date ); |
| 331 | |
| 332 | // now find host to resolve after the outdated one |
| 333 | std::string first_outdated = cache->get_first_outdated_cname( |
| 334 | "skip_chain_first.test", 5); |
| 335 | BOOST_CHECK_EQUAL( first_outdated, correct_host_after_skip ); |
| 336 | } |
| 337 | |
| 338 | BOOST_AUTO_TEST_CASE( cache_skip_tests ) |
| 339 | { |
| 340 | // build a cname chain where first one is out of date |
| 341 | cname_skip_test(0, 120, 120, 60, Cache, "skip_chain_second.test"); |
| 342 | |
| 343 | // build a cname chain where second one is out of date |
| 344 | cname_skip_test(120, 0, 120, 60, Cache, "skip_chain_third.test"); |
| 345 | |
| 346 | // build a cname chain where third one is out of date |
| 347 | cname_skip_test(120, 120, 0, 120, Cache, "skip_chain_fourth.test"); |
| 348 | |
| 349 | // build a cname chain where just IPs are out of date |
| 350 | cname_skip_test(120, 120, 120, 0, Cache, ""); |
| 351 | |
| 352 | // build a cname chain where all are out of date |
| 353 | cname_skip_test(0, 0, 0, 0, Cache, "skip_chain_second.test"); |
| 354 | |
| 355 | // build a cname chain where all is up to date |
| 356 | cname_skip_test(120, 120, 120, 120, Cache, ""); |
| 357 | |
| 358 | // test case with very short cname list that is up-to-date |
| 359 | BOOST_CHECK_EQUAL( Cache->get_first_outdated_cname("cname.test", 5), "" ); |
| 360 | |
| 361 | // test case where there is no cname at all |
| 362 | BOOST_CHECK_EQUAL( Cache->get_first_outdated_cname("host1.test", 5), "" ); |
| 363 | } |
| 364 | |
| 365 | |
| 366 | void create_cache(const std::string &file_name, IoServiceItem io_serv) |
| 367 | { |
| 368 | BOOST_TEST_MESSAGE( "creating cache for file " << file_name ); |
| 369 | if ( I2n::file_exists(file_name) ) |
| 370 | BOOST_CHECK( I2n::unlink(file_name) ); // try to remove |
| 371 | DnsCache save_cache( io_serv, file_name, min_time_between_resolves ); |
| 372 | |
| 373 | HostAddressVec ips; |
| 374 | ips.push_back( HostAddress(address::from_string("11.22.33.44"), 567) ); |
| 375 | save_cache.update("abc.xyz", DNS_IPv4, ips); |
| 376 | |
| 377 | save_cache.update("cname1.xyz", Cname("abc.xyz", 27)); |
| 378 | |
| 379 | // is saved when destructed |
| 380 | } |
| 381 | |
| 382 | |
| 383 | void test_cache(const std::string &file_name, IoServiceItem io_serv) |
| 384 | { |
| 385 | BOOST_TEST_MESSAGE( "loading cache from file " << file_name ); |
| 386 | DnsCache loaded_cache( io_serv, |
| 387 | file_name, |
| 388 | min_time_between_resolves ); |
| 389 | HostAddressVec ips = loaded_cache.get_ips("abc.xyz", DNS_IPv4); |
| 390 | BOOST_CHECK_EQUAL( ips.size(), 1 ); |
| 391 | if (ips.size() == 1) |
| 392 | { |
| 393 | HostAddress ip = ips.front(); |
| 394 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "11.22.33.44" ); |
| 395 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 567 ); |
| 396 | //BOOST_CHECK_EQUAL( ip.get_ttl().get_updated_value(), 0 ); |
| 397 | } |
| 398 | |
| 399 | Cname cname = loaded_cache.get_cname("cname1.xyz"); |
| 400 | BOOST_CHECK_EQUAL( cname.Host, "abc.xyz" ); |
| 401 | BOOST_CHECK_EQUAL( cname.Ttl.get_value(), 27 ); |
| 402 | //BOOST_CHECK_EQUAL( cname.Ttl.get_updated_value(), 0 ); |
| 403 | |
| 404 | // not testing Ttl set time since is private |
| 405 | } |
| 406 | |
| 407 | |
| 408 | BOOST_AUTO_TEST_CASE( cache_save_and_load_test ) |
| 409 | { |
| 410 | std::stringstream file_name_temp; |
| 411 | file_name_temp << DATA_DIR_STRING << "/" << "dns_cache_save_load_test.xml"; |
| 412 | std::string file_name = file_name_temp.str(); |
| 413 | |
| 414 | // create and save |
| 415 | create_cache( file_name, IoService ); |
| 416 | |
| 417 | // now load and test |
| 418 | test_cache( file_name, IoService ); |
| 419 | |
| 420 | } |
| 421 | |
| 422 | BOOST_AUTO_TEST_CASE( cache_load_compatibility_test ) |
| 423 | { |
| 424 | std::stringstream file_name; |
| 425 | file_name << DATA_DIR_STRING << "/" << "dns_cache_compatibility_test.xml"; |
| 426 | test_cache( file_name.str(), IoService ); |
| 427 | |
| 428 | // If this test fails because the cache structure was changed, |
| 429 | // you can overwrite the dns_cache_compatibility_test.xml by uncommenting |
| 430 | // the following code line. |
| 431 | //create_cache( file_name.str(), IoService ); |
| 432 | // |
| 433 | // Run test again with arg --log_level=MESSAGE and look out for message |
| 434 | // "create cache for file [...]dns_cache_compatibility_test.xml" |
| 435 | // You should then copy the dns_cache_compatibility_test.xml to test/data |
| 436 | // in git and commit together with the new cache structure code |
| 437 | } |
| 438 | |
| 439 | BOOST_AUTO_TEST_CASE( cache_outdated_test ) |
| 440 | { |
| 441 | bool check_up_to_date = false; |
| 442 | HostAddressVec ips = Cache->get_ips("host_outdated.test", DNS_IPv4, |
| 443 | check_up_to_date); |
| 444 | BOOST_CHECK_EQUAL( ips.size(), 4 ); |
| 445 | ips = Cache->get_ips_recursive("host_outdated.test", DNS_IPv4, |
| 446 | check_up_to_date); |
| 447 | BOOST_CHECK_EQUAL( ips.size(), 4 ); |
| 448 | Cname cname = Cache->get_cname("cname_outdated.test", check_up_to_date); |
| 449 | BOOST_CHECK( !cname.Host.empty() ); |
| 450 | ips = Cache->get_ips_recursive("cname_outdated.test", DNS_IPv4, |
| 451 | check_up_to_date); |
| 452 | BOOST_CHECK_EQUAL( ips.size(), 4 ); |
| 453 | ips = Cache->get_ips_recursive("cname_up_to_date.test", DNS_IPv4, |
| 454 | check_up_to_date); |
| 455 | BOOST_CHECK_EQUAL( ips.size(), 4 ); |
| 456 | |
| 457 | check_up_to_date = true; |
| 458 | ips = Cache->get_ips( "host_outdated.test", DNS_IPv4, check_up_to_date ); |
| 459 | BOOST_CHECK_EQUAL( ips.size(), 1 ); |
| 460 | ips = Cache->get_ips_recursive("host_outdated.test", DNS_IPv4, |
| 461 | check_up_to_date); |
| 462 | BOOST_CHECK_EQUAL( ips.size(), 1 ); |
| 463 | cname = Cache->get_cname("cname_outdated.test", check_up_to_date); |
| 464 | BOOST_CHECK( cname.Host.empty() ); |
| 465 | ips = Cache->get_ips_recursive("cname_outdated.test", DNS_IPv4, |
| 466 | check_up_to_date); |
| 467 | BOOST_CHECK_EQUAL( ips.size(), 0 ); |
| 468 | ips = Cache->get_ips_recursive("cname_up_to_date.test", DNS_IPv4, |
| 469 | check_up_to_date); |
| 470 | BOOST_CHECK_EQUAL( ips.size(), 1 ); |
| 471 | } |
| 472 | |
| 473 | BOOST_AUTO_TEST_CASE( cache_ttl_below_thresh_test ) |
| 474 | { |
| 475 | HostAddressVec ips = Cache->get_ips("host_ttl_below_thresh.test", DNS_IPv4, |
| 476 | false); |
| 477 | BOOST_REQUIRE_EQUAL( ips.size(), 1 ); |
| 478 | HostAddress ip = ips.front(); |
| 479 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), min_time_between_resolves ); |
| 480 | |
| 481 | Cname cname = Cache->get_cname("cname_ttl_below_thresh.test", false); |
| 482 | BOOST_CHECK_EQUAL( cname.Ttl.get_value(), min_time_between_resolves ); |
| 483 | } |
| 484 | |
| 485 | BOOST_AUTO_TEST_CASE( cache_retrieve_loop ) |
| 486 | { |
| 487 | BOOST_CHECK_EQUAL( |
| 488 | Cache->get_ips_recursive("cname_loop1.test", DNS_IPv4).size(), 0 ); |
| 489 | BOOST_CHECK_EQUAL( |
| 490 | Cache->get_ips_recursive("cname_loop2.test", DNS_IPv4).size(), 0 ); |
| 491 | BOOST_CHECK_EQUAL( |
| 492 | Cache->get_ips_recursive("cname_loop3.test", DNS_IPv4).size(), 0 ); |
| 493 | } |
| 494 | |
| 495 | |
| 496 | BOOST_AUTO_TEST_CASE( cache_IPv6 ) |
| 497 | { |
| 498 | HostAddressVec ips = Cache->get_ips("host_v4_and_v6.test", DNS_IPv4); |
| 499 | BOOST_REQUIRE_EQUAL( ips.size(), 1 ); |
| 500 | HostAddress ip = ips.front(); |
| 501 | BOOST_CHECK( ip.is_valid() ); |
| 502 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.8" ); |
| 503 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 432 ); |
| 504 | |
| 505 | ips = Cache->get_ips("host_v4_and_v6.test", DNS_IPv6); |
| 506 | BOOST_REQUIRE_EQUAL( ips.size(), 1 ); |
| 507 | ip = ips.front(); |
| 508 | BOOST_CHECK( ip.is_valid() ); |
| 509 | BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "2a00:1450:4001:808::1004" ); |
| 510 | BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 543 ); |
| 511 | } |
| 512 | |
| 513 | |
| 514 | BOOST_AUTO_TEST_SUITE_END() // of TestDnsCache |
| 515 | |
| 516 | |
| 517 | // ----------------------------------------------------------------------------- |
| 518 | // test resolver |
| 519 | // ----------------------------------------------------------------------------- |
| 520 | |
| 521 | BOOST_FIXTURE_TEST_SUITE( TestDnsResolver, TestFixture ) |
| 522 | |
| 523 | BOOST_AUTO_TEST_CASE( create_resolver_v4 ) |
| 524 | { |
| 525 | // create resolver |
| 526 | std::string hostname = "www.intra2net.com"; |
| 527 | ResolverItem resolver = Master->get_resolver_for(hostname, |
| 528 | PingProtocol_ICMP); |
| 529 | BOOST_CHECK_EQUAL( resolver->get_hostname(), hostname ); |
| 530 | BOOST_CHECK( !resolver->is_resolving() ); |
| 531 | BOOST_CHECK( !resolver->is_waiting_to_resolve() ); |
| 532 | |
| 533 | // cancel should have no effect |
| 534 | resolver->cancel_resolve(); |
| 535 | BOOST_CHECK( !resolver->is_resolving() ); |
| 536 | BOOST_CHECK( !resolver->is_waiting_to_resolve() ); |
| 537 | |
| 538 | // should not have any ips since cache did not load anything |
| 539 | BOOST_CHECK_EQUAL( resolver->get_resolved_ip_count(), 0 ); |
| 540 | BOOST_CHECK( !resolver->have_up_to_date_ip() ); |
| 541 | std::string no_ip = "0.0.0.0"; |
| 542 | BOOST_CHECK_EQUAL( resolver->get_next_ip().get_ip().to_string(), no_ip ); |
| 543 | } |
| 544 | |
| 545 | |
| 546 | struct ResolveCallback |
| 547 | { |
| 548 | public: |
| 549 | IoServiceItem IoService; |
| 550 | ResolverItem Resolver; |
| 551 | int CallCount; |
| 552 | bool LastCallWasSuccess; |
| 553 | int LastCallRecursionCount; |
| 554 | |
| 555 | ResolveCallback(IoServiceItem &io_serv, ResolverItem &resolver) |
| 556 | : IoService(io_serv) |
| 557 | , Resolver(resolver) |
| 558 | , CallCount(0) |
| 559 | , LastCallWasSuccess(true) |
| 560 | , LastCallRecursionCount(-10) |
| 561 | {} |
| 562 | |
| 563 | void call(const bool was_success, const int recursion_count) |
| 564 | { |
| 565 | BOOST_TEST_MESSAGE( "Callback called" ); |
| 566 | ++CallCount; |
| 567 | |
| 568 | Resolver->cancel_resolve(); |
| 569 | IoService->stop(); |
| 570 | |
| 571 | LastCallWasSuccess = was_success; |
| 572 | LastCallRecursionCount = recursion_count; |
| 573 | } |
| 574 | }; |
| 575 | |
| 576 | BOOST_AUTO_TEST_CASE( do_resolve ) |
| 577 | { |
| 578 | // create resolver |
| 579 | std::string hostname = "www.intra2net.com"; |
| 580 | ResolverItem resolver = Master->get_resolver_for(hostname, |
| 581 | PingProtocol_ICMP); |
| 582 | BOOST_CHECK( !resolver->is_resolving() ); |
| 583 | BOOST_CHECK( !resolver->is_waiting_to_resolve() ); |
| 584 | |
| 585 | // set callback |
| 586 | ResolveCallback *callback_obj = new ResolveCallback(IoService, resolver); |
| 587 | // have to manually delete this obj in the end! |
| 588 | callback_type callback = boost::bind( &ResolveCallback::call, callback_obj, |
| 589 | _1, _2 ); |
| 590 | |
| 591 | // start resolving |
| 592 | resolver->async_resolve(callback); |
| 593 | BOOST_CHECK( resolver->is_resolving() ); |
| 594 | IoService->run(); |
| 595 | // this will block until io service is stopped in resolve_callback |
| 596 | BOOST_TEST_MESSAGE( "Back to synchronous operation" ); |
| 597 | IoService->reset(); |
| 598 | |
| 599 | // check for result |
| 600 | BOOST_CHECK_EQUAL( callback_obj->CallCount, 1 ); |
| 601 | BOOST_CHECK( callback_obj->LastCallWasSuccess ); |
| 602 | BOOST_CHECK_EQUAL( callback_obj->LastCallRecursionCount, 0 ); |
| 603 | BOOST_CHECK( resolver->have_up_to_date_ip() ); |
| 604 | |
| 605 | delete callback_obj; |
| 606 | } |
| 607 | |
| 608 | BOOST_AUTO_TEST_SUITE_END() // of TestDnsResolver |
| 609 | |
| 610 | BOOST_AUTO_TEST_SUITE_END() |