WIP draft test helper for generating test cases (Cartesian product)
This commit is contained in:
parent
eb5e0ab9ff
commit
786ecbe829
7 changed files with 226 additions and 30 deletions
|
|
@ -25,7 +25,7 @@
|
|||
** Metaprogramming facilities to generate combination cases.
|
||||
** Similar to the plain typelist-based generators, a custom supplied
|
||||
** template will be instantiated with combinations of the parameter types
|
||||
** and then mixed into the resulting type
|
||||
** and then mixed into the resulting type
|
||||
**
|
||||
** @see generator-combinations-test.cpp
|
||||
** @see generator.hpp
|
||||
|
|
@ -54,40 +54,35 @@ namespace typelist{
|
|||
{ };
|
||||
|
||||
|
||||
template<class SUBLIST>
|
||||
struct PickFirst;
|
||||
|
||||
template<class TY, class TAIL>
|
||||
struct PickFirst<Node<TY,TAIL> >
|
||||
{
|
||||
typedef TY Type;
|
||||
};
|
||||
|
||||
|
||||
template<class SUBLIST>
|
||||
struct PickSecond;
|
||||
|
||||
template<class TY, class TAIL>
|
||||
struct PickSecond<Node<TY,TAIL> >
|
||||
{
|
||||
typedef typename PickFirst<TAIL>::Type Type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template< template<class,class,class> class _X_>
|
||||
struct PickParametersFromSublist
|
||||
{
|
||||
template<class SUBLIST, class BASE>
|
||||
struct CaseInstantiation
|
||||
: _X_< PickFirst<SUBLIST>::Type
|
||||
, PickSecond<SUBLIST>::Type
|
||||
struct SingleCaseInstantiation
|
||||
: _X_< Pick<SUBLIST,0>::Type
|
||||
, Pick<SUBLIST,1>::Type
|
||||
, BASE
|
||||
>
|
||||
{ };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Build a Case matrix.
|
||||
* The given parameter template _X_
|
||||
* will be instantiated for each possible combination
|
||||
* of the elements from both parameter type-lists.
|
||||
* All these instantiations will be chained up
|
||||
* into a linear inheritance chain rooted
|
||||
* at the BASE type.
|
||||
* @note the custom-supplied template _X_ needs to take a 3rd parameter,
|
||||
* and inherit from this parameter, in order to form that chain.
|
||||
* Typically you'll define some (static) functions within that
|
||||
* template, which then forward the call to the given BASE
|
||||
* (and of course, that BASE then needs to define this
|
||||
* function as well).
|
||||
*/
|
||||
template
|
||||
< class TYPES_1, class TYPES_2 ///< the two type collections to pick combinations from
|
||||
, template<class,class,class> class _X_ ///< template with two arg types and a base type
|
||||
|
|
@ -95,7 +90,7 @@ namespace typelist{
|
|||
>
|
||||
class InstantiateChainedCombinations
|
||||
: InstantiateChained< CartesianProduct<TYPES_1,TYPES_2>::List
|
||||
, PickParametersFromSublist<_X_>::template CaseInstantiation
|
||||
, PickParametersFromSublist<_X_>::template SingleCaseInstantiation
|
||||
, BASE
|
||||
>
|
||||
{ };
|
||||
|
|
|
|||
|
|
@ -97,6 +97,26 @@ namespace typelist{
|
|||
};
|
||||
|
||||
|
||||
/** pick the n-th element from a typelist */
|
||||
template<class TYPES, uint i>
|
||||
struct Pick
|
||||
{
|
||||
typedef NullType Type;
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct Pick<Node<TY,TYPES>, 0>
|
||||
{
|
||||
typedef TY Type;
|
||||
};
|
||||
template<class TY, class TYPES, uint i>
|
||||
struct Pick<Node<TY,TYPES>, i>
|
||||
{
|
||||
typedef typename Pick<TYPES, i-1>::Type Type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** apply a transformation (template) to each type in the list */
|
||||
template<class TY, template<class> class _TRANS_>
|
||||
struct Apply { typedef TY List; };
|
||||
|
|
|
|||
|
|
@ -38,6 +38,24 @@ namespace lumiera {
|
|||
|
||||
namespace typelist {
|
||||
|
||||
/** Compile-time Type equality:
|
||||
* Simple Trait template to pick up types considered
|
||||
* \em identical by the compiler.
|
||||
* @warning identical, not sub-type!
|
||||
*/
|
||||
template<typename T1, typename T2>
|
||||
class is_sameType
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_sameType<T,T>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
|
||||
/** semi-automatic detection if an instantiation is possible.
|
||||
* Requires help by the template to be tested, which needs to define
|
||||
* a typedef member \c is_defined. The embedded metafunction Test can be used
|
||||
|
|
|
|||
|
|
@ -1104,6 +1104,11 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "Typelist combinations generator" GeneratorCombinations_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "TypedAllocationManager" TypedAllocationManager_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
|
|
|||
137
tests/lib/meta/generator-combinations-test.cpp
Normal file
137
tests/lib/meta/generator-combinations-test.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
GeneratorCombinations(Test) - verify generating case combinations
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program 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 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/meta/generator.hpp"
|
||||
#include "lib/meta/generator-combinations.hpp"
|
||||
#include "meta/typelist-diagnostics.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using ::test::Test;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist{
|
||||
namespace test {
|
||||
|
||||
|
||||
namespace { // test cases and data....
|
||||
|
||||
typedef Types< Num<1>
|
||||
, Num<3>
|
||||
, Num<5>
|
||||
> Types1;
|
||||
typedef Types< Num<2>
|
||||
, Num<4>
|
||||
, Num<6>
|
||||
> Types2;
|
||||
|
||||
|
||||
using boost::str;
|
||||
using boost::format;
|
||||
format fmt ("-<%u%u>%s");
|
||||
|
||||
/**
|
||||
* A Test-Template to be instantiated
|
||||
* for all possible combinations
|
||||
* of the {Types1} x {Types2}
|
||||
*/
|
||||
template<class T1, class T2, class BASE>
|
||||
struct TestCase
|
||||
{
|
||||
static string
|
||||
visitAll()
|
||||
{
|
||||
T1 param1;
|
||||
T2 param2;
|
||||
return str(fmt % param1 % param2
|
||||
% BASE::visitAll());
|
||||
}
|
||||
};
|
||||
|
||||
struct TestCase<void,void,NullType>
|
||||
{
|
||||
static string
|
||||
visitAll()
|
||||
{
|
||||
return "-|";
|
||||
}
|
||||
};
|
||||
typedef TestCase<void,void,NullType> IterationEnd;
|
||||
|
||||
} // (End) test data
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* @test check utilities for generating case combinations.
|
||||
* - verify the Cartesian product is built properly
|
||||
* - instantiate a two-parameter test template
|
||||
* for all those cases, as given by the
|
||||
* Cartesian product of two Type collections
|
||||
*/
|
||||
class GeneratorCombinations_test : public Test
|
||||
{
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
checkCartesian();
|
||||
checkCaseInstantiation();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkCartesian ()
|
||||
{
|
||||
typedef CartesianProduct<Types1,Types2> Cartesian;
|
||||
DISPLAY (Cartesian);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkCaseInstantiation ()
|
||||
{
|
||||
typedef InstantiateChainedCombinations< Types1,Types2
|
||||
, TestCase
|
||||
, IterationEnd > CombnationCases;
|
||||
|
||||
cout << "All-Test-Combinations-" << CombnationCases::visitAll() << endl;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (GeneratorCombinations_test, "unit common");
|
||||
|
||||
|
||||
|
||||
}}} // namespace lumiera::typelist::test
|
||||
|
|
@ -200,10 +200,10 @@ namespace typelist{
|
|||
|
||||
|
||||
#define DISPLAY(NAME) \
|
||||
cout << STRINGIFY(NAME) << "\t:" << showType<NAME>() << "\n";
|
||||
cout << STRINGIFY(NAME) << "\t:" << showType<NAME>() << endl;
|
||||
|
||||
#define DUMPVAL(NAME) \
|
||||
cout << STRINGIFY(NAME) << "\t:" << showDump (NAME) << "\n";
|
||||
cout << STRINGIFY(NAME) << "\t:" << showDump (NAME) << endl;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -43,12 +43,11 @@
|
|||
#include "lib/meta/typelist-util.hpp"
|
||||
#include "meta/typelist-diagnostics.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using ::test::Test;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
|
|
@ -96,6 +95,7 @@ namespace test {
|
|||
run (Arg)
|
||||
{
|
||||
check_diagnostics ();
|
||||
check_pick_elm ();
|
||||
check_apply ();
|
||||
check_filter ();
|
||||
check_append ();
|
||||
|
|
@ -113,7 +113,7 @@ namespace test {
|
|||
{
|
||||
// Explanation: the DISPLAY macro results in the following definition....
|
||||
typedef InstantiateChained<List1::List, Printer, NullP > Contents_List1;
|
||||
cout << "List1" << "\t:" << Contents_List1::print() << "\n";
|
||||
cout << "List1" << "\t:" << Contents_List1::print() << endl;
|
||||
|
||||
// That is: we instantiate the "Printer" template for each of the types in List1,
|
||||
// forming an inheritance chain. I.e. the defined Type "Contents_List1" inherits
|
||||
|
|
@ -124,6 +124,27 @@ namespace test {
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
check_pick_elm ()
|
||||
{
|
||||
Pick<List2,0>::Type e0;
|
||||
Pick<List2,1>::Type e1;
|
||||
Pick<List2,2>::Type e2;
|
||||
|
||||
Pick<List2,3>::Type E3;
|
||||
Pick<NullType,23>::Type Nil;
|
||||
Pick<void*,456>::Type Irrelevant;
|
||||
|
||||
CHECK (5 == e0);
|
||||
CHECK (6 == e1);
|
||||
CHECK (7 == e2);
|
||||
|
||||
CHECK (is_sameType<NullType, E3>::value);
|
||||
CHECK (is_sameType<NullType, Nil>::value);
|
||||
CHECK (is_sameType<NullType, Irrelevant>::value);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_append ()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue