Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85448 - in trunk/libs/log: src test test/run
From: andrey.semashev_at_[hidden]
Date: 2013-08-24 13:13:18


Author: andysem
Date: 2013-08-24 13:13:18 EDT (Sat, 24 Aug 2013)
New Revision: 85448
URL: http://svn.boost.org/trac/boost/changeset/85448

Log:
Fixed construction of filters with numeric operands. The constructed filters will now also work with string attribute values. Otherwise it was not possible to create filters on string attribute values that use numeric operands. Added a test for filter parser.

Added:
   trunk/libs/log/test/run/setup_filter_parser.cpp (contents, props changed)
Text files modified:
   trunk/libs/log/src/default_filter_factory.cpp | 230 +++++++++++----
   trunk/libs/log/test/Jamfile.v2 | 1
   trunk/libs/log/test/run/setup_filter_parser.cpp | 574 ++++++++++++++++++++++++++++++++++++++++
   3 files changed, 737 insertions(+), 68 deletions(-)

Modified: trunk/libs/log/src/default_filter_factory.cpp
==============================================================================
--- trunk/libs/log/src/default_filter_factory.cpp Sat Aug 24 10:38:14 2013 (r85447)
+++ trunk/libs/log/src/default_filter_factory.cpp 2013-08-24 13:13:18 EDT (Sat, 24 Aug 2013) (r85448)
@@ -18,6 +18,10 @@
 #include <string>
 #include <boost/move/core.hpp>
 #include <boost/move/utility.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/back_inserter.hpp>
 #include <boost/spirit/include/qi_core.hpp>
 #include <boost/spirit/include/qi_eoi.hpp>
 #include <boost/spirit/include/qi_as.hpp>
@@ -29,7 +33,6 @@
 #include <boost/log/utility/functional/begins_with.hpp>
 #include <boost/log/utility/functional/ends_with.hpp>
 #include <boost/log/utility/functional/contains.hpp>
-#include <boost/log/utility/functional/bind.hpp>
 #include <boost/log/utility/functional/as_action.hpp>
 #include <boost/log/detail/code_conversion.hpp>
 #if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
@@ -52,117 +55,208 @@
 
 BOOST_LOG_ANONYMOUS_NAMESPACE {
 
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+
+//! A special filtering predicate that adopts the string operand to the attribute value character type
 template< typename RelationT >
-struct on_integral_argument
+class string_predicate :
+ public RelationT
 {
- typedef void result_type;
+private:
+ template< typename StringT >
+ struct initializer
+ {
+ typedef void result_type;
+
+ explicit initializer(StringT const& val) : m_initializer(val)
+ {
+ }
+
+ template< typename T >
+ result_type operator() (T& val) const
+ {
+ try
+ {
+ log::aux::code_convert(m_initializer, val);
+ }
+ catch (...)
+ {
+ val.clear();
+ }
+ }
 
- on_integral_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
+ private:
+ StringT const& m_initializer;
+ };
+
+public:
+ typedef RelationT relation_type;
+ typedef typename relation_type::result_type result_type;
+
+ template< typename StringT >
+ string_predicate(relation_type const& rel, StringT const& operand) : relation_type(rel)
     {
+ fusion::for_each(m_operands, initializer< StringT >(operand));
     }
 
- result_type operator() (long val) const
+ template< typename T >
+ typename boost::enable_if<
+ mpl::contains< log::string_types::type, T >,
+ result_type
+ >::type operator() (T const& val) const
     {
- typedef binder2nd< RelationT, long > predicate;
- m_filter = predicate_wrapper< log::numeric_types::type, predicate >(m_name, predicate(RelationT(), val));
+ typedef std::basic_string< typename T::value_type > operand_type;
+ return relation_type::operator() (val, fusion::at_key< operand_type >(m_operands));
     }
 
 private:
- attribute_name m_name;
- filter& m_filter;
+ fusion::set< std::string, std::wstring > m_operands;
 };
 
+#else // defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+
+//! A special filtering predicate that adopts the string operand to the attribute value character type
 template< typename RelationT >
-struct on_fp_argument
+class string_predicate :
+ public RelationT
 {
- typedef void result_type;
+private:
+#if defined(BOOST_LOG_USE_CHAR)
+ typedef std::basic_string< char > string_type;
+#elif defined(BOOST_LOG_USE_WCHAR_T)
+ typedef std::basic_string< wchar_t > string_type;
+#else
+#error Boost.Log: Inconsistent character configuration
+#endif
+
+public:
+ typedef RelationT relation_type;
+ typedef typename relation_type::result_type result_type;
 
- on_fp_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
+public:
+ string_predicate(relation_type const& rel, string_type const& operand) : relation_type(rel), m_operand(operand)
     {
     }
 
- result_type operator() (double val) const
+ template< typename T >
+ typename boost::enable_if<
+ mpl::contains< log::string_types::type, T >,
+ result_type
+ >::type operator() (T const& val) const
     {
- typedef binder2nd< RelationT, double > predicate;
- m_filter = predicate_wrapper< log::floating_point_types::type, predicate >(m_name, predicate(RelationT(), val));
+ return relation_type::operator() (val, m_operand);
     }
 
 private:
- attribute_name m_name;
- filter& m_filter;
+ const string_type m_operand;
 };
 
+#endif // defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+
+//! A filtering predicate for numeric relations
+template< typename NumericT, typename RelationT >
+class numeric_predicate :
+ public string_predicate< RelationT >
+{
+ typedef string_predicate< RelationT > base_type;
+
+public:
+ typedef NumericT numeric_type;
+ typedef typename base_type::relation_type relation_type;
+ typedef typename base_type::result_type result_type;
+
+public:
+ template< typename StringT >
+ numeric_predicate(relation_type const& rel, StringT const& string_operand, numeric_type numeric_operand) :
+ base_type(rel, string_operand),
+ m_numeric_operand(numeric_operand)
+ {
+ }
+
+ using base_type::operator();
+
+ template< typename T >
+ typename boost::disable_if<
+ mpl::contains< log::string_types::type, T >,
+ result_type
+ >::type operator() (T const& val) const
+ {
+ return relation_type::operator() (val, m_numeric_operand);
+ }
+
+private:
+ const numeric_type m_numeric_operand;
+};
+
+
 template< typename RelationT >
 struct on_string_argument
 {
     typedef void result_type;
 
-#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
- //! A special filtering predicate that adopts the string operand to the attribute value character type
- struct predicate :
- public RelationT
+ on_string_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
     {
- template< typename StringT >
- struct initializer
- {
- typedef void result_type;
+ }
 
- explicit initializer(StringT const& val) : m_initializer(val)
- {
- }
+ template< typename StringT >
+ result_type operator() (StringT const& val) const
+ {
+ typedef string_predicate< RelationT > predicate;
+ m_filter = predicate_wrapper< log::string_types, predicate >(m_name, predicate(RelationT(), val));
+ }
 
- template< typename T >
- result_type operator() (T& val) const
- {
- try
- {
- log::aux::code_convert(m_initializer, val);
- }
- catch (...)
- {
- val.clear();
- }
- }
+private:
+ attribute_name m_name;
+ filter& m_filter;
+};
 
- private:
- StringT const& m_initializer;
- };
+template< typename RelationT, typename StringT >
+struct on_integral_argument
+{
+ typedef void result_type;
 
- typedef typename RelationT::result_type result_type;
+ on_integral_argument(attribute_name const& name, StringT const& operand, filter& f) : m_name(name), m_operand(operand), m_filter(f)
+ {
+ }
 
- template< typename StringT >
- predicate(RelationT const& rel, StringT const& operand) : RelationT(rel)
- {
- fusion::for_each(m_operands, initializer< StringT >(operand));
- }
+ result_type operator() (long val) const
+ {
+ typedef numeric_predicate< long, RelationT > predicate;
+ typedef mpl::copy<
+ log::string_types,
+ mpl::back_inserter< log::numeric_types >
+ >::type value_types;
+ m_filter = predicate_wrapper< value_types, predicate >(m_name, predicate(RelationT(), m_operand, val));
+ }
 
- template< typename T >
- result_type operator() (T const& val) const
- {
- typedef std::basic_string< typename T::value_type > operand_type;
- return RelationT::operator() (val, fusion::at_key< operand_type >(m_operands));
- }
+private:
+ attribute_name m_name;
+ StringT const& m_operand;
+ filter& m_filter;
+};
 
- private:
- fusion::set< std::string, std::wstring > m_operands;
- };
-#endif
+template< typename RelationT, typename StringT >
+struct on_fp_argument
+{
+ typedef void result_type;
 
- on_string_argument(attribute_name const& name, filter& f) : m_name(name), m_filter(f)
+ on_fp_argument(attribute_name const& name, StringT const& operand, filter& f) : m_name(name), m_operand(operand), m_filter(f)
     {
     }
 
- template< typename StringT >
- result_type operator() (StringT const& val) const
+ result_type operator() (double val) const
     {
-#if !defined(BOOST_LOG_USE_CHAR) || !defined(BOOST_LOG_USE_WCHAR_T)
- typedef binder2nd< RelationT, StringT > predicate;
-#endif
- m_filter = predicate_wrapper< log::string_types::type, predicate >(m_name, predicate(RelationT(), val));
+ typedef numeric_predicate< double, RelationT > predicate;
+ typedef mpl::copy<
+ log::string_types,
+ mpl::back_inserter< log::floating_point_types >
+ >::type value_types;
+ m_filter = predicate_wrapper< value_types, predicate >(m_name, predicate(RelationT(), m_operand, val));
     }
 
 private:
     attribute_name m_name;
+ StringT const& m_operand;
     filter& m_filter;
 };
 
@@ -243,8 +337,8 @@
     const qi::real_parser< double, qi::strict_real_policies< double > > real_;
 
     filter f;
- const on_fp_argument< RelationT > on_fp(name, f);
- const on_integral_argument< RelationT > on_int(name, f);
+ const on_fp_argument< RelationT, string_type > on_fp(name, arg, f);
+ const on_integral_argument< RelationT, string_type > on_int(name, arg, f);
     const on_string_argument< RelationT > on_str(name, f);
 
     const bool res = qi::parse

Modified: trunk/libs/log/test/Jamfile.v2
==============================================================================
--- trunk/libs/log/test/Jamfile.v2 Sat Aug 24 10:38:14 2013 (r85447)
+++ trunk/libs/log/test/Jamfile.v2 2013-08-24 13:13:18 EDT (Sat, 24 Aug 2013) (r85448)
@@ -21,6 +21,7 @@
         <toolset>intel-win:<define>_CRT_SECURE_NO_DEPRECATE
         <toolset>gcc:<cxxflags>-fno-strict-aliasing # avoids strict aliasing violations in other Boost components
         <library>/boost/log//boost_log
+ <library>/boost/log//boost_log_setup
         <library>/boost/date_time//boost_date_time
         <library>/boost/regex//boost_regex
         <library>/boost/filesystem//boost_filesystem

Added: trunk/libs/log/test/run/setup_filter_parser.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/log/test/run/setup_filter_parser.cpp 2013-08-24 13:13:18 EDT (Sat, 24 Aug 2013) (r85448)
@@ -0,0 +1,574 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file setup_filter_parser.cpp
+ * \author Andrey Semashev
+ * \date 24.08.2013
+ *
+ * \brief This header contains tests for the filter parser.
+ */
+
+#define BOOST_TEST_MODULE setup_filter_parser
+
+#include <string>
+#include <boost/test/unit_test.hpp>
+#include <boost/log/utility/setup/filter_parser.hpp>
+
+#if !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)
+
+#include <boost/log/attributes/constant.hpp>
+#include <boost/log/attributes/attribute_set.hpp>
+#include <boost/log/attributes/attribute_value_set.hpp>
+#include <boost/log/expressions/filter.hpp>
+
+namespace logging = boost::log;
+namespace attrs = logging::attributes;
+
+typedef logging::attribute_set attr_set;
+typedef logging::attribute_value_set attr_values;
+
+// Tests for attribute presence check
+BOOST_AUTO_TEST_CASE(attr_presence)
+{
+ attrs::constant< int > attr1(10);
+ attr_set set1, set2, set3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ set1["MyAttr"] = attr1;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyAttr%");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter(" % MyAttr % ");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ }
+}
+
+// Tests for integer relation filter
+BOOST_AUTO_TEST_CASE(int_relation)
+{
+ attrs::constant< int > attr1(10);
+ attrs::constant< long > attr2(20);
+ attrs::constant< int > attr3(-2);
+ attr_set set1, set2, set3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ set1["MyAttr"] = attr1;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ set1["MyAttr"] = attr2;
+ attr_values values3(set1, set2, set3);
+ values3.freeze();
+
+ set1["MyAttr"] = attr3;
+ attr_values values4(set1, set2, set3);
+ values4.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% = 10");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(!f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% != 10");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% < 20");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% < -7");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(!f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% > 10");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(!f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% > -5");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% <= 20");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% >= 20");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(!f(values4));
+ }
+}
+
+// Tests for floating point relation filter
+BOOST_AUTO_TEST_CASE(fp_relation)
+{
+ attrs::constant< float > attr1(2.5);
+ attrs::constant< float > attr2(8.8);
+ attrs::constant< double > attr3(-9.1);
+ attrs::constant< float > attr4(0);
+ attr_set set1, set2, set3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ set1["MyAttr"] = attr1;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ set1["MyAttr"] = attr2;
+ attr_values values3(set1, set2, set3);
+ values3.freeze();
+
+ set1["MyAttr"] = attr3;
+ attr_values values4(set1, set2, set3);
+ values4.freeze();
+
+ set1["MyAttr"] = attr4;
+ attr_values values5(set1, set2, set3);
+ values5.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% = 10.3");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(!f(values4));
+ BOOST_CHECK(!f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% != 10");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(f(values4));
+ BOOST_CHECK(f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% < 5.5");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(f(values4));
+ BOOST_CHECK(f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% < -7");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(f(values4));
+ BOOST_CHECK(!f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% > 5.6");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(!f(values4));
+ BOOST_CHECK(!f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% > -5");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(!f(values4));
+ BOOST_CHECK(f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% <= 20");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(f(values4));
+ BOOST_CHECK(f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% >= 20");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(!f(values4));
+ BOOST_CHECK(!f(values5));
+ }
+}
+
+// Tests for string relation filter
+BOOST_AUTO_TEST_CASE(string_relation)
+{
+ attrs::constant< std::string > attr1("hello");
+ attr_set set1, set2, set3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ set1["MyStr"] = attr1;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyStr% = hello");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% = \"hello\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter(" % MyStr % = \"hello\" ");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% = \" hello\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% = \"hello \"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% = \"world\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% = \"Hello\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% != hello");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% != world");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% < world");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% > world");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+
+ // Check that strings that look like numbers can still be used in filters
+ attrs::constant< std::string > attr2("55");
+ set1["MyStr"] = attr2;
+ attr_values values3(set1, set2, set3);
+ values3.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyStr% = \"55\"");
+ BOOST_CHECK(f(values3));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% < \"555\"");
+ BOOST_CHECK(f(values3));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% > \"44\"");
+ BOOST_CHECK(f(values3));
+ }
+}
+
+// Tests for multiple expression filter
+BOOST_AUTO_TEST_CASE(multi_expression)
+{
+ attrs::constant< int > attr1(10);
+ attrs::constant< int > attr2(20);
+ attrs::constant< std::string > attr3("hello");
+ attrs::constant< std::string > attr4("world");
+ attr_set set1, set2, set3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ set1["MyAttr"] = attr1;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ set1["MyAttr"] = attr2;
+ attr_values values3(set1, set2, set3);
+ values3.freeze();
+
+ set1["MyStr"] = attr3;
+ attr_values values4(set1, set2, set3);
+ values4.freeze();
+
+ set1["MyStr"] = attr4;
+ attr_values values5(set1, set2, set3);
+ values5.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% = 10 & %MyStr% = \"hello\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(!f(values4));
+ BOOST_CHECK(!f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% > 10 & %MyStr% = \"hello\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(f(values4));
+ BOOST_CHECK(!f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% > 10 and %MyStr% = \"hello\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(f(values4));
+ BOOST_CHECK(!f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% = 10 | %MyStr% = \"world\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(!f(values4));
+ BOOST_CHECK(f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% > 10 | %MyStr% = \"world\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(f(values4));
+ BOOST_CHECK(f(values5));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyAttr% = 10 or %MyStr% = \"world\"");
+ BOOST_CHECK(!f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(!f(values3));
+ BOOST_CHECK(!f(values4));
+ BOOST_CHECK(f(values5));
+ }
+}
+
+// Tests for negation
+BOOST_AUTO_TEST_CASE(negation)
+{
+ attrs::constant< int > attr1(10);
+ attrs::constant< int > attr2(20);
+ attrs::constant< std::string > attr3("hello");
+ attr_set set1, set2, set3;
+
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ set1["MyAttr"] = attr1;
+ attr_values values2(set1, set2, set3);
+ values2.freeze();
+
+ set1["MyAttr"] = attr2;
+ attr_values values3(set1, set2, set3);
+ values3.freeze();
+
+ set1["MyStr"] = attr3;
+ attr_values values4(set1, set2, set3);
+ values4.freeze();
+
+ // Test with presence filter
+ {
+ logging::filter f = logging::parse_filter("!%MyAttr%");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter(" ! % MyAttr % ");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+ {
+ logging::filter f = logging::parse_filter("not %MyAttr%");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(!f(values2));
+ }
+
+ // Test with relations
+ {
+ logging::filter f = logging::parse_filter("!(%MyAttr% = 10)");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ }
+ {
+ logging::filter f = logging::parse_filter("not ( %MyAttr% = 10 ) ");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ }
+ {
+ logging::filter f = logging::parse_filter("!(%MyAttr% < 20)");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ }
+
+ // Test with multiple subexpressions
+ {
+ logging::filter f = logging::parse_filter("!(%MyAttr% = 20 & %MyStr% = hello)");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(!f(values4));
+ }
+ {
+ logging::filter f = logging::parse_filter("!(%MyAttr% = 10 | %MyStr% = hello)");
+ BOOST_CHECK(f(values1));
+ BOOST_CHECK(!f(values2));
+ BOOST_CHECK(f(values3));
+ BOOST_CHECK(!f(values4));
+ }
+}
+
+// Tests for begins_with relation filter
+BOOST_AUTO_TEST_CASE(begins_with_relation)
+{
+ attrs::constant< std::string > attr1("abcdABCD");
+ attr_set set1, set2, set3;
+
+ set1["MyStr"] = attr1;
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyStr% begins_with \"abcd\"");
+ BOOST_CHECK(f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% begins_with \"ABCD\"");
+ BOOST_CHECK(!f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% begins_with \"efgh\"");
+ BOOST_CHECK(!f(values1));
+ }
+}
+
+// Tests for ends_with relation filter
+BOOST_AUTO_TEST_CASE(ends_with_relation)
+{
+ attrs::constant< std::string > attr1("abcdABCD");
+ attr_set set1, set2, set3;
+
+ set1["MyStr"] = attr1;
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyStr% ends_with \"abcd\"");
+ BOOST_CHECK(!f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% ends_with \"ABCD\"");
+ BOOST_CHECK(f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% ends_with \"efgh\"");
+ BOOST_CHECK(!f(values1));
+ }
+}
+
+// Tests for contains relation filter
+BOOST_AUTO_TEST_CASE(contains_relation)
+{
+ attrs::constant< std::string > attr1("abcdABCD");
+ attr_set set1, set2, set3;
+
+ set1["MyStr"] = attr1;
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyStr% contains \"abcd\"");
+ BOOST_CHECK(f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% contains \"ABCD\"");
+ BOOST_CHECK(f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% contains \"cdAB\"");
+ BOOST_CHECK(f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% contains \"efgh\"");
+ BOOST_CHECK(!f(values1));
+ }
+}
+
+// Tests for regex matching relation filter
+BOOST_AUTO_TEST_CASE(matches_relation)
+{
+ attrs::constant< std::string > attr1("hello");
+ attr_set set1, set2, set3;
+
+ set1["MyStr"] = attr1;
+ attr_values values1(set1, set2, set3);
+ values1.freeze();
+
+ {
+ logging::filter f = logging::parse_filter("%MyStr% matches \"h.*\"");
+ BOOST_CHECK(f(values1));
+ }
+ {
+ logging::filter f = logging::parse_filter("%MyStr% matches \"w.*\"");
+ BOOST_CHECK(!f(values1));
+ }
+}
+
+#endif // !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk