//============================================================================ // 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace vtkm::cont::testing::serialization; namespace { using TestTypesListScalar = vtkm::List; using TestTypesListVec = vtkm::List; using TestTypesList = vtkm::ListAppend; using StorageListInefficientExtract = vtkm::List< vtkm::cont::StorageTagCast, vtkm::cont::StorageTagConstant, vtkm::cont::StorageTagCounting, vtkm::cont::StorageTagIndex, vtkm::cont::StorageTagPermutation>; //----------------------------------------------------------------------------- struct TestEqualArrayHandle { public: template VTKM_CONT void operator()(const ArrayHandle1& array1, const ArrayHandle2& array2) const { VTKM_TEST_ASSERT(test_equal_ArrayHandles(array1, array2)); } template VTKM_CONT void operator()(const vtkm::cont::UncertainArrayHandle& array1, const vtkm::cont::UnknownArrayHandle& array2) const { // This results in an excessive amount of compiling. However, we do it here to avoid // warnings about inefficient copies of the weirder arrays. That slowness might be OK // to test arrays, but we want to make sure that the serialization itself does not do // that. array1.CastAndCall([array2](const auto& concreteArray1) { using ArrayType = std::decay_t; ArrayType concreteArray2; array2.AsArrayHandle(concreteArray2); test_equal_ArrayHandles(concreteArray1, concreteArray2); }); } template VTKM_CONT void operator()( const vtkm::cont::UncertainArrayHandle& array1, const vtkm::cont::UncertainArrayHandle& array2) const { (*this)(array1, vtkm::cont::UnknownArrayHandle(array2)); } VTKM_CONT void operator()(const vtkm::cont::UnknownArrayHandle& array1, const vtkm::cont::UnknownArrayHandle& array2) const { bool isInefficient = false; vtkm::ListForEach( [&](auto type) { using StorageTag = std::decay_t; if (array1.IsStorageType()) { isInefficient = true; } }, StorageListInefficientExtract{}); if (isInefficient) { (*this)(array1.ResetTypes(), array2); } else { test_equal_ArrayHandles(array1, array2); } } }; //----------------------------------------------------------------------------- template inline void RunTest(const T& obj) { TestSerialization(obj, TestEqualArrayHandle{}); } //----------------------------------------------------------------------------- constexpr vtkm::Id ArraySize = 10; template inline vtkm::cont::UnknownArrayHandle MakeTestUnknownArrayHandle( const vtkm::cont::ArrayHandle& array) { return array; } template inline vtkm::cont::UncertainArrayHandle, vtkm::List> MakeTestUncertainArrayHandle( const vtkm::cont::ArrayHandle& array) { return array; } struct TestArrayHandleBasic { template void operator()(T) const { auto array = RandomArrayHandle::Make(ArraySize); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleBasicEmpty { template void operator()(T) const { vtkm::cont::ArrayHandle array; array.Allocate(0); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleSOA { template void operator()(T) const { vtkm::cont::ArrayHandleSOA array; vtkm::cont::ArrayCopy(RandomArrayHandle::Make(ArraySize), array); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleCartesianProduct { template void operator()(T) const { auto array = vtkm::cont::make_ArrayHandleCartesianProduct(RandomArrayHandle::Make(ArraySize), RandomArrayHandle::Make(ArraySize), RandomArrayHandle::Make(ArraySize)); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleCast { template void operator()(T) const { auto array = vtkm::cont::make_ArrayHandleCast(RandomArrayHandle::Make(ArraySize)); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } template void operator()(vtkm::Vec) const { auto array = vtkm::cont::make_ArrayHandleCast>( RandomArrayHandle>::Make(ArraySize)); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleConstant { template void operator()(T) const { T cval = RandomValue::Make(); auto array = vtkm::cont::make_ArrayHandleConstant(cval, ArraySize); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleCounting { template void operator()(T) const { T start = RandomValue::Make(); T step = RandomValue::Make(0, 5); auto array = vtkm::cont::make_ArrayHandleCounting(start, step, ArraySize); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleGroupVec { template void operator()(T) const { auto numComps = RandomValue::Make(2, 4); auto flat = RandomArrayHandle::Make(ArraySize * numComps); switch (numComps) { case 3: { auto array = vtkm::cont::make_ArrayHandleGroupVec<3>(flat); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); break; } case 4: { auto array = vtkm::cont::make_ArrayHandleGroupVec<4>(flat); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); break; } default: { auto array = vtkm::cont::make_ArrayHandleGroupVec<2>(flat); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); break; } } } }; struct TestArrayHandleGroupVecVariable { template void operator()(T) const { auto rangen = UniformRandomValueGenerator(1, 4); vtkm::Id size = 0; std::vector comps(ArraySize); std::generate(comps.begin(), comps.end(), [&size, &rangen]() { auto offset = size; size += rangen(); return offset; }); auto array = vtkm::cont::make_ArrayHandleGroupVecVariable( RandomArrayHandle::Make(size), vtkm::cont::make_ArrayHandle(comps, vtkm::CopyFlag::On)); RunTest(array); // cannot make a UnknownArrayHandle containing ArrayHandleGroupVecVariable // because of the variable number of components of its values. // RunTest(MakeTestUnknownArrayHandle(array)); } }; void TestArrayHandleIndex() { auto size = RandomValue::Make(2, 10); auto array = vtkm::cont::ArrayHandleIndex(size); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } struct TestArrayHandlePermutation { template void operator()(T) const { std::uniform_int_distribution distribution(0, ArraySize - 1); std::vector inds(ArraySize); std::generate(inds.begin(), inds.end(), [&distribution]() { return distribution(generator); }); auto array = vtkm::cont::make_ArrayHandlePermutation( RandomArrayHandle::Make(ArraySize, 0, ArraySize - 1), RandomArrayHandle::Make(ArraySize)); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleReverse { template void operator()(T) const { auto array = vtkm::cont::make_ArrayHandleReverse(RandomArrayHandle::Make(ArraySize)); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } }; struct TestArrayHandleSwizzle { template void operator()(T) const { constexpr vtkm::IdComponent NUM_COMPONENTS = vtkm::VecTraits::NUM_COMPONENTS; vtkm::Vec map; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; ++i) { map[i] = NUM_COMPONENTS - (i + 1); } auto array = vtkm::cont::make_ArrayHandleSwizzle(RandomArrayHandle::Make(ArraySize), map); RunTest(array); } }; vtkm::cont::ArrayHandleUniformPointCoordinates MakeRandomArrayHandleUniformPointCoordinates() { auto dimensions = RandomValue::Make(1, 3); auto origin = RandomValue::Make(); auto spacing = RandomValue::Make(0.1f, 10.0f); return vtkm::cont::ArrayHandleUniformPointCoordinates(dimensions, origin, spacing); } void TestArrayHandleUniformPointCoordinates() { auto array = MakeRandomArrayHandleUniformPointCoordinates(); RunTest(array); RunTest(MakeTestUnknownArrayHandle(array)); RunTest(MakeTestUncertainArrayHandle(array)); } //----------------------------------------------------------------------------- void TestArrayHandleSerialization() { std::cout << "Testing ArrayHandleBasic\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleBasic(), TestTypesList()); vtkm::testing::Testing::TryTypes( TestArrayHandleBasic(), vtkm::List()); std::cout << "Testing empty ArrayHandleBasic\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleBasicEmpty(), TestTypesList()); vtkm::testing::Testing::TryTypes( TestArrayHandleBasicEmpty(), vtkm::List()); std::cout << "Testing ArrayHandleSOA\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleSOA(), TestTypesListVec()); std::cout << "Testing ArrayHandleCartesianProduct\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleCartesianProduct(), vtkm::List()); std::cout << "Testing TestArrayHandleCast\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleCast(), TestTypesList()); std::cout << "Testing ArrayHandleConstant\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleConstant(), TestTypesList()); std::cout << "Testing ArrayHandleCounting\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleCounting(), TestTypesList()); std::cout << "Testing ArrayHandleGroupVec\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleGroupVec(), TestTypesListScalar()); std::cout << "Testing ArrayHandleGroupVecVariable\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleGroupVecVariable(), TestTypesList()); std::cout << "Testing ArrayHandleIndex\n"; TestArrayHandleIndex(); std::cout << "Testing ArrayHandlePermutation\n"; vtkm::testing::Testing::TryTypes(TestArrayHandlePermutation(), TestTypesList()); std::cout << "Testing ArrayHandleReverse\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleReverse(), TestTypesList()); std::cout << "Testing ArrayHandleSwizzle\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleSwizzle(), TestTypesList()); std::cout << "Testing ArrayHandleUniformPointCoordinates\n"; TestArrayHandleUniformPointCoordinates(); } } // anonymous namespace //----------------------------------------------------------------------------- int UnitTestSerializationArrayHandle(int argc, char* argv[]) { // Normally VTK-m `Testing::Run` would setup the diy MPI env, // but since we need to access it before execution we have // to manually set it up vtkmdiy::mpi::environment env(argc, argv); auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); decltype(generator)::result_type seed = 0; if (comm.rank() == 0) { seed = static_cast(std::time(nullptr)); std::cout << "using seed: " << seed << "\n"; } vtkmdiy::mpi::broadcast(comm, seed, 0); generator.seed(seed); return vtkm::cont::testing::Testing::Run(TestArrayHandleSerialization, argc, argv); }