| /* |
| * 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)); |
| } |