form_named_scope.cpp 27 KB

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