• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   form_named_scope.cpp
9  * \author Andrey Semashev
10  * \date   07.02.2009
11  *
12  * \brief  This header contains tests for the \c named_scope formatter.
13  */
14 
15 #define BOOST_TEST_MODULE form_named_scope
16 
17 #include <string>
18 #include <boost/config.hpp>
19 #include <boost/preprocessor/cat.hpp>
20 #include <boost/test/unit_test.hpp>
21 #include <boost/log/attributes/constant.hpp>
22 #include <boost/log/attributes/attribute_set.hpp>
23 #include <boost/log/attributes/named_scope.hpp>
24 #include <boost/log/expressions.hpp>
25 #include <boost/log/utility/formatting_ostream.hpp>
26 #include <boost/log/utility/string_literal.hpp>
27 #include <boost/log/core/record.hpp>
28 #include "char_definitions.hpp"
29 #include "make_record.hpp"
30 
31 namespace logging = boost::log;
32 namespace attrs = logging::attributes;
33 namespace expr = logging::expressions;
34 namespace keywords = logging::keywords;
35 
36 namespace {
37 
38     template< typename CharT >
39     struct named_scope_test_data;
40 
41     struct named_scope_test_data_base
42     {
scope1__anonf3e30c380111::named_scope_test_data_base43         static logging::string_literal scope1() { return logging::str_literal("scope1"); }
scope2__anonf3e30c380111::named_scope_test_data_base44         static logging::string_literal scope2() { return logging::str_literal("scope2"); }
45 
file__anonf3e30c380111::named_scope_test_data_base46         static logging::string_literal file() { return logging::str_literal(__FILE__); }
posix_file__anonf3e30c380111::named_scope_test_data_base47         static logging::string_literal posix_file() { return logging::str_literal("/home/user/posix_file.cpp"); }
windows_file1__anonf3e30c380111::named_scope_test_data_base48         static logging::string_literal windows_file1() { return logging::str_literal("C:\\user\\windows_file1.cpp"); }
windows_file2__anonf3e30c380111::named_scope_test_data_base49         static logging::string_literal windows_file2() { return logging::str_literal("C:/user/windows_file2.cpp"); }
50     };
51 
52 #ifdef BOOST_LOG_USE_CHAR
53     template< >
54     struct named_scope_test_data< char > :
55         public test_data< char >,
56         public named_scope_test_data_base
57     {
default_format__anonf3e30c380111::named_scope_test_data58         static logging::string_literal default_format() { return logging::str_literal("%n"); }
full_format__anonf3e30c380111::named_scope_test_data59         static logging::string_literal full_format() { return logging::str_literal("%n (%f:%l)"); }
short_filename_format__anonf3e30c380111::named_scope_test_data60         static logging::string_literal short_filename_format() { return logging::str_literal("%n (%F:%l)"); }
scope_function_name_format__anonf3e30c380111::named_scope_test_data61         static logging::string_literal scope_function_name_format() { return logging::str_literal("%c"); }
function_name_format__anonf3e30c380111::named_scope_test_data62         static logging::string_literal function_name_format() { return logging::str_literal("%C"); }
delimiter1__anonf3e30c380111::named_scope_test_data63         static logging::string_literal delimiter1() { return logging::str_literal("|"); }
incomplete_marker__anonf3e30c380111::named_scope_test_data64         static logging::string_literal incomplete_marker() { return logging::str_literal("<<and more>>"); }
empty_marker__anonf3e30c380111::named_scope_test_data65         static logging::string_literal empty_marker() { return logging::str_literal("[empty]"); }
66     };
67 #endif // BOOST_LOG_USE_CHAR
68 
69 #ifdef BOOST_LOG_USE_WCHAR_T
70     template< >
71     struct named_scope_test_data< wchar_t > :
72         public test_data< wchar_t >,
73         public named_scope_test_data_base
74     {
default_format__anonf3e30c380111::named_scope_test_data75         static logging::wstring_literal default_format() { return logging::str_literal(L"%n"); }
full_format__anonf3e30c380111::named_scope_test_data76         static logging::wstring_literal full_format() { return logging::str_literal(L"%n (%f:%l)"); }
short_filename_format__anonf3e30c380111::named_scope_test_data77         static logging::wstring_literal short_filename_format() { return logging::str_literal(L"%n (%F:%l)"); }
scope_function_name_format__anonf3e30c380111::named_scope_test_data78         static logging::wstring_literal scope_function_name_format() { return logging::str_literal(L"%c"); }
function_name_format__anonf3e30c380111::named_scope_test_data79         static logging::wstring_literal function_name_format() { return logging::str_literal(L"%C"); }
delimiter1__anonf3e30c380111::named_scope_test_data80         static logging::wstring_literal delimiter1() { return logging::str_literal(L"|"); }
incomplete_marker__anonf3e30c380111::named_scope_test_data81         static logging::wstring_literal incomplete_marker() { return logging::str_literal(L"<<and more>>"); }
empty_marker__anonf3e30c380111::named_scope_test_data82         static logging::wstring_literal empty_marker() { return logging::str_literal(L"[empty]"); }
83     };
84 #endif // BOOST_LOG_USE_WCHAR_T
85 
86     template< typename CharT >
check_formatting(logging::basic_string_literal<CharT> const & format,logging::record_view const & rec,std::basic_string<CharT> const & expected)87     inline bool check_formatting(logging::basic_string_literal< CharT > const& format, logging::record_view const& rec, std::basic_string< CharT > const& expected)
88     {
89         typedef logging::basic_formatter< CharT > formatter;
90         typedef std::basic_string< CharT > string;
91         typedef logging::basic_formatting_ostream< CharT > osstream;
92         typedef named_scope_test_data< CharT > data;
93 
94         string str;
95         osstream strm(str);
96         formatter f = expr::stream << expr::format_named_scope(data::attr1(), keywords::format = format.c_str());
97         f(rec, strm);
98         return equal_strings(strm.str(), expected);
99     }
100 
101 } // namespace
102 
103 // The test checks that named scopes stack formatting works
BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_formatting,CharT,char_types)104 BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_formatting, CharT, char_types)
105 {
106     typedef attrs::named_scope named_scope;
107     typedef named_scope::sentry sentry;
108 
109     typedef logging::attribute_set attr_set;
110     typedef std::basic_string< CharT > string;
111     typedef logging::basic_formatting_ostream< CharT > osstream;
112     typedef logging::basic_formatter< CharT > formatter;
113     typedef logging::record_view record_view;
114     typedef named_scope_test_data< CharT > data;
115 
116     named_scope attr;
117 
118     // First scope
119     const unsigned int line1 = __LINE__;
120     sentry scope1(data::scope1(), data::file(), line1);
121     const unsigned int line2 = __LINE__;
122     sentry scope2(data::scope2(), data::file(), line2);
123 
124     attr_set set1;
125     set1[data::attr1()] = attr;
126 
127     record_view rec = make_record_view(set1);
128 
129     // Default format
130     {
131         string str;
132         osstream strm(str);
133         strm << data::scope1() << "->" << data::scope2();
134         BOOST_CHECK(check_formatting(data::default_format(), rec, strm.str()));
135     }
136     // Full format
137     {
138         string str;
139         osstream strm(str);
140         strm << data::scope1() << " (" << data::file() << ":" << line1 << ")->"
141              << data::scope2() << " (" << data::file() << ":" << line2 << ")";
142         BOOST_CHECK(check_formatting(data::full_format(), rec, strm.str()));
143     }
144     // Different delimiter
145     {
146         string str1, str2;
147         osstream strm1(str1), strm2(str2);
148         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
149             keywords::format = data::default_format().c_str(),
150             keywords::delimiter = data::delimiter1().c_str());
151         f(rec, strm1);
152         strm2 << data::scope1() << "|" << data::scope2();
153         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
154     }
155     // Different direction
156     {
157         string str1, str2;
158         osstream strm1(str1), strm2(str2);
159         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
160             keywords::format = data::default_format().c_str(),
161             keywords::iteration = expr::reverse);
162         f(rec, strm1);
163         strm2 << data::scope2() << "<-" << data::scope1();
164         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
165     }
166     {
167         string str1, str2;
168         osstream strm1(str1), strm2(str2);
169         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
170             keywords::format = data::default_format().c_str(),
171             keywords::delimiter = data::delimiter1().c_str(),
172             keywords::iteration = expr::reverse);
173         f(rec, strm1);
174         strm2 << data::scope2() << "|" << data::scope1();
175         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
176     }
177     // Limiting the number of scopes
178     {
179         string str1, str2;
180         osstream strm1(str1), strm2(str2);
181         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
182             keywords::format = data::default_format().c_str(),
183             keywords::depth = 1);
184         f(rec, strm1);
185         strm2 << "..." << data::scope2();
186         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
187     }
188     {
189         string str1, str2;
190         osstream strm1(str1), strm2(str2);
191         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
192             keywords::format = data::default_format().c_str(),
193             keywords::depth = 1,
194             keywords::iteration = expr::reverse);
195         f(rec, strm1);
196         strm2 << data::scope2() << "...";
197         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
198     }
199     {
200         string str1, str2;
201         osstream strm1(str1), strm2(str2);
202         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
203             keywords::format = data::default_format().c_str(),
204             keywords::delimiter = data::delimiter1().c_str(),
205             keywords::depth = 1);
206         f(rec, strm1);
207         strm2 << "..." << data::scope2();
208         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
209     }
210     {
211         string str1, str2;
212         osstream strm1(str1), strm2(str2);
213         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
214             keywords::format = data::default_format().c_str(),
215             keywords::delimiter = data::delimiter1().c_str(),
216             keywords::depth = 1,
217             keywords::iteration = expr::reverse);
218         f(rec, strm1);
219         strm2 << data::scope2() << "...";
220         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
221     }
222     {
223         string str1, str2;
224         osstream strm1(str1), strm2(str2);
225         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
226             keywords::format = data::default_format().c_str(),
227             keywords::incomplete_marker = data::incomplete_marker().c_str(),
228             keywords::depth = 1);
229         f(rec, strm1);
230         strm2 << "<<and more>>" << data::scope2();
231         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
232     }
233     {
234         string str1, str2;
235         osstream strm1(str1), strm2(str2);
236         formatter f = expr::stream << expr::format_named_scope(data::attr1(),
237             keywords::format = data::default_format().c_str(),
238             keywords::incomplete_marker = data::incomplete_marker().c_str(),
239             keywords::depth = 1,
240             keywords::iteration = expr::reverse);
241         f(rec, strm1);
242         strm2 << data::scope2() << "<<and more>>";
243         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
244     }
245 }
246 
247 // The test checks that empty named scopes stack formatting works
BOOST_AUTO_TEST_CASE_TEMPLATE(empty_scopes_formatting,CharT,char_types)248 BOOST_AUTO_TEST_CASE_TEMPLATE(empty_scopes_formatting, CharT, char_types)
249 {
250     typedef attrs::named_scope named_scope;
251     typedef named_scope::sentry sentry;
252 
253     typedef logging::attribute_set attr_set;
254     typedef std::basic_string< CharT > string;
255     typedef logging::basic_formatting_ostream< CharT > osstream;
256     typedef logging::basic_formatter< CharT > formatter;
257     typedef logging::record_view record_view;
258     typedef named_scope_test_data< CharT > data;
259 
260     named_scope attr;
261 
262     attr_set set1;
263     set1[data::attr1()] = attr;
264 
265     record_view rec = make_record_view(set1);
266 
267     formatter f = expr::stream << expr::format_named_scope(data::attr1(),
268         keywords::format = data::default_format().c_str(),
269         keywords::empty_marker = data::empty_marker().c_str());
270 
271     {
272         string str1, str2;
273         osstream strm1(str1), strm2(str2);
274         f(rec, strm1);
275         strm2 << "[empty]";
276         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
277     }
278 
279     const unsigned int line1 = __LINE__;
280     sentry scope1(data::scope1(), data::file(), line1);
281     const unsigned int line2 = __LINE__;
282     sentry scope2(data::scope2(), data::file(), line2);
283 
284     {
285         string str1, str2;
286         osstream strm1(str1), strm2(str2);
287         f(rec, strm1);
288         strm2 << data::scope1() << "->" << data::scope2();
289         BOOST_CHECK(equal_strings(strm1.str(), strm2.str()));
290     }
291 }
292 
BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_filename_formatting_posix,CharT,char_types)293 BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_filename_formatting_posix, CharT, char_types)
294 {
295     typedef attrs::named_scope named_scope;
296     typedef named_scope::sentry sentry;
297 
298     typedef logging::attribute_set attr_set;
299     typedef std::basic_string< CharT > string;
300     typedef logging::basic_formatting_ostream< CharT > osstream;
301     typedef logging::record_view record_view;
302     typedef named_scope_test_data< CharT > data;
303 
304     named_scope attr;
305 
306     // First scope
307     const unsigned int line1 = __LINE__;
308     sentry scope1(data::scope1(), data::posix_file(), line1);
309 
310     attr_set set1;
311     set1[data::attr1()] = attr;
312 
313     record_view rec = make_record_view(set1);
314 
315     // File names without the full path
316     {
317         string str;
318         osstream strm(str);
319         strm << data::scope1() << " (posix_file.cpp:" << line1 << ")";
320         BOOST_CHECK(check_formatting(data::short_filename_format(), rec, strm.str()));
321     }
322 }
323 
324 #if defined(BOOST_WINDOWS)
325 
BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_filename_formatting_windows,CharT,char_types)326 BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_filename_formatting_windows, CharT, char_types)
327 {
328     typedef attrs::named_scope named_scope;
329     typedef named_scope::sentry sentry;
330 
331     typedef logging::attribute_set attr_set;
332     typedef std::basic_string< CharT > string;
333     typedef logging::basic_formatting_ostream< CharT > osstream;
334     typedef logging::record_view record_view;
335     typedef named_scope_test_data< CharT > data;
336 
337     named_scope attr;
338 
339     // First scope
340     const unsigned int line1 = __LINE__;
341     sentry scope1(data::scope1(), data::windows_file1(), line1);
342     const unsigned int line2 = __LINE__;
343     sentry scope2(data::scope2(), data::windows_file2(), line2);
344 
345     attr_set set1;
346     set1[data::attr1()] = attr;
347 
348     record_view rec = make_record_view(set1);
349 
350     // File names without the full path
351     {
352         string str;
353         osstream strm(str);
354         strm << data::scope1() << " (windows_file1.cpp:" << line1 << ")->"
355              << data::scope2() << " (windows_file2.cpp:" << line2 << ")";
356         BOOST_CHECK(check_formatting(data::short_filename_format(), rec, strm.str()));
357     }
358 }
359 
360 #endif // defined(BOOST_WINDOWS)
361 
362 namespace {
363 
364 struct named_scope_test_case
365 {
366     logging::string_literal scope_name;
367     const char* function_name;
368     const char* function_name_no_scope;
369 };
370 
371 const named_scope_test_case named_scope_test_cases[] =
372 {
373     // Generic signatures
374     { logging::str_literal("int main(int, char *[])"), "main", "main" },
375     { logging::str_literal("namespace_name::type foo()"), "foo", "foo" },
376     { logging::str_literal("namespace_name::type& foo::bar(int[], std::string const&)"), "foo::bar", "bar" },
377     { logging::str_literal("void* namespc::foo<char>::bar()"), "namespc::foo<char>::bar", "bar" },
378     { logging::str_literal("void* namespc::foo<char>::bar<int>(int) const"), "namespc::foo<char>::bar<int>", "bar<int>" },
379 
380     // MSVC-specific
381     { logging::str_literal("int __cdecl main(int, char *[])"), "main", "main" },
382     { logging::str_literal("struct namespc::strooct __cdecl foo3(int [])"), "foo3", "foo3" },
383     { logging::str_literal("void (__cdecl *__cdecl foo4(void))(void)"), "foo4", "foo4" }, // function returning pointer to function
384     { logging::str_literal("void (__cdecl *__cdecl foo5(void (__cdecl *)(void)))(void)"), "foo5", "foo5" },
385     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<int>::member1(void (__cdecl *)(void)))(void)"), "namespc::my_class<int>::member1", "member1" },
386     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<int>::member2<int>(int))(void)"), "namespc::my_class<int>::member2<int>", "member2<int>" },
387     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<int>::member2<void(__cdecl *)(void)>(void (__cdecl *)(void)))(void)"), "namespc::my_class<int>::member2<void(__cdecl *)(void)>", "member2<void(__cdecl *)(void)>" },
388     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<int>::member3<void __cdecl foo1(void)>(void))(void)"), "namespc::my_class<int>::member3<void __cdecl foo1(void)>", "member3<void __cdecl foo1(void)>" },
389     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<void (__cdecl*)(void)>::member1(void (__cdecl *)(void)))(void)"), "namespc::my_class<void (__cdecl*)(void)>::member1", "member1" },
390     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<void (__cdecl*)(void)>::member2<int>(int))(void)"), "namespc::my_class<void (__cdecl*)(void)>::member2<int>", "member2<int>" },
391     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<void (__cdecl*)(void)>::member2<void(__cdecl *)(void)>(void (__cdecl *)(void)))(void)"), "namespc::my_class<void (__cdecl*)(void)>::member2<void(__cdecl *)(void)>", "member2<void(__cdecl *)(void)>" },
392     { logging::str_literal("void (__cdecl *__cdecl namespc::my_class<void (__cdecl*)(void)>::member3<void __cdecl foo1(void)>(void))(void)"), "namespc::my_class<void (__cdecl*)(void)>::member3<void __cdecl foo1(void)>", "member3<void __cdecl foo1(void)>" },
393     { logging::str_literal("void (__cdecl namespc::my_class2::* __cdecl namespc::foo6(void (__cdecl *)(void)))(void)"), "namespc::foo6", "foo6" },
394     { logging::str_literal("struct namespc::my_class<void __cdecl(int)> __cdecl namespc::foo7(void)"), "namespc::foo7", "foo7" },
395     { logging::str_literal("void (__cdecl namespc::my_class2::* const (&__cdecl namespc::foo8(void (__cdecl *)(void)))[2])(void)"), "namespc::foo8", "foo8" },
396     { logging::str_literal("__cdecl namespc::my_class2::my_class2(void)"), "namespc::my_class2::my_class2", "my_class2" },
397     { logging::str_literal("__cdecl namespc::my_class2::~my_class2(void)"), "namespc::my_class2::~my_class2", "~my_class2" },
398     { logging::str_literal("void __cdecl namespc::my_class2::operator =(const struct namespc::my_class2 &)"), "namespc::my_class2::operator =", "operator =" },
399     { logging::str_literal("void __cdecl namespc::my_class2::operator *(void) const"), "namespc::my_class2::operator *", "operator *" },
400     { logging::str_literal("void __cdecl namespc::my_class2::operator ()(void)"), "namespc::my_class2::operator ()", "operator ()" },
401     { logging::str_literal("bool __cdecl namespc::my_class2::operator <(int) const"), "namespc::my_class2::operator <", "operator <" },
402     { logging::str_literal("bool __cdecl namespc::my_class2::operator >(int) const"), "namespc::my_class2::operator >", "operator >" },
403     { logging::str_literal("bool __cdecl namespc::my_class2::operator <=(int) const"), "namespc::my_class2::operator <=", "operator <=" },
404     { logging::str_literal("bool __cdecl namespc::my_class2::operator >=(int) const"), "namespc::my_class2::operator >=", "operator >=" },
405     { logging::str_literal("__cdecl namespc::my_class2::operator bool(void) const"), "namespc::my_class2::operator bool", "operator bool" },
406     // MSVC generates incorrect strings in case of conversion operators to function types. We don't support these.
407 //    { logging::str_literal("__cdecl namespc::my_class2::operator char (__cdecl *)(double)(__cdecl *(void) const)(double)"), "namespc::my_class2::operator char (__cdecl *)(double)", "operator char (__cdecl *)(double)" },
408 //    { logging::str_literal("__cdecl namespc::my_class2::operator char (__cdecl namespc::my_class2::* )(double)(__cdecl namespc::my_class2::* (void) const)(double)"), "namespc::my_class2::operator char (__cdecl namespc::my_class2::* )(double)", "operator char (__cdecl namespc::my_class2::* )(double)" },
409     { logging::str_literal("class std::basic_ostream<char,struct std::char_traits<char> > &__cdecl namespc::operator <<<char,struct std::char_traits<char>>(class std::basic_ostream<char,struct std::char_traits<char> > &,const struct namespc::my_class2 &)"), "namespc::operator <<<char,struct std::char_traits<char>>", "operator <<<char,struct std::char_traits<char>>" },
410     { logging::str_literal("class std::basic_istream<char,struct std::char_traits<char> > &__cdecl namespc::operator >><char,struct std::char_traits<char>>(class std::basic_istream<char,struct std::char_traits<char> > &,struct namespc::my_class2 &)"), "namespc::operator >><char,struct std::char_traits<char>>", "operator >><char,struct std::char_traits<char>>" },
411 
412     // GCC-specific
413     { logging::str_literal("namespc::strooct foo3(int*)"), "foo3", "foo3" },
414     { logging::str_literal("void (* foo4())()"), "foo4", "foo4" }, // function returning pointer to function
415     { logging::str_literal("void (* foo5(pfun2_t))()"), "foo5", "foo5" },
416     { logging::str_literal("static void (* namespc::my_class<T>::member1(pfun2_t))() [with T = int; pfun1_t = void (*)(); pfun2_t = void (*)()]"), "namespc::my_class<T>::member1", "member1" },
417     { logging::str_literal("static void (* namespc::my_class<T>::member2(U))() [with U = int; T = int; pfun2_t = void (*)()]"), "namespc::my_class<T>::member2", "member2" },
418     { logging::str_literal("static void (* namespc::my_class<T>::member2(U))() [with U = void (*)(); T = int; pfun2_t = void (*)()]"), "namespc::my_class<T>::member2", "member2" },
419     { logging::str_literal("static void (* namespc::my_class<T>::member3())() [with void (* Fun)() = foo1; T = int; pfun2_t = void (*)()]"), "namespc::my_class<T>::member3", "member3" },
420     { logging::str_literal("static void (* namespc::my_class<T>::member1(pfun2_t))() [with T = void (*)(); pfun1_t = void (*)(); pfun2_t = void (*)()]"), "namespc::my_class<T>::member1", "member1" },
421     { logging::str_literal("static void (* namespc::my_class<T>::member2(U))() [with U = int; T = void (*)(); pfun2_t = void (*)()]"), "namespc::my_class<T>::member2", "member2" },
422     { logging::str_literal("static void (* namespc::my_class<T>::member2(U))() [with U = void (*)(); T = void (*)(); pfun2_t = void (*)()]"), "namespc::my_class<T>::member2", "member2" },
423     { logging::str_literal("static void (* namespc::my_class<T>::member3())() [with void (* Fun)() = foo1; T = void (*)(); pfun2_t = void (*)()]"), "namespc::my_class<T>::member3", "member3" },
424     { logging::str_literal("void (namespc::my_class2::* namespc::foo6(pfun2_t))()"), "namespc::foo6", "foo6" },
425     { logging::str_literal("namespc::my_class<void(int)> namespc::foo7()"), "namespc::foo7", "foo7" },
426     { logging::str_literal("void (namespc::my_class2::* const (& namespc::foo8(pfun2_t))[2])()"), "namespc::foo8", "foo8" },
427     { logging::str_literal("namespc::my_class2::my_class2()"), "namespc::my_class2::my_class2", "my_class2" }, // constructor
428     { logging::str_literal("namespc::my_class2::~my_class2()"), "namespc::my_class2::~my_class2", "~my_class2" }, // destructor
429     { logging::str_literal("void namespc::my_class2::operator=(const namespc::my_class2&)"), "namespc::my_class2::operator=", "operator=" },
430     { logging::str_literal("void namespc::my_class2::operator*() const"), "namespc::my_class2::operator*", "operator*" },
431     { logging::str_literal("void namespc::my_class2::operator()()"), "namespc::my_class2::operator()", "operator()" },
432     { logging::str_literal("bool namespc::my_class2::operator<(int) const"), "namespc::my_class2::operator<", "operator<" },
433     { logging::str_literal("bool namespc::my_class2::operator>(int) const"), "namespc::my_class2::operator>", "operator>" },
434     { logging::str_literal("bool namespc::my_class2::operator<=(int) const"), "namespc::my_class2::operator<=", "operator<=" },
435     { logging::str_literal("bool namespc::my_class2::operator>=(int) const"), "namespc::my_class2::operator>=", "operator>=" },
436     { logging::str_literal("namespc::my_class2::operator bool() const"), "namespc::my_class2::operator bool", "operator bool" },
437     { logging::str_literal("namespc::my_class2::operator pfun1_t() const"), "namespc::my_class2::operator pfun1_t", "operator pfun1_t" },
438     { logging::str_literal("std::basic_ostream<_CharT, _Traits>& namespc::operator<<(std::basic_ostream<_CharT, _Traits>&, const namespc::my_class2&) [with CharT = char; TraitsT = std::char_traits<char>]"), "namespc::operator<<", "operator<<" },
439     { logging::str_literal("std::basic_istream<_CharT, _Traits>& namespc::operator>>(std::basic_istream<_CharT, _Traits>&, namespc::my_class2&) [with CharT = char; TraitsT = std::char_traits<char>]"), "namespc::operator>>", "operator>>" },
440 
441     // BOOST_CURRENT_FUNCTION fallback value
442     { logging::str_literal("(unknown)"), "(unknown)", "(unknown)" }
443 };
444 
445 } // namespace
446 
447 // Function name formatting
BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_scope_function_name_formatting,CharT,char_types)448 BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_scope_function_name_formatting, CharT, char_types)
449 {
450     typedef attrs::named_scope named_scope;
451     typedef named_scope::sentry sentry;
452 
453     typedef logging::attribute_set attr_set;
454     typedef std::basic_string< CharT > string;
455     typedef logging::basic_formatting_ostream< CharT > osstream;
456     typedef logging::record_view record_view;
457     typedef named_scope_test_data< CharT > data;
458 
459     named_scope attr;
460 
461     // First scope
462     const unsigned int line1 = __LINE__;
463 
464     attr_set set1;
465     set1[data::attr1()] = attr;
466 
467     record_view rec = make_record_view(set1);
468 
469     for (unsigned int i = 0; i < sizeof(named_scope_test_cases) / sizeof(*named_scope_test_cases); ++i)
470     {
471         sentry scope1(named_scope_test_cases[i].scope_name, data::file(), line1, attrs::named_scope_entry::function);
472         string str;
473         osstream strm(str);
474         strm << named_scope_test_cases[i].function_name;
475         BOOST_CHECK_MESSAGE(check_formatting(data::scope_function_name_format(), rec, strm.str()), "Scope name: " << named_scope_test_cases[i].scope_name);
476     }
477 }
478 
479 // Function name without scope formatting
BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_function_name_formatting,CharT,char_types)480 BOOST_AUTO_TEST_CASE_TEMPLATE(scopes_function_name_formatting, CharT, char_types)
481 {
482     typedef attrs::named_scope named_scope;
483     typedef named_scope::sentry sentry;
484 
485     typedef logging::attribute_set attr_set;
486     typedef std::basic_string< CharT > string;
487     typedef logging::basic_formatting_ostream< CharT > osstream;
488     typedef logging::record_view record_view;
489     typedef named_scope_test_data< CharT > data;
490 
491     named_scope attr;
492 
493     // First scope
494     const unsigned int line1 = __LINE__;
495 
496     attr_set set1;
497     set1[data::attr1()] = attr;
498 
499     record_view rec = make_record_view(set1);
500 
501     for (unsigned int i = 0; i < sizeof(named_scope_test_cases) / sizeof(*named_scope_test_cases); ++i)
502     {
503         sentry scope1(named_scope_test_cases[i].scope_name, data::file(), line1, attrs::named_scope_entry::function);
504         string str;
505         osstream strm(str);
506         strm << named_scope_test_cases[i].function_name_no_scope;
507         BOOST_CHECK_MESSAGE(check_formatting(data::function_name_format(), rec, strm.str()), "Scope name: " << named_scope_test_cases[i].scope_name);
508     }
509 }
510 
511 // The test checks that function name formatters do not affect scopes denoted with BOOST_LOG_NAMED_SCOPE
BOOST_AUTO_TEST_CASE_TEMPLATE(function_name_does_not_affect_non_function_scopes,CharT,char_types)512 BOOST_AUTO_TEST_CASE_TEMPLATE(function_name_does_not_affect_non_function_scopes, CharT, char_types)
513 {
514     typedef attrs::named_scope named_scope;
515 
516     typedef logging::attribute_set attr_set;
517     typedef std::basic_string< CharT > string;
518     typedef logging::basic_formatting_ostream< CharT > osstream;
519     typedef logging::record_view record_view;
520     typedef named_scope_test_data< CharT > data;
521 
522     named_scope attr;
523 
524     attr_set set1;
525     set1[data::attr1()] = attr;
526 
527     record_view rec = make_record_view(set1);
528 
529     {
530         BOOST_LOG_NAMED_SCOPE("void foo()");
531         string str;
532         osstream strm(str);
533         strm << "void foo()";
534         BOOST_CHECK(check_formatting(data::scope_function_name_format(), rec, strm.str()));
535         BOOST_CHECK(check_formatting(data::function_name_format(), rec, strm.str()));
536     }
537 }
538