1 /*
2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7 /*!
8 * \file attr_attribute_value_impl.cpp
9 * \author Andrey Semashev
10 * \date 25.01.2009
11 *
12 * \brief This header contains tests for the basic attribute value class.
13 */
14
15 #define BOOST_TEST_MODULE attr_attribute_value_impl
16
17 #include <string>
18 #include <boost/smart_ptr/intrusive_ptr.hpp>
19 #include <boost/mpl/vector.hpp>
20 #include <boost/test/unit_test.hpp>
21 #include <boost/test/tools/floating_point_comparison.hpp>
22 #include <boost/log/attributes/attribute_value.hpp>
23 #include <boost/log/attributes/attribute_value_impl.hpp>
24 #include <boost/log/attributes/value_extraction.hpp>
25 #include <boost/log/attributes/value_visitation.hpp>
26 #include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
27 #include <boost/log/utility/functional/bind_assign.hpp>
28
29 namespace logging = boost::log;
30 namespace attrs = logging::attributes;
31
32 namespace {
33
34 // Type dispatcher for the supported types
35 struct my_dispatcher :
36 public logging::static_type_dispatcher<
37 boost::mpl::vector< int, double, std::string >
38 >
39 {
40 typedef logging::static_type_dispatcher<
41 boost::mpl::vector< int, double, std::string >
42 > base_type;
43
44 enum type_expected
45 {
46 none_expected,
47 int_expected,
48 double_expected,
49 string_expected
50 };
51
my_dispatcher__anon560e92860111::my_dispatcher52 my_dispatcher() :
53 base_type(*this),
54 m_Expected(none_expected),
55 m_Int(0),
56 m_Double(0.0)
57 {
58 }
59
set_expected__anon560e92860111::my_dispatcher60 void set_expected()
61 {
62 m_Expected = none_expected;
63 }
set_expected__anon560e92860111::my_dispatcher64 void set_expected(int value)
65 {
66 m_Expected = int_expected;
67 m_Int = value;
68 }
set_expected__anon560e92860111::my_dispatcher69 void set_expected(double value)
70 {
71 m_Expected = double_expected;
72 m_Double = value;
73 }
set_expected__anon560e92860111::my_dispatcher74 void set_expected(std::string const& value)
75 {
76 m_Expected = string_expected;
77 m_String = value;
78 }
79
80 // Implement visitation logic for all supported types
operator ()__anon560e92860111::my_dispatcher81 void operator() (int const& value) const
82 {
83 BOOST_CHECK_EQUAL(m_Expected, int_expected);
84 BOOST_CHECK_EQUAL(m_Int, value);
85 }
operator ()__anon560e92860111::my_dispatcher86 void operator() (double const& value) const
87 {
88 BOOST_CHECK_EQUAL(m_Expected, double_expected);
89 BOOST_CHECK_CLOSE(m_Double, value, 0.001);
90 }
operator ()__anon560e92860111::my_dispatcher91 void operator() (std::string const& value) const
92 {
93 BOOST_CHECK_EQUAL(m_Expected, string_expected);
94 BOOST_CHECK_EQUAL(m_String, value);
95 }
96
97 private:
98 type_expected m_Expected;
99 int m_Int;
100 double m_Double;
101 std::string m_String;
102 };
103
104 } // namespace
105
106 // The test verifies that type dispatching works
BOOST_AUTO_TEST_CASE(type_dispatching)107 BOOST_AUTO_TEST_CASE(type_dispatching)
108 {
109 my_dispatcher disp;
110 logging::attribute_value p1(attrs::make_attribute_value< int >(10));
111 logging::attribute_value p2(attrs::make_attribute_value< double > (5.5));
112 logging::attribute_value p3(attrs::make_attribute_value< std::string >(std::string("Hello, world!")));
113 logging::attribute_value p4(attrs::make_attribute_value< float >(static_cast< float >(-7.2)));
114
115 disp.set_expected(10);
116 BOOST_CHECK(p1.dispatch(disp));
117 BOOST_CHECK(p1.dispatch(disp)); // check that the contained value doesn't change over time or upon dispatching
118
119 disp.set_expected(5.5);
120 BOOST_CHECK(p2.dispatch(disp));
121
122 disp.set_expected("Hello, world!");
123 BOOST_CHECK(p3.dispatch(disp));
124
125 disp.set_expected();
126 BOOST_CHECK(!p4.dispatch(disp));
127 }
128
129 // The test verifies that value extraction works
BOOST_AUTO_TEST_CASE(value_extraction)130 BOOST_AUTO_TEST_CASE(value_extraction)
131 {
132 logging::attribute_value p1(attrs::make_attribute_value< int >(10));
133 logging::attribute_value p2(attrs::make_attribute_value< double >(5.5));
134
135 logging::value_ref< int > val1 = p1.extract< int >();
136 BOOST_CHECK(!!val1);
137 BOOST_CHECK_EQUAL(val1.get(), 10);
138
139 logging::value_ref< double > val2 = p1.extract< double >();
140 BOOST_CHECK(!val2);
141
142 double val3 = 0.0;
143 BOOST_CHECK(p2.visit< double >(logging::bind_assign(val3)));
144 BOOST_CHECK_CLOSE(val3, 5.5, 0.001);
145 }
146
147 // The test verifies that the detach_from_thread returns a valid pointer
BOOST_AUTO_TEST_CASE(detaching_from_thread)148 BOOST_AUTO_TEST_CASE(detaching_from_thread)
149 {
150 boost::intrusive_ptr< logging::attribute_value::impl > p1(new attrs::attribute_value_impl< int >(10));
151 boost::intrusive_ptr< logging::attribute_value::impl > p2 = p1->detach_from_thread();
152 BOOST_CHECK(!!p2);
153 }
154