vtk-m/vtkm/testing/UnitTestList.cxx
Kenneth Moreland 2b64630674 Enable predicate parameter to ListAll and ListAny
In pretty much any practical circumstance, whenusing `ListAll` or
`ListAny`, you have a list of types on which you run some sort of
predicate on each item in the list to determine whether any or all of
the items match the predicate. To make this easier, add a second
argument to `ListAll` and `ListAny` to provide a predicate that will
automatically be added.

If no predicate is given, then the operation is run directly on the
list. This is implemented by just using an identity operation.
2022-03-08 09:26:35 -07:00

324 lines
13 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/List.h>
#include <vtkm/testing/Testing.h>
#include <vector>
namespace
{
template <int N>
struct TestClass : std::integral_constant<int, N>
{
};
} // anonymous namespace
namespace vtkm
{
namespace testing
{
template <int N>
struct TypeName<TestClass<N>>
{
static std::string Name()
{
std::stringstream stream;
stream << "TestClass<" << N << ">";
return stream.str();
}
};
}
} // namespace vtkm::testing
namespace
{
template <typename T>
struct DoubleTransformLazy;
template <int N>
struct DoubleTransformLazy<TestClass<N>>
{
using type = TestClass<2 * N>;
};
template <typename T>
using DoubleTransform = typename DoubleTransformLazy<T>::type;
template <typename T>
struct EvenPredicate;
template <int N>
struct EvenPredicate<TestClass<N>> : std::integral_constant<bool, (N % 2) == 0>
{
};
template <typename T>
using OddPredicate = vtkm::internal::meta::Not<EvenPredicate<T>>;
template <typename T1, typename T2>
struct AddOperator : TestClass<T1::value + T2::value>
{
};
template <typename T1, typename T2>
void CheckSame(T1, T2)
{
VTKM_STATIC_ASSERT((std::is_same<T1, T2>::value));
std::cout << " Got expected type: " << vtkm::testing::TypeName<T1>::Name() << std::endl;
}
template <typename ExpectedList, typename List>
void CheckList(ExpectedList, List)
{
VTKM_IS_LIST(List);
CheckSame(ExpectedList{}, List{});
}
template <int N>
int test_number(TestClass<N>)
{
return N;
}
template <typename T>
struct MutableFunctor
{
std::vector<T> FoundTypes;
template <typename U>
VTKM_CONT void operator()(U u)
{
this->FoundTypes.push_back(test_number(u));
}
};
template <typename T>
struct ConstantFunctor
{
template <typename U, typename VectorType>
VTKM_CONT void operator()(U u, VectorType& vector) const
{
vector.push_back(test_number(u));
}
};
void TryForEach()
{
using TestList =
vtkm::List<TestClass<1>, TestClass<1>, TestClass<2>, TestClass<3>, TestClass<5>, TestClass<8>>;
const std::vector<int> expectedList = { 1, 1, 2, 3, 5, 8 };
std::cout << "Check mutable for each" << std::endl;
MutableFunctor<int> functor;
vtkm::ListForEach(functor, TestList{});
VTKM_TEST_ASSERT(expectedList == functor.FoundTypes);
std::cout << "Check constant for each" << std::endl;
std::vector<int> foundTypes;
vtkm::ListForEach(ConstantFunctor<int>{}, TestList{}, foundTypes);
VTKM_TEST_ASSERT(expectedList == foundTypes);
}
void TestLists()
{
using SimpleCount = vtkm::List<TestClass<1>, TestClass<2>, TestClass<3>, TestClass<4>>;
using EvenList = vtkm::List<TestClass<2>, TestClass<4>, TestClass<6>, TestClass<8>>;
using LongList = vtkm::List<TestClass<1>,
TestClass<2>,
TestClass<3>,
TestClass<4>,
TestClass<5>,
TestClass<6>,
TestClass<7>,
TestClass<8>,
TestClass<9>,
TestClass<10>,
TestClass<11>,
TestClass<12>,
TestClass<13>,
TestClass<14>>;
using RepeatList = vtkm::List<TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<1>,
TestClass<14>>;
TryForEach();
std::cout << "Valid List Tag Checks" << std::endl;
VTKM_TEST_ASSERT(vtkm::internal::IsList<vtkm::List<TestClass<11>>>::value);
VTKM_TEST_ASSERT(vtkm::internal::IsList<vtkm::List<TestClass<21>, TestClass<22>>>::value);
VTKM_TEST_ASSERT(vtkm::internal::IsList<vtkm::ListEmpty>::value);
VTKM_TEST_ASSERT(vtkm::internal::IsList<vtkm::ListUniversal>::value);
std::cout << "ListEmpty" << std::endl;
CheckList(vtkm::List<>{}, vtkm::ListEmpty{});
std::cout << "ListAppend" << std::endl;
CheckList(vtkm::List<TestClass<31>,
TestClass<32>,
TestClass<33>,
TestClass<11>,
TestClass<21>,
TestClass<22>>{},
vtkm::ListAppend<vtkm::List<TestClass<31>, TestClass<32>, TestClass<33>>,
vtkm::List<TestClass<11>>,
vtkm::List<TestClass<21>, TestClass<22>>>{});
std::cout << "ListFill" << std::endl;
CheckList(vtkm::List<int, int, int, int, int>{}, vtkm::ListFill<int, 5>{});
std::cout << "ListTransform" << std::endl;
CheckList(EvenList{}, vtkm::ListTransform<SimpleCount, DoubleTransform>{});
std::cout << "ListRemoveIf" << std::endl;
CheckList(vtkm::List<TestClass<1>, TestClass<3>>{},
vtkm::ListRemoveIf<SimpleCount, EvenPredicate>{});
std::cout << "ListIntersect" << std::endl;
CheckList(vtkm::List<TestClass<3>, TestClass<5>>{},
vtkm::ListIntersect<
vtkm::List<TestClass<1>, TestClass<2>, TestClass<3>, TestClass<4>, TestClass<5>>,
vtkm::List<TestClass<3>, TestClass<5>, TestClass<6>>>{});
CheckList(vtkm::List<TestClass<1>, TestClass<2>>{},
vtkm::ListIntersect<vtkm::List<TestClass<1>, TestClass<2>>, vtkm::ListUniversal>{});
CheckList(vtkm::List<TestClass<1>, TestClass<2>>{},
vtkm::ListIntersect<vtkm::ListUniversal, vtkm::List<TestClass<1>, TestClass<2>>>{});
std::cout << "ListSize" << std::endl;
VTKM_TEST_ASSERT(vtkm::ListSize<vtkm::ListEmpty>::value == 0);
VTKM_TEST_ASSERT(vtkm::ListSize<vtkm::List<TestClass<2>>>::value == 1);
VTKM_TEST_ASSERT(vtkm::ListSize<vtkm::List<TestClass<2>, TestClass<4>>>::value == 2);
std::cout << "ListCross" << std::endl;
CheckList(vtkm::List<vtkm::List<TestClass<31>, TestClass<11>>,
vtkm::List<TestClass<31>, TestClass<12>>,
vtkm::List<TestClass<32>, TestClass<11>>,
vtkm::List<TestClass<32>, TestClass<12>>,
vtkm::List<TestClass<33>, TestClass<11>>,
vtkm::List<TestClass<33>, TestClass<12>>>{},
vtkm::ListCross<vtkm::List<TestClass<31>, TestClass<32>, TestClass<33>>,
vtkm::List<TestClass<11>, TestClass<12>>>{});
std::cout << "ListAt" << std::endl;
CheckSame(TestClass<2>{}, vtkm::ListAt<EvenList, 0>{});
CheckSame(TestClass<4>{}, vtkm::ListAt<EvenList, 1>{});
CheckSame(TestClass<6>{}, vtkm::ListAt<EvenList, 2>{});
CheckSame(TestClass<8>{}, vtkm::ListAt<EvenList, 3>{});
std::cout << "ListIndexOf" << std::endl;
VTKM_TEST_ASSERT(vtkm::ListIndexOf<EvenList, TestClass<2>>::value == 0);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<EvenList, TestClass<4>>::value == 1);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<EvenList, TestClass<6>>::value == 2);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<EvenList, TestClass<8>>::value == 3);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<EvenList, TestClass<1>>::value == -1);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<1>>::value == 0);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<2>>::value == 1);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<3>>::value == 2);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<4>>::value == 3);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<5>>::value == 4);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<6>>::value == 5);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<7>>::value == 6);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<8>>::value == 7);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<9>>::value == 8);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<10>>::value == 9);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<11>>::value == 10);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<12>>::value == 11);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<13>>::value == 12);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<14>>::value == 13);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<15>>::value == -1);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<LongList, TestClass<0>>::value == -1);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<RepeatList, TestClass<0>>::value == -1);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<RepeatList, TestClass<1>>::value == 0);
VTKM_TEST_ASSERT(vtkm::ListIndexOf<RepeatList, TestClass<14>>::value == 13);
std::cout << "ListHas" << std::endl;
VTKM_TEST_ASSERT(vtkm::ListHas<EvenList, TestClass<2>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<EvenList, TestClass<4>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<EvenList, TestClass<6>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<EvenList, TestClass<8>>::value);
VTKM_TEST_ASSERT(!vtkm::ListHas<EvenList, TestClass<1>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<1>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<2>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<3>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<4>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<5>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<6>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<7>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<7>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<8>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<9>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<10>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<11>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<12>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<13>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<LongList, TestClass<14>>::value);
VTKM_TEST_ASSERT(!vtkm::ListHas<LongList, TestClass<15>>::value);
VTKM_TEST_ASSERT(!vtkm::ListHas<LongList, TestClass<0>>::value);
VTKM_TEST_ASSERT(!vtkm::ListHas<RepeatList, TestClass<0>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<RepeatList, TestClass<1>>::value);
VTKM_TEST_ASSERT(vtkm::ListHas<RepeatList, TestClass<14>>::value);
std::cout << "ListReduce" << std::endl;
using Zero = std::integral_constant<int, 0>;
VTKM_TEST_ASSERT((vtkm::ListReduce<SimpleCount, AddOperator, Zero>::value == 10));
VTKM_TEST_ASSERT((vtkm::ListReduce<EvenList, AddOperator, Zero>::value == 20));
VTKM_TEST_ASSERT((vtkm::ListReduce<LongList, AddOperator, Zero>::value == 105));
VTKM_TEST_ASSERT((vtkm::ListReduce<RepeatList, AddOperator, Zero>::value == 27));
std::cout << "ListAll" << std::endl;
VTKM_TEST_ASSERT(
(vtkm::ListAll<vtkm::ListTransform<SimpleCount, EvenPredicate>>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::ListTransform<EvenList, EvenPredicate>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::ListTransform<LongList, EvenPredicate>>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::List<>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAll<SimpleCount, EvenPredicate>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAll<EvenList, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAll<LongList, EvenPredicate>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::List<>, EvenPredicate>::value == true));
std::cout << "ListAny" << std::endl;
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::ListTransform<SimpleCount, EvenPredicate>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::ListTransform<EvenList, EvenPredicate>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::ListTransform<EvenList, OddPredicate>>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::ListTransform<LongList, EvenPredicate>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::List<>>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAny<SimpleCount, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<EvenList, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<EvenList, OddPredicate>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAny<LongList, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::List<>, EvenPredicate>::value == false));
}
} // anonymous namespace
int UnitTestList(int argc, char* argv[])
{
return vtkm::testing::Testing::Run(TestLists, argc, argv);
}