WIP draft test helper for generating test cases (Cartesian product)

This commit is contained in:
Fischlurch 2011-05-27 21:27:55 +02:00
parent eb5e0ab9ff
commit 786ecbe829
7 changed files with 226 additions and 30 deletions

View file

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

View file

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

View file

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

View file

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

View 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

View file

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

View file

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