core.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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 core.cpp
  9. * \author Andrey Semashev
  10. * \date 08.02.2009
  11. *
  12. * \brief This header contains tests for the logging core.
  13. */
  14. #define BOOST_TEST_MODULE core
  15. #include <cstddef>
  16. #include <map>
  17. #include <string>
  18. #include <boost/smart_ptr/shared_ptr.hpp>
  19. #include <boost/move/utility_core.hpp>
  20. #include <boost/test/unit_test.hpp>
  21. #include <boost/log/core/core.hpp>
  22. #include <boost/log/attributes/constant.hpp>
  23. #include <boost/log/attributes/attribute_set.hpp>
  24. #include <boost/log/attributes/attribute_value_set.hpp>
  25. #include <boost/log/expressions.hpp>
  26. #include <boost/log/sinks/sink.hpp>
  27. #include <boost/log/core/record.hpp>
  28. #ifndef BOOST_LOG_NO_THREADS
  29. #include <boost/thread/thread.hpp>
  30. #endif // BOOST_LOG_NO_THREADS
  31. #include "char_definitions.hpp"
  32. #include "test_sink.hpp"
  33. namespace logging = boost::log;
  34. namespace attrs = logging::attributes;
  35. namespace sinks = logging::sinks;
  36. namespace expr = logging::expressions;
  37. // The test checks that message filtering works
  38. BOOST_AUTO_TEST_CASE(filtering)
  39. {
  40. typedef logging::attribute_set attr_set;
  41. typedef logging::core core;
  42. typedef logging::record record_type;
  43. typedef test_data< char > data;
  44. attrs::constant< int > attr1(10);
  45. attrs::constant< double > attr2(5.5);
  46. attr_set set1;
  47. set1[data::attr1()] = attr1;
  48. set1[data::attr2()] = attr2;
  49. boost::shared_ptr< core > pCore = core::get();
  50. boost::shared_ptr< test_sink > pSink(new test_sink());
  51. pCore->add_sink(pSink);
  52. // No filtering at all
  53. {
  54. record_type rec = pCore->open_record(set1);
  55. BOOST_REQUIRE(rec);
  56. pCore->push_record(boost::move(rec));
  57. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
  58. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
  59. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
  60. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
  61. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
  62. pSink->clear();
  63. }
  64. // Core-level filtering
  65. {
  66. pCore->set_filter(expr::has_attr(data::attr3()));
  67. record_type rec = pCore->open_record(set1);
  68. BOOST_CHECK(!rec);
  69. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 0UL);
  70. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 0UL);
  71. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 0UL);
  72. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
  73. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
  74. pSink->clear();
  75. }
  76. {
  77. pCore->set_filter(expr::has_attr(data::attr2()));
  78. record_type rec = pCore->open_record(set1);
  79. BOOST_REQUIRE(rec);
  80. pCore->push_record(boost::move(rec));
  81. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
  82. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
  83. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
  84. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
  85. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
  86. pSink->clear();
  87. }
  88. // Sink-level filtering
  89. {
  90. pCore->reset_filter();
  91. pSink->set_filter(expr::has_attr(data::attr2()));
  92. record_type rec = pCore->open_record(set1);
  93. BOOST_REQUIRE(rec);
  94. pCore->push_record(boost::move(rec));
  95. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
  96. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
  97. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
  98. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
  99. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
  100. pSink->clear();
  101. }
  102. {
  103. pSink->set_filter(expr::has_attr(data::attr3()));
  104. record_type rec = pCore->open_record(set1);
  105. BOOST_CHECK(!rec);
  106. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 0UL);
  107. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 0UL);
  108. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 0UL);
  109. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
  110. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
  111. pSink->clear();
  112. pSink->reset_filter();
  113. }
  114. // Only one sink of the two accepts the record
  115. {
  116. pSink->set_filter(expr::has_attr(data::attr2()));
  117. boost::shared_ptr< test_sink > pSink2(new test_sink());
  118. pCore->add_sink(pSink2);
  119. pSink2->set_filter(expr::has_attr(data::attr3()));
  120. record_type rec = pCore->open_record(set1);
  121. BOOST_REQUIRE(rec);
  122. pCore->push_record(boost::move(rec));
  123. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
  124. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
  125. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
  126. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
  127. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
  128. pSink->clear();
  129. BOOST_CHECK_EQUAL(pSink2->m_RecordCounter, 0UL);
  130. BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr1()], 0UL);
  131. BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr2()], 0UL);
  132. BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr3()], 0UL);
  133. BOOST_CHECK_EQUAL(pSink2->m_Consumed[data::attr4()], 0UL);
  134. pCore->remove_sink(pSink2);
  135. }
  136. pCore->remove_sink(pSink);
  137. pCore->reset_filter();
  138. }
  139. #ifndef BOOST_LOG_NO_THREADS
  140. namespace {
  141. //! A test routine that runs in a separate thread
  142. void thread_attributes_test()
  143. {
  144. typedef test_data< char > data;
  145. typedef logging::core core;
  146. typedef logging::record record_type;
  147. typedef logging::attribute_set attr_set;
  148. attrs::constant< short > attr4(255);
  149. boost::shared_ptr< core > pCore = core::get();
  150. pCore->add_thread_attribute(data::attr4(), attr4);
  151. attr_set set1;
  152. record_type rec = pCore->open_record(set1);
  153. BOOST_CHECK(rec);
  154. if (rec)
  155. pCore->push_record(boost::move(rec));
  156. }
  157. } // namespace
  158. #endif // BOOST_LOG_NO_THREADS
  159. // The test checks that global and thread-specific attributes work
  160. BOOST_AUTO_TEST_CASE(attributes)
  161. {
  162. typedef logging::attribute_set attr_set;
  163. typedef logging::core core;
  164. typedef logging::record record_type;
  165. typedef test_data< char > data;
  166. attrs::constant< int > attr1(10);
  167. attrs::constant< double > attr2(5.5);
  168. attrs::constant< std::string > attr3("Hello, world!");
  169. attr_set set1;
  170. set1[data::attr1()] = attr1;
  171. boost::shared_ptr< core > pCore = core::get();
  172. boost::shared_ptr< test_sink > pSink(new test_sink());
  173. pCore->add_sink(pSink);
  174. attr_set::iterator itGlobal = pCore->add_global_attribute(data::attr2(), attr2).first;
  175. attr_set::iterator itThread = pCore->add_thread_attribute(data::attr3(), attr3).first;
  176. {
  177. attr_set glob = pCore->get_global_attributes();
  178. BOOST_CHECK_EQUAL(glob.size(), 1UL);
  179. BOOST_CHECK_EQUAL(glob.count(data::attr2()), 1UL);
  180. attr_set thr = pCore->get_thread_attributes();
  181. BOOST_CHECK_EQUAL(thr.size(), 1UL);
  182. BOOST_CHECK_EQUAL(thr.count(data::attr3()), 1UL);
  183. }
  184. {
  185. record_type rec = pCore->open_record(set1);
  186. BOOST_REQUIRE(rec);
  187. pCore->push_record(boost::move(rec));
  188. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
  189. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 1UL);
  190. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
  191. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 1UL);
  192. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 0UL);
  193. pSink->clear();
  194. }
  195. #ifndef BOOST_LOG_NO_THREADS
  196. {
  197. boost::thread th(&thread_attributes_test);
  198. th.join();
  199. BOOST_CHECK_EQUAL(pSink->m_RecordCounter, 1UL);
  200. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr1()], 0UL);
  201. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr2()], 1UL);
  202. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr3()], 0UL);
  203. BOOST_CHECK_EQUAL(pSink->m_Consumed[data::attr4()], 1UL);
  204. pSink->clear();
  205. // Thread-specific attributes must not interfere
  206. attr_set thr = pCore->get_thread_attributes();
  207. BOOST_CHECK_EQUAL(thr.size(), 1UL);
  208. BOOST_CHECK_EQUAL(thr.count(data::attr3()), 1UL);
  209. }
  210. #endif // BOOST_LOG_NO_THREADS
  211. pCore->remove_global_attribute(itGlobal);
  212. pCore->remove_thread_attribute(itThread);
  213. pCore->remove_sink(pSink);
  214. }