blob: 237908129f886c155386ea0125c09b716aef150d [file] [log] [blame]
/*
* 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));
}