/* * 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_named_scope.cpp * \author Andrey Semashev * \date 25.01.2009 * * \brief This header contains tests for the named scope attribute. */ #define BOOST_TEST_MODULE attr_named_scope #include #include #include #include #include #include #include #include #include #include #include "char_definitions.hpp" namespace logging = boost::log; namespace attrs = logging::attributes; namespace { template< typename > struct scope_test_data; template< > struct scope_test_data< char > { static logging::string_literal scope1() { return logging::str_literal("scope1"); } static logging::string_literal scope2() { return logging::str_literal("scope2"); } static logging::string_literal file() { return logging::str_literal(__FILE__); } }; } // namespace // The test verifies that the scope macros are defined BOOST_AUTO_TEST_CASE(macros) { #ifdef BOOST_LOG_USE_CHAR BOOST_CHECK(BOOST_IS_DEFINED(BOOST_LOG_NAMED_SCOPE(name))); BOOST_CHECK(BOOST_IS_DEFINED(BOOST_LOG_FUNCTION())); #endif // BOOST_LOG_USE_CHAR } // The test checks that scope tracking works correctly BOOST_AUTO_TEST_CASE(scope_tracking) { typedef attrs::named_scope named_scope; typedef named_scope::sentry sentry; typedef attrs::named_scope_list scopes; typedef attrs::named_scope_entry scope; typedef scope_test_data< char > scope_data; named_scope attr; // First scope const unsigned int line1 = __LINE__; sentry scope1(scope_data::scope1(), scope_data::file(), line1); BOOST_CHECK(!named_scope::get_scopes().empty()); BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL); logging::attribute_value val = attr.get_value(); BOOST_REQUIRE(!!val); logging::value_ref< scopes > sc = val.extract< scopes >(); BOOST_REQUIRE(!!sc); BOOST_REQUIRE(!sc->empty()); BOOST_CHECK_EQUAL(sc->size(), 1UL); scope const& s1 = sc->front(); BOOST_CHECK(s1.scope_name == scope_data::scope1()); BOOST_CHECK(s1.file_name == scope_data::file()); BOOST_CHECK(s1.line == line1); // Second scope const unsigned int line2 = __LINE__; scope new_scope(scope_data::scope2(), scope_data::file(), line2); named_scope::push_scope(new_scope); BOOST_CHECK(!named_scope::get_scopes().empty()); BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 2UL); val = attr.get_value(); BOOST_REQUIRE(!!val); sc = val.extract< scopes >(); BOOST_REQUIRE(!!sc); BOOST_REQUIRE(!sc->empty()); BOOST_CHECK_EQUAL(sc->size(), 2UL); scopes::const_iterator it = sc->begin(); scope const& s2 = *(it++); BOOST_CHECK(s2.scope_name == scope_data::scope1()); BOOST_CHECK(s2.file_name == scope_data::file()); BOOST_CHECK(s2.line == line1); scope const& s3 = *(it++); BOOST_CHECK(s3.scope_name == scope_data::scope2()); BOOST_CHECK(s3.file_name == scope_data::file()); BOOST_CHECK(s3.line == line2); BOOST_CHECK(it == sc->end()); // Second scope goes out named_scope::pop_scope(); BOOST_CHECK(!named_scope::get_scopes().empty()); BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 1UL); val = attr.get_value(); BOOST_REQUIRE(!!val); sc = val.extract< scopes >(); BOOST_REQUIRE(!!sc); BOOST_REQUIRE(!sc->empty()); BOOST_CHECK_EQUAL(sc->size(), 1UL); scope const& s4 = sc->back(); // should be the same as front BOOST_CHECK(s4.scope_name == scope_data::scope1()); BOOST_CHECK(s4.file_name == scope_data::file()); BOOST_CHECK(s4.line == line1); } // The test checks that detaching from thread works correctly BOOST_AUTO_TEST_CASE(detaching_from_thread) { typedef attrs::named_scope named_scope; typedef named_scope::sentry sentry; typedef attrs::named_scope_list scopes; typedef scope_test_data< char > scope_data; named_scope attr; sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__); logging::attribute_value val1 = attr.get_value(); val1.detach_from_thread(); sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__); logging::attribute_value val2 = attr.get_value(); val2.detach_from_thread(); logging::value_ref< scopes > sc1 = val1.extract< scopes >(), sc2 = val2.extract< scopes >(); BOOST_REQUIRE(!!sc1); BOOST_REQUIRE(!!sc2); BOOST_CHECK_EQUAL(sc1->size(), 1UL); BOOST_CHECK_EQUAL(sc2->size(), 2UL); } // The test checks that output streaming is possible BOOST_AUTO_TEST_CASE(ostreaming) { typedef attrs::named_scope named_scope; typedef named_scope::sentry sentry; typedef scope_test_data< char > scope_data; sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__); sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__); std::basic_ostringstream< char > strm; strm << named_scope::get_scopes(); BOOST_CHECK(!strm.str().empty()); } // The test checks that the scope list becomes thread-independent after copying BOOST_AUTO_TEST_CASE(copying) { typedef attrs::named_scope named_scope; typedef named_scope::sentry sentry; typedef attrs::named_scope_list scopes; typedef scope_test_data< char > scope_data; sentry scope1(scope_data::scope1(), scope_data::file(), __LINE__); scopes sc = named_scope::get_scopes(); sentry scope2(scope_data::scope2(), scope_data::file(), __LINE__); BOOST_CHECK_EQUAL(sc.size(), 1UL); BOOST_CHECK_EQUAL(named_scope::get_scopes().size(), 2UL); }