blob: 11730d8cc72090ac14b5e967106cfca568b64dbb [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 attr_value_visitation.cpp
* \author Andrey Semashev
* \date 21.01.2009
*
* \brief This header contains tests for the attribute value extraction helpers.
*/
#define BOOST_TEST_MODULE attr_value_visitation
#include <string>
#include <boost/mpl/vector.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/log/attributes/value_visitation.hpp>
#include <boost/log/attributes/constant.hpp>
#include <boost/log/attributes/attribute_set.hpp>
#include <boost/log/attributes/attribute_value_set.hpp>
#include "char_definitions.hpp"
namespace mpl = boost::mpl;
namespace logging = boost::log;
namespace attrs = logging::attributes;
namespace {
// The receiver functional object that verifies the extracted attribute values
struct my_receiver
{
typedef void result_type;
enum type_expected
{
none_expected,
int_expected,
double_expected,
string_expected
};
my_receiver() : 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 operator() (int const& value)
{
BOOST_CHECK_EQUAL(m_Expected, int_expected);
BOOST_CHECK_EQUAL(m_Int, value);
}
void operator() (double const& value)
{
BOOST_CHECK_EQUAL(m_Expected, double_expected);
BOOST_CHECK_CLOSE(m_Double, value, 0.001);
}
void operator() (std::string const& value)
{
BOOST_CHECK_EQUAL(m_Expected, string_expected);
BOOST_CHECK_EQUAL(m_String, value);
}
void operator() (char value)
{
// This one should not be called
BOOST_ERROR("The unexpected operator() has been called");
}
private:
type_expected m_Expected;
int m_Int;
double m_Double;
std::string m_String;
};
} // namespace
// The test checks invokers specialized on a single attribute value type
BOOST_AUTO_TEST_CASE(single_type)
{
typedef logging::attribute_set attr_set;
typedef logging::attribute_value_set attr_values;
typedef test_data< char > data;
attrs::constant< int > attr1(10);
attrs::constant< double > attr2(5.5);
attrs::constant< std::string > attr3("Hello, world!");
attr_set set1, set2, set3;
set1[data::attr1()] = attr1;
set1[data::attr2()] = attr2;
attr_values values1(set1, set2, set3);
values1.freeze();
my_receiver recv;
logging::value_visitor_invoker< int > invoker1;
logging::value_visitor_invoker< double > invoker2;
logging::value_visitor_invoker< std::string > invoker3;
logging::value_visitor_invoker< char > invoker4;
// These two extractors will find their values in the set
recv.set_expected(10);
BOOST_CHECK(invoker1(data::attr1(), values1, recv));
recv.set_expected(5.5);
BOOST_CHECK(invoker2(data::attr2(), values1, recv));
// This one will not
recv.set_expected();
BOOST_CHECK(!invoker3(data::attr3(), values1, recv));
// But it will find it in this set
set1[data::attr3()] = attr3;
attr_values values2(set1, set2, set3);
values2.freeze();
recv.set_expected("Hello, world!");
BOOST_CHECK(invoker3(data::attr3(), values2, recv));
// This one will find the sought attribute value, but it will have an incorrect type
recv.set_expected();
BOOST_CHECK(!invoker4(data::attr1(), values1, recv));
// This one is the same, but there is a value of the requested type in the set
BOOST_CHECK(!invoker1(data::attr2(), values1, recv));
}
// The test checks invokers specialized with type lists
BOOST_AUTO_TEST_CASE(multiple_types)
{
typedef logging::attribute_set attr_set;
typedef logging::attribute_value_set attr_values;
typedef test_data< char > data;
typedef mpl::vector< int, double, std::string, char >::type types;
attrs::constant< int > attr1(10);
attrs::constant< double > attr2(5.5);
attrs::constant< std::string > attr3("Hello, world!");
attr_set set1, set2, set3;
set1[data::attr1()] = attr1;
set1[data::attr2()] = attr2;
attr_values values1(set1, set2, set3);
values1.freeze();
my_receiver recv;
logging::value_visitor_invoker< types > invoker;
// These two extractors will find their values in the set
recv.set_expected(10);
BOOST_CHECK(invoker(data::attr1(), values1, recv));
recv.set_expected(5.5);
BOOST_CHECK(invoker(data::attr2(), values1, recv));
// This one will not
recv.set_expected();
BOOST_CHECK(!invoker(data::attr3(), values1, recv));
// But it will find it in this set
set1[data::attr3()] = attr3;
attr_values values2(set1, set2, set3);
values2.freeze();
recv.set_expected("Hello, world!");
BOOST_CHECK(invoker(data::attr3(), values2, recv));
}
// The test verifies the visit function
BOOST_AUTO_TEST_CASE(visit_function)
{
typedef logging::attribute_set attr_set;
typedef logging::attribute_value_set attr_values;
typedef test_data< char > data;
typedef mpl::vector< int, double, std::string, char >::type types;
attrs::constant< int > attr1(10);
attrs::constant< double > attr2(5.5);
attrs::constant< std::string > attr3("Hello, world!");
attr_set set1, set2, set3;
set1[data::attr1()] = attr1;
set1[data::attr2()] = attr2;
attr_values values1(set1, set2, set3);
values1.freeze();
my_receiver recv;
// These two extractors will find their values in the set
recv.set_expected(10);
BOOST_CHECK(logging::visit< types >(data::attr1(), values1, recv));
recv.set_expected(5.5);
BOOST_CHECK(logging::visit< double >(data::attr2(), values1, recv));
// These will not
recv.set_expected();
BOOST_CHECK(!logging::visit< types >(data::attr3(), values1, recv));
BOOST_CHECK(!logging::visit< char >(data::attr1(), values1, recv));
// But it will find it in this set
set1[data::attr3()] = attr3;
attr_values values2(set1, set2, set3);
values2.freeze();
recv.set_expected("Hello, world!");
BOOST_CHECK(logging::visit< std::string >(data::attr3(), values2, recv));
}