Boost logo

Boost :

Subject: Re: [boost] Using BOOST_AUTO_TEST_CASE_TEMPLATE but passing a list of test values too
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2015-12-10 12:08:07


> -----Original Message-----
> From: Boost [mailto:boost-bounces_at_[hidden]] On Behalf Of Paul A. Bristow
> Sent: 02 December 2015 10:56
> To: boost_at_[hidden]
> Subject: [boost] Using BOOST_AUTO_TEST_CASE_TEMPLATE but passing a list of test values too
>
> I want to test a (quite large) variety of user-defined types using Boost.Test.
>
> As a very contrived example, suppose I wanted to check numeric_limits digits for integer types
>
> I'd like to avoid a tediously long list like this
>
> BOOST_CHECK_EQUAL(std::numeric_limits<char>::digits, 8);
> BOOST_CHECK_EQUAL(std::numeric_limits<char>::digits, 16);
> BOOST_CHECK_EQUAL(std::numeric_limits<char>::digits, 32); ...
>
> and follow the example of
>
> BOOST_AUTO_TEST_CASE_TEMPLATE
>
> but allow a test value to be passed too,
>
> something like this:
>
> typedef boost::mpl::list<char, int, long> test_types;
>
> and a list of test values, perhaps like this
>
> typedef list_c<int, 8, 32, 64> test_values;
>
> (However it would be *far* more useful to be able to test strings and floats and User-defined
types
> too).
>
> BOOST_AUTO_TEST_CASE_TEMPLATE_????(digits_test, T, test_types, test_values) {
> BOOST_CHECK_EQUAL(std::numeric_limits<T>::digits, test_values); }
>
> Has any Macro Guru produced a BOOST_AUTO_TEST_CASE_TEMPLATE_? that includes a list of test
> values?

After some discussion with Gennadiy Rozental (Boost.Test author) ,
the answer is that he is working on a dataset system that would permit this (but not imminent).

Two possible workarounds:

1 Gennadiy suggested using

// List of types to test.
typedef boost::mpl::list<char, short, int, long, long long> test_types;

// Values that types should have.
template<typename T> struct ExpectedTDigits;
template<> struct ExpectedTDigits<char> { static const int value = 8 - 1; };
template<> struct ExpectedTDigits<short> { static const int value = 16 - 1; };
template<> struct ExpectedTDigits<int> { static const int value = 32 - 1; };
template<> struct ExpectedTDigits<long> { static const int value = 32 - 1; };
template<> struct ExpectedTDigits<long long > { static const int value = 64 - 1; };

// But a serious downside of this scheme is that it can't work with std::string or User-defined
types.
// This is because these types can't be made static which is essential for this to work.
template<typename T> struct ExpectedTstring;
template<> struct ExpectedTstring<char> { static const std::string value = "char"; };
// Error C2864 'ExpectedTstring<char>::value': a static data member with an in-class
initializer must have non-volatile const integral type

BOOST_AUTO_TEST_CASE_TEMPLATE(my_test, T, test_types)
{
  // Find the expected value for the type T.
  BOOST_CHECK_EQUAL(std::numeric_limits<T>::digits, ExpectedTDigits<T>::value);
}

so it works OK with my very contrived example, but not for all types
(for my application a killer as need check against UDT values).

2 Playing dirty and using a global indexer to containers (array, vector..) of the values to check
against.

int index = 0; // Global so that can be accessed by digits_test

// Container for expected values of std::numeric_limits<T>::digits for the types above.
// It's size must match the size of the list of types to test.
std::array<const int, 5> type_values { { 8-1, 16-1, 32-1, 32-1, 64-1 } };
// Similarly OK for an array of any value type, including UDT, for example
//std::array<const char*, 5> type_strings { { "char", "short", "int", "long", "long long" } };
//std::array<const std::string, 5> type_std_strings { { "char", "short", "int", "long", "long long"
} };

template <typename T>
void digits_test()
{
  int digits = type_values[index]; // 8 if T == char, 16 if T == short, 32 if T == int ...
  BOOST_CHECK_EQUAL(std::numeric_limits<T>::digits, digits); // Test for corresponding value.
 // Possibly check against other items like type_strings[index] ...
  index++; // ready for next type.
  return;
} // void digits_test()

BOOST_AUTO_TEST_CASE_TEMPLATE(my_test, T, test_types)
{
   // Find the expected value for the type T from the array type_values.
    digits_test<T>();

} // BOOST_AUTO_TEST_CASE_TEMPLATE(my_test, T, test_types)

Two working examples attached in case anyone wants to solve the same sort of problem.

Paul

---
Paul A. Bristow
Prizet Farmhouse
Kendal UK LA8 8AB
+44 (0) 1539 561830





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