blob: 485569d255c23520ebc3ad7b7a406b914ada9562 [file] [log] [blame]
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file util_dynamic_type_disp.cpp
* \author Andrey Semashev
* \date 09.01.2009
*
* \brief This header contains tests for the dynamic type dispatcher.
*/
#define BOOST_TEST_MODULE util_dynamic_type_disp
#include <string>
#include <boost/bind.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp>
namespace logging = boost::log;
namespace {
// A simple attribute value
template< typename T >
struct my_value
{
T m_Value;
explicit my_value(T const& value) : m_Value(value) {}
// The function passes the contained type into the dispatcher
bool dispatch(logging::type_dispatcher& dispatcher)
{
logging::type_dispatcher::callback< T > callback = dispatcher.get_callback< T >();
if (callback)
{
callback(m_Value);
return true;
}
else
return false;
}
};
struct my_visitor
{
enum type_expected
{
none_expected,
int_expected,
double_expected,
string_expected
};
my_visitor() : m_Expected(none_expected), m_Int(0), m_Double(0.0) {}
void set_expected()
{
m_Expected = none_expected;
}
void set_expected(int value)
{
m_Expected = int_expected;
m_Int = value;
}
void set_expected(double value)
{
m_Expected = double_expected;
m_Double = value;
}
void set_expected(std::string const& value)
{
m_Expected = string_expected;
m_String = value;
}
// Implement visitation logic for all supported types
void on_int(int const& value)
{
BOOST_CHECK_EQUAL(m_Expected, int_expected);
BOOST_CHECK_EQUAL(m_Int, value);
}
void on_double(double const& value)
{
BOOST_CHECK_EQUAL(m_Expected, double_expected);
BOOST_CHECK_CLOSE(m_Double, value, 0.001);
}
void on_string(std::string const& value)
{
BOOST_CHECK_EQUAL(m_Expected, string_expected);
BOOST_CHECK_EQUAL(m_String, value);
}
private:
type_expected m_Expected;
int m_Int;
double m_Double;
std::string m_String;
};
} // namespace
// The test checks that general functionality works
BOOST_AUTO_TEST_CASE(type_dispatch)
{
my_visitor vis;
logging::dynamic_type_dispatcher disp;
// Register type visitors
disp.register_type< int >(boost::bind(&my_visitor::on_int, &vis, _1));
disp.register_type< double >(boost::bind(&my_visitor::on_double, &vis, _1));
BOOST_CHECK(disp.registered_types_count() == 2);
// Right now strings are not supported by the dispatcher
my_value< std::string > val1("Hello world!");
BOOST_CHECK(!val1.dispatch(disp));
// And now they are
disp.register_type< std::string >(boost::bind(&my_visitor::on_string, &vis, _1));
BOOST_CHECK(disp.registered_types_count() == 3);
vis.set_expected(val1.m_Value);
BOOST_CHECK(val1.dispatch(disp));
my_value< double > val2(1.2);
vis.set_expected(val2.m_Value);
BOOST_CHECK(val2.dispatch(disp));
// This one is not supported
my_value< float > val3(static_cast< float >(-4.3));
vis.set_expected();
BOOST_CHECK(!val3.dispatch(disp));
}