Skip to content

Adding dedicated test_const_name. #3578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions include/pybind11/detail/descr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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...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)...);
};

Expand All @@ -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 {'%'}; }

// The "_" might be defined as a macro - don't define it if so.
// Repeating the const_name code to avoid introducing a #define.
// If "_" is defined as a macro, py::detail::_ cannot be provided.
// 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 _
#define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
template <size_t N>
constexpr descr<N-1> _(char const(&text)[N]) { return const_name<N>(text); }
template <bool B, size_t N1, size_t N2>
Expand All @@ -107,7 +111,7 @@ auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::dig
return const_name<Size>();
}
template <typename Type> constexpr descr<1, Type> _() { return const_name<Type>(); }
#endif
#endif // #ifndef _

constexpr descr<0> concat() { return {}; }

Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ set(PYBIND11_TEST_FILES
test_callbacks.cpp
test_chrono.cpp
test_class.cpp
test_const_name.cpp
test_constants_and_functions.cpp
test_copy_move.cpp
test_custom_type_casters.cpp
Expand Down
70 changes: 70 additions & 0 deletions tests/test_const_name.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 31 additions & 0 deletions tests/test_const_name.py
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/test_custom_type_casters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace pybind11 { namespace detail {
template <> struct type_caster<ArgInspector1> {
public:
// Classic
#ifndef _
#ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
#else
PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1"));
Expand Down