2 * Copyright Andrey Semashev 2007 - 2014.
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)
8 * \file attr_named_scope.cpp
9 * \author Andrey Semashev
12 * \brief This header contains tests for the named scope attribute.
15 #define BOOST_TEST_MODULE attr_named_scope
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"
29 namespace logging = boost::log;
30 namespace attrs = logging::attributes;
35 struct scope_test_data;
38 struct scope_test_data< char >
40 static logging::string_literal scope1() { return logging::str_literal("scope1"); }
41 static logging::string_literal scope2() { return logging::str_literal("scope2"); }
42 static logging::string_literal file() { return logging::str_literal(__FILE__); }
47 // The test verifies that the scope macros are defined
48 BOOST_AUTO_TEST_CASE(macros)
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
56 // The test checks that scope tracking works correctly
57 BOOST_AUTO_TEST_CASE(scope_tracking)
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;
68 const unsigned int line1 = __LINE__;
69 sentry scope1(scope_data::scope1(), scope_data::file(), line1);
71 BOOST_CHECK(!named_scope::get_scopes().empty());
72 BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL);
74 logging::attribute_value val = attr.get_value();
77 logging::value_ref< scopes > sc = val.extract< scopes >();
79 BOOST_REQUIRE(!sc->empty());
80 BOOST_CHECK_EQUAL(sc->size(), 1UL);
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);
88 const unsigned int line2 = __LINE__;
89 scope new_scope(scope_data::scope2(), scope_data::file(), line2);
90 named_scope::push_scope(new_scope);
92 BOOST_CHECK(!named_scope::get_scopes().empty());
93 BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 2UL);
95 val = attr.get_value();
98 sc = val.extract< scopes >();
100 BOOST_REQUIRE(!sc->empty());
101 BOOST_CHECK_EQUAL(sc->size(), 2UL);
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);
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);
114 BOOST_CHECK(it == sc->end());
116 // Second scope goes out
117 named_scope::pop_scope();
119 BOOST_CHECK(!named_scope::get_scopes().empty());
120 BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL);
122 val = attr.get_value();
123 BOOST_REQUIRE(!!val);
125 sc = val.extract< scopes >();
127 BOOST_REQUIRE(!sc->empty());
128 BOOST_CHECK_EQUAL(sc->size(), 1UL);
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);
136 // The test checks that detaching from thread works correctly
137 BOOST_AUTO_TEST_CASE(detaching_from_thread)
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;
146 sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
147 logging::attribute_value val1 = attr.get_value();
148 val1.detach_from_thread();
150 sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
151 logging::attribute_value val2 = attr.get_value();
152 val2.detach_from_thread();
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);
161 // The test checks that output streaming is possible
162 BOOST_AUTO_TEST_CASE(ostreaming)
164 typedef attrs::named_scope named_scope;
165 typedef named_scope::sentry sentry;
166 typedef scope_test_data< char > scope_data;
168 sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__);
169 sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__);
171 std::basic_ostringstream< char > strm;
172 strm << named_scope::get_scopes();
174 BOOST_CHECK(!strm.str().empty());
177 // The test checks that the scope list becomes thread-independent after copying
178 BOOST_AUTO_TEST_CASE(copying)
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;
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);