Update pingcheck to work with cmake 3.28
[pingcheck] / test / test_dns.cpp
... / ...
CommitLineData
1/*
2The software in this package is distributed under the GNU General
3Public License version 2 (with a special exception described below).
4
5A copy of GNU General Public License (GPL) is included in this distribution,
6in the file COPYING.GPL.
7
8As a special exception, if other files instantiate templates or use macros
9or inline functions from this file, or you compile this file and link it
10with other works to produce a work based on this file, this file
11does not by itself cause the resulting work to be covered
12by the GNU General Public License.
13
14However the source code for this file must still be made available
15in accordance with section (3) of the GNU General Public License.
16
17This exception does not invalidate any other reasons why a work based
18on 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
42using boost::asio::ip::address;
43
44// constants for master
45address name_server = address::from_string("127.0.0.1");
46const int resolved_ip_ttl_threshold = 5; // this should be greater than...
47const uint32_t min_time_between_resolves = 3; // ... this!
48const int max_address_resolution_attempts = 2;
49const int max_recursion_count = 10;
50const 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
57struct GlobalFixture;
58GlobalFixture *global_fixture;
59
60
61struct 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
200BOOST_GLOBAL_FIXTURE( GlobalFixture )
201
202
203// using this as suite-level fixture makes variable Master accessible in all
204// test cases
205struct 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
230BOOST_FIXTURE_TEST_SUITE( TestDns, TestFixture )
231
232BOOST_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//------------------------------------------------------------------------------
244BOOST_FIXTURE_TEST_SUITE( TestDnsCache, TestFixture )
245
246BOOST_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
257BOOST_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
271BOOST_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
281BOOST_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
292BOOST_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
303void 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
338BOOST_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
366void 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
383void 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
408BOOST_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
422BOOST_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
439BOOST_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
473BOOST_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
485BOOST_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
496BOOST_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
514BOOST_AUTO_TEST_SUITE_END() // of TestDnsCache
515
516
517// -----------------------------------------------------------------------------
518// test resolver
519// -----------------------------------------------------------------------------
520
521BOOST_FIXTURE_TEST_SUITE( TestDnsResolver, TestFixture )
522
523BOOST_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
546struct ResolveCallback
547{
548public:
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
576BOOST_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
608BOOST_AUTO_TEST_SUITE_END() // of TestDnsResolver
609
610BOOST_AUTO_TEST_SUITE_END()