Boost logo

Boost :

Subject: Re: [boost] [test] Test cases parametrized by both type and value?
From: Robert Ramey (ramey_at_[hidden])
Date: 2018-01-05 16:02:51


On 1/5/18 3:39 AM, Andrzej Krzemienski via Boost wrote:
> Hi,
> Can anyone tell me if Boost.Test can solve the problem that I describe
> below.
>
> I have a function template inspect:
>
> ```
> template <typename T>
> bool inspect(T const& v);
> ```
>
> I want to test if it returns `true` for the following values:
>
> 1 (type int)
> 10 (type int)
> 1.0 (type double)
> "Y" (type const char *)
>
> Basically, different values of different types, but sometimes different
> values have the same type. I would like to write one test or "test
> template" with the following contents:
>
> ```
> BOOST_TEST((inspect(v)));
> ```
>
> Where `v` is name of the currently tested value. (But `v`s will have
> different types). I can emulate this behavior using template test cases and
> artificial types:
>
> ```
> struct int_1 {
> static int value() { return 1; }
> };
> struct int_10 {
> static int value() { return 10; }
> };
> struct double_1 {
> static double value() { return 1.0; }
> };
> struct cstr_Y {
> static const char * value() { return "Y"; }
> };
>
> typedef boost::mpl::list<int_1, int_10, double_1, cstr_Y> test_types;
>
> BOOST_AUTO_TEST_CASE_TEMPLATE( my_test, T, test_types )
> {
> BOOST_TEST(inspect(T::value()));
> }
> ```
>
> (See working example in WandBox:
> https://wandbox.org/permlink/KcJqT8KvL3zIqAxL)
>
> But maybe there exists a direct solution in Boost.Test? Where I would just
> pass a list of values: `{1, 10, 1.0, "Y"}`
>
> It is easy to deduce types from values:
>
> ```
> template <typename... T>
> mpl::liss<T...> Values(T... values);
>
> using test_types = decltype(Values(1, 10, 1.0, "Y"));
> ```
>
> Does something like this exist, or ois it a reasonable extension?
>
> Regards,
> &rzej;
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>

I've handled this a number of ways. My latest favorite is

struct t {
     static bool m_error;
     template<typename T>
     void operator()(const T &){ std::cout
             << "** testing "
             << boost::core::demangle(typeid(T).name())
             << std::endl;
         m_error &=
             std::numeric_limits<T>::is_signed
             ? test_pairs(signed_value<T>, signed_multiplication_results)
             : test_pairs(unsigned_value<T>,
unsigned_multiplication_results)
         ;
     }
};
bool t::m_error = true;

bool test_all_types(){
     t rval;
     boost::mp11::mp_for_each<
         boost::mp11::mp_list<
             std::int8_t, std::int16_t, std::int32_t, std::int64_t,
             std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t
>
>(rval);
     return rval.m_error; // maybe call BOOST_TEST macro here.
}

I've also used boost preprocessor to do something similar. It's hard to
post here as it's spread across various header flles. You can see how
this is used by checking out the code in the current safe numerics
implementation.

I don't use boost test, but I don't seen how things would change much if
I did.

Robert Ramey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk