404 lines
13 KiB
C++
404 lines
13 KiB
C++
/*
|
|
* Copyright Andrey Semashev 2007 - 2015.
|
|
* 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 filt_attr.cpp
|
|
* \author Andrey Semashev
|
|
* \date 31.01.2009
|
|
*
|
|
* \brief This header contains tests for the \c attr filter.
|
|
*/
|
|
|
|
#define BOOST_TEST_MODULE filt_attr
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <boost/regex.hpp>
|
|
#include <boost/mpl/vector.hpp>
|
|
#include <boost/phoenix/bind.hpp>
|
|
#include <boost/test/unit_test.hpp>
|
|
#include <boost/log/attributes/constant.hpp>
|
|
#include <boost/log/attributes/attribute_set.hpp>
|
|
#include <boost/log/attributes/attribute_value_set.hpp>
|
|
#include <boost/log/utility/type_dispatch/standard_types.hpp>
|
|
#include <boost/log/support/regex.hpp>
|
|
#include <boost/log/expressions.hpp>
|
|
#include "char_definitions.hpp"
|
|
|
|
namespace phoenix = boost::phoenix;
|
|
|
|
namespace logging = boost::log;
|
|
namespace attrs = logging::attributes;
|
|
namespace expr = logging::expressions;
|
|
|
|
// The test checks that general conditions work
|
|
BOOST_AUTO_TEST_CASE(general_conditions)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
set1[data::attr1()] = attr1;
|
|
set1[data::attr2()] = attr2;
|
|
set1[data::attr3()] = attr3;
|
|
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
|
|
filter f = expr::attr< int >(data::attr1()) == 10;
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::attr< int >(data::attr1()) < 0;
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::attr< float >(data::attr1()).or_throw() > 0;
|
|
BOOST_CHECK_THROW(f(values1), logging::runtime_error);
|
|
f = expr::attr< float >(data::attr1()) > 0;
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::attr< int >(data::attr4()).or_throw() >= 1;
|
|
BOOST_CHECK_THROW(f(values1), logging::runtime_error);
|
|
f = expr::attr< int >(data::attr4()) >= 1;
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::attr< int >(data::attr4()) < 1;
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::attr< logging::numeric_types >(data::attr2()) > 5;
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::attr< std::string >(data::attr3()) == "Hello, world!";
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::attr< std::string >(data::attr3()) > "AAA";
|
|
BOOST_CHECK(f(values1));
|
|
}
|
|
|
|
// The test checks that is_in_range condition works
|
|
BOOST_AUTO_TEST_CASE(in_range_check)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
set1[data::attr1()] = attr1;
|
|
set1[data::attr2()] = attr2;
|
|
set1[data::attr3()] = attr3;
|
|
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
|
|
filter f = expr::is_in_range(expr::attr< int >(data::attr1()), 5, 20);
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::is_in_range(expr::attr< int >(data::attr1()), 5, 10);
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::is_in_range(expr::attr< int >(data::attr1()), 10, 20);
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::is_in_range(expr::attr< logging::numeric_types >(data::attr2()), 5, 6);
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::is_in_range(expr::attr< std::string >(data::attr3()), "AAA", "zzz");
|
|
BOOST_CHECK(f(values1));
|
|
|
|
// Check that strings are saved into the filter by value
|
|
char buf1[128];
|
|
char buf2[128];
|
|
std::strcpy(buf1, "AAA");
|
|
std::strcpy(buf2, "zzz");
|
|
f = expr::is_in_range(expr::attr< std::string >(data::attr3()), buf1, buf2);
|
|
std::fill_n(buf1, sizeof(buf1), static_cast< char >(0));
|
|
std::fill_n(buf2, sizeof(buf2), static_cast< char >(0));
|
|
BOOST_CHECK(f(values1));
|
|
|
|
std::strcpy(buf1, "AAA");
|
|
std::strcpy(buf2, "zzz");
|
|
f = expr::is_in_range(expr::attr< std::string >(data::attr3()),
|
|
static_cast< const char* >(buf1), static_cast< const char* >(buf2));
|
|
std::fill_n(buf1, sizeof(buf1), static_cast< char >(0));
|
|
std::fill_n(buf2, sizeof(buf2), static_cast< char >(0));
|
|
BOOST_CHECK(f(values1));
|
|
}
|
|
|
|
namespace {
|
|
|
|
struct predicate
|
|
{
|
|
typedef bool result_type;
|
|
|
|
explicit predicate(unsigned int& present_counter, bool& result) :
|
|
m_PresentCounter(present_counter),
|
|
m_Result(result)
|
|
{
|
|
}
|
|
|
|
template< typename T, typename TagT >
|
|
result_type operator() (logging::value_ref< T, TagT > const& val) const
|
|
{
|
|
m_PresentCounter += !val.empty();
|
|
return m_Result;
|
|
}
|
|
|
|
private:
|
|
unsigned int& m_PresentCounter;
|
|
bool& m_Result;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
// The test checks that phoenix::bind interaction works
|
|
BOOST_AUTO_TEST_CASE(bind_support_check)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
set1[data::attr1()] = attr1;
|
|
set1[data::attr2()] = attr2;
|
|
set1[data::attr3()] = attr3;
|
|
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
|
|
unsigned int present_counter = 0;
|
|
bool predicate_result = false;
|
|
|
|
filter f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr1()));
|
|
BOOST_CHECK_EQUAL(f(values1), predicate_result);
|
|
BOOST_CHECK_EQUAL(present_counter, 1U);
|
|
|
|
predicate_result = true;
|
|
BOOST_CHECK_EQUAL(f(values1), predicate_result);
|
|
BOOST_CHECK_EQUAL(present_counter, 2U);
|
|
|
|
f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< logging::numeric_types >(data::attr2()));
|
|
BOOST_CHECK_EQUAL(f(values1), predicate_result);
|
|
BOOST_CHECK_EQUAL(present_counter, 3U);
|
|
|
|
f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr2()).or_throw());
|
|
BOOST_CHECK_THROW(f(values1), logging::runtime_error);
|
|
f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr2()));
|
|
BOOST_CHECK_EQUAL(f(values1), true);
|
|
BOOST_CHECK_EQUAL(present_counter, 3U);
|
|
|
|
f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr4()).or_throw());
|
|
BOOST_CHECK_THROW(f(values1), logging::runtime_error);
|
|
f = phoenix::bind(predicate(present_counter, predicate_result), expr::attr< int >(data::attr4()));
|
|
BOOST_CHECK_EQUAL(f(values1), true);
|
|
BOOST_CHECK_EQUAL(present_counter, 3U);
|
|
}
|
|
|
|
// The test checks that begins_with condition works
|
|
BOOST_AUTO_TEST_CASE(begins_with_check)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
set1[data::attr1()] = attr1;
|
|
set1[data::attr2()] = attr2;
|
|
set1[data::attr3()] = attr3;
|
|
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
|
|
filter f = expr::begins_with(expr::attr< std::string >(data::attr3()), "Hello");
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::begins_with(expr::attr< std::string >(data::attr3()), "hello");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::begins_with(expr::attr< std::string >(data::attr3()).or_throw(), "Bye");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::begins_with(expr::attr< std::string >(data::attr3()).or_throw(), "world!");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::begins_with(expr::attr< std::string >(data::attr2()), "Hello");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::begins_with(expr::attr< std::string >(data::attr4()), "Hello");
|
|
BOOST_CHECK(!f(values1));
|
|
}
|
|
|
|
// The test checks that ends_with condition works
|
|
BOOST_AUTO_TEST_CASE(ends_with_check)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
set1[data::attr1()] = attr1;
|
|
set1[data::attr2()] = attr2;
|
|
set1[data::attr3()] = attr3;
|
|
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
|
|
filter f = expr::ends_with(expr::attr< std::string >(data::attr3()), "world!");
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::ends_with(expr::attr< std::string >(data::attr3()), "World!");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::ends_with(expr::attr< std::string >(data::attr3()).or_throw(), "Bye");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::ends_with(expr::attr< std::string >(data::attr3()).or_throw(), "Hello");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::ends_with(expr::attr< std::string >(data::attr2()), "world!");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::ends_with(expr::attr< std::string >(data::attr4()), "world!");
|
|
BOOST_CHECK(!f(values1));
|
|
}
|
|
|
|
// The test checks that contains condition works
|
|
BOOST_AUTO_TEST_CASE(contains_check)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
set1[data::attr1()] = attr1;
|
|
set1[data::attr2()] = attr2;
|
|
set1[data::attr3()] = attr3;
|
|
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
|
|
filter f = expr::contains(expr::attr< std::string >(data::attr3()), "Hello");
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::contains(expr::attr< std::string >(data::attr3()), "hello");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::contains(expr::attr< std::string >(data::attr3()).or_throw(), "o, w");
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::contains(expr::attr< std::string >(data::attr3()).or_throw(), "world!");
|
|
BOOST_CHECK(f(values1));
|
|
|
|
f = expr::contains(expr::attr< std::string >(data::attr2()), "Hello");
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::contains(expr::attr< std::string >(data::attr4()), "Hello");
|
|
BOOST_CHECK(!f(values1));
|
|
}
|
|
|
|
// The test checks that matches condition works
|
|
BOOST_AUTO_TEST_CASE(matches_check)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
set1[data::attr1()] = attr1;
|
|
set1[data::attr2()] = attr2;
|
|
set1[data::attr3()] = attr3;
|
|
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
|
|
boost::regex rex("hello");
|
|
filter f = expr::matches(expr::attr< std::string >(data::attr3()), rex);
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
rex = ".*world.*";
|
|
f = expr::matches(expr::attr< std::string >(data::attr3()).or_throw(), rex);
|
|
BOOST_CHECK(f(values1));
|
|
|
|
rex = ".*";
|
|
f = expr::matches(expr::attr< std::string >(data::attr2()), rex);
|
|
BOOST_CHECK(!f(values1));
|
|
|
|
f = expr::matches(expr::attr< std::string >(data::attr4()), rex);
|
|
BOOST_CHECK(!f(values1));
|
|
}
|
|
|
|
// The test checks that the filter composition works
|
|
BOOST_AUTO_TEST_CASE(composition_check)
|
|
{
|
|
typedef logging::attribute_set attr_set;
|
|
typedef logging::attribute_value_set attr_values;
|
|
typedef logging::filter filter;
|
|
typedef test_data< char > data;
|
|
|
|
attrs::constant< int > attr1(10);
|
|
attrs::constant< double > attr2(5.5);
|
|
attrs::constant< std::string > attr3("Hello, world!");
|
|
|
|
attr_set set1, set2, set3;
|
|
attr_values values1(set1, set2, set3);
|
|
values1.freeze();
|
|
set1[data::attr2()] = attr2;
|
|
attr_values values2(set1, set2, set3);
|
|
values2.freeze();
|
|
set1[data::attr3()] = attr3;
|
|
set1[data::attr1()] = attr1;
|
|
attr_values values3(set1, set2, set3);
|
|
values3.freeze();
|
|
|
|
filter f =
|
|
expr::attr< int >(data::attr1()) <= 10 ||
|
|
expr::is_in_range(expr::attr< double >(data::attr2()), 2.2, 7.7);
|
|
BOOST_CHECK(!f(values1));
|
|
BOOST_CHECK(f(values2));
|
|
BOOST_CHECK(f(values3));
|
|
|
|
f = expr::attr< int >(data::attr1()) == 10 &&
|
|
expr::begins_with(expr::attr< std::string >(data::attr3()), "Hello");
|
|
BOOST_CHECK(!f(values1));
|
|
BOOST_CHECK(!f(values2));
|
|
BOOST_CHECK(f(values3));
|
|
}
|