context/test/test_invoke.cpp
2015-12-11 19:44:11 +01:00

234 lines
5.1 KiB
C++

// Copyright Oliver Kowalke 2009.
// 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 <iostream>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <utility>
#include <boost/assert.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/context/detail/invoke.hpp>
#include <boost/context/detail/config.hpp>
namespace ctx = boost::context;
struct callable {
int k{ 0 };
callable() = default;
callable( int k_) :
k{ k_ } {
}
int foo( int i, int j) const {
return i + j + k;
}
int operator()( int i, int j) const {
return foo( i, j);
}
};
struct movable {
int k{ 0 };
movable() = default;
movable( int k_) :
k{ k_ } {
}
movable( movable const&) = delete;
movable & operator=( movable const&) = delete;
movable( movable && other) :
k{ other.k } {
other.k = -1;
}
movable & operator=( movable && other) {
if ( this == & other) return * this;
k = other.k;
other.k = -1;
return * this;
}
int foo( int i, int j) const {
return i + j + k;
}
int operator()( int i, int j) const {
return foo( i, j);
}
};
int fn1( int i, int j) {
return i + j;
}
int * fn2( int * ip) {
return ip;
}
int * fn3( int & ir) {
return & ir;
}
int & fn4( int & ir) {
return ir;
}
template< typename T >
int fn5( int i, T && t_) {
T t = std::forward< T >( t_);
return i + t.k;
}
void test1() {
int result = ctx::detail::invoke( fn1, 1, 2);
BOOST_CHECK_EQUAL( result, 3);
}
void test2() {
{
int i = 3;
int * ip = & i;
int * result = ctx::detail::invoke( fn2, ip);
BOOST_CHECK_EQUAL( result, ip);
BOOST_CHECK_EQUAL( * result, i);
}
{
int i = 3;
int * result = ctx::detail::invoke( fn2, & i);
BOOST_CHECK_EQUAL( result, & i);
BOOST_CHECK_EQUAL( * result, i);
}
}
void test3() {
{
int i = 3;
int & ir = i;
int * result = ctx::detail::invoke( fn3, ir);
BOOST_CHECK_EQUAL( result, & ir);
BOOST_CHECK_EQUAL( * result, i);
}
{
int i = 3;
int * result = ctx::detail::invoke( fn3, i);
BOOST_CHECK_EQUAL( result, & i);
BOOST_CHECK_EQUAL( * result, i);
}
}
void test4() {
{
int i = 3;
int & ir = i;
int & result = ctx::detail::invoke( fn4, ir);
BOOST_CHECK_EQUAL( result, ir);
BOOST_CHECK_EQUAL( & result, & ir);
BOOST_CHECK_EQUAL( result, i);
}
{
int i = 3;
int & result = ctx::detail::invoke( fn4, i);
BOOST_CHECK_EQUAL( & result, & i);
BOOST_CHECK_EQUAL( result, i);
}
}
void test5() {
{
callable c( 5);
int result = ctx::detail::invoke( fn5< callable >, 1, std::move( c) );
BOOST_CHECK_EQUAL( result, 6);
BOOST_CHECK_EQUAL( c.k, 5);
}
{
movable m( 5);
int result = ctx::detail::invoke( fn5< movable >, 1, std::move( m) );
BOOST_CHECK_EQUAL( result, 6);
BOOST_CHECK_EQUAL( m.k, -1);
}
}
void test6() {
{
callable c;
int result = ctx::detail::invoke( c, 1, 2);
BOOST_CHECK_EQUAL( result, 3);
BOOST_CHECK_EQUAL( c.k, 0);
}
{
callable c;
int result = ctx::detail::invoke( & callable::foo, c, 1, 2);
BOOST_CHECK_EQUAL( result, 3);
BOOST_CHECK_EQUAL( c.k, 0);
}
}
void test7() {
{
int result = ctx::detail::invoke( movable{}, 1, 2);
BOOST_CHECK_EQUAL( result, 3);
}
{
int result = ctx::detail::invoke( & movable::foo, movable{}, 1, 2);
BOOST_CHECK_EQUAL( result, 3);
}
}
template< typename R, typename Fn, typename ... Args >
R apply( Fn && fn, Args && ... args) {
return ctx::detail::invoke(
std::forward< Fn >( fn),
std::forward< Args >( args) ... );
}
void test8() {
{
int result = apply< int >( fn1, 1, 2);
BOOST_CHECK_EQUAL( result, 3);
}
{
int i = 3;
int & ir = i;
int * result = apply< int * >( fn3, ir);
BOOST_CHECK_EQUAL( result, & ir);
BOOST_CHECK_EQUAL( * result, i);
}
{
movable m( 5);
int result = apply< int >( fn5< movable >, 1, std::move( m) );
BOOST_CHECK_EQUAL( result, 6);
BOOST_CHECK_EQUAL( m.k, -1);
}
}
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
{
boost::unit_test::test_suite * test =
BOOST_TEST_SUITE("Boost.Context: invoke test suite");
test->add( BOOST_TEST_CASE( & test1) );
test->add( BOOST_TEST_CASE( & test2) );
test->add( BOOST_TEST_CASE( & test3) );
test->add( BOOST_TEST_CASE( & test4) );
test->add( BOOST_TEST_CASE( & test5) );
test->add( BOOST_TEST_CASE( & test6) );
test->add( BOOST_TEST_CASE( & test7) );
test->add( BOOST_TEST_CASE( & test8) );
return test;
}