doctest icon indicating copy to clipboard operation
doctest copied to clipboard

TYPE_TO_STRING does not work inside a TEST_SUITE / namespace

Open anton-potapov opened this issue 11 months ago • 2 comments

Description

usage of macro fails with an error: error: ‘String’ does not name a type

Steps to reproduce

reproducer:

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"

TEST_SUITE(""){

TYPE_TO_STRING(short);
// TYPE_TO_STRING_AS("Int", int);

}

live at godbolt.org

Extra information

  • doctest version: v2.4.11
  • Operating System: Ubuntu 22.04.3 LTS
  • Compiler+version: gcc version 12.3.0 (Ubuntu 12.3.0-1ubuntu1~22.04)

anton-potapov avatar Mar 11 '24 10:03 anton-potapov

Why would you not use it in global scope - as it's meant to be used?

onqtam avatar Mar 14 '24 13:03 onqtam

Why would you not use it in global scope - as it's meant to be used?

Idea is not to pollute global namespace with test suite local names. Both to avoid name clashes , and simplify understanding of the test code (via reducing scope of names)

anton-potapov avatar Jun 26 '24 14:06 anton-potapov

It does not pollute global namespace, it expands into the doctest namespace. The macro call TYPE_TO_STRING(MyClass) expands into

namespace doctest {
    template <> inline String toString<MyClass>() {
        return "MyClass";
    }
}

cdeln avatar Aug 16 '24 06:08 cdeln

@cdeln "pollute" was used in regard to test suite specific types, e.g. :

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"

TEST_SUITE("use distance with random access iterator"){
 struct random_iterator {}; 

TYPE_TO_STRING(bidirectional_iterator );  //does not compile
//...
// test to make sure std::distance works with random access iterator 
// 
}

TEST_SUITE("use distance with random access iterator"){
 struct bidirectional_iterator {}; 
TYPE_TO_STRING(bidirectional_iterator ); //does not compile
//...
// test to make sure std::distance works with random bidirectional iterator 
// 
}

here for TYPE_TO_STRING types random_iterator and bidirectional_iterator have to be moved out of the test suites (e.g. to global namespace thus polluting them). This is not convenient and makes test suites logic harder to understand

anton-potapov avatar Aug 30 '24 11:08 anton-potapov

This is not possible to do. TEST_SUITE defines an "opaque namespace" (that is, a generated, non user visible namespace).

The following code

TEST_SUITE("RandomIterator") {
    struct random_iterator {};
    TYPE_TO_STRING(random_iterator);
}

expands into something like

namespace DOCTEST_ANON_SUITE_2 {
   struct random_iterator {};
   namespace doctest {
   namespace detail {
   template <> inline const char* type_to_string<random_iterator>() {
       return "<" "random_iterator" ">";
   }
   } // detail
   } // doctest
   static_assert(true, "")                                         ;
} // DOCTEST_ANON_SUITE_2

which is an explicit template instantiation in the wrong namespace DOCTEST_ANON_SUITE_2::doctest::detail. I suggest you rewrite tests requiring test suite specific types as follows

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>

namespace testing {
    struct random_iterator {};
}

TYPE_TO_STRING(::testing::random_iterator);

TEST_SUITE("RandomIterator") {}

I am curious why you use test suite specific types to begin with, but I guess there is an use case ;)

cdeln avatar Aug 31 '24 06:08 cdeln