2010-11-10 00:24:00 +01:00
|
|
|
/*
|
|
|
|
* Created by Phil on 08/11/2010.
|
|
|
|
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
|
|
|
*
|
|
|
|
* 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)
|
|
|
|
*/
|
2012-08-16 19:47:41 +02:00
|
|
|
#ifdef __clang__
|
2012-08-13 08:46:10 +02:00
|
|
|
#pragma clang diagnostic ignored "-Wpadded"
|
2012-08-16 19:47:41 +02:00
|
|
|
#endif
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2011-04-26 09:32:40 +02:00
|
|
|
#include "catch.hpp"
|
2010-11-10 00:24:00 +01:00
|
|
|
|
|
|
|
#include <string>
|
2011-03-15 23:41:27 +01:00
|
|
|
#include <limits>
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2012-07-17 09:04:19 +02:00
|
|
|
struct TestData {
|
2010-11-10 00:24:00 +01:00
|
|
|
TestData()
|
|
|
|
: int_seven( 7 ),
|
|
|
|
str_hello( "hello" ),
|
|
|
|
float_nine_point_one( 9.1f ),
|
|
|
|
double_pi( 3.1415926535 )
|
|
|
|
{}
|
|
|
|
|
|
|
|
int int_seven;
|
|
|
|
std::string str_hello;
|
|
|
|
float float_nine_point_one;
|
|
|
|
double double_pi;
|
|
|
|
};
|
|
|
|
|
2012-07-17 09:04:19 +02:00
|
|
|
|
|
|
|
struct TestDef {
|
|
|
|
TestDef& operator + ( const std::string& ) {
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
TestDef& operator[]( const std::string& ) {
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
// The "failing" tests all use the CHECK macro, which continues if the specific test fails.
|
|
|
|
// This allows us to see all results, even if an earlier check fails
|
2010-11-10 00:24:00 +01:00
|
|
|
|
|
|
|
// Equality tests
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Equality checks that should succeed", "" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
2012-07-17 09:04:19 +02:00
|
|
|
|
|
|
|
TestDef td;
|
|
|
|
td + "hello" + "hello";
|
|
|
|
|
2010-11-10 00:24:00 +01:00
|
|
|
TestData data;
|
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.int_seven == 7 );
|
|
|
|
REQUIRE( data.float_nine_point_one == Approx( 9.1f ) );
|
|
|
|
REQUIRE( data.double_pi == Approx( 3.1415926535 ) );
|
|
|
|
REQUIRE( data.str_hello == "hello" );
|
2011-06-29 20:22:56 +02:00
|
|
|
REQUIRE( "hello" == data.str_hello );
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.str_hello.size() == 5 );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
|
|
|
double x = 1.1 + 0.1 + 0.1;
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( x == Approx( 1.3 ) );
|
2010-11-10 00:24:00 +01:00
|
|
|
}
|
|
|
|
|
2014-05-20 19:11:43 +02:00
|
|
|
TEST_CASE( "Equality checks that should fail", "[.][failing]" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
|
|
|
TestData data;
|
|
|
|
|
|
|
|
CHECK( data.int_seven == 6 );
|
|
|
|
CHECK( data.int_seven == 8 );
|
|
|
|
CHECK( data.int_seven == 0 );
|
|
|
|
CHECK( data.float_nine_point_one == Approx( 9.11f ) );
|
|
|
|
CHECK( data.float_nine_point_one == Approx( 9.0f ) );
|
2011-01-31 11:10:20 +01:00
|
|
|
CHECK( data.float_nine_point_one == Approx( 1 ) );
|
|
|
|
CHECK( data.float_nine_point_one == Approx( 0 ) );
|
2010-11-10 00:24:00 +01:00
|
|
|
CHECK( data.double_pi == Approx( 3.1415 ) );
|
|
|
|
CHECK( data.str_hello == "goodbye" );
|
|
|
|
CHECK( data.str_hello == "hell" );
|
|
|
|
CHECK( data.str_hello == "hello1" );
|
|
|
|
CHECK( data.str_hello.size() == 6 );
|
|
|
|
|
|
|
|
double x = 1.1 + 0.1 + 0.1;
|
|
|
|
CHECK( x == Approx( 1.301 ) );
|
|
|
|
}
|
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Inequality checks that should succeed", "" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
|
|
|
TestData data;
|
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.int_seven != 6 );
|
|
|
|
REQUIRE( data.int_seven != 8 );
|
|
|
|
REQUIRE( data.float_nine_point_one != Approx( 9.11f ) );
|
|
|
|
REQUIRE( data.float_nine_point_one != Approx( 9.0f ) );
|
2011-01-31 11:10:20 +01:00
|
|
|
REQUIRE( data.float_nine_point_one != Approx( 1 ) );
|
|
|
|
REQUIRE( data.float_nine_point_one != Approx( 0 ) );
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.double_pi != Approx( 3.1415 ) );
|
|
|
|
REQUIRE( data.str_hello != "goodbye" );
|
|
|
|
REQUIRE( data.str_hello != "hell" );
|
|
|
|
REQUIRE( data.str_hello != "hello1" );
|
|
|
|
REQUIRE( data.str_hello.size() != 6 );
|
2010-11-10 00:24:00 +01:00
|
|
|
}
|
|
|
|
|
2014-05-20 19:11:43 +02:00
|
|
|
TEST_CASE( "Inequality checks that should fail", "[.][failing]" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
|
|
|
TestData data;
|
|
|
|
|
|
|
|
CHECK( data.int_seven != 7 );
|
|
|
|
CHECK( data.float_nine_point_one != Approx( 9.1f ) );
|
|
|
|
CHECK( data.double_pi != Approx( 3.1415926535 ) );
|
|
|
|
CHECK( data.str_hello != "hello" );
|
|
|
|
CHECK( data.str_hello.size() != 5 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ordering comparison tests
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Ordering comparison checks that should succeed", "" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
|
|
|
TestData data;
|
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.int_seven < 8 );
|
|
|
|
REQUIRE( data.int_seven > 6 );
|
|
|
|
REQUIRE( data.int_seven > 0 );
|
|
|
|
REQUIRE( data.int_seven > -1 );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.int_seven >= 7 );
|
|
|
|
REQUIRE( data.int_seven >= 6 );
|
|
|
|
REQUIRE( data.int_seven <= 7 );
|
|
|
|
REQUIRE( data.int_seven <= 8 );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.float_nine_point_one > 9 );
|
|
|
|
REQUIRE( data.float_nine_point_one < 10 );
|
|
|
|
REQUIRE( data.float_nine_point_one < 9.2 );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.str_hello <= "hello" );
|
|
|
|
REQUIRE( data.str_hello >= "hello" );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( data.str_hello < "hellp" );
|
|
|
|
REQUIRE( data.str_hello < "zebra" );
|
|
|
|
REQUIRE( data.str_hello > "hellm" );
|
|
|
|
REQUIRE( data.str_hello > "a" );
|
2010-11-10 00:24:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
|
|
|
TestData data;
|
|
|
|
|
|
|
|
CHECK( data.int_seven > 7 );
|
|
|
|
CHECK( data.int_seven < 7 );
|
|
|
|
CHECK( data.int_seven > 8 );
|
|
|
|
CHECK( data.int_seven < 6 );
|
|
|
|
CHECK( data.int_seven < 0 );
|
|
|
|
CHECK( data.int_seven < -1 );
|
|
|
|
|
|
|
|
CHECK( data.int_seven >= 8 );
|
|
|
|
CHECK( data.int_seven <= 6 );
|
|
|
|
|
|
|
|
CHECK( data.float_nine_point_one < 9 );
|
|
|
|
CHECK( data.float_nine_point_one > 10 );
|
|
|
|
CHECK( data.float_nine_point_one > 9.2 );
|
|
|
|
|
|
|
|
CHECK( data.str_hello > "hello" );
|
|
|
|
CHECK( data.str_hello < "hello" );
|
|
|
|
CHECK( data.str_hello > "hellp" );
|
|
|
|
CHECK( data.str_hello > "z" );
|
|
|
|
CHECK( data.str_hello < "hellm" );
|
|
|
|
CHECK( data.str_hello < "a" );
|
|
|
|
|
|
|
|
CHECK( data.str_hello >= "z" );
|
|
|
|
CHECK( data.str_hello <= "a" );
|
|
|
|
}
|
|
|
|
|
2011-03-09 20:45:05 +01:00
|
|
|
// Comparisons with int literals
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned", "" )
|
2011-03-09 20:45:05 +01:00
|
|
|
{
|
|
|
|
int i = 1;
|
|
|
|
unsigned int ui = 2;
|
|
|
|
long l = 3;
|
|
|
|
unsigned long ul = 4;
|
|
|
|
char c = 5;
|
|
|
|
unsigned char uc = 6;
|
|
|
|
|
|
|
|
REQUIRE( i == 1 );
|
|
|
|
REQUIRE( ui == 2 );
|
|
|
|
REQUIRE( l == 3 );
|
|
|
|
REQUIRE( ul == 4 );
|
|
|
|
REQUIRE( c == 5 );
|
|
|
|
REQUIRE( uc == 6 );
|
|
|
|
|
|
|
|
REQUIRE( 1 == i );
|
|
|
|
REQUIRE( 2 == ui );
|
|
|
|
REQUIRE( 3 == l );
|
|
|
|
REQUIRE( 4 == ul );
|
|
|
|
REQUIRE( 5 == c );
|
|
|
|
REQUIRE( 6 == uc );
|
|
|
|
|
2011-03-21 09:09:47 +01:00
|
|
|
REQUIRE( (std::numeric_limits<unsigned long>::max)() > ul );
|
2011-03-09 20:45:05 +01:00
|
|
|
}
|
|
|
|
|
2012-06-05 11:38:18 +02:00
|
|
|
// Disable warnings about sign conversions for the next two tests
|
|
|
|
// (as we are deliberately invoking them)
|
2013-03-21 09:58:22 +01:00
|
|
|
// - Currently only disabled for GCC/ LLVM. Should add VC++ too
|
2012-08-16 21:35:52 +02:00
|
|
|
#ifdef __GNUC__
|
2012-06-05 11:38:18 +02:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
|
|
|
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
2012-08-16 21:35:52 +02:00
|
|
|
#endif
|
2013-03-25 09:46:48 +01:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
|
|
|
|
#endif
|
2012-06-05 11:38:18 +02:00
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "comparisons between int variables", "" )
|
2012-04-28 13:20:29 +02:00
|
|
|
{
|
2012-06-03 00:08:07 +02:00
|
|
|
long long_var = 1L;
|
2012-04-28 13:20:29 +02:00
|
|
|
unsigned char unsigned_char_var = 1;
|
|
|
|
unsigned short unsigned_short_var = 1;
|
|
|
|
unsigned int unsigned_int_var = 1;
|
|
|
|
unsigned long unsigned_long_var = 1L;
|
|
|
|
|
|
|
|
REQUIRE( long_var == unsigned_char_var );
|
|
|
|
REQUIRE( long_var == unsigned_short_var );
|
|
|
|
REQUIRE( long_var == unsigned_int_var );
|
|
|
|
REQUIRE( long_var == unsigned_long_var );
|
|
|
|
}
|
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "comparisons between const int variables", "" )
|
2012-11-16 22:03:59 +01:00
|
|
|
{
|
|
|
|
const unsigned char unsigned_char_var = 1;
|
|
|
|
const unsigned short unsigned_short_var = 1;
|
|
|
|
const unsigned int unsigned_int_var = 1;
|
|
|
|
const unsigned long unsigned_long_var = 1L;
|
|
|
|
|
|
|
|
REQUIRE( unsigned_char_var == 1 );
|
|
|
|
REQUIRE( unsigned_short_var == 1 );
|
|
|
|
REQUIRE( unsigned_int_var == 1 );
|
|
|
|
REQUIRE( unsigned_long_var == 1 );
|
|
|
|
}
|
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ standard behaviour", "" )
|
2011-03-15 23:22:19 +01:00
|
|
|
{
|
2011-04-01 09:15:45 +02:00
|
|
|
CHECK( ( -1 > 2u ) );
|
|
|
|
CHECK( -1 > 2u );
|
2011-03-15 23:22:19 +01:00
|
|
|
|
2011-04-01 09:15:45 +02:00
|
|
|
CHECK( ( 2u < -1 ) );
|
|
|
|
CHECK( 2u < -1 );
|
2011-03-15 23:22:19 +01:00
|
|
|
|
2011-04-01 09:15:45 +02:00
|
|
|
const int minInt = (std::numeric_limits<int>::min)();
|
|
|
|
CHECK( ( minInt > 2u ) );
|
|
|
|
CHECK( minInt > 2u );
|
2011-03-15 23:22:19 +01:00
|
|
|
}
|
2012-06-05 11:38:18 +02:00
|
|
|
|
2012-07-17 09:04:19 +02:00
|
|
|
template<typename T>
|
|
|
|
struct Ex
|
|
|
|
{
|
|
|
|
Ex( T ){}
|
|
|
|
|
|
|
|
bool operator == ( const T& ) const { return true; }
|
|
|
|
T operator * ( const T& ) const { return T(); }
|
|
|
|
};
|
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Comparisons between ints where one side is computed", "" )
|
2012-07-17 09:04:19 +02:00
|
|
|
{
|
|
|
|
CHECK( 54 == 6*9 );
|
|
|
|
}
|
|
|
|
|
2012-08-16 21:35:52 +02:00
|
|
|
#ifdef __GNUC__
|
2012-06-05 11:38:18 +02:00
|
|
|
#pragma GCC diagnostic pop
|
2012-08-16 21:35:52 +02:00
|
|
|
#endif
|
2011-03-15 23:22:19 +01:00
|
|
|
|
2012-05-07 20:45:55 +02:00
|
|
|
inline const char* returnsConstNull(){ return NULL; }
|
|
|
|
inline char* returnsNull(){ return NULL; }
|
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "Pointers can be compared to null", "" )
|
2011-03-18 15:39:58 +01:00
|
|
|
{
|
|
|
|
TestData* p = NULL;
|
|
|
|
TestData* pNULL = NULL;
|
|
|
|
|
|
|
|
REQUIRE( p == NULL );
|
|
|
|
REQUIRE( p == pNULL );
|
|
|
|
|
|
|
|
TestData data;
|
|
|
|
p = &data;
|
2011-03-18 20:08:33 +01:00
|
|
|
|
2011-03-18 15:39:58 +01:00
|
|
|
REQUIRE( p != NULL );
|
2011-03-18 20:08:33 +01:00
|
|
|
|
|
|
|
const TestData* cp = p;
|
|
|
|
REQUIRE( cp != NULL );
|
|
|
|
|
|
|
|
const TestData* const cpc = p;
|
|
|
|
REQUIRE( cpc != NULL );
|
|
|
|
|
2012-05-07 20:45:55 +02:00
|
|
|
REQUIRE( returnsNull() == NULL );
|
|
|
|
REQUIRE( returnsConstNull() == NULL );
|
|
|
|
|
2012-05-09 09:17:51 +02:00
|
|
|
REQUIRE( NULL != p );
|
2011-03-18 15:39:58 +01:00
|
|
|
}
|
|
|
|
|
2010-11-10 00:24:00 +01:00
|
|
|
// Not (!) tests
|
2010-11-10 08:59:07 +01:00
|
|
|
// The problem with the ! operator is that it has right-to-left associativity.
|
2010-12-14 10:05:51 +01:00
|
|
|
// This means we can't isolate it when we decompose. The simple REQUIRE( !false ) form, therefore,
|
2010-11-10 08:59:07 +01:00
|
|
|
// cannot have the operand value extracted. The test will work correctly, and the situation
|
|
|
|
// is detected and a warning issued.
|
2010-12-14 10:00:09 +01:00
|
|
|
// An alternative form of the macros (CHECK_FALSE and REQUIRE_FALSE) can be used instead to capture
|
2010-11-10 08:59:07 +01:00
|
|
|
// the operand value.
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "'Not' checks that should succeed", "" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
|
|
|
bool falseValue = false;
|
|
|
|
|
2011-09-19 19:17:51 +02:00
|
|
|
REQUIRE( false == false );
|
|
|
|
REQUIRE( true == true );
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( !false );
|
|
|
|
REQUIRE_FALSE( false );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( !falseValue );
|
|
|
|
REQUIRE_FALSE( falseValue );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
2010-12-14 10:00:09 +01:00
|
|
|
REQUIRE( !(1 == 2) );
|
|
|
|
REQUIRE_FALSE( 1 == 2 );
|
2010-11-10 00:24:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-19 08:21:03 +01:00
|
|
|
TEST_CASE( "'Not' checks that should fail", "[.][failing]" )
|
2010-11-10 00:24:00 +01:00
|
|
|
{
|
|
|
|
bool trueValue = true;
|
|
|
|
|
2011-09-19 19:17:51 +02:00
|
|
|
CHECK( false != false );
|
|
|
|
CHECK( true != true );
|
2010-11-10 00:24:00 +01:00
|
|
|
CHECK( !true );
|
2010-12-14 10:00:09 +01:00
|
|
|
CHECK_FALSE( true );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
|
|
|
CHECK( !trueValue );
|
2010-12-14 10:00:09 +01:00
|
|
|
CHECK_FALSE( trueValue );
|
2010-11-10 00:24:00 +01:00
|
|
|
|
|
|
|
CHECK( !(1 == 1) );
|
2010-12-14 10:00:09 +01:00
|
|
|
CHECK_FALSE( 1 == 1 );
|
2010-11-10 00:24:00 +01:00
|
|
|
}
|
|
|
|
|