Merge pull request #112 from Flamefire/improve_tests

Improve tests
This commit is contained in:
Alexander Grund 2022-02-10 17:45:17 +01:00 committed by GitHub
commit 90d9ac8055
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 276 additions and 99 deletions

View file

@ -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();
} }
} }
}; };

View file

@ -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);
} }

View file

@ -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

View file

@ -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();

View file

@ -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);
} }

View file

@ -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 )");
} }

View file

@ -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);
}

View file

@ -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)

View file

@ -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");
}