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