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_named_scope.cpp
9 * \author Andrey Semashev
10 * \date 25.01.2009
11 *
12 * \brief This header contains tests for the named scope attribute.
13 */
14
15 #define BOOST_TEST_MODULE attr_named_scope
16
17 #include <sstream>
18 #include <boost/mpl/vector.hpp>
19 #include <boost/preprocessor/cat.hpp>
20 #include <boost/test/unit_test.hpp>
21 #include <boost/log/attributes/attribute.hpp>
22 #include <boost/log/attributes/named_scope.hpp>
23 #include <boost/log/attributes/attribute_value.hpp>
24 #include <boost/log/attributes/value_extraction.hpp>
25 #include <boost/log/utility/string_literal.hpp>
26 #include <boost/log/utility/value_ref.hpp>
27 #include "char_definitions.hpp"
28
29 namespace logging = boost::log;
30 namespace attrs = logging::attributes;
31
32 namespace {
33
34 template< typename >
35 struct scope_test_data;
36
37 template< >
38 struct scope_test_data< char >
39 {
scope1__anon25d0d1df0111::scope_test_data40 static logging::string_literal scope1() { return logging::str_literal("scope1"); }
scope2__anon25d0d1df0111::scope_test_data41 static logging::string_literal scope2() { return logging::str_literal("scope2"); }
file__anon25d0d1df0111::scope_test_data42 static logging::string_literal file() { return logging::str_literal(__FILE__); }
43 };
44
45 } // namespace
46
47 // The test verifies that the scope macros are defined
BOOST_AUTO_TEST_CASE(macros)48 BOOST_AUTO_TEST_CASE(macros)
49 {
50 #ifdef BOOST_LOG_USE_CHAR
51 BOOST_CHECK(BOOST_IS_DEFINED(BOOST_LOG_NAMED_SCOPE(name)));
52 BOOST_CHECK(BOOST_IS_DEFINED(BOOST_LOG_FUNCTION()));
53 #endif // BOOST_LOG_USE_CHAR
54 }
55
56 // The test checks that scope tracking works correctly
BOOST_AUTO_TEST_CASE(scope_tracking)57 BOOST_AUTO_TEST_CASE(scope_tracking)
58 {
59 typedef attrs::named_scope named_scope;
60 typedef named_scope::sentry sentry;
61 typedef attrs::named_scope_list scopes;
62 typedef attrs::named_scope_entry scope;
63 typedef scope_test_data< char > scope_data;
64
65 named_scope attr;
66
67 // First scope
68 const unsigned int line1 = __LINE__;
69 sentry scope1(scope_data::scope1(), scope_data::file(), line1);
70
71 BOOST_CHECK(!named_scope::get_scopes().empty());
72 BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL);
73
74 logging::attribute_value val = attr.get_value();
75 BOOST_REQUIRE(!!val);
76
77 logging::value_ref< scopes > sc = val.extract< scopes >();
78 BOOST_REQUIRE(!!sc);
79 BOOST_REQUIRE(!sc->empty());
80 BOOST_CHECK_EQUAL(sc->size(), 1UL);
81
82 scope const& s1 = sc->front();
83 BOOST_CHECK(s1.scope_name == scope_data::scope1());
84 BOOST_CHECK(s1.file_name == scope_data::file());
85 BOOST_CHECK(s1.line == line1);
86
87 // Second scope
88 const unsigned int line2 = __LINE__;
89 scope new_scope(scope_data::scope2(), scope_data::file(), line2);
90 named_scope::push_scope(new_scope);
91
92 BOOST_CHECK(!named_scope::get_scopes().empty());
93 BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 2UL);
94
95 val = attr.get_value();
96 BOOST_REQUIRE(!!val);
97
98 sc = val.extract< scopes >();
99 BOOST_REQUIRE(!!sc);
100 BOOST_REQUIRE(!sc->empty());
101 BOOST_CHECK_EQUAL(sc->size(), 2UL);
102
103 scopes::const_iterator it = sc->begin();
104 scope const& s2 = *(it++);
105 BOOST_CHECK(s2.scope_name == scope_data::scope1());
106 BOOST_CHECK(s2.file_name == scope_data::file());
107 BOOST_CHECK(s2.line == line1);
108
109 scope const& s3 = *(it++);
110 BOOST_CHECK(s3.scope_name == scope_data::scope2());
111 BOOST_CHECK(s3.file_name == scope_data::file());
112 BOOST_CHECK(s3.line == line2);
113
114 BOOST_CHECK(it == sc->end());
115
116 // Second scope goes out
117 named_scope::pop_scope();
118
119 BOOST_CHECK(!named_scope::get_scopes().empty());
120 BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL);
121
122 val = attr.get_value();
123 BOOST_REQUIRE(!!val);
124
125 sc = val.extract< scopes >();
126 BOOST_REQUIRE(!!sc);
127 BOOST_REQUIRE(!sc->empty());
128 BOOST_CHECK_EQUAL(sc->size(), 1UL);
129
130 scope const& s4 = sc->back(); // should be the same as front
131 BOOST_CHECK(s4.scope_name == scope_data::scope1());
132 BOOST_CHECK(s4.file_name == scope_data::file());
133 BOOST_CHECK(s4.line == line1);
134 }
135
136 // The test checks that detaching from thread works correctly
BOOST_AUTO_TEST_CASE(detaching_from_thread)137 BOOST_AUTO_TEST_CASE(detaching_from_thread)
138 {
139 typedef attrs::named_scope named_scope;
140 typedef named_scope::sentry sentry;
141 typedef attrs::named_scope_list scopes;
142 typedef scope_test_data< char > scope_data;
143
144 named_scope attr;
145
146 sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
147 logging::attribute_value val1 = attr.get_value();
148 val1.detach_from_thread();
149
150 sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
151 logging::attribute_value val2 = attr.get_value();
152 val2.detach_from_thread();
153
154 logging::value_ref< scopes > sc1 = val1.extract< scopes >(), sc2 = val2.extract< scopes >();
155 BOOST_REQUIRE(!!sc1);
156 BOOST_REQUIRE(!!sc2);
157 BOOST_CHECK_EQUAL(sc1->size(), 1UL);
158 BOOST_CHECK_EQUAL(sc2->size(), 2UL);
159 }
160
161 // The test checks that output streaming is possible
BOOST_AUTO_TEST_CASE(ostreaming)162 BOOST_AUTO_TEST_CASE(ostreaming)
163 {
164 typedef attrs::named_scope named_scope;
165 typedef named_scope::sentry sentry;
166 typedef scope_test_data< char > scope_data;
167
168 sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
169 sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
170
171 std::basic_ostringstream< char > strm;
172 strm << named_scope::get_scopes();
173
174 BOOST_CHECK(!strm.str().empty());
175 }
176
177 // The test checks that the scope list becomes thread-independent after copying
BOOST_AUTO_TEST_CASE(copying)178 BOOST_AUTO_TEST_CASE(copying)
179 {
180 typedef attrs::named_scope named_scope;
181 typedef named_scope::sentry sentry;
182 typedef attrs::named_scope_list scopes;
183 typedef scope_test_data< char > scope_data;
184
185 sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
186 scopes sc = named_scope::get_scopes();
187 sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
188 BOOST_CHECK_EQUAL(sc.size(), 1UL);
189 BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 2UL);
190 }
191