diff --git a/UTests/utestFBasicParticle.cpp b/UTests/utestFBasicParticle.cpp index 36f93fbb8799f2b9970f190c8001d334c1ae14f4..34c2c692081190f6d04d08e3aecaa9ebc5f366d4 100644 --- a/UTests/utestFBasicParticle.cpp +++ b/UTests/utestFBasicParticle.cpp @@ -5,66 +5,172 @@ #include "Adaptive/new/FVariadicParticleContainer.hpp" -using FReal = double; -constexpr std::size_t Dim = 3; - namespace sd = scalfmm::details; +namespace sfinae { + template<typename ... Ts> using void_t = void; + +} struct test_FBasicParticle_simple { - using Particle = FBasicParticle<FReal, Dim, scalfmm::pack<5, FReal> >; + + using FReal = double; + enum {Dim = 3}; + + using Particle = FBasicParticle<FReal, Dim, float, scalfmm::pack<4, FReal> >; + + // Check the attribute count + static_assert(Particle::NbAttributes == 5, "Wrong count of attributes"); using Container = FVariadicParticleContainer<Particle>; void run() { + bool asserts_are_run = false; + assert(asserts_are_run = true); + if(!asserts_are_run) { + std::cerr << "Asserts are not run"; + exit(-1); + } + test_default_constructor(); test_variadic_constructor(); + test_incomplete_variadic_constructor(); + test_variadic_constructor_overflow_failure(); + test_constructor_from_tuple(); + test_position_getter(); test_pull_push(); } + /** + * \brief Test the default constructor + * + * Expected result: particle builds + */ void test_default_constructor() { - Particle p; - static_assert(Particle::NbAttributes == 5, "Wrong count of attributes"); + Particle p{}; } + /** + * \brief Test the variadic constructor + * + * Expected result: + * - particle builds + * - position is right + * - attributes are right + */ void test_variadic_constructor() { const Particle::position_t pos(1.5,2.5,3.5); Particle p(pos,1,2,3,4,5); - const auto pos2 = p.position(); + assert(1.5 == pos[0]); + assert(2.5 == pos[1]); + assert(3.5 == pos[2]); - assert(pos2[0] == pos[0]); - assert(pos2[1] == pos[1]); - assert(pos2[2] == pos[2]); + assert(std::get<3>(p) == 1); + assert(std::get<4>(p) == 2); + assert(std::get<5>(p) == 3); + assert(std::get<6>(p) == 4); + assert(std::get<7>(p) == 5); + } - assert(get<3>(p) == 1); - assert(get<4>(p) == 2); - assert(get<5>(p) == 3); - assert(get<6>(p) == 4); - assert(get<7>(p) == 5); + /** + * \brief Test variadic constructor with incomplete arguments + * + * Expected result: + * - particle builds + * - position is right + * - attributes are right + * - non given attributes are zeroed + */ + void test_incomplete_variadic_constructor() { + const Particle::position_t pos(1.5,2.5,3.5); + Particle p(pos,1,2); + assert(1.5 == pos[0]); + assert(2.5 == pos[1]); + assert(3.5 == pos[2]); - double a = 1.5, b = 2.5, c = 3.5, d = 1, e = 2, f = 3, g = 4, h = 5; + assert(std::get<3>(p) == 1); + assert(std::get<4>(p) == 2); + assert(std::get<5>(p) == 0); + assert(std::get<6>(p) == 0); + assert(std::get<7>(p) == 0); + } - Particle p2(std::make_tuple(1.5,2.5,3.5,1,2,3,4,5)); + /** + * \brief Check if constructor can be called with specified attributes. + * + * Holds a #value that is false if constructor `U({0,0,0}, attributes...)` + * exists. + * + * \tparam T Class to check + * \tparam attributes int parameter pack of attribute values + */ + template<class T, int ... attributes> + struct check_constructor_overflow_failure { + /// Exists if the constructor `U({0,0,0}, attributes...)` exists + template<class U, class = decltype(U({0,0,0}, attributes...))> + static constexpr std::false_type check(U*) {return {};} + /// SFINAE fallback + static constexpr std::true_type check(...) {return {};} + + /// value is true if the constructor does not exist + enum {value = decltype(check((T*)nullptr))::value}; + }; + + /** + * \brief Test variadic constructor when too many arguments are given + * + * Expected result: + * - the constructor instanciated raises a false static_assert + */ + void test_variadic_constructor_overflow_failure() { + using test = check_constructor_overflow_failure<Particle,1,2,3,4,5,6>; + static_assert(test::value, "Variadic constructor accepts too many attributes"); + assert(test::value); + } - assert(get<3>(p2) == 1); - assert(get<4>(p2) == 2); - assert(get<5>(p2) == 3); - assert(get<6>(p2) == 4); - assert(get<7>(p2) == 5); + /** + * \brief Test constructor from a std::tuple + * + * Expected result: + * - the particle is created + * - the position and attributes are correct + */ + void test_constructor_from_tuple() { + Particle p(std::make_tuple(1.5,2.5,3.5,1,2,3,4,5)); + // position + assert(std::get<0>(p) == 1.5); + assert(std::get<1>(p) == 2.5); + assert(std::get<2>(p) == 3.5); + // attributes + assert(std::get<3>(p) == 1); + assert(std::get<4>(p) == 2); + assert(std::get<5>(p) == 3); + assert(std::get<6>(p) == 4); + assert(std::get<7>(p) == 5); + } - scalfmm::pack_expand_tuple<scalfmm::pack<8,const double&> > tup (a,b,c,d,e,f,g,h); - Particle p3(tup); - assert(get<3>(p3) == 1); - assert(get<4>(p3) == 2); - assert(get<5>(p3) == 3); - assert(get<6>(p3) == 4); - assert(get<7>(p3) == 5); + /** + * \brief Test position getter + * + * Expected result: + * - p.position() returns a copy of the particle position + */ + void test_position_getter() { + typename Particle::position_t ref{1.5,2.5,3.5}; + const Particle p(ref, 1,2,3,4,5); + // check value + auto pos = p.position(); + assert(pos == ref); + // check that a copy is returned, not a reference + pos[0] += 1; + assert(pos != p.position()); } + void test_pull_push() { Particle p({2.3,3.4,4.5}, 5, 6, 7, 8, 9);