Simple wrapper for ZeroConf key/value pairs.
The servus class allows simple announcement and discovery of key/value pairs using ZeroConf networking. The same instance can be used to announce and/or to browse a ZeroConf service. If the Servus library is compiled without zeroconf support (
#define BOOST_TEST_MODULE servus_servus
#include <boost/test/unit_test.hpp>
#include <servus/servus.h>
#ifdef SERVUS_USE_CXX03
# include <boost/random.hpp>
# include <boost/lexical_cast.hpp>
namespace rnd=boost::random;
#else
# include <random>
#endif
#ifdef SERVUS_USE_DNSSD
# include <dns_sd.h>
#endif
#ifdef _MSC_VER
# include <windows.h>
# define _sleep Sleep
#else
# define _sleep ::sleep
#endif
static const int _propagationTime = 1000;
static const int _propagationTries = 10;
uint16_t getRandomPort()
{
#ifdef SERVUS_USE_CXX03
static rnd::minstd_rand engine;
#else
static rnd::random_device device;
static rnd::minstd_rand engine( device( ));
#endif
rnd::uniform_int_distribution< uint16_t > generator( 1024u, 65535u );
return generator( engine );
}
template< class T > std::string toString( const T& what )
{
#ifdef SERVUS_USE_CXX03
return boost::lexical_cast< std::string >( what );
#else
return std::to_string( what );
#endif
}
BOOST_AUTO_TEST_CASE(test_servus)
{
const uint32_t port = getRandomPort();
std::string serviceName = "_servustest_" + toString( port ) + "._tcp";
try
{
}
catch( const std::runtime_error& e )
{
if( getenv( "TRAVIS" ))
{
std::cerr << "Bailing, no avahi on a Travis CI setup" << std::endl;
BOOST_CHECK_EQUAL(
e.what(), "Can't setup avahi client: Daemon not running" );
return;
}
throw;
}
toString( port ));
BOOST_CHECK_EQUAL( service.getName(), serviceName );
{
return;
}
#ifdef SERVUS_USE_DNSSD
BOOST_CHECK( servus::Result::SUCCESS == kDNSServiceErr_NoError );
#endif
if( result != servus::Result::SUCCESS )
{
std::cerr << "Bailing, got " << result
<< ": looks like a broken zeroconf setup" << std::endl;
return;
}
BOOST_CHECK_EQUAL( result, result );
service.withdraw();
service.set( "foo", "bar" );
BOOST_CHECK_EQUAL( service.get( "foo" ), "bar" );
BOOST_CHECK_EQUAL( service.get( "bar" ), std::string( ));
BOOST_CHECK( service.announce( port, toString( port )));
int nLoops = _propagationTries;
while( --nLoops )
{
const servus::Strings& hosts =
if( hosts.empty() && nLoops > 1 )
{
if( getenv( "TRAVIS" ))
{
std::cerr << "Bailing, got no hosts on a Travis CI setup"
<< std::endl;
return;
}
continue;
}
BOOST_REQUIRE_EQUAL( hosts.size(), 1 );
BOOST_CHECK_EQUAL( hosts.front(), toString( port ));
BOOST_CHECK( service.containsKey( hosts.front(), "foo" ));
BOOST_CHECK_EQUAL( service.get( hosts.front(), "foo" ), "bar" );
BOOST_CHECK_EQUAL( service.get( "bar", "foo" ), std::string( ));
BOOST_CHECK_EQUAL( service.get( hosts.front(), "foobar" ),
std::string( ));
break;
}
service.set( "foobar", "42" );
nLoops = _propagationTries;
while( --nLoops )
{
const servus::Strings& hosts =
const bool hasFoobar = !hosts.empty() &&
service.containsKey( hosts.front(), "foobar" );
if(( hosts.empty() || !hasFoobar ) && nLoops > 1 )
continue;
BOOST_REQUIRE_EQUAL( hosts.size(), 1 );
BOOST_CHECK_EQUAL( service.get( hosts.front(), "foobar" ), "42" );
BOOST_CHECK_EQUAL( service.getKeys().size(), 2 );
break;
}
BOOST_CHECK( !service.isBrowsing( ));
BOOST_CHECK( service.isBrowsing( ));
BOOST_CHECK( service.isBrowsing( ));
BOOST_CHECK_EQUAL( service.browse( _propagationTime ),
service.browse( 0 ));
servus::Strings hosts = service.getInstances();
BOOST_REQUIRE_EQUAL( hosts.size(), 1 );
BOOST_CHECK_EQUAL( service.get( hosts.front(), "foo" ), "bar" );
BOOST_CHECK_EQUAL( service.getKeys().size(), 2 );
{
BOOST_CHECK( service2.announce( port+1, toString( port+1 )));
nLoops = _propagationTries;
while( --nLoops )
{
BOOST_CHECK( service.browse( _propagationTime ));
hosts = service.getInstances();
if( hosts.size() < 2 && nLoops > 1 )
continue;
BOOST_CHECK_EQUAL( hosts.size(), 2 );
break;
}
}
nLoops = _propagationTries;
while( --nLoops )
{
BOOST_CHECK( service.browse( _propagationTime ));
hosts = service.getInstances();
if( hosts.size() > 1 && nLoops > 1 )
continue;
BOOST_CHECK_EQUAL( hosts.size(), 1 );
break;
}
BOOST_CHECK( service.isBrowsing( ));
service.endBrowsing();
BOOST_CHECK( !service.isBrowsing( ));
hosts = service.getInstances();
BOOST_REQUIRE_EQUAL( hosts.size(), 1 );
BOOST_CHECK_EQUAL( service.get( hosts.front(), "foo" ), "bar" );
BOOST_CHECK_EQUAL( service.getKeys().size(), 2 );
}