mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
commit
90d9ac8055
9 changed files with 276 additions and 99 deletions
|
|
@ -27,16 +27,25 @@ namespace mock { namespace detail {
|
||||||
functor()
|
functor()
|
||||||
{
|
{
|
||||||
scoped_lock _(functor_mutex);
|
scoped_lock _(functor_mutex);
|
||||||
static functor* f = 0;
|
// MOCK_FUNCTOR creates 2 functor objects:
|
||||||
|
// The user-usable one with the passed name and a 2nd used by MOCK_EXPECT with a suffixed name
|
||||||
|
// We need the 2nd to be a copy of the first and use a static variable for storing a pointer to the first
|
||||||
|
static functor* f = nullptr;
|
||||||
if(f)
|
if(f)
|
||||||
{
|
{
|
||||||
*this = *f;
|
// Release the lock from the first call (see below) so other threads can create functors again
|
||||||
f = 0;
|
// after the function exits (the scoped_lock still holds the mutex)
|
||||||
functor_mutex.unlock();
|
functor_mutex.unlock();
|
||||||
|
// Copy the first functor to the current (2nd) one
|
||||||
|
*this = *f;
|
||||||
|
f = nullptr;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
functor_mutex.lock();
|
// This is the first object, store its pointer
|
||||||
f = this;
|
f = this;
|
||||||
|
// Lock the mutex again so only this thread can create new instances of a functor
|
||||||
|
// making sure that we copy the right instance above and not one from a concurrent thread
|
||||||
|
functor_mutex.lock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,7 @@ namespace mock { namespace detail {
|
||||||
};
|
};
|
||||||
std::unique_ptr<const char, Deleter> demangled(abi::__cxa_demangle(name, 0, 0, &status));
|
std::unique_ptr<const char, Deleter> demangled(abi::__cxa_demangle(name, 0, 0, &status));
|
||||||
if(!status && demangled)
|
if(!status && demangled)
|
||||||
serialize(s, demangled.get());
|
name = demangled.get();
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
serialize(s, name);
|
serialize(s, name);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ foreach(testFile IN LISTS testFiles)
|
||||||
target_compile_definitions(${name}_use_conversions PRIVATE MOCK_USE_CONVERSIONS)
|
target_compile_definitions(${name}_use_conversions PRIVATE MOCK_USE_CONVERSIONS)
|
||||||
|
|
||||||
target_link_libraries(${name}_thread_safe PRIVATE Boost::thread)
|
target_link_libraries(${name}_thread_safe PRIVATE Boost::thread)
|
||||||
target_compile_definitions(${name}_thread_safe PRIVATE MOCK_THREAD_SAFE BOOST_THREAD_USES_MOVE)
|
target_compile_definitions(${name}_thread_safe PRIVATE MOCK_THREAD_SAFE)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Link test only to check for a regression
|
# Link test only to check for a regression
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "../undefined.hpp"
|
#include "../undefined.hpp"
|
||||||
#include <turtle/constraints.hpp>
|
#include <turtle/constraints.hpp>
|
||||||
#include <turtle/detail/function.hpp>
|
#include <turtle/detail/function.hpp>
|
||||||
|
#include <turtle/detail/void_t.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -24,6 +25,42 @@ static_assert(std::is_same<void, decltype(mock::detail::function<void()>{}())>::
|
||||||
static_assert(std::is_same<int, decltype(mock::detail::function<int()>{}())>::value, "!");
|
static_assert(std::is_same<int, decltype(mock::detail::function<int()>{}())>::value, "!");
|
||||||
static_assert(std::is_same<void, decltype(mock::detail::function<void(float)>{}(std::declval<float>()))>::value, "!");
|
static_assert(std::is_same<void, decltype(mock::detail::function<void(float)>{}(std::declval<float>()))>::value, "!");
|
||||||
static_assert(std::is_same<int, decltype(mock::detail::function<int(float)>{}(std::declval<float>()))>::value, "!");
|
static_assert(std::is_same<int, decltype(mock::detail::function<int(float)>{}(std::declval<float>()))>::value, "!");
|
||||||
|
|
||||||
|
template<class TFunction, typename... TParams>
|
||||||
|
using with_call_t = decltype(std::declval<TFunction>().expect().with(std::declval<TParams>()...));
|
||||||
|
template<class AlwaysVoid, class TFunction, typename... TParams>
|
||||||
|
struct with_is_callable : std::false_type
|
||||||
|
{};
|
||||||
|
template<class TFunction, class... TParams>
|
||||||
|
struct with_is_callable<mock::detail::void_t<with_call_t<TFunction, TParams...>>, TFunction, TParams...> :
|
||||||
|
std::true_type
|
||||||
|
{};
|
||||||
|
// Detect if we can call function.expect().with(params)
|
||||||
|
template<class TFunction, class... TParams>
|
||||||
|
using with_is_callable_t = with_is_callable<void, TFunction, TParams...>;
|
||||||
|
|
||||||
|
// For function with no parameters `with` can never be called
|
||||||
|
using function_0_args = mock::detail::function<int()>;
|
||||||
|
static_assert(!with_is_callable_t<function_0_args>::value, "Can't call with()");
|
||||||
|
static_assert(!with_is_callable_t<function_0_args, int>::value, "Can't call with(int)");
|
||||||
|
static_assert(!with_is_callable_t<function_0_args, bool()>::value, "Can't call with custom constraint");
|
||||||
|
|
||||||
|
// For functions with parameters `with` can be called with a custom constraint (taking all params)
|
||||||
|
// or exactly as many parameters as the function has (here 1 and 4 respectively)
|
||||||
|
using function_1_args = mock::detail::function<int(int)>;
|
||||||
|
static_assert(!with_is_callable_t<function_1_args>::value, "Can't call with()");
|
||||||
|
static_assert(with_is_callable_t<function_1_args, int>::value, "Can call with(int)");
|
||||||
|
static_assert(with_is_callable_t<function_1_args, bool(int)>::value, "Can call with custom constraint");
|
||||||
|
static_assert(!with_is_callable_t<function_1_args, int, int>::value, "Can't call with(int, int)");
|
||||||
|
|
||||||
|
using function_4_args = mock::detail::function<int(int, int, int, int)>;
|
||||||
|
static_assert(!with_is_callable_t<function_4_args>::value, "Can't call with()");
|
||||||
|
static_assert(with_is_callable_t<function_4_args, bool(int, int, int, int)>::value, "Can call with custom constraint");
|
||||||
|
static_assert(!with_is_callable_t<function_4_args, int, int>::value, "Can't call with(int, int)");
|
||||||
|
static_assert(!with_is_callable_t<function_4_args, int, int, int>::value, "Can't call with(int, int, int)");
|
||||||
|
static_assert(with_is_callable_t<function_4_args, int, int, int, int>::value, "Can call with(int, int, int, int)");
|
||||||
|
static_assert(!with_is_callable_t<function_4_args, int, int, int, int, int>::value,
|
||||||
|
"Can't call with(int, int, int, int, int)");
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// functor
|
// functor
|
||||||
|
|
@ -714,11 +751,18 @@ BOOST_FIXTURE_TEST_CASE(expectation_can_be_serialized_to_be_human_readable, mock
|
||||||
{
|
{
|
||||||
mock::detail::function<void(int)> f;
|
mock::detail::function<void(int)> f;
|
||||||
f.expect().once().with(1);
|
f.expect().once().with(1);
|
||||||
f.expect().once().with(2);
|
f.expect().once().with(mock::close(3, 1));
|
||||||
|
int target = 0;
|
||||||
|
f.expect().once().with(mock::retrieve(target));
|
||||||
|
f.expect().once().with(mock::same(target));
|
||||||
BOOST_CHECK_NO_THROW(f(2));
|
BOOST_CHECK_NO_THROW(f(2));
|
||||||
const std::string expected = "?\n"
|
std::string expected = "?\n"; // Not in a current call context
|
||||||
". once().with( 1 )\n"
|
expected += ". once().with( 1 )\n"; // Unmet/Unverified expectation with value
|
||||||
"v once().with( 2 )";
|
expected += "v once().with( close( 3, 1 ) )\n"; // Verified expectation with constraint
|
||||||
|
target = 42;
|
||||||
|
// (Unverified) expectation with retrieve/same constraint print current value
|
||||||
|
expected += ". once().with( retrieve( 42 ) )\n";
|
||||||
|
expected += ". once().with( same( 42 ) )";
|
||||||
BOOST_CHECK_EQUAL(expected, to_string(f));
|
BOOST_CHECK_EQUAL(expected, to_string(f));
|
||||||
CHECK_CALLS(1);
|
CHECK_CALLS(1);
|
||||||
f.reset();
|
f.reset();
|
||||||
|
|
|
||||||
|
|
@ -8,69 +8,113 @@
|
||||||
|
|
||||||
#include <turtle/detail/invocation.hpp>
|
#include <turtle/detail/invocation.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
/// Serialize using the base class as done by e.g. the expectation class
|
||||||
|
std::string to_string(const mock::detail::invocation& invocation)
|
||||||
|
{
|
||||||
|
std::ostringstream s;
|
||||||
|
s << invocation;
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(unlimited)
|
BOOST_AUTO_TEST_CASE(unlimited)
|
||||||
{
|
{
|
||||||
mock::detail::unlimited invocation;
|
mock::detail::unlimited invocation;
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(invocation.verify());
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(!invocation.exhausted());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(invocation.invoke());
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(invocation.verify());
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(!invocation.exhausted());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(invocation.invoke());
|
||||||
|
BOOST_TEST(to_string(invocation) == "unlimited()");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(once)
|
BOOST_AUTO_TEST_CASE(once)
|
||||||
{
|
{
|
||||||
mock::detail::once invocation;
|
mock::detail::once invocation;
|
||||||
BOOST_CHECK(!invocation.verify());
|
BOOST_TEST(!invocation.verify());
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(!invocation.exhausted());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(invocation.invoke());
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(invocation.verify());
|
||||||
BOOST_CHECK(invocation.exhausted());
|
BOOST_TEST(invocation.exhausted());
|
||||||
BOOST_CHECK(!invocation.invoke());
|
BOOST_TEST(!invocation.invoke());
|
||||||
|
BOOST_TEST(to_string(invocation) == "once()");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(never)
|
BOOST_AUTO_TEST_CASE(never)
|
||||||
{
|
{
|
||||||
mock::detail::never invocation;
|
mock::detail::never invocation;
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(invocation.verify());
|
||||||
BOOST_CHECK(invocation.exhausted());
|
BOOST_TEST(invocation.exhausted());
|
||||||
BOOST_CHECK(!invocation.invoke());
|
BOOST_TEST(!invocation.invoke());
|
||||||
|
BOOST_TEST(to_string(invocation) == "never()");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(at_most)
|
BOOST_AUTO_TEST_CASE(at_most)
|
||||||
{
|
{
|
||||||
mock::detail::at_most invocation(1);
|
mock::detail::at_most invocation(1);
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(to_string(invocation) == "at_most( 0/1 )");
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(invocation.verify());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(!invocation.exhausted());
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(invocation.invoke());
|
||||||
BOOST_CHECK(invocation.exhausted());
|
BOOST_TEST(to_string(invocation) == "at_most( 1/1 )");
|
||||||
BOOST_CHECK(!invocation.invoke());
|
BOOST_TEST(invocation.verify());
|
||||||
|
BOOST_TEST(invocation.exhausted());
|
||||||
|
BOOST_TEST(!invocation.invoke());
|
||||||
|
BOOST_TEST(to_string(invocation) == "at_most( 1/1 )");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(at_least)
|
BOOST_AUTO_TEST_CASE(at_least)
|
||||||
{
|
{
|
||||||
mock::detail::at_least invocation(1);
|
mock::detail::at_least invocation(1);
|
||||||
BOOST_CHECK(!invocation.verify());
|
BOOST_TEST(to_string(invocation) == "at_least( 0/1 )");
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(!invocation.verify());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(!invocation.exhausted());
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(invocation.invoke());
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(invocation.verify());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(to_string(invocation) == "at_least( 1/1 )");
|
||||||
|
BOOST_TEST(!invocation.exhausted());
|
||||||
|
BOOST_TEST(invocation.invoke());
|
||||||
|
BOOST_TEST(invocation.verify());
|
||||||
|
BOOST_TEST(to_string(invocation) == "at_least( 2/1 )");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(between)
|
BOOST_AUTO_TEST_CASE(between)
|
||||||
|
{
|
||||||
{
|
{
|
||||||
mock::detail::between invocation(1, 2);
|
mock::detail::between invocation(1, 2);
|
||||||
BOOST_CHECK(!invocation.verify());
|
BOOST_TEST(to_string(invocation) == "between( 0/[1,2] )");
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(!invocation.verify());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(!invocation.exhausted());
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(invocation.invoke());
|
||||||
BOOST_CHECK(!invocation.exhausted());
|
BOOST_TEST(invocation.verify());
|
||||||
BOOST_CHECK(invocation.invoke());
|
BOOST_TEST(to_string(invocation) == "between( 1/[1,2] )");
|
||||||
BOOST_CHECK(invocation.verify());
|
BOOST_TEST(!invocation.exhausted());
|
||||||
BOOST_CHECK(invocation.exhausted());
|
BOOST_TEST(invocation.invoke());
|
||||||
BOOST_CHECK(!invocation.invoke());
|
BOOST_TEST(invocation.verify());
|
||||||
|
BOOST_TEST(to_string(invocation) == "between( 2/[1,2] )");
|
||||||
|
BOOST_TEST(invocation.exhausted());
|
||||||
|
BOOST_TEST(!invocation.invoke());
|
||||||
|
BOOST_TEST(to_string(invocation) == "between( 2/[1,2] )");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
mock::detail::between invocation(2, 2);
|
||||||
|
BOOST_TEST(to_string(invocation) == "between( 0/[2,2] )");
|
||||||
|
BOOST_TEST(!invocation.verify());
|
||||||
|
BOOST_TEST(!invocation.exhausted());
|
||||||
|
BOOST_TEST(invocation.invoke());
|
||||||
|
BOOST_TEST(!invocation.verify());
|
||||||
|
BOOST_TEST(to_string(invocation) == "between( 1/[2,2] )");
|
||||||
|
BOOST_TEST(!invocation.exhausted());
|
||||||
|
BOOST_TEST(invocation.invoke());
|
||||||
|
BOOST_TEST(invocation.verify());
|
||||||
|
BOOST_TEST(to_string(invocation) == "between( 2/[2,2] )");
|
||||||
|
BOOST_TEST(invocation.exhausted());
|
||||||
|
BOOST_TEST(!invocation.invoke());
|
||||||
|
BOOST_TEST(to_string(invocation) == "between( 2/[2,2] )");
|
||||||
|
}
|
||||||
|
|
||||||
|
// First must be equal or less than 2nd
|
||||||
|
BOOST_CHECK_THROW(mock::detail::between invalid(2, 1), std::invalid_argument);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,39 @@
|
||||||
|
|
||||||
#include <turtle/constraint.hpp>
|
#include <turtle/constraint.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
MOCK_CONSTRAINT(constraint_0, actual == 0)
|
MOCK_CONSTRAINT(constraint_0, actual == 0)
|
||||||
MOCK_CONSTRAINT(constraint_1, expected, actual == expected)
|
MOCK_CONSTRAINT(constraint_1, expected, actual == expected)
|
||||||
MOCK_CONSTRAINT(constraint_2, expected_0, expected_1, actual == expected_0 || actual == expected_1)
|
MOCK_CONSTRAINT(constraint_2, expected_0, expected_1, actual == expected_0 || actual == expected_1)
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::string to_string(const mock::constraint<T>& t)
|
||||||
|
{
|
||||||
|
std::ostringstream s;
|
||||||
|
s << t.c_;
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(mock_constraint_is_supported_by_compilers_with_variadic_macros)
|
BOOST_AUTO_TEST_CASE(mock_constraint_works_for_0_to_2_args)
|
||||||
{
|
{
|
||||||
BOOST_CHECK(constraint_0.c_(0));
|
BOOST_TEST(constraint_0.c_(0));
|
||||||
BOOST_CHECK(constraint_1(0).c_(0));
|
BOOST_TEST(!constraint_0.c_(42));
|
||||||
BOOST_CHECK(constraint_2(0, 0).c_(0));
|
|
||||||
|
BOOST_TEST(constraint_1(0).c_(0));
|
||||||
|
BOOST_TEST(!constraint_1(1).c_(0));
|
||||||
|
BOOST_TEST(!constraint_1(42).c_(1337));
|
||||||
|
|
||||||
|
BOOST_TEST(constraint_2(42, 1337).c_(42));
|
||||||
|
BOOST_TEST(constraint_2(42, 1337).c_(1337));
|
||||||
|
BOOST_TEST(!constraint_2(42, 1337).c_(99));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(mock_constraint_outputs_human_readable_representation)
|
||||||
|
{
|
||||||
|
BOOST_TEST(to_string(constraint_0) == "constraint_0");
|
||||||
|
BOOST_TEST(to_string(constraint_1(42)) == "constraint_1( 42 )");
|
||||||
|
BOOST_TEST(to_string(constraint_2(42, 1337)) == "constraint_2( 42, 1337 )");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -726,12 +726,12 @@ BOOST_FIXTURE_TEST_CASE(std_unique_ptr_argument_is_supported_in_retrieve_constra
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::unique_ptr<int> i;
|
std::unique_ptr<int> i;
|
||||||
MOCK_FUNCTOR(f, void(std::unique_ptr<int>));
|
MOCK_FUNCTOR(f, void(std::unique_ptr<int>, std::unique_ptr<int>, std::unique_ptr<int>));
|
||||||
MOCK_EXPECT(f).once().with(nullptr);
|
MOCK_EXPECT(f).once().with(nullptr, nullptr, nullptr);
|
||||||
MOCK_EXPECT(f).once().with(mock::retrieve(i));
|
MOCK_EXPECT(f).once().with(nullptr, mock::retrieve(i), nullptr);
|
||||||
f(0);
|
f(nullptr, nullptr, nullptr);
|
||||||
std::unique_ptr<int> j(new int(7));
|
std::unique_ptr<int> j(new int(7));
|
||||||
f(std::move(j));
|
f(nullptr, std::move(j), nullptr);
|
||||||
BOOST_CHECK(!j);
|
BOOST_CHECK(!j);
|
||||||
BOOST_REQUIRE(i);
|
BOOST_REQUIRE(i);
|
||||||
BOOST_CHECK_EQUAL(7, *i);
|
BOOST_CHECK_EQUAL(7, *i);
|
||||||
|
|
@ -745,3 +745,20 @@ struct my_unique_ptr_class
|
||||||
MOCK_METHOD(m, 1, void(std::unique_ptr<int>), m)
|
MOCK_METHOD(m, 1, void(std::unique_ptr<int>), m)
|
||||||
MOCK_STATIC_METHOD(ms, 1, void(std::unique_ptr<int>), ms)
|
MOCK_STATIC_METHOD(ms, 1, void(std::unique_ptr<int>), ms)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(unique_ptr_works_in_class, mock_error_fixture)
|
||||||
|
{
|
||||||
|
MOCK_EXPECT(my_unique_ptr_class::constructor).once().with(nullptr);
|
||||||
|
MOCK_EXPECT(my_unique_ptr_class::ms).once().with(7);
|
||||||
|
my_unique_ptr_class instance(nullptr);
|
||||||
|
auto j = std::make_unique<int>(7);
|
||||||
|
my_unique_ptr_class::ms(std::move(j));
|
||||||
|
BOOST_TEST(!j); // Otherwise it wasn't a value parameter and we leak memory
|
||||||
|
MOCK_EXPECT(instance.ms).once().with(42);
|
||||||
|
j = std::make_unique<int>(42);
|
||||||
|
instance.ms(std::move(j));
|
||||||
|
BOOST_TEST(!j); // Same here
|
||||||
|
|
||||||
|
BOOST_TEST(mock::verify());
|
||||||
|
CHECK_CALLS(3);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,18 +32,23 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// Convention:
|
||||||
|
// "Serializable: Implements operator<<(std::ostream&, ...)
|
||||||
|
// "Streamable": Implements operator<<(mock::stream&, ...)
|
||||||
|
// "Mock Streamable": Implements operator<<(stream&, ...) in namespace mock
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::string to_string(const T& t)
|
std::string to_string(const T& t)
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::ostringstream s;
|
||||||
s << mock::format(t);
|
s << mock::format(t);
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::string to_string(T* t)
|
std::string to_string(T* t)
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::ostringstream s;
|
||||||
s << mock::format(t);
|
s << mock::format(t);
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +61,6 @@ BOOST_AUTO_TEST_CASE(pointer_yields_its_value_when_serialized)
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << &i;
|
s << &i;
|
||||||
const std::string pointerValue = s.str();
|
const std::string pointerValue = s.str();
|
||||||
BOOST_CHECK_NE("?", to_string(&i));
|
|
||||||
BOOST_CHECK_EQUAL(pointerValue, to_string(&i));
|
BOOST_CHECK_EQUAL(pointerValue, to_string(&i));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +68,6 @@ BOOST_AUTO_TEST_CASE(pointer_yields_its_value_when_serialized)
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << &i;
|
s << &i;
|
||||||
const std::string pointerValue = s.str();
|
const std::string pointerValue = s.str();
|
||||||
BOOST_CHECK_NE("?", to_string(&i));
|
|
||||||
BOOST_CHECK_EQUAL(pointerValue, to_string(&i));
|
BOOST_CHECK_EQUAL(pointerValue, to_string(&i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -178,6 +181,19 @@ BOOST_AUTO_TEST_CASE(type_derived_from_streamable_yields_a_question_mark_when_se
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Class which can be converted to many other types making implicit conversions ambiguous
|
||||||
|
struct ambiguous_convertible
|
||||||
|
{
|
||||||
|
operator float() const;
|
||||||
|
operator int() const;
|
||||||
|
operator serializable() const;
|
||||||
|
operator streamable() const;
|
||||||
|
template<typename T>
|
||||||
|
operator T() const;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
#ifndef MOCK_USE_CONVERSIONS // all this does not compile with conversions activated, which is precisely the purpose of
|
#ifndef MOCK_USE_CONVERSIONS // all this does not compile with conversions activated, which is precisely the purpose of
|
||||||
// having this compilation flag
|
// having this compilation flag
|
||||||
|
|
||||||
|
|
@ -217,33 +233,14 @@ BOOST_AUTO_TEST_CASE(type_convertible_to_streamable_yields_a_question_mark_when_
|
||||||
BOOST_CHECK_EQUAL("?", to_string(convertible_to_streamable()));
|
BOOST_CHECK_EQUAL("?", to_string(convertible_to_streamable()));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct ambiguous_convertible
|
|
||||||
{
|
|
||||||
operator float() const;
|
|
||||||
operator int() const;
|
|
||||||
operator serializable() const;
|
|
||||||
operator streamable() const;
|
|
||||||
template<typename T>
|
|
||||||
operator T() const;
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(type_ambiguous_convertible_yields_a_question_mark_when_serialized)
|
BOOST_AUTO_TEST_CASE(type_ambiguous_convertible_yields_a_question_mark_when_serialized)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL("?", to_string(ambiguous_convertible()));
|
BOOST_CHECK_EQUAL("?", to_string(ambiguous_convertible()));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct ambiguous_convertible_serializable
|
struct ambiguous_convertible_serializable : public ambiguous_convertible
|
||||||
{
|
{};
|
||||||
operator float() const;
|
|
||||||
operator int() const;
|
|
||||||
operator serializable() const;
|
|
||||||
operator streamable() const;
|
|
||||||
template<typename T>
|
|
||||||
operator T() const;
|
|
||||||
};
|
|
||||||
std::ostream& operator<<(std::ostream& s, const ambiguous_convertible_serializable&)
|
std::ostream& operator<<(std::ostream& s, const ambiguous_convertible_serializable&)
|
||||||
{
|
{
|
||||||
return s << "ambiguous_convertible_serializable";
|
return s << "ambiguous_convertible_serializable";
|
||||||
|
|
@ -258,15 +255,8 @@ BOOST_AUTO_TEST_CASE(type_convertible_serializable_yields_its_value_when_seriali
|
||||||
#endif // MOCK_USE_CONVERSIONS
|
#endif // MOCK_USE_CONVERSIONS
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct ambiguous_convertible_streamable
|
struct ambiguous_convertible_streamable : public ambiguous_convertible
|
||||||
{
|
{};
|
||||||
operator float() const;
|
|
||||||
operator int() const;
|
|
||||||
operator serializable() const;
|
|
||||||
operator streamable() const;
|
|
||||||
template<typename T>
|
|
||||||
operator T() const;
|
|
||||||
};
|
|
||||||
BOOST_ATTRIBUTE_UNUSED std::ostream& operator<<(std::ostream& s, const ambiguous_convertible_streamable&)
|
BOOST_ATTRIBUTE_UNUSED std::ostream& operator<<(std::ostream& s, const ambiguous_convertible_streamable&)
|
||||||
{
|
{
|
||||||
BOOST_FAIL("should not have been called");
|
BOOST_FAIL("should not have been called");
|
||||||
|
|
@ -435,17 +425,17 @@ BOOST_AUTO_TEST_CASE(std_vectors_are_serialized)
|
||||||
BOOST_AUTO_TEST_CASE(std_maps_are_serialized)
|
BOOST_AUTO_TEST_CASE(std_maps_are_serialized)
|
||||||
{
|
{
|
||||||
std::map<int, std::string> m;
|
std::map<int, std::string> m;
|
||||||
m[12] = "12";
|
m[12] = "15";
|
||||||
m[42] = "42";
|
m[42] = "46";
|
||||||
BOOST_CHECK_EQUAL("((12,\"12\"),(42,\"42\"))", to_string(m));
|
BOOST_CHECK_EQUAL("((12,\"15\"),(42,\"46\"))", to_string(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(std_multimaps_are_serialized)
|
BOOST_AUTO_TEST_CASE(std_multimaps_are_serialized)
|
||||||
{
|
{
|
||||||
std::multimap<int, std::string> m;
|
std::multimap<int, std::string> m;
|
||||||
m.insert(std::make_pair(12, "12"));
|
m.insert(std::make_pair(12, "15"));
|
||||||
m.insert(std::make_pair(42, "42"));
|
m.insert(std::make_pair(42, "46"));
|
||||||
BOOST_CHECK_EQUAL("((12,\"12\"),(42,\"42\"))", to_string(m));
|
BOOST_CHECK_EQUAL("((12,\"15\"),(42,\"46\"))", to_string(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(std_sets_are_serialized)
|
BOOST_AUTO_TEST_CASE(std_sets_are_serialized)
|
||||||
|
|
@ -495,7 +485,7 @@ BOOST_AUTO_TEST_CASE(boost_assign_list_of_are_serialized)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(boost_assign_map_list_of_are_serialized)
|
BOOST_AUTO_TEST_CASE(boost_assign_map_list_of_are_serialized)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL("((12,\"12\"),(42,\"42\"))", to_string(boost::assign::map_list_of(12, "12")(42, "42")));
|
BOOST_CHECK_EQUAL("((12,\"16\"),(42,\"43\"))", to_string(boost::assign::map_list_of(12, "16")(42, "43")));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(std_reference_wrappers_are_serialized)
|
BOOST_AUTO_TEST_CASE(std_reference_wrappers_are_serialized)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
#include <turtle/detail/function.hpp>
|
#include <turtle/detail/function.hpp>
|
||||||
|
#include <turtle/matcher.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template<typename Expected, typename Actual>
|
template<typename Expected, typename Actual>
|
||||||
|
|
@ -72,3 +74,52 @@ BOOST_FIXTURE_TEST_CASE(const_char_pointer_and_std_string_can_be_compared, fixtu
|
||||||
BOOST_CHECK(match(std::string("same text"), actual));
|
BOOST_CHECK(match(std::string("same text"), actual));
|
||||||
BOOST_CHECK(!match(std::string("different text"), actual));
|
BOOST_CHECK(!match(std::string("different text"), actual));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<typename T>
|
||||||
|
std::string serialize(const T& t)
|
||||||
|
{
|
||||||
|
std::ostringstream s;
|
||||||
|
s << t;
|
||||||
|
return s.str();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(default_matcher_is_serialized_to_any)
|
||||||
|
{
|
||||||
|
using mock::detail::default_matcher;
|
||||||
|
BOOST_TEST(serialize(default_matcher<void()>{}) == "");
|
||||||
|
BOOST_TEST(serialize(default_matcher<void(int)>{}) == "any");
|
||||||
|
BOOST_TEST(serialize(default_matcher<void(int, int)>{}) == "any, any");
|
||||||
|
BOOST_TEST(serialize(default_matcher<void(int, int, int, int, int)>{}) == "any, any, any, any, any");
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct custom_constraint
|
||||||
|
{
|
||||||
|
int expected_ = 42;
|
||||||
|
custom_constraint(int expected = 42) : expected_(expected) {}
|
||||||
|
friend std::ostream& operator<<(std::ostream& s, const custom_constraint& c)
|
||||||
|
{
|
||||||
|
return s << "custom" << c.expected_;
|
||||||
|
}
|
||||||
|
bool operator()(int actual) { return actual == expected_; }
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(single_matcher_serializes)
|
||||||
|
{
|
||||||
|
using mock::detail::single_matcher;
|
||||||
|
BOOST_TEST(serialize(single_matcher<void(int), void(int)>(1)) == "1");
|
||||||
|
BOOST_TEST(serialize(single_matcher<void(int, int), void(int, int)>(1, 2)) == "1, 2");
|
||||||
|
BOOST_TEST(
|
||||||
|
serialize(
|
||||||
|
single_matcher<void(int, int, mock::constraint<custom_constraint>, int, int), void(int, int, int, int, int)>(
|
||||||
|
1, 2, custom_constraint(), 4, 5)) == "1, 2, custom42, 4, 5");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(multi_matcher_serializes)
|
||||||
|
{
|
||||||
|
using mock::detail::multi_matcher;
|
||||||
|
BOOST_TEST(serialize(multi_matcher<custom_constraint, void(int)>(custom_constraint(1337))) == "custom1337");
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue