140 lines
4.6 KiB
C++
140 lines
4.6 KiB
C++
/*
|
|
* 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_manip_add_value.cpp
|
|
* \author Andrey Semashev
|
|
* \date 07.11.2013
|
|
*
|
|
* \brief This header contains tests for the \c add_value manipulator.
|
|
*/
|
|
|
|
#define BOOST_TEST_MODULE util_manip_add_value
|
|
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <boost/move/core.hpp>
|
|
#include <boost/io/ios_state.hpp>
|
|
#include <boost/test/unit_test.hpp>
|
|
#include <boost/log/core.hpp>
|
|
#include <boost/log/sources/record_ostream.hpp>
|
|
#include <boost/log/attributes/attribute_set.hpp>
|
|
#include <boost/log/attributes/value_extraction.hpp>
|
|
#include <boost/log/expressions/keyword.hpp>
|
|
#include <boost/log/utility/manipulators/add_value.hpp>
|
|
#include "make_record.hpp"
|
|
|
|
namespace logging = boost::log;
|
|
|
|
struct my_type
|
|
{
|
|
BOOST_COPYABLE_AND_MOVABLE(my_type)
|
|
|
|
public:
|
|
unsigned int value;
|
|
|
|
explicit my_type(unsigned int n = 0) : value(n) {}
|
|
my_type(my_type const& that) : value(that.value) {}
|
|
my_type(BOOST_RV_REF(my_type) that) : value(that.value) { that.value = 0xbaadbaad; }
|
|
~my_type() { value = 0xdeaddead; }
|
|
|
|
my_type& operator= (BOOST_COPY_ASSIGN_REF(my_type) that) { value = that.value; return *this; }
|
|
my_type& operator= (BOOST_RV_REF(my_type) that) { value = that.value; that.value = 0xbaadbaad; return *this; }
|
|
};
|
|
|
|
inline bool operator== (my_type const& left, my_type const& right)
|
|
{
|
|
return left.value == right.value;
|
|
}
|
|
|
|
inline bool operator!= (my_type const& left, my_type const& right)
|
|
{
|
|
return left.value != right.value;
|
|
}
|
|
|
|
template< typename CharT, typename TraitsT >
|
|
inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, my_type const& val)
|
|
{
|
|
if (strm.good())
|
|
{
|
|
boost::io::ios_flags_saver flags(strm);
|
|
boost::io::basic_ios_fill_saver< CharT, TraitsT > fill(strm);
|
|
strm << std::hex << std::internal << std::setfill(static_cast< CharT >('0')) << std::setw(10) << val.value;
|
|
}
|
|
return strm;
|
|
}
|
|
|
|
struct my_pod_type
|
|
{
|
|
unsigned int value;
|
|
};
|
|
|
|
inline bool operator== (my_pod_type const& left, my_pod_type const& right)
|
|
{
|
|
return left.value == right.value;
|
|
}
|
|
|
|
inline bool operator!= (my_pod_type const& left, my_pod_type const& right)
|
|
{
|
|
return left.value != right.value;
|
|
}
|
|
|
|
template< typename CharT, typename TraitsT >
|
|
inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, my_pod_type const& val)
|
|
{
|
|
if (strm.good())
|
|
{
|
|
boost::io::ios_flags_saver flags(strm);
|
|
boost::io::basic_ios_fill_saver< CharT, TraitsT > fill(strm);
|
|
strm << std::hex << std::internal << std::setfill(static_cast< CharT >('0')) << std::setw(10) << val.value;
|
|
}
|
|
return strm;
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(manual_add_attr)
|
|
{
|
|
logging::record rec = make_record(logging::attribute_set());
|
|
BOOST_REQUIRE(!!rec);
|
|
logging::record_ostream strm(rec);
|
|
|
|
my_type val(0xaaaaaaaa);
|
|
const my_type const_val(0xbbbbbbbb);
|
|
strm << logging::add_value("MyAttr1", val) << logging::add_value("MyAttr2", const_val) << logging::add_value("MyAttr3", my_type(0xcccccccc));
|
|
|
|
// Test for MSVC bug: if the value is a scalar type, it saves a dangling reference to the add_value_manip,
|
|
// which results in garbage in the attribute value
|
|
strm << logging::add_value("MyAttr4", 100u);
|
|
strm << logging::add_value("MyAttr5", my_pod_type());
|
|
|
|
strm.detach_from_record();
|
|
|
|
BOOST_CHECK_EQUAL(rec["MyAttr1"].extract< my_type >(), val);
|
|
BOOST_CHECK_EQUAL(rec["MyAttr2"].extract< my_type >(), const_val);
|
|
BOOST_CHECK_EQUAL(rec["MyAttr3"].extract< my_type >(), my_type(0xcccccccc));
|
|
BOOST_CHECK_EQUAL(rec["MyAttr4"].extract< unsigned int >(), 100u);
|
|
BOOST_CHECK_EQUAL(rec["MyAttr5"].extract< my_pod_type >(), my_pod_type());
|
|
}
|
|
|
|
BOOST_LOG_ATTRIBUTE_KEYWORD(a_my1, "MyAttr1", my_type)
|
|
BOOST_LOG_ATTRIBUTE_KEYWORD(a_my2, "MyAttr2", my_type)
|
|
BOOST_LOG_ATTRIBUTE_KEYWORD(a_my3, "MyAttr3", my_type)
|
|
|
|
BOOST_AUTO_TEST_CASE(keyword_add_attr)
|
|
{
|
|
logging::record rec = make_record(logging::attribute_set());
|
|
BOOST_REQUIRE(!!rec);
|
|
logging::record_ostream strm(rec);
|
|
|
|
my_type val(0xaaaaaaaa);
|
|
const my_type const_val(0xbbbbbbbb);
|
|
strm << logging::add_value(a_my1, val) << logging::add_value(a_my2, const_val) << logging::add_value(a_my3, my_type(0xcccccccc));
|
|
strm.detach_from_record();
|
|
|
|
BOOST_CHECK_EQUAL(rec[a_my1], val);
|
|
BOOST_CHECK_EQUAL(rec[a_my2], const_val);
|
|
BOOST_CHECK_EQUAL(rec[a_my3], my_type(0xcccccccc));
|
|
}
|