filt_attr.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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 filt_attr.cpp
  9. * \author Andrey Semashev
  10. * \date 31.01.2009
  11. *
  12. * \brief This header contains tests for the \c attr filter.
  13. */
  14. #define BOOST_TEST_MODULE filt_attr
  15. #include <memory>
  16. #include <string>
  17. #include <algorithm>
  18. #include <boost/regex.hpp>
  19. #include <boost/mpl/vector.hpp>
  20. #include <boost/phoenix/bind.hpp>
  21. #include <boost/test/unit_test.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/utility/type_dispatch/standard_types.hpp>
  26. #include <boost/log/support/regex.hpp>
  27. #include <boost/log/expressions.hpp>
  28. #include "char_definitions.hpp"
  29. namespace phoenix = boost::phoenix;
  30. namespace logging = boost::log;
  31. namespace attrs = logging::attributes;
  32. namespace expr = logging::expressions;
  33. // The test checks that general conditions work
  34. BOOST_AUTO_TEST_CASE(general_conditions)
  35. {
  36. typedef logging::attribute_set attr_set;
  37. typedef logging::attribute_value_set attr_values;
  38. typedef logging::filter filter;
  39. typedef test_data< char > data;
  40. attrs::constant< int > attr1(10);
  41. attrs::constant< double > attr2(5.5);
  42. attrs::constant< std::string > attr3("Hello, world!");
  43. attr_set set1, set2, set3;
  44. set1[data::attr1()] = attr1;
  45. set1[data::attr2()] = attr2;
  46. set1[data::attr3()] = attr3;
  47. attr_values values1(set1, set2, set3);
  48. values1.freeze();
  49. filter f = expr::attr< int >(data::attr1()) == 10;
  50. BOOST_CHECK(f(values1));
  51. f = expr::attr< int >(data::attr1()) < 0;
  52. BOOST_CHECK(!f(values1));
  53. f = expr::attr< float >(data::attr1()).or_throw() > 0;
  54. BOOST_CHECK_THROW(f(values1), logging::runtime_error);
  55. f = expr::attr< float >(data::attr1()) > 0;
  56. BOOST_CHECK(!f(values1));
  57. f = expr::attr< int >(data::attr4()).or_throw() >= 1;
  58. BOOST_CHECK_THROW(f(values1), logging::runtime_error);
  59. f = expr::attr< int >(data::attr4()) >= 1;
  60. BOOST_CHECK(!f(values1));
  61. f = expr::attr< int >(data::attr4()) < 1;
  62. BOOST_CHECK(!f(values1));
  63. f = expr::attr< logging::numeric_types >(data::attr2()) > 5;
  64. BOOST_CHECK(f(values1));
  65. f = expr::attr< std::string >(data::attr3()) == "Hello, world!";
  66. BOOST_CHECK(f(values1));
  67. f = expr::attr< std::string >(data::attr3()) > "AAA";
  68. BOOST_CHECK(f(values1));
  69. }
  70. // The test checks that is_in_range condition works
  71. BOOST_AUTO_TEST_CASE(in_range_check)
  72. {
  73. typedef logging::attribute_set attr_set;
  74. typedef logging::attribute_value_set attr_values;
  75. typedef logging::filter filter;
  76. typedef test_data< char > data;
  77. attrs::constant< int > attr1(10);
  78. attrs::constant< double > attr2(5.5);
  79. attrs::constant< std::string > attr3("Hello, world!");
  80. attr_set set1, set2, set3;
  81. set1[data::attr1()] = attr1;
  82. set1[data::attr2()] = attr2;
  83. set1[data::attr3()] = attr3;
  84. attr_values values1(set1, set2, set3);
  85. values1.freeze();
  86. filter f = expr::is_in_range(expr::attr< int >(data::attr1()), 5, 20);
  87. BOOST_CHECK(f(values1));
  88. f = expr::is_in_range(expr::attr< int >(data::attr1()), 5, 10);
  89. BOOST_CHECK(!f(values1));
  90. f = expr::is_in_range(expr::attr< int >(data::attr1()), 10, 20);
  91. BOOST_CHECK(f(values1));
  92. f = expr::is_in_range(expr::attr< logging::numeric_types >(data::attr2()), 5, 6);
  93. BOOST_CHECK(f(values1));
  94. f = expr::is_in_range(expr::attr< std::string >(data::attr3()), "AAA", "zzz");
  95. BOOST_CHECK(f(values1));
  96. // Check that strings are saved into the filter by value
  97. char buf1[128];
  98. char buf2[128];
  99. std::strcpy(buf1, "AAA");
  100. std::strcpy(buf2, "zzz");
  101. f = expr::is_in_range(expr::attr< std::string >(data::attr3()), buf1, buf2);
  102. std::fill_n(buf1, sizeof(buf1), static_cast< char >(0));
  103. std::fill_n(buf2, sizeof(buf2), static_cast< char >(0));
  104. BOOST_CHECK(f(values1));
  105. std::strcpy(buf1, "AAA");
  106. std::strcpy(buf2, "zzz");
  107. f = expr::is_in_range(expr::attr< std::string >(data::attr3()),
  108. static_cast< const char* >(buf1), static_cast< const char* >(buf2));
  109. std::fill_n(buf1, sizeof(buf1), static_cast< char >(0));
  110. std::fill_n(buf2, sizeof(buf2), static_cast< char >(0));
  111. BOOST_CHECK(f(values1));
  112. }
  113. namespace {
  114. struct predicate
  115. {
  116. typedef bool result_type;
  117. explicit predicate(unsigned int& present_counter, bool& result) :
  118. m_PresentCounter(present_counter),
  119. m_Result(result)
  120. {
  121. }
  122. template< typename T, typename TagT >
  123. result_type operator() (logging::value_ref< T, TagT > const& val) const
  124. {
  125. m_PresentCounter += !val.empty();
  126. return m_Result;
  127. }
  128. private:
  129. unsigned int& m_PresentCounter;
  130. bool& m_Result;
  131. };
  132. } // namespace
  133. // The test checks that phoenix::bind interaction works
  134. BOOST_AUTO_TEST_CASE(bind_support_check)
  135. {
  136. typedef logging::attribute_set attr_set;
  137. typedef logging::attribute_value_set attr_values;
  138. typedef logging::filter filter;
  139. typedef test_data< char > data;
  140. attrs::constant< int > attr1(10);
  141. attrs::constant< double > attr2(5.5);
  142. attrs::constant< std::string > attr3("Hello, world!");
  143. attr_set set1, set2, set3;
  144. set1[data::attr1()] = attr1;
  145. set1[data::attr2()] = attr2;
  146. set1[data::attr3()] = attr3;
  147. attr_values values1(set1, set2, set3);
  148. values1.freeze();
  149. unsigned int present_counter = 0;
  150. bool predicate_result = false;
  151. filter f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr1()));
  152. BOOST_CHECK_EQUAL(f(values1), predicate_result);
  153. BOOST_CHECK_EQUAL(present_counter, 1U);
  154. predicate_result = true;
  155. BOOST_CHECK_EQUAL(f(values1), predicate_result);
  156. BOOST_CHECK_EQUAL(present_counter, 2U);
  157. f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< logging::numeric_types >(data::attr2()));
  158. BOOST_CHECK_EQUAL(f(values1), predicate_result);
  159. BOOST_CHECK_EQUAL(present_counter, 3U);
  160. f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr2()).or_throw());
  161. BOOST_CHECK_THROW(f(values1), logging::runtime_error);
  162. f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr2()));
  163. BOOST_CHECK_EQUAL(f(values1), true);
  164. BOOST_CHECK_EQUAL(present_counter, 3U);
  165. f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr4()).or_throw());
  166. BOOST_CHECK_THROW(f(values1), logging::runtime_error);
  167. f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr4()));
  168. BOOST_CHECK_EQUAL(f(values1), true);
  169. BOOST_CHECK_EQUAL(present_counter, 3U);
  170. }
  171. // The test checks that begins_with condition works
  172. BOOST_AUTO_TEST_CASE(begins_with_check)
  173. {
  174. typedef logging::attribute_set attr_set;
  175. typedef logging::attribute_value_set attr_values;
  176. typedef logging::filter filter;
  177. typedef test_data< char > data;
  178. attrs::constant< int > attr1(10);
  179. attrs::constant< double > attr2(5.5);
  180. attrs::constant< std::string > attr3("Hello, world!");
  181. attr_set set1, set2, set3;
  182. set1[data::attr1()] = attr1;
  183. set1[data::attr2()] = attr2;
  184. set1[data::attr3()] = attr3;
  185. attr_values values1(set1, set2, set3);
  186. values1.freeze();
  187. filter f = expr::begins_with(expr::attr< std::string >(data::attr3()), "Hello");
  188. BOOST_CHECK(f(values1));
  189. f = expr::begins_with(expr::attr< std::string >(data::attr3()), "hello");
  190. BOOST_CHECK(!f(values1));
  191. f = expr::begins_with(expr::attr< std::string >(data::attr3()).or_throw(), "Bye");
  192. BOOST_CHECK(!f(values1));
  193. f = expr::begins_with(expr::attr< std::string >(data::attr3()).or_throw(), "world!");
  194. BOOST_CHECK(!f(values1));
  195. f = expr::begins_with(expr::attr< std::string >(data::attr2()), "Hello");
  196. BOOST_CHECK(!f(values1));
  197. f = expr::begins_with(expr::attr< std::string >(data::attr4()), "Hello");
  198. BOOST_CHECK(!f(values1));
  199. }
  200. // The test checks that ends_with condition works
  201. BOOST_AUTO_TEST_CASE(ends_with_check)
  202. {
  203. typedef logging::attribute_set attr_set;
  204. typedef logging::attribute_value_set attr_values;
  205. typedef logging::filter filter;
  206. typedef test_data< char > data;
  207. attrs::constant< int > attr1(10);
  208. attrs::constant< double > attr2(5.5);
  209. attrs::constant< std::string > attr3("Hello, world!");
  210. attr_set set1, set2, set3;
  211. set1[data::attr1()] = attr1;
  212. set1[data::attr2()] = attr2;
  213. set1[data::attr3()] = attr3;
  214. attr_values values1(set1, set2, set3);
  215. values1.freeze();
  216. filter f = expr::ends_with(expr::attr< std::string >(data::attr3()), "world!");
  217. BOOST_CHECK(f(values1));
  218. f = expr::ends_with(expr::attr< std::string >(data::attr3()), "World!");
  219. BOOST_CHECK(!f(values1));
  220. f = expr::ends_with(expr::attr< std::string >(data::attr3()).or_throw(), "Bye");
  221. BOOST_CHECK(!f(values1));
  222. f = expr::ends_with(expr::attr< std::string >(data::attr3()).or_throw(), "Hello");
  223. BOOST_CHECK(!f(values1));
  224. f = expr::ends_with(expr::attr< std::string >(data::attr2()), "world!");
  225. BOOST_CHECK(!f(values1));
  226. f = expr::ends_with(expr::attr< std::string >(data::attr4()), "world!");
  227. BOOST_CHECK(!f(values1));
  228. }
  229. // The test checks that contains condition works
  230. BOOST_AUTO_TEST_CASE(contains_check)
  231. {
  232. typedef logging::attribute_set attr_set;
  233. typedef logging::attribute_value_set attr_values;
  234. typedef logging::filter filter;
  235. typedef test_data< char > data;
  236. attrs::constant< int > attr1(10);
  237. attrs::constant< double > attr2(5.5);
  238. attrs::constant< std::string > attr3("Hello, world!");
  239. attr_set set1, set2, set3;
  240. set1[data::attr1()] = attr1;
  241. set1[data::attr2()] = attr2;
  242. set1[data::attr3()] = attr3;
  243. attr_values values1(set1, set2, set3);
  244. values1.freeze();
  245. filter f = expr::contains(expr::attr< std::string >(data::attr3()), "Hello");
  246. BOOST_CHECK(f(values1));
  247. f = expr::contains(expr::attr< std::string >(data::attr3()), "hello");
  248. BOOST_CHECK(!f(values1));
  249. f = expr::contains(expr::attr< std::string >(data::attr3()).or_throw(), "o, w");
  250. BOOST_CHECK(f(values1));
  251. f = expr::contains(expr::attr< std::string >(data::attr3()).or_throw(), "world!");
  252. BOOST_CHECK(f(values1));
  253. f = expr::contains(expr::attr< std::string >(data::attr2()), "Hello");
  254. BOOST_CHECK(!f(values1));
  255. f = expr::contains(expr::attr< std::string >(data::attr4()), "Hello");
  256. BOOST_CHECK(!f(values1));
  257. }
  258. // The test checks that matches condition works
  259. BOOST_AUTO_TEST_CASE(matches_check)
  260. {
  261. typedef logging::attribute_set attr_set;
  262. typedef logging::attribute_value_set attr_values;
  263. typedef logging::filter filter;
  264. typedef test_data< char > data;
  265. attrs::constant< int > attr1(10);
  266. attrs::constant< double > attr2(5.5);
  267. attrs::constant< std::string > attr3("Hello, world!");
  268. attr_set set1, set2, set3;
  269. set1[data::attr1()] = attr1;
  270. set1[data::attr2()] = attr2;
  271. set1[data::attr3()] = attr3;
  272. attr_values values1(set1, set2, set3);
  273. values1.freeze();
  274. boost::regex rex("hello");
  275. filter f = expr::matches(expr::attr< std::string >(data::attr3()), rex);
  276. BOOST_CHECK(!f(values1));
  277. rex = ".*world.*";
  278. f = expr::matches(expr::attr< std::string >(data::attr3()).or_throw(), rex);
  279. BOOST_CHECK(f(values1));
  280. rex = ".*";
  281. f = expr::matches(expr::attr< std::string >(data::attr2()), rex);
  282. BOOST_CHECK(!f(values1));
  283. f = expr::matches(expr::attr< std::string >(data::attr4()), rex);
  284. BOOST_CHECK(!f(values1));
  285. }
  286. // The test checks that the filter composition works
  287. BOOST_AUTO_TEST_CASE(composition_check)
  288. {
  289. typedef logging::attribute_set attr_set;
  290. typedef logging::attribute_value_set attr_values;
  291. typedef logging::filter filter;
  292. typedef test_data< char > data;
  293. attrs::constant< int > attr1(10);
  294. attrs::constant< double > attr2(5.5);
  295. attrs::constant< std::string > attr3("Hello, world!");
  296. attr_set set1, set2, set3;
  297. attr_values values1(set1, set2, set3);
  298. values1.freeze();
  299. set1[data::attr2()] = attr2;
  300. attr_values values2(set1, set2, set3);
  301. values2.freeze();
  302. set1[data::attr3()] = attr3;
  303. set1[data::attr1()] = attr1;
  304. attr_values values3(set1, set2, set3);
  305. values3.freeze();
  306. filter f =
  307. expr::attr< int >(data::attr1()) <= 10 ||
  308. expr::is_in_range(expr::attr< double >(data::attr2()), 2.2, 7.7);
  309. BOOST_CHECK(!f(values1));
  310. BOOST_CHECK(f(values2));
  311. BOOST_CHECK(f(values3));
  312. f = expr::attr< int >(data::attr1()) == 10 &&
  313. expr::begins_with(expr::attr< std::string >(data::attr3()), "Hello");
  314. BOOST_CHECK(!f(values1));
  315. BOOST_CHECK(!f(values2));
  316. BOOST_CHECK(f(values3));
  317. }