测试两种类型列表中的所有组合
Test all the combinations out of two type lists
我正在使用 Google 测试框架,我有两个类型列表,我需要 运行 相同的测试套件。我正在使用宏 TYPED_TEST_CASE
但这里的问题是它被强制只用于一个类型列表,而不是两个或更多。
我需要 运行 这个测试套件包含这两个类型列表之间的所有组合。有可能完成吗?如果TYPED_TEST_CASE
宏只接受一个列表类型,是否可以用之前的所有组合生成这个列表,将它们插入一个列表中,然后使用one-list-only宏?
好了。它一如既往地需要一些元魔法。为了让它顺利地适应 GTest,我使用了 ::testing::Types
,现在你只需将 cartesian_product
作为类型参数传递给测试。
编辑:因为 ::testing::Types
不是真正的可变参数,所以我不得不做一些帮助和转换:
template<class... Args>
struct Types { };
template<class First, class Second>
struct type_pair {
using first = First;
using second = Second;
};
template<class TypeList, template <class> class Mapper>
struct meta_map {
using type = void;
};
template<template <class> class Mapper, class... Args>
struct meta_map<Types<Args...>, Mapper> {
using type = Types<Mapper<Args>...>;
};
template<class Arg, class TypeList>
struct create_pairs {
template<class T>
using make_pair = type_pair<T, Arg>;
using type = typename meta_map<TypeList, make_pair>::type;
};
template<class List, class... Lists>
struct sum {
using type = void;
};
template<class... Ts>
struct sum<Types<Ts...>> {
using type = Types<Ts...>;
};
template<class... T1, class... T2>
struct sum<Types<T1...>, Types<T2...>> {
using type = typename sum<Types<T1..., T2...>>::type;
};
template<class... T1, class... T2>
struct sum<Types<T1...>, T2...> {
using type = typename sum<Types<T1...>, typename sum<T2...>::type>::type;
};
template<class List, template <class...> class Reducer>
struct meta_reduce {
using type = void;
};
template<class... Args, template <class...> class Reducer>
struct meta_reduce<Types<Args...>, Reducer> {
using type = typename Reducer<Args...>::type;
};
template<class TypeList1, class TypeList2>
struct cartesian_product_helper {
using type = void;
};
template<class TypeList1, class... Args>
struct cartesian_product_helper<TypeList1, Types<Args...>> {
using type = typename meta_reduce<Types<typename create_pairs<Args, TypeList1>::type...>, sum>::type;
};
template<class List1, class List2>
using cartesian_product = typename cartesian_product_helper<List1, List2>::type;
template<class TypeList>
struct to_test_types {
using type = void;
};
template<class... Ts>
struct to_test_types<Types<Ts...>> {
using type = ::testing::Types<Ts...>;
};
template<class TypeList>
using to_test_types_t = typename to_test_types<TypeList>::type;
用法如下:
to_test_types_t<cartesian_product<
Types<char, bool, unsigned>,
Types<char, bool>
>>;
实例:
https://godbolt.org/z/XmyHDT
编辑:在 godbolt 上添加了 gtest,它似乎可以正常使用此代码
我正在使用 Google 测试框架,我有两个类型列表,我需要 运行 相同的测试套件。我正在使用宏 TYPED_TEST_CASE
但这里的问题是它被强制只用于一个类型列表,而不是两个或更多。
我需要 运行 这个测试套件包含这两个类型列表之间的所有组合。有可能完成吗?如果TYPED_TEST_CASE
宏只接受一个列表类型,是否可以用之前的所有组合生成这个列表,将它们插入一个列表中,然后使用one-list-only宏?
好了。它一如既往地需要一些元魔法。为了让它顺利地适应 GTest,我使用了 ::testing::Types
,现在你只需将 cartesian_product
作为类型参数传递给测试。
编辑:因为 ::testing::Types
不是真正的可变参数,所以我不得不做一些帮助和转换:
template<class... Args>
struct Types { };
template<class First, class Second>
struct type_pair {
using first = First;
using second = Second;
};
template<class TypeList, template <class> class Mapper>
struct meta_map {
using type = void;
};
template<template <class> class Mapper, class... Args>
struct meta_map<Types<Args...>, Mapper> {
using type = Types<Mapper<Args>...>;
};
template<class Arg, class TypeList>
struct create_pairs {
template<class T>
using make_pair = type_pair<T, Arg>;
using type = typename meta_map<TypeList, make_pair>::type;
};
template<class List, class... Lists>
struct sum {
using type = void;
};
template<class... Ts>
struct sum<Types<Ts...>> {
using type = Types<Ts...>;
};
template<class... T1, class... T2>
struct sum<Types<T1...>, Types<T2...>> {
using type = typename sum<Types<T1..., T2...>>::type;
};
template<class... T1, class... T2>
struct sum<Types<T1...>, T2...> {
using type = typename sum<Types<T1...>, typename sum<T2...>::type>::type;
};
template<class List, template <class...> class Reducer>
struct meta_reduce {
using type = void;
};
template<class... Args, template <class...> class Reducer>
struct meta_reduce<Types<Args...>, Reducer> {
using type = typename Reducer<Args...>::type;
};
template<class TypeList1, class TypeList2>
struct cartesian_product_helper {
using type = void;
};
template<class TypeList1, class... Args>
struct cartesian_product_helper<TypeList1, Types<Args...>> {
using type = typename meta_reduce<Types<typename create_pairs<Args, TypeList1>::type...>, sum>::type;
};
template<class List1, class List2>
using cartesian_product = typename cartesian_product_helper<List1, List2>::type;
template<class TypeList>
struct to_test_types {
using type = void;
};
template<class... Ts>
struct to_test_types<Types<Ts...>> {
using type = ::testing::Types<Ts...>;
};
template<class TypeList>
using to_test_types_t = typename to_test_types<TypeList>::type;
用法如下:
to_test_types_t<cartesian_product<
Types<char, bool, unsigned>,
Types<char, bool>
>>;
实例: https://godbolt.org/z/XmyHDT
编辑:在 godbolt 上添加了 gtest,它似乎可以正常使用此代码