2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
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.
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.
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.
21 #define BOOST_TEST_MAIN
22 #define BOOST_TEST_DYN_LINK
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>
31 #include <logfunc.hpp>
33 #include "host/pingprotocol.h"
34 #include "dns/hostaddress.h"
35 #include "dns/dnsmaster.h"
36 #include "dns/dnscache.h"
37 #include "dns/resolverbase.h"
38 #include "dns/cname.h"
40 using boost::asio::ip::address;
42 //------------------------------------------------------------------------------
43 // Global Test fixture (created once for test suite)
44 //------------------------------------------------------------------------------
46 // constants for master
47 address name_server = address::from_string("127.0.0.1");
48 int resolved_ip_ttl_threshold = 3;
49 int max_address_resolution_attempts = 2;
50 std::string cache_file = DnsCache::DoNotUseCacheFile;
52 // rely on boost that there will only be one instance
54 GlobalFixture *global_fixture;
65 BOOST_TEST_MESSAGE("Create global fixture");
67 // setup logging so we can see output from out code
68 I2n::Logger::enable_stderr_log( true );
69 I2n::Logger::set_log_level( I2n::Logger::LogLevel::Debug );
70 I2n::Logger::GlobalLogger.info() << "Logging enabled for DnsTest";
73 IoServiceItem io_service_temp( new boost::asio::io_service() );
74 io_service_temp.swap( IoService );
75 io_service_temp.reset();
78 DnsCacheItem cache_temp = DnsCacheItem(
79 new DnsCache(IoService, cache_file) );
80 cache_temp.swap( Cache );
85 DnsMaster::create_master(IoService,
87 resolved_ip_ttl_threshold,
88 max_address_resolution_attempts,
90 Master = DnsMaster::get_instance();
92 // remember this instance, so we can later access all these variables
93 if (global_fixture == 0)
94 global_fixture = this;
99 BOOST_TEST_MESSAGE("Destructing global fixture");
107 BOOST_TEST_MESSAGE( "Filling cache..." );
109 HostAddress ip(address::from_string("192.168.42.1"), 61);
112 Cache->update("host1.test", ips);
116 HostAddress ip1(address::from_string("192.168.42.2"), 92);
117 HostAddress ip2(address::from_string("192.168.42.3"), 93);
121 Cache->update("host2_3.test", ips);
124 // cname.test --> host1.test
125 Cache->update("cname.test", Cname("host1.test", 35) );
127 // cname2.test --> cname.test --> host1.test
128 Cache->update("cname2.test", Cname("cname.test", 33) );
130 // cname3.test --> cname2.test --> cname.test --> host1.test
131 Cache->update("cname3.test", Cname("cname2.test", 37) );
133 BOOST_TEST_MESSAGE( "Done filling cache." );
136 // these variables will not be available in test cases:
137 IoServiceItem IoService;
139 DnsMasterItem Master;
142 // this causes above fixture to be created only once before tests start and
143 // destructed after tests end; however, variables are not accessible in test
145 BOOST_GLOBAL_FIXTURE( GlobalFixture )
148 // using this as suite-level fixture makes variable Master accessible in all
152 IoServiceItem IoService;
154 DnsMasterItem Master;
161 BOOST_TEST_MESSAGE("Create test-level fixture");
162 GlobalFixture *global = global_fixture;
163 IoService = global->IoService;
164 Cache = global->Cache;
165 Master = global->Master;
168 virtual ~TestFixture() {}
171 //------------------------------------------------------------------------------
173 //------------------------------------------------------------------------------
175 BOOST_FIXTURE_TEST_SUITE( TestDns, TestFixture )
177 BOOST_AUTO_TEST_CASE( create_master )
180 BOOST_CHECK_EQUAL( Master->get_resolved_ip_ttl_threshold(),
181 resolved_ip_ttl_threshold );
182 BOOST_CHECK_EQUAL( Master->get_max_address_resolution_attempts(),
183 max_address_resolution_attempts );
186 //------------------------------------------------------------------------------
188 //------------------------------------------------------------------------------
189 BOOST_FIXTURE_TEST_SUITE( TestDnsCache, TestFixture )
191 BOOST_AUTO_TEST_CASE( cache_retrieve_ip1 )
193 HostAddressVec ips = Cache->get_ips("host1.test");
194 BOOST_CHECK_EQUAL( ips.size(), 1 );
195 HostAddress ip = ips.front();
196 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" );
197 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 61 );
201 BOOST_AUTO_TEST_CASE( cache_retrieve_ip2 )
203 HostAddressVec ips = Cache->get_ips("host2_3.test");
204 BOOST_CHECK_EQUAL( ips.size(), 2 );
205 HostAddress ip = ips[0];
206 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.2" );
207 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 92 );
209 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.3" );
210 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 93 );
213 BOOST_AUTO_TEST_CASE( cache_retrieve_cname )
215 HostAddressVec ips = Cache->get_ips("cname.test");
216 BOOST_CHECK( ips.empty() );
218 Cname cname = Cache->get_cname("cname.test");
219 BOOST_CHECK_EQUAL( cname.Host, "host1.test" );
220 BOOST_CHECK_EQUAL( cname.Ttl.get_value(), 35 );
223 BOOST_AUTO_TEST_CASE( cache_retrieve_recursive1 )
225 // should get IP from host1 but ttl from cname since is smaller
226 HostAddressVec ips = Cache->get_ips_recursive("cname.test");
227 BOOST_CHECK_EQUAL( ips.size(), 1 );
228 HostAddress ip = ips.front();
229 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" );
230 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 35 );
233 BOOST_AUTO_TEST_CASE( cache_retrieve_recursive2 )
235 // should get IP from host1 but ttl from cname2 since is smaller
236 HostAddressVec ips = Cache->get_ips_recursive("cname3.test");
237 BOOST_CHECK_EQUAL( ips.size(), 1 );
238 HostAddress ip = ips.front();
239 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" );
240 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 33 );
243 void cname_skip_test(const uint32_t ttl1, const uint32_t ttl2,
244 const uint32_t ttl3, const uint32_t ttl4,
245 const DnsCacheItem &cache,
246 const std::string &correct_host_after_skip)
248 { // create cname chain:
249 // skip_chain_first -(ttl1)-> skip_chain_second -(ttl2)->
250 // skip_chain_third -(ttl3)-> skip_chain_fourth -(ttl4)-> IPs
251 cache->update( "skip_chain_first.test",
252 Cname("skip_chain_second.test", ttl1) );
253 cache->update( "skip_chain_second.test",
254 Cname("skip_chain_third.test", ttl2) );
255 cache->update( "skip_chain_third.test",
256 Cname("skip_chain_fourth.test", ttl3) );
258 ips.push_back( HostAddress( address::from_string("192.168.42.4"), ttl4) );
259 cache->update("skip_chain_fourth.test", ips);
262 // normal recursive call should give nothing since one cname is outdated
263 bool check_up_to_date = true;
264 HostAddressVec ips = cache->get_ips_recursive("skip_chain_first.test",
266 bool one_is_out_of_date = (ttl1 < 5) || (ttl2 < 5)
267 || (ttl3 < 5) || (ttl4 < 5);
268 BOOST_CHECK_EQUAL( ips.empty(), one_is_out_of_date );
270 // now find host to resolve after the outdated one
271 std::string first_outdated = cache->get_first_outdated_cname(
272 "skip_chain_first.test", 5);
273 BOOST_CHECK_EQUAL( first_outdated, correct_host_after_skip );
276 BOOST_AUTO_TEST_CASE( cache_skip_tests )
278 // build a cname chain where first one is out of date
279 cname_skip_test(0, 120, 120, 60, Cache, "skip_chain_second.test");
281 // build a cname chain where second one is out of date
282 cname_skip_test(120, 0, 120, 60, Cache, "skip_chain_third.test");
284 // build a cname chain where third one is out of date
285 cname_skip_test(120, 120, 0, 120, Cache, "skip_chain_fourth.test");
287 // build a cname chain where just IPs are out of date
288 cname_skip_test(120, 120, 120, 0, Cache, "");
290 // build a cname chain where all are out of date
291 cname_skip_test(0, 0, 0, 0, Cache, "skip_chain_second.test");
293 // build a cname chain where all is up to date
294 cname_skip_test(120, 120, 120, 120, Cache, "");
296 // test case with very short cname list that is up-to-date
297 BOOST_CHECK_EQUAL( Cache->get_first_outdated_cname("cname.test", 5), "" );
299 // test case where there is no cname at all
300 BOOST_CHECK_EQUAL( Cache->get_first_outdated_cname("host1.test", 5), "" );
304 BOOST_AUTO_TEST_SUITE_END() // of TestDnsCache
307 // -----------------------------------------------------------------------------
309 // -----------------------------------------------------------------------------
311 BOOST_FIXTURE_TEST_SUITE( TestDnsResolver, TestFixture )
313 BOOST_AUTO_TEST_CASE( create_resolver_v4 )
316 std::string hostname = "www.intra2net.com";
317 ResolverItem resolver = Master->get_resolver_for(hostname,
319 BOOST_CHECK_EQUAL( resolver->get_hostname(), hostname );
320 BOOST_CHECK( !resolver->is_resolving() );
322 // cancel should have no effect
323 resolver->cancel_resolve();
324 BOOST_CHECK( !resolver->is_resolving() );
326 // should not have any ips since cache did not load anything
327 BOOST_CHECK_EQUAL( resolver->get_resolved_ip_count(), 0 );
328 BOOST_CHECK( !resolver->have_up_to_date_ip() );
329 std::string no_ip = "0.0.0.0";
330 BOOST_CHECK_EQUAL( resolver->get_next_ip().get_ip().to_string(), no_ip );
334 void resolve_callback(IoServiceItem io_serv, ResolverItem resolver,
335 const bool was_success, const int cname_count)
337 resolver->cancel_resolve();
339 BOOST_TEST_MESSAGE( "Stopped io_service" );
343 BOOST_AUTO_TEST_CASE( do_resolve )
346 std::string hostname = "www.intra2net.com";
347 ResolverItem resolver = Master->get_resolver_for(hostname,
351 callback_type callback = boost::bind( resolve_callback, IoService, resolver,
354 resolver->async_resolve(callback);
356 // this will block until io service is stopped in resolve_callback
359 BOOST_CHECK( resolver->have_up_to_date_ip() );
362 BOOST_AUTO_TEST_SUITE_END() // of TestDnsResolver
364 BOOST_AUTO_TEST_SUITE_END()