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 Cname cname("host1.test", 35);
126 Cache->update("cname.test", cname);
129 { // cname2.test --> cname.test --> host1.test
130 Cname cname("cname.test", 33);
131 Cache->update("cname2.test", cname);
134 { // cname3.test --> cname2.test --> cname.test --> host1.test
135 Cname cname("cname2.test", 37);
136 Cache->update("cname3.test", cname);
138 BOOST_TEST_MESSAGE( "Done filling cache." );
141 // these variables will not be available in test cases:
142 IoServiceItem IoService;
144 DnsMasterItem Master;
147 // this causes above fixture to be created only once before tests start and
148 // destructed after tests end; however, variables are not accessible in test
150 BOOST_GLOBAL_FIXTURE( GlobalFixture )
153 // using this as suite-level fixture makes variable Master accessible in all
157 IoServiceItem IoService;
159 DnsMasterItem Master;
166 BOOST_TEST_MESSAGE("Create test-level fixture");
167 GlobalFixture *global = global_fixture;
168 IoService = global->IoService;
169 Cache = global->Cache;
170 Master = global->Master;
173 virtual ~TestFixture() {}
176 //------------------------------------------------------------------------------
178 //------------------------------------------------------------------------------
180 BOOST_FIXTURE_TEST_SUITE( TestDns, TestFixture )
182 BOOST_AUTO_TEST_CASE( create_master )
185 BOOST_CHECK_EQUAL( Master->get_resolved_ip_ttl_threshold(),
186 resolved_ip_ttl_threshold );
187 BOOST_CHECK_EQUAL( Master->get_max_address_resolution_attempts(),
188 max_address_resolution_attempts );
191 //------------------------------------------------------------------------------
193 //------------------------------------------------------------------------------
194 BOOST_FIXTURE_TEST_SUITE( TestDnsCache, TestFixture )
196 BOOST_AUTO_TEST_CASE( cache_retrieve_ip1 )
198 HostAddressVec ips = Cache->get_ips("host1.test");
199 BOOST_CHECK_EQUAL( ips.size(), 1 );
200 HostAddress ip = ips.front();
201 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" );
202 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 61 );
206 BOOST_AUTO_TEST_CASE( cache_retrieve_ip2 )
208 HostAddressVec ips = Cache->get_ips("host2_3.test");
209 BOOST_CHECK_EQUAL( ips.size(), 2 );
210 HostAddress ip = ips[0];
211 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.2" );
212 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 92 );
214 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.3" );
215 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 93 );
218 BOOST_AUTO_TEST_CASE( cache_retrieve_cname )
220 HostAddressVec ips = Cache->get_ips("cname.test");
221 BOOST_CHECK( ips.empty() );
223 Cname cname = Cache->get_cname("cname.test");
224 BOOST_CHECK_EQUAL( cname.Host, "host1.test" );
225 BOOST_CHECK_EQUAL( cname.Ttl.get_value(), 35 );
228 BOOST_AUTO_TEST_CASE( cache_retrieve_recursive1 )
230 // should get IP from host1 but ttl from cname since is smaller
231 HostAddressVec ips = Cache->get_ips_recursive("cname.test");
232 BOOST_CHECK_EQUAL( ips.size(), 1 );
233 HostAddress ip = ips.front();
234 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" );
235 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 35 );
238 BOOST_AUTO_TEST_CASE( cache_retrieve_recursive2 )
240 // should get IP from host1 but ttl from cname2 since is smaller
241 HostAddressVec ips = Cache->get_ips_recursive("cname3.test");
242 BOOST_CHECK_EQUAL( ips.size(), 1 );
243 HostAddress ip = ips.front();
244 BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" );
245 BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 33 );
248 BOOST_AUTO_TEST_CASE( cache_skip_test1 )
250 // build a cname chain where first one is out of date
251 { // skip_chain_first -(120)-> skip_chain_second -(0)-> skip_chain_third
252 // -(120)-> skip_chain_fourth -(60)-> IPs
253 Cname first("skip_chain_second.test", 120);
254 Cache->update("skip_chain_first.test", first);
255 Cname second("skip_chain_third.test", 0);
256 Cache->update("skip_chain_second.test", second);
257 Cname third("skip_chain_fourth.test", 120);
258 Cache->update("skip_chain_third.test", third);
260 ips.push_back( HostAddress( address::from_string("192.168.42.4"), 60) );
261 Cache->update("skip_chain_fourth.test", ips);
264 // normal recursive call should give nothing since all are outdated
265 bool check_up_to_date = true;
266 HostAddressVec ips = Cache->get_ips_recursive("skip_chain_first.test",
268 BOOST_CHECK( ips.empty() );
271 std::string first_outdated = Cache->get_first_outdated_cname(
272 "skip_chain_first.test", 5);
273 BOOST_CHECK_EQUAL( first_outdated, "skip_chain_third.test" );
277 BOOST_AUTO_TEST_SUITE_END() // of TestDnsCache
280 // -----------------------------------------------------------------------------
282 // -----------------------------------------------------------------------------
284 BOOST_FIXTURE_TEST_SUITE( TestDnsResolver, TestFixture )
286 void resolve_callback(IoServiceItem io_serv, ResolverItem resolver,
287 const bool was_success, const int cname_count);
289 BOOST_AUTO_TEST_CASE( create_resolver_v4 )
292 std::string hostname = "www.intra2net.com";
293 ResolverItem resolver = Master->get_resolver_for(hostname,
295 BOOST_CHECK_EQUAL( resolver->get_hostname(), hostname );
296 BOOST_CHECK( !resolver->is_resolving() );
298 // cancel should have no effect
299 resolver->cancel_resolve();
300 BOOST_CHECK( !resolver->is_resolving() );
302 // should not have any ips since cache did not load anything
303 BOOST_CHECK_EQUAL( resolver->get_resolved_ip_count(), 0 );
304 BOOST_CHECK( !resolver->have_up_to_date_ip() );
305 std::string no_ip = "0.0.0.0";
306 BOOST_CHECK_EQUAL( resolver->get_next_ip().get_ip().to_string(), no_ip );
310 void resolve_callback(IoServiceItem io_serv, ResolverItem resolver,
311 const bool was_success, const int cname_count)
313 resolver->cancel_resolve();
315 BOOST_TEST_MESSAGE( "Stopped io_service" );
319 BOOST_AUTO_TEST_CASE( do_resolve )
322 std::string hostname = "www.intra2net.com";
323 ResolverItem resolver = Master->get_resolver_for(hostname,
327 callback_type callback = boost::bind( resolve_callback, IoService, resolver,
330 resolver->async_resolve(callback);
332 // this will block until io service is stopped in resolve_callback
335 BOOST_CHECK( resolver->have_up_to_date_ip() );
338 BOOST_AUTO_TEST_SUITE_END() // of TestDnsResolver
340 BOOST_AUTO_TEST_SUITE_END()