Adding dedicated test_const_name. (#3578)

* Adding dedicated test_const_name.

Also exercises pybind11::detail::_ backward compatibility.

See also: PR #3423

* Backing out tests involving int_to_str (requires C++17 or higher).

* Suppressing clang-tidy errors.

* Disabling test_const_name for MSVC 2015 due to bizarre failures.

* Stacking @pytest.mark.parametrize (thanks to @skylion007 for pointing out).
This commit is contained in:
Ralf W. Grosse-Kunstleve 2021-12-29 12:54:25 -08:00 committed by GitHub
parent 9b4f71d12d
commit 1bbaeb3462
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 4 deletions

View File

@ -59,6 +59,7 @@ constexpr descr<0> const_name(char const(&)[1]) { return {}; }
template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { }; template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
template <size_t...Digits> struct int_to_str<0, Digits...> { template <size_t...Digits> struct int_to_str<0, Digits...> {
// WARNING: This only works with C++17 or higher.
static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...); static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
}; };
@ -84,9 +85,12 @@ auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size %
template <typename Type> constexpr descr<1, Type> const_name() { return {'%'}; } template <typename Type> constexpr descr<1, Type> const_name() { return {'%'}; }
// The "_" might be defined as a macro - don't define it if so. // If "_" is defined as a macro, py::detail::_ cannot be provided.
// Repeating the const_name code to avoid introducing a #define. // It is therefore best to use py::detail::const_name universally.
// This block is for backward compatibility only.
// (The const_name code is repeated to avoid introducing a "_" #define ourselves.)
#ifndef _ #ifndef _
#define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
template <size_t N> template <size_t N>
constexpr descr<N-1> _(char const(&text)[N]) { return const_name<N>(text); } constexpr descr<N-1> _(char const(&text)[N]) { return const_name<N>(text); }
template <bool B, size_t N1, size_t N2> template <bool B, size_t N1, size_t N2>
@ -107,7 +111,7 @@ auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::dig
return const_name<Size>(); return const_name<Size>();
} }
template <typename Type> constexpr descr<1, Type> _() { return const_name<Type>(); } template <typename Type> constexpr descr<1, Type> _() { return const_name<Type>(); }
#endif #endif // #ifndef _
constexpr descr<0> concat() { return {}; } constexpr descr<0> concat() { return {}; }

View File

@ -101,6 +101,7 @@ set(PYBIND11_TEST_FILES
test_callbacks.cpp test_callbacks.cpp
test_chrono.cpp test_chrono.cpp
test_class.cpp test_class.cpp
test_const_name.cpp
test_constants_and_functions.cpp test_constants_and_functions.cpp
test_copy_move.cpp test_copy_move.cpp
test_custom_type_casters.cpp test_custom_type_casters.cpp

70
tests/test_const_name.cpp Normal file
View File

@ -0,0 +1,70 @@
// Copyright (c) 2021 The Pybind Development Team.
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "pybind11_tests.h"
#if defined(_MSC_VER) && _MSC_VER < 1910
// MSVC 2015 fails in bizarre ways.
# define PYBIND11_SKIP_TEST_CONST_NAME
#else // Only test with MSVC 2017 or newer.
// IUT = Implementation Under Test
# define CONST_NAME_TESTS(TEST_FUNC, IUT) \
std::string TEST_FUNC(int selector) { \
switch (selector) { \
case 0: \
return IUT("").text; \
case 1: \
return IUT("A").text; \
case 2: \
return IUT("Bd").text; \
case 3: \
return IUT("Cef").text; \
case 4: \
return IUT<int>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
case 5: \
return IUT<std::string>().text; /*NOLINT(bugprone-macro-parentheses)*/ \
case 6: \
return IUT<true>("T1", "T2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
case 7: \
return IUT<false>("U1", "U2").text; /*NOLINT(bugprone-macro-parentheses)*/ \
case 8: \
/*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
return IUT<true>(IUT("D1"), IUT("D2")).text; \
case 9: \
/*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
return IUT<false>(IUT("E1"), IUT("E2")).text; \
case 10: \
return IUT("KeepAtEnd").text; \
default: \
break; \
} \
throw std::runtime_error("Invalid selector value."); \
}
CONST_NAME_TESTS(const_name_tests, py::detail::const_name)
# ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
CONST_NAME_TESTS(underscore_tests, py::detail::_)
# endif
#endif // MSVC >= 2017
TEST_SUBMODULE(const_name, m) {
#ifdef PYBIND11_SKIP_TEST_CONST_NAME
m.attr("const_name_tests") = "PYBIND11_SKIP_TEST_CONST_NAME";
#else
m.def("const_name_tests", const_name_tests);
#endif
#ifdef PYBIND11_SKIP_TEST_CONST_NAME
m.attr("underscore_tests") = "PYBIND11_SKIP_TEST_CONST_NAME";
#elif defined(PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY)
m.def("underscore_tests", underscore_tests);
#else
m.attr("underscore_tests") = "PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY not defined.";
#endif
}

31
tests/test_const_name.py Normal file
View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
import pytest
import env
from pybind11_tests import const_name as m
@pytest.mark.parametrize("func", (m.const_name_tests, m.underscore_tests))
@pytest.mark.parametrize(
"selector, expected",
enumerate(
(
"",
"A",
"Bd",
"Cef",
"%",
"%",
"T1",
"U2",
"D1",
"E2",
"KeepAtEnd",
)
),
)
def test_const_name(func, selector, expected):
if isinstance(func, type(u"") if env.PY2 else str):
pytest.skip(func)
text = func(selector)
assert text == expected

View File

@ -19,7 +19,7 @@ namespace pybind11 { namespace detail {
template <> struct type_caster<ArgInspector1> { template <> struct type_caster<ArgInspector1> {
public: public:
// Classic // Classic
#ifndef _ #ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1")); PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
#else #else
PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1")); PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1"));