iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tests/test-GenericBag.C
/*! @file
@author Shane Grant
@copyright GNU Public License (GPL v3)
@section License
@verbatim
// ////////////////////////////////////////////////////////////////////////
// The iLab Neuromorphic Robotics Toolkit (NRT) //
// Copyright 2010-2012 by the University of Southern California (USC) //
// and the iLab at USC. //
// //
// iLab - University of Southern California //
// Hedco Neurociences Building, Room HNB-10 //
// Los Angeles, Ca 90089-2520 - USA //
// //
// See http://ilab.usc.edu for information about this project. //
// ////////////////////////////////////////////////////////////////////////
// This file is part of The iLab Neuromorphic Robotics Toolkit. //
// //
// The iLab Neuromorphic Robotics Toolkit is free software: you can //
// redistribute it and/or modify it under the terms of the GNU General //
// Public License as published by the Free Software Foundation, either //
// version 3 of the License, or (at your option) any later version. //
// //
// The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
// that it will be useful, but WITHOUT ANY WARRANTY; without even the //
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
// PURPOSE. See the GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with The iLab Neuromorphic Robotics Toolkit. If not, see //
// <http://www.gnu.org/licenses/>. //
// ////////////////////////////////////////////////////////////////////////
@endverbatim */
template <class T>
struct AddFunctor
{
AddFunctor( T val ) : itsVal( val ) {}
template <class U>
U operator()( U const & val ) const
{
return val + itsVal;
}
const T itsVal;
};
template <class T>
struct InPlaceAdd
{
InPlaceAdd( T val ) : itsVal( val ) {}
template <class U>
void operator()( U & val ) const
{
val += itsVal;
}
const T itsVal;
};
struct DereferenceFunctor
{
template <class T> inline
T & operator()( T * ptr ) const
{
return *ptr;
}
};
using namespace nrt;
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE GenericBagTest
#include <boost/test/unit_test.hpp>
typedef GenericBag<int, bool> BagT1;
typedef GenericBag<float, int, double> BagT2;
typedef GenericBag<bool, int> BagT3;
typedef StreamableGenericBag<int, bool> SBagT1;
typedef StreamableGenericBag<float, int, double> SBagT2;
// ######################################################################
BOOST_AUTO_TEST_CASE( BasicGenericBagUse )
{
BagT1 bag1;
BagT2 bag2( 3.4f, 7, 8.3234 );
BagT3 bag3( true, 0 );
bag1.get<int>() = 4;
bag1.get<bool>() = false;
// Test type access
BOOST_CHECK_EQUAL( bag1.get<int>(), 4 );
BOOST_CHECK_EQUAL( bag1.get<bool>(), false );
// Test index access
BOOST_CHECK_EQUAL( bag1.get<0>(), 4 );
BOOST_CHECK_EQUAL( bag1.get<1>(), false );
// Basic assignment
bag1 = BagT1( bag2 );
BOOST_CHECK_EQUAL( bag1.get<int>(), 7 );
bag2 = bag3;
BOOST_CHECK_EQUAL( bag2.get<int>(), 0 );
bag1 = bag3;
BOOST_CHECK_EQUAL( bag1.get<bool>(), true );
BOOST_CHECK_EQUAL( bag1.get<int>(), 0 );
BOOST_CHECK_EQUAL( bag1.hasType<int>(), true );
BOOST_CHECK_EQUAL( bag1.hasType<float>(), false );
bool caught = false;
try
{
BOOST_CHECK_EQUAL( bag2.tryGet<float>(), 3.4f );
bag2.tryGet<bool>();
caught = false;
}
{
caught = true;
}
BOOST_CHECK_EQUAL( caught, true );
}
// ######################################################################
BOOST_AUTO_TEST_CASE( StreamableGenericBagGeneral )
{
BagT1 bag1( 3, true );
SBagT1 sbag1( bag1 );
SBagT2 sbag2( 3.0f, 2, 4.5 );
std::ostringstream stream;
BOOST_CHECK_EQUAL( sbag1.get<int>(), 3 );
stream << sbag1;
BOOST_CHECK_EQUAL( stream.str(), "3; 1" );
stream.clear(); stream.str("");
stream << sbag2;
BOOST_CHECK_EQUAL( stream.str(), "3; 2; 4.5" );
bag1 = sbag1;
BOOST_CHECK_EQUAL( bag1.get<int>(), 3 );
BOOST_CHECK_EQUAL( bag1.get<bool>(), true );
BagT1 temp1( sbag1 );
BOOST_CHECK_EQUAL( temp1.get<int>(), 3 );
BOOST_CHECK_EQUAL( temp1.get<bool>(), true );
SBagT1 temp2( sbag1 );
stream.clear(); stream.str("");
stream << temp2;
BOOST_CHECK_EQUAL( stream.str(), "3; 1" );
SBagT1 temp3( sbag2 );
stream.clear(); stream.str("");
stream << temp3;
BOOST_CHECK_EQUAL( stream.str(), "2; 0" );
SBagT1 temp4( std::move( bag1 ) );
stream.clear(); stream.str("");
stream << temp4;
BOOST_CHECK_EQUAL( stream.str(), "3; 1" );
SBagT1 temp5;
stream.clear(); stream.str("");
stream << temp5;
BOOST_CHECK_EQUAL( stream.str(), "0; 0" );
SBagT1 temp6;
BOOST_CHECK_EQUAL( temp6.get<int>(), 0 );
BOOST_CHECK_EQUAL( temp6.get<bool>(), 0 );
sbag1 = sbag1;
BOOST_CHECK_EQUAL( sbag1.get<int>(), 3 );
BOOST_CHECK_EQUAL( sbag1.get<bool>(), true );
sbag1 = SBagT1( sbag2 );
BOOST_CHECK_EQUAL( sbag1.get<int>(), 2 );
BOOST_CHECK_EQUAL( sbag1.get<bool>(), false );
sbag1 = SBagT1( sbag1 );
BOOST_CHECK_EQUAL( sbag1.get<int>(), 2 );
BOOST_CHECK_EQUAL( sbag1.get<bool>(), false );
BagT3 bag3( true, 0 );
sbag1 = bag3;
BOOST_CHECK_EQUAL( sbag1.get<int>(), 0 );
BOOST_CHECK_EQUAL( sbag1.get<bool>(), true );
sbag2 = sbag1;
stream.clear(); stream.str("");
stream << sbag2;
BOOST_CHECK_EQUAL( stream.str(), "3; 0; 4.5" );
std::istringstream is("3.9; 45; 524.234");
is >> sbag2;
stream.clear(); stream.str("");
stream << sbag2;
BOOST_CHECK_EQUAL( stream.str(), "3.9; 45; 524.234" );
}
// ######################################################################
BOOST_AUTO_TEST_CASE( ReferenceTypeTest )
{
typedef typename getReferenceType<int, int, const bool, float>::type intRef;
typedef typename getReferenceType<const int, int, const bool, float>::type intRef2;
typedef typename getReferenceType<bool, int, const bool, float>::type boolRef;
typedef typename getReferenceType<char, int, const bool, float>::type notFoundRef;
typedef typename getReferenceType<double, const double &>::type doubleRef;
BOOST_CHECK_EQUAL( (std::is_same<intRef, int&>::value), 1 );
BOOST_CHECK_EQUAL( (std::is_same<intRef2, int&>::value), 1 );
BOOST_CHECK_EQUAL( (std::is_same<boolRef, bool&>::value), 0 );
BOOST_CHECK_EQUAL( (std::is_same<boolRef, const bool&>::value), 1 );
BOOST_CHECK_EQUAL( (std::is_same<doubleRef, const double&>::value), 1 );
BOOST_CHECK_EQUAL( (std::is_reference<notFoundRef>::value), 0 );
}
// ######################################################################
BOOST_AUTO_TEST_CASE( TypeTestsGenericBag )
{
// Testing references
int testInt = 3;
GenericBag<int &> testBag( testInt );
BOOST_CHECK_EQUAL( testInt, testBag.get<int>() );
testBag.get<int>() = 7;
BOOST_CHECK_EQUAL( testInt, testBag.get<int>() );
BOOST_CHECK_EQUAL( testInt, 7 );
testBag.get<int&>() = 6;
BOOST_CHECK_EQUAL( testInt, testBag.get<int>() );
BOOST_CHECK_EQUAL( testInt, 6 );
testBag.get<int &&>() = 5;
BOOST_CHECK_EQUAL( testInt, testBag.get<int>() );
BOOST_CHECK_EQUAL( testInt, 5 );
GenericBag<int> testBagNoRef( 2 );
BOOST_CHECK_EQUAL( testBagNoRef.get<int>(), 2 );
BOOST_CHECK_EQUAL( testBagNoRef.get<int&>(), 2 );
BOOST_CHECK_EQUAL( testBagNoRef.get<const int>(), 2 );
BOOST_CHECK_EQUAL( testBagNoRef.get<const int &>(), 2 );
testBagNoRef = testBag;
BOOST_CHECK_EQUAL( testBagNoRef.get<int>(), testBag.get<int>() );
testBagNoRef.get<int>() = 3;
testBag.get<int>() = 4;
BOOST_CHECK_EQUAL( testBagNoRef.get<int>(), 3 );
BOOST_CHECK_EQUAL( testBag.get<int>(), 4 );
testBag = testBagNoRef;
BOOST_CHECK_EQUAL( testInt, testBag.get<int>() );
BOOST_CHECK_EQUAL( testInt, testBagNoRef.get<int>() );
// Test const stuff
GenericBag<int> nonConstBag( 3 );
GenericBag<const int> constBag( 4 );
//constBag = nonConstBag; // Not allowed!
//constBag.get<int>() = 3; // not allowed!
//constBag.get<const int>() = 3; // not allowed!
//constBag.get<const int &>() = 3; // not allowed!
nonConstBag = constBag;
BOOST_CHECK_EQUAL( nonConstBag.get<0>(), constBag.get<const int>() );
GenericBag<const int> constBag2( constBag );
BOOST_CHECK_EQUAL( constBag2.get<int>(), constBag.get<int>() );
GenericBag<const int> constBag3( GenericBag<int, const bool>( 3, true ) );
BOOST_CHECK_EQUAL( constBag3.get<int>(), 3 );
// Try creating ref bags from other bags
StreamableGenericBag<int, double> streamBag( 42, 4.2 );
GenericBag<int &, const double &> refBag( streamBag );
BOOST_CHECK_EQUAL( streamBag.get<double>(), refBag.get<double>() );
//refBag.get<double>() = 4.234; // not allowed
streamBag.get<double>() = 3.9;
BOOST_CHECK_EQUAL( refBag.get<double>(), 3.9 );
refBag.get<int>() = 32;
BOOST_CHECK_EQUAL( streamBag.get<int>(), 32 );
// the following won't compile because we don't have a match for one of the refs
// GenericBag<int &, const double &, char &> refBagError( streamBag ); // not allowed!
}
// ######################################################################
BOOST_AUTO_TEST_CASE( MoveTesting )
{
GenericBag<int> myBag( 3 );
GenericBag<int, double> myOtherBag( std::move( myBag ) );
BOOST_CHECK_EQUAL( myOtherBag.get<double>(), 0 );
BOOST_CHECK_EQUAL( myOtherBag.get<int>(), 3 );
StreamableGenericBag<double> streamableBag( GenericBag<char, double>( 'a', 3.2 ) );
BOOST_CHECK_EQUAL( streamableBag.get<double>(), 3.2 );
//GenericBag<int &> bagRef( GenericBag<int>( 3 ) ); // should not compile
GenericBag<int const &> bagRef( GenericBag<int>( 3 ) ); // OK since C++ allows const & to temporaries for whatever reason
GenericBag<int> bagFromEmpty( GenericBag<>{} );
StreamableGenericBag<int> bagFromEmpty2( GenericBag<>{} );
BOOST_CHECK_EQUAL( bagFromEmpty.get<int>(), 0 );
BOOST_CHECK_EQUAL( bagFromEmpty2.get<int>(), 0 );
int x = 3;
GenericBag<int&> bagMoveRef(x);
bagMoveRef = GenericBag<int>(4);
BOOST_CHECK_EQUAL( bagMoveRef.get<int>(), 4 );
}
// ######################################################################
BOOST_AUTO_TEST_CASE( FunctionTesting )
{
AddFunctor<int> myFunctor( 3 );
GenericBag<int, double> fbag( 3, 3.4 );
StreamableGenericBag<int,double> result;
result = fbag.applyFunction<int, double>( myFunctor );
BOOST_CHECK_EQUAL( fbag.get<int>() + 3, result.get<int>() );
result.applyFunctionInPlace( InPlaceAdd<int>( 3 ) );
BOOST_CHECK_EQUAL( fbag.get<int>() + 6, result.get<int>() );
int testX;
bool testY;
GenericBag<int *, bool *> testPtr( &testX, &testY );
auto testRefBag = testPtr.applyFunction<int&, bool&>( DereferenceFunctor() );
testY = true;
testRefBag.get<int>() = 3;
BOOST_CHECK_EQUAL( testRefBag.get<bool>(), true );
BOOST_CHECK_EQUAL( testRefBag.get<int>(), 3 );
BOOST_CHECK_EQUAL( testX, 3 );
BOOST_CHECK_EQUAL( testY, true );
}