2
0
mirror of https://github.com/boostorg/test.git synced 2026-02-19 02:42:13 +00:00
Files
test/test/writing-test-ts/assertion-construction-test.cpp
2016-01-26 23:24:49 +01:00

480 lines
14 KiB
C++

// (C) Copyright Gennadiy Rozental 2011-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)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision: 62023 $
//
// Description : unit test for new assertion construction based on input expression
// ***************************************************************************
// Boost.Test
#define BOOST_TEST_MODULE Boost.Test assertion consruction test
#include <boost/test/unit_test.hpp>
#include <boost/test/tools/assertion.hpp>
#include <boost/test/utils/is_forward_iterable.hpp>
#include <boost/noncopyable.hpp>
#include <map>
#include <set>
namespace utf = boost::unit_test;
//____________________________________________________________________________//
#define EXPR_TYPE( expr ) ( assertion::seed() ->* expr )
// some broken compilers do not implement properly decltype on expressions
// partial implementation of is_forward_iterable when decltype not available
struct not_fwd_iterable_1 {
typedef int const_iterator;
typedef int value_type;
bool size();
};
struct not_fwd_iterable_2 {
typedef int const_iterator;
typedef int value_type;
bool begin();
};
struct not_fwd_iterable_3 {
typedef int value_type;
bool begin();
bool size();
};
BOOST_AUTO_TEST_CASE( test_forward_iterable_concept )
{
{
typedef std::vector<int> type;
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
// should also work for references, but from is_forward_iterable
typedef std::vector<int>& type;
BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef std::list<int> type;
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef std::map<int, int> type;
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef std::set<int, int> type;
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef float type;
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef not_fwd_iterable_1 type;
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef not_fwd_iterable_2 type;
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef not_fwd_iterable_3 type;
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
typedef char type;
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
{
// tables are not in the forward_iterable concept
typedef int type[10];
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_size<type>::value, "has_member_size failed");
BOOST_CHECK_MESSAGE(!utf::ut_detail::has_member_begin<type>::value, "has_member_begin failed");
BOOST_CHECK_MESSAGE(!utf::is_forward_iterable< type >::value, "is_forward_iterable failed");
}
}
BOOST_AUTO_TEST_CASE( test_basic_value_expression_construction )
{
using namespace boost::test_tools;
{
predicate_result const& res = EXPR_TYPE( 1 ).evaluate();
BOOST_TEST( res );
BOOST_TEST( res.message().is_empty() );
}
{
predicate_result const& res = EXPR_TYPE( 0 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)0 is false]" );
}
{
predicate_result const& res = EXPR_TYPE( true ).evaluate();
BOOST_TEST( res );
BOOST_TEST( res.message().is_empty() );
}
{
predicate_result const& res = EXPR_TYPE( 1.5 ).evaluate();
BOOST_TEST( res );
}
{
predicate_result const& res = EXPR_TYPE( "abc" ).evaluate();
BOOST_TEST( res );
}
{
predicate_result const& res = EXPR_TYPE( 1>2 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [1 <= 2]" );
}
}
//____________________________________________________________________________//
BOOST_AUTO_TEST_CASE( test_comparison_expression )
{
using namespace boost::test_tools;
{
predicate_result const& res = EXPR_TYPE( 1>2 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [1 <= 2]" );
}
{
predicate_result const& res = EXPR_TYPE( 100 < 50 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [100 >= 50]" );
}
{
predicate_result const& res = EXPR_TYPE( 5 <= 4 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [5 > 4]" );
}
{
predicate_result const& res = EXPR_TYPE( 10>=20 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [10 < 20]" );
}
{
int i = 10;
predicate_result const& res = EXPR_TYPE( i != 10 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [10 == 10]" );
}
{
int i = 5;
predicate_result const& res = EXPR_TYPE( i == 3 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [5 != 3]" );
}
}
//____________________________________________________________________________//
BOOST_AUTO_TEST_CASE( test_arithmetic_ops )
{
using namespace boost::test_tools;
{
int i = 3;
int j = 5;
predicate_result const& res = EXPR_TYPE( i+j !=8 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [3 + 5 == 8]" );
}
{
int i = 3;
int j = 5;
predicate_result const& res = EXPR_TYPE( 2*i-j > 1 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [2 * 3 - 5 <= 1]" );
}
{
int j = 5;
predicate_result const& res = EXPR_TYPE( 2<<j < 30 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [2 << 5 >= 30]" );
}
{
int i = 2;
int j = 5;
predicate_result const& res = EXPR_TYPE( i&j ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [2 & 5]" );
}
{
int i = 3;
int j = 5;
predicate_result const& res = EXPR_TYPE( i^j^6 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [3 ^ 5 ^ 6]" );
}
// do not support
// EXPR_TYPE( 99/2 == 48 || 101/2 > 50 );
// EXPR_TYPE( a ? 100 < 50 : 25*2 == 50 );
// EXPR_TYPE( true,false );
}
//____________________________________________________________________________//
struct Testee {
static int s_copy_counter;
Testee() : m_value( false ) {}
Testee( Testee const& ) : m_value(false) { s_copy_counter++; }
Testee( Testee&& ) : m_value(false) {}
Testee( Testee const&& ) : m_value(false) {}
bool foo() { return m_value; }
operator bool() const { return m_value; }
friend std::ostream& operator<<( std::ostream& ostr, Testee const& ) { return ostr << "Testee"; }
bool m_value;
};
int Testee::s_copy_counter = 0;
Testee get_obj() { return Testee(); }
Testee const get_const_obj() { return Testee(); }
class NC : boost::noncopyable {
public:
NC() {}
bool operator==(NC const&) const { return false; }
friend std::ostream& operator<<(std::ostream& ostr, NC const&)
{
return ostr << "NC";
}
};
BOOST_AUTO_TEST_CASE( test_objects )
{
using namespace boost::test_tools;
int expected_copy_count = 0;
{
Testee obj;
Testee::s_copy_counter = 0;
predicate_result const& res = EXPR_TYPE( obj ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)Testee is false]" );
BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
}
{
Testee const obj;
Testee::s_copy_counter = 0;
predicate_result const& res = EXPR_TYPE( obj ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)Testee is false]" );
BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
}
{
Testee::s_copy_counter = 0;
predicate_result const& res = EXPR_TYPE( get_obj() ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)Testee is false]" );
BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
}
{
Testee::s_copy_counter = 0;
predicate_result const& res = EXPR_TYPE( get_const_obj() ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)Testee is false]" );
BOOST_TEST( Testee::s_copy_counter == expected_copy_count );
}
{
Testee::s_copy_counter = 0;
Testee t1;
Testee t2;
predicate_result const& res = EXPR_TYPE( t1 != t2 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [Testee == Testee]" );
BOOST_TEST( Testee::s_copy_counter == 0 );
}
{
NC nc1;
NC nc2;
predicate_result const& res = EXPR_TYPE( nc1 == nc2 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [NC != NC]" );
}
}
//____________________________________________________________________________//
BOOST_AUTO_TEST_CASE( test_pointers )
{
using namespace boost::test_tools;
{
Testee* ptr = 0;
predicate_result const& res = EXPR_TYPE( ptr ).evaluate();
BOOST_TEST( !res );
}
{
Testee obj1;
Testee obj2;
predicate_result const& res = EXPR_TYPE( &obj1 == &obj2 ).evaluate();
BOOST_TEST( !res );
}
{
Testee obj;
Testee* ptr =&obj;
predicate_result const& res = EXPR_TYPE( *ptr ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)Testee is false]" );
}
{
Testee obj;
Testee* ptr =&obj;
bool Testee::* mem_ptr =&Testee::m_value;
predicate_result const& res = EXPR_TYPE( ptr->*mem_ptr ).evaluate();
BOOST_TEST( !res );
}
// do not support
// Testee obj;
// bool Testee::* mem_ptr =&Testee::m_value;
// EXPR_TYPE( obj.*mem_ptr );
}
//____________________________________________________________________________//
BOOST_AUTO_TEST_CASE( test_mutating_ops )
{
using namespace boost::test_tools;
{
int j = 5;
predicate_result const& res = EXPR_TYPE( j = 0 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)0 is false]" );
BOOST_TEST( j == 0 );
}
{
int j = 5;
predicate_result const& res = EXPR_TYPE( j -= 5 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)0 is false]" );
BOOST_TEST( j == 0 );
}
{
int j = 5;
predicate_result const& res = EXPR_TYPE( j *= 0 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)0 is false]" );
BOOST_TEST( j == 0 );
}
{
int j = 5;
predicate_result const& res = EXPR_TYPE( j /= 10 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)0 is false]" );
BOOST_TEST( j == 0 );
}
{
int j = 4;
predicate_result const& res = EXPR_TYPE( j %= 2 ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)0 is false]" );
BOOST_TEST( j == 0 );
}
{
int j = 5;
predicate_result const& res = EXPR_TYPE( j ^= j ).evaluate();
BOOST_TEST( !res );
BOOST_TEST( res.message() == " [(bool)0 is false]" );
BOOST_TEST( j == 0 );
}
}
// EOF