diff --git a/build/boost/doc/changelog.qbk b/build/boost/doc/changelog.qbk
index 7ed16c5..c6d733e 100644
--- a/build/boost/doc/changelog.qbk
+++ b/build/boost/doc/changelog.qbk
@@ -1,5 +1,12 @@
[section Changelog]
+[section trunk]
+Not yet released
+
+* Reworked MOCK_CONSTRAINT to be able to provide names to parameters
+
+[endsect]
+
[section 1.2.3]
Released 20 May 2013
diff --git a/build/boost/doc/customization.qbk b/build/boost/doc/customization.qbk
index 01b56e0..9e99f77 100644
--- a/build/boost/doc/customization.qbk
+++ b/build/boost/doc/customization.qbk
@@ -99,7 +99,7 @@ See [link turtle.reference.expectation.constraints constraints] for an explanati
For more information about the serialization operator and the use of mock::format, refer to [link turtle.customization.logging loggin].
-[note The [link turtle.reference.helpers.mock_constraint MOCK_CONSTRAINT] macro takes care of everything for simple cases.]
+[note The [link turtle.reference.constraint constraint helper macro] takes care of everything for simple cases.]
[endsect]
diff --git a/build/boost/doc/example/reference.cpp b/build/boost/doc/example/reference.cpp
index 4c4711e..2cd9462 100644
--- a/build/boost/doc/example/reference.cpp
+++ b/build/boost/doc/example/reference.cpp
@@ -759,8 +759,8 @@ BOOST_AUTO_TEST_CASE( demonstrates_resetting_a_static_mock_method )
namespace helpers_example_1
{
//[ helpers_example_1
-MOCK_CONSTRAINT( 0, any, true ) // this is (almost) how mock::any is defined
-MOCK_CONSTRAINT( 0, forty_two, actual == 42 ) // this defines a 'forty_two' constraint
+MOCK_CONSTRAINT( any, true ) // this is how mock::any could be defined
+MOCK_CONSTRAINT( forty_two, actual == 42 ) // this defines a 'forty_two' constraint
BOOST_AUTO_TEST_CASE( mock_constraint_0_arity )
{
@@ -774,8 +774,8 @@ BOOST_AUTO_TEST_CASE( mock_constraint_0_arity )
namespace helpers_example_2
{
//[ helpers_example_2
-MOCK_CONSTRAINT( 1, equal, actual == expected_0 ) // this is how mock::equal is defined
-MOCK_CONSTRAINT( 1, near, std::abs( actual - expected_0 ) < 0.01 ) // this defines a 'near' constraint which can be used as 'near( 42 )'
+MOCK_CONSTRAINT( equal, expected, actual == expected ) // this is how mock::equal could be defined
+MOCK_CONSTRAINT( near, expected, std::abs( actual - expected ) < 0.01 ) // this defines a 'near' constraint which can be used as 'near( 42 )'
BOOST_AUTO_TEST_CASE( mock_constraint_1_arity )
{
@@ -789,7 +789,50 @@ BOOST_AUTO_TEST_CASE( mock_constraint_1_arity )
namespace helpers_example_3
{
//[ helpers_example_3
-MOCK_CONSTRAINT( 2, near, std::abs( actual - expected_0 ) < expected_1 ) // this is how mock::near is defined
+MOCK_CONSTRAINT( near, expected, tolerance, std::abs( actual - expected ) < tolerance ) // this is how mock::near could be defined
+
+BOOST_AUTO_TEST_CASE( mock_constraint_2_arity )
+{
+ MOCK_FUNCTOR( f, void( int ) );
+ MOCK_EXPECT( f ).with( near( 42, 0.001 ) );
+}
+//]
+}
+
+namespace helpers_example_4
+{
+//[ helpers_example_4
+MOCK_CONSTRAINT_EXT( any, 0,, true ) // this is (almost) how mock::any is defined
+MOCK_CONSTRAINT_EXT( forty_two, 0,, actual == 42 ) // this defines a 'forty_two' constraint
+
+BOOST_AUTO_TEST_CASE( mock_constraint_0_arity )
+{
+ MOCK_FUNCTOR( f, void( int ) );
+ MOCK_EXPECT( f ).with( forty_two );
+ MOCK_EXPECT( f ).with( any );
+}
+//]
+}
+
+namespace helpers_example_5
+{
+//[ helpers_example_5
+MOCK_CONSTRAINT_EXT( equal, 1, ( expected ), actual == expected ) // this is how mock::equal is defined
+MOCK_CONSTRAINT_EXT( near, 1, ( expected ), std::abs( actual - expected ) < 0.01 ) // this defines a 'near' constraint which can be used as 'near( 42 )'
+
+BOOST_AUTO_TEST_CASE( mock_constraint_1_arity )
+{
+ MOCK_FUNCTOR( f, void( int ) );
+ MOCK_EXPECT( f ).with( near( 42 ) );
+ MOCK_EXPECT( f ).with( equal( 42 ) );
+}
+//]
+}
+
+namespace helpers_example_6
+{
+//[ helpers_example_6
+MOCK_CONSTRAINT_EXT( near, 2, ( expected, tolerance ), std::abs( actual - expected ) < tolerance ) // this is how mock::near is defined
BOOST_AUTO_TEST_CASE( mock_constraint_2_arity )
{
diff --git a/build/boost/doc/reference.qbk b/build/boost/doc/reference.qbk
index 145cc7f..b082d9d 100644
--- a/build/boost/doc/reference.qbk
+++ b/build/boost/doc/reference.qbk
@@ -96,7 +96,7 @@ Synopsis :
[note [link turtle.reference.creation.constructor Constructors], [link turtle.reference.creation.destructor destructors] and [link turtle.reference.creation.conversion_operator conversion operators] require special care.]
-With a compiler without support for variadic macros the signature and the identifier cannot be specified, thus in case of ambiguity another set of macros must be used.
+For compilers without support for variadic macros the signature and the identifier cannot be specified, thus in case of ambiguity another set of macros must be used.
Synopsis :
@@ -150,7 +150,7 @@ Synopsis :
[note A static object is used behind the scene in order to keep track of the expectations of a mock static method, therefore to ensure all tests run in isolation it is strongly suggested to manually [link turtle.reference.verification verify] and [link turtle.reference.reset reset] the static method at the end of each test.]
-[warning With a compiler without support for variadic macros the identifier cannot be ommitted and must be given explicitly.]
+[warning For compilers without support for variadic macros the identifier cannot be ommitted and must be given explicitly.]
Example :
@@ -244,7 +244,7 @@ Synopsis :
[note A static object is used behind the scene in order to keep track of the expectations of a mock function, therefore to ensure all tests run in isolation it is strongly suggested to manually [link turtle.reference.verification verify] and [link turtle.reference.reset reset] the mock function at the end of each test.]
-[warning With a compiler without support for variadic macros the identifier cannot be ommitted and must be given explicitly.]
+[warning For compilers without support for variadic macros the identifier cannot be ommitted and must be given explicitly.]
Example :
@@ -308,6 +308,8 @@ Synopsis :
MOCK_EXPECT( identifier ).with( constraint_1, constraint_2, ... );
+The number of constraints must match the number of mocked parameters.
+
Constraints :
[table
@@ -395,7 +397,7 @@ A sequence enforces a given order between two or more expectations.
Synopsis :
- MOCK_EXPECT( identifier_1 ).in( sequence_1 [, sequence_2 [, ...]] );
+ MOCK_EXPECT( identifier_1 ).in( sequence_1, sequence_2, ... );
Each sequence is an instance of mock::sequence.
@@ -488,33 +490,47 @@ Example :
[endsect]
-[section Helpers]
+[section Constraint]
-This section presents various useful tools.
-
-[section MOCK_CONSTRAINT]
+This section presents a simple means of creating a new constraint.
Synopsis :
- MOCK_CONSTRAINT( arity, name, expression ) // defines a constraint 'name' based on the given 'expression'
+ MOCK_CONSTRAINT( name, expected_1, expected_2, ..., expression ) // defines a constraint 'name' based on the given 'expression'
-The expression manipulates the received parameter ['actual] in order to implement the constraint, as well as ['arity] extra expected arguments ['expected_0], ['expected_1], etc...
+The expression manipulates a received parameter ['actual] in order to implement the constraint, as well as extra optional arguments named ['expected_1], ['expected_2], ...
-[note The type of all expected arguments must be copy-constructible and assignable.]
+For compilers without supporting variadic macros the alternate following macro must be used.
+
+Synopsis :
+
+ MOCK_CONSTRAINT_EXT( name, arity, ( expected_1, expected_2, ... ), expression ) // defines a constraint 'name' based on the given 'expression'
+
+Of course this macro is also available for compilers which support variadic macros.
Example without any extra argument :
[helpers_example_1]
+or with the alternate more portable macro :
+
+[helpers_example_4]
+
Example with one extra argument :
[helpers_example_2]
+or with the alternate more portable macro :
+
+[helpers_example_5]
+
Example with two extra arguments :
[helpers_example_3]
-[endsect]
+or with the alternate more portable macro :
+
+[helpers_example_6]
[endsect]
diff --git a/build/boost/test/Jamfile.jam b/build/boost/test/Jamfile.jam
index 83222d8..447f5a9 100644
--- a/build/boost/test/Jamfile.jam
+++ b/build/boost/test/Jamfile.jam
@@ -18,6 +18,7 @@ rule run-test ( name )
}
alias mock_tests :
+ [ run-test test_constraint ]
[ run-test test_constraints ]
[ run-test test_error ]
[ run-test test_integration ]
diff --git a/build/vc100/turtle_test.vcxproj b/build/vc100/turtle_test.vcxproj
index 72ab186..50ed852 100644
--- a/build/vc100/turtle_test.vcxproj
+++ b/build/vc100/turtle_test.vcxproj
@@ -28,6 +28,7 @@
+
diff --git a/build/vc100/turtle_test.vcxproj.filters b/build/vc100/turtle_test.vcxproj.filters
index 9d769d5..8e5240c 100644
--- a/build/vc100/turtle_test.vcxproj.filters
+++ b/build/vc100/turtle_test.vcxproj.filters
@@ -63,5 +63,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/test/test_constraint.cpp b/test/test_constraint.cpp
new file mode 100644
index 0000000..d748eb0
--- /dev/null
+++ b/test/test_constraint.cpp
@@ -0,0 +1,28 @@
+// http://turtle.sourceforge.net
+//
+// Copyright Mathieu Champlon 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)
+
+#include
+#include
+
+#ifndef BOOST_NO_VARIADIC_MACROS
+
+namespace
+{
+ MOCK_CONSTRAINT( constraint_0, actual == 0 )
+ MOCK_CONSTRAINT( constraint_1, expected, actual == expected )
+ MOCK_CONSTRAINT( constraint_2, expected_0, expected_1, actual == expected_0 || actual == expected_1 )
+}
+
+BOOST_AUTO_TEST_CASE( mock_constraint_is_supported_by_compilers_with_variadic_macros )
+{
+ BOOST_CHECK( constraint_0.c_( 0 ) );
+ BOOST_CHECK( constraint_1( 0 ).c_( 0 ) );
+ BOOST_CHECK( constraint_2( 0, 0 ).c_( 0 ) );
+}
+
+#endif // BOOST_NO_VARIADIC_MACROS
diff --git a/turtle/constraint.hpp b/turtle/constraint.hpp
index a7f885a..6f3a6bf 100644
--- a/turtle/constraint.hpp
+++ b/turtle/constraint.hpp
@@ -11,12 +11,14 @@
#include "config.hpp"
#include "log.hpp"
+#include
#include
#include
+#include
#include
#include
#include
-#include
+#include
namespace mock
{
@@ -124,7 +126,7 @@ namespace detail
}
} // mock
-#define MOCK_UNARY_CONSTRAINT(n, Name, Expr) \
+#define MOCK_UNARY_CONSTRAINT(Name, n, Args, Expr) \
namespace detail \
{ \
struct Name \
@@ -154,25 +156,34 @@ namespace detail
#define MOCK_CONSTRAINT_MEMBER(z, n, d) \
Expected_##n expected##n;
-#define MOCK_NARY_CONSTRAINT(n, Name, Expr) \
+#define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \
+ BOOST_DEDUCED_TYPENAME \
+ boost::unwrap_reference< Expected_##n >::type \
+ BOOST_PP_ARRAY_ELEM(n, Args)
+
+#define MOCK_CONSTRAINT_PARAM(z, n, Args) \
+ T##n BOOST_PP_ARRAY_ELEM(n, Args)
+
+#define MOCK_NARY_CONSTRAINT(Name, n, Args, Expr) \
namespace detail \
{ \
template< BOOST_PP_ENUM_PARAMS(n, typename Expected_) > \
struct Name \
{ \
explicit Name( \
- BOOST_PP_ENUM_BINARY_PARAMS(n, const Expected_, & e ) ) \
+ BOOST_PP_ENUM_BINARY_PARAMS(n, const Expected_, & e) ) \
: BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ASSIGN, _) \
{} \
template< typename Actual > \
bool operator()( const Actual& actual ) const \
{ \
return test( actual, \
- BOOST_PP_ENUM(n, MOCK_CONSTRAINT_UNWRAP_REF, _ ) ); \
+ BOOST_PP_ENUM(n, MOCK_CONSTRAINT_UNWRAP_REF, _) ); \
} \
- template< typename Actual, BOOST_PP_ENUM_PARAMS(n, typename T) > \
+ template< typename Actual > \
bool test( const Actual& actual, \
- BOOST_PP_ENUM_BINARY_PARAMS(n, const T, & expected_ ) ) const \
+ BOOST_PP_ENUM(n, \
+ MOCK_CONSTRAINT_CREF_PARAM, (n, Args)) ) const \
{ \
return Expr; \
} \
@@ -185,18 +196,52 @@ namespace detail
BOOST_PP_REPEAT(n, MOCK_CONSTRAINT_MEMBER, _) \
}; \
} \
- template< BOOST_PP_ENUM_PARAMS(n, typename Expected_) > \
- mock::constraint< detail::Name< \
- BOOST_PP_ENUM_PARAMS(n, Expected_) > \
- > Name( BOOST_PP_ENUM_BINARY_PARAMS(n, Expected_, expected_ ) ) \
+ template< BOOST_PP_ENUM_PARAMS(n, typename T) > \
+ mock::constraint< \
+ detail::Name< BOOST_PP_ENUM_PARAMS(n, T) > \
+ > Name( BOOST_PP_ENUM(n, MOCK_CONSTRAINT_PARAM, (n, Args)) ) \
{ \
- return detail::Name< BOOST_PP_ENUM_PARAMS(n, Expected_) >( \
- BOOST_PP_ENUM_PARAMS(n, expected_ ) ); \
+ return detail::Name< BOOST_PP_ENUM_PARAMS(n, T) > Args; \
}
-#define MOCK_CONSTRAINT(n, Name, Expr) \
+#define MOCK_CONSTRAINT_EXT(Name, n, Args, Expr) \
BOOST_PP_IF(n, \
MOCK_NARY_CONSTRAINT, \
- MOCK_UNARY_CONSTRAINT)(n, Name, Expr)
+ MOCK_UNARY_CONSTRAINT)(Name, n, Args, Expr)
+
+#ifndef BOOST_NO_VARIADIC_MACROS
+
+#if BOOST_MSVC
+# define MOCK_VARIADIC_SIZE(...) \
+ BOOST_PP_CAT(MOCK_VARIADIC_SIZE_I(__VA_ARGS__, \
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, \
+ 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, \
+ 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,),)
+#else // BOOST_MSVC
+# define MOCK_VARIADIC_SIZE(...) \
+ MOCK_VARIADIC_SIZE_I(__VA_ARGS__, \
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, \
+ 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, \
+ 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,)
+#endif // BOOST_MSVC
+#define MOCK_VARIADIC_SIZE_I( \
+ e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, \
+ e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, \
+ e25, e26, e27, e28, e29, e30, e31, size, ...) size
+
+#define MOCK_CONSTRAINT_AUX_AUX(Name, n, Array) \
+ MOCK_CONSTRAINT_EXT( \
+ Name, n, \
+ BOOST_PP_ARRAY_TO_TUPLE(BOOST_PP_ARRAY_POP_BACK(Array)), \
+ BOOST_PP_ARRAY_ELEM(n, Array))
+
+#define MOCK_CONSTRAINT_AUX(Name, Size, Tuple) \
+ MOCK_CONSTRAINT_AUX_AUX(Name, BOOST_PP_DEC(Size), (Size,Tuple))
+
+#define MOCK_CONSTRAINT(Name, ...) \
+ MOCK_CONSTRAINT_AUX( \
+ Name, MOCK_VARIADIC_SIZE(__VA_ARGS__), (__VA_ARGS__))
+
+#endif // BOOST_NO_VARIADIC_MACROS
#endif // MOCK_CONSTRAINT_HPP_INCLUDED
diff --git a/turtle/constraints.hpp b/turtle/constraints.hpp
index 655fbc6..b1a7827 100644
--- a/turtle/constraints.hpp
+++ b/turtle/constraints.hpp
@@ -19,28 +19,28 @@
namespace mock
{
- MOCK_CONSTRAINT( 0, any, true && &actual )
- MOCK_CONSTRAINT( 0, affirm, !! actual )
- MOCK_CONSTRAINT( 0, negate, ! actual )
- MOCK_CONSTRAINT( 0, evaluate, actual() )
+ MOCK_CONSTRAINT_EXT( any, 0,, true && &actual )
+ MOCK_CONSTRAINT_EXT( affirm, 0,, !! actual )
+ MOCK_CONSTRAINT_EXT( negate, 0,, ! actual )
+ MOCK_CONSTRAINT_EXT( evaluate, 0,, actual() )
- MOCK_CONSTRAINT( 1, equal, actual == expected_0 )
- MOCK_CONSTRAINT( 1, less, actual < expected_0 )
- MOCK_CONSTRAINT( 1, greater, actual > expected_0 )
- MOCK_CONSTRAINT( 1, less_equal, actual <= expected_0 )
- MOCK_CONSTRAINT( 1, greater_equal, actual >= expected_0 )
+ MOCK_CONSTRAINT_EXT( equal, 1, ( expected ), actual == expected )
+ MOCK_CONSTRAINT_EXT( less, 1, ( expected ), actual < expected )
+ MOCK_CONSTRAINT_EXT( greater, 1, ( expected ), actual > expected )
+ MOCK_CONSTRAINT_EXT( less_equal, 1, ( expected ), actual <= expected )
+ MOCK_CONSTRAINT_EXT( greater_equal, 1, ( expected ), actual >= expected )
- MOCK_CONSTRAINT( 1, small, \
- ( boost::test_tools::check_is_small( actual, expected_0 ) ) )
- MOCK_CONSTRAINT( 2, close, \
+ MOCK_CONSTRAINT_EXT( small, 1, ( expected ), \
+ ( boost::test_tools::check_is_small( actual, expected ) ) )
+ MOCK_CONSTRAINT_EXT( close, 2, ( expected, tolerance ), \
( boost::test_tools::check_is_close( \
- actual, expected_0, \
- boost::test_tools::percent_tolerance( expected_1 ) ) ) )
- MOCK_CONSTRAINT( 2, close_fraction, \
+ actual, expected, \
+ boost::test_tools::percent_tolerance( tolerance ) ) ) )
+ MOCK_CONSTRAINT_EXT( close_fraction, 2, ( expected, tolerance ), \
( boost::test_tools::check_is_close( \
- actual, expected_0, \
- boost::test_tools::fraction_tolerance( expected_1 ) ) ) )
- MOCK_CONSTRAINT( 2, near, std::abs( actual - expected_0 ) < expected_1 )
+ actual, expected, \
+ boost::test_tools::fraction_tolerance( tolerance ) ) ) )
+ MOCK_CONSTRAINT_EXT( near, 2, ( expected, tolerance ), std::abs( actual - expected ) < tolerance )
namespace detail
{