From 2fe82b2fdf94e0b17747a30a05b63d830cd7d790 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 19 Apr 2025 00:18:23 -0700 Subject: [PATCH] [skip ci] Simplify test case. --- tests/test_class_sh_trampoline_weak_ptr.cpp | 64 +++++++++------------ tests/test_class_sh_trampoline_weak_ptr.py | 35 +++++------ 2 files changed, 40 insertions(+), 59 deletions(-) diff --git a/tests/test_class_sh_trampoline_weak_ptr.cpp b/tests/test_class_sh_trampoline_weak_ptr.cpp index dd53206e4..9b7651cce 100644 --- a/tests/test_class_sh_trampoline_weak_ptr.cpp +++ b/tests/test_class_sh_trampoline_weak_ptr.cpp @@ -1,41 +1,37 @@ -// Copyright (c) 2021 The Pybind Development Team. +// Copyright (c) 2025 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" -#include +#include namespace pybind11_tests { namespace class_sh_trampoline_weak_ptr { -// // For testing whether a python subclass of a C++ object can be accessed from a C++ weak_ptr -struct WpBase { - // returns true if the base virtual function is called - virtual bool is_base_used() { return true; } +struct VirtBase { + virtual ~VirtBase() = default; + virtual int get_code() { return 100; } +}; - // returns true if there's an associated python instance - bool has_python_instance() { - auto *tinfo = py::detail::get_type_info(typeid(WpBase)); - return (bool) py::detail::get_object_handle(this, tinfo); +struct PyVirtBase : VirtBase, py::trampoline_self_life_support { + using VirtBase::VirtBase; + int get_code() override { PYBIND11_OVERRIDE(int, VirtBase, get_code); } +}; + +struct WpOwner { + void set_wp(std::shared_ptr sp) { wp = sp; } + + int get_code() { + auto sp = wp.lock(); + if (!sp) { + return -999; + } + return sp->get_code(); } - WpBase() = default; - WpBase(const WpBase &) = delete; - virtual ~WpBase() = default; -}; - -struct PyWpBase : WpBase { - using WpBase::WpBase; - bool is_base_used() override { PYBIND11_OVERRIDE(bool, WpBase, is_base_used); } -}; - -struct WpBaseTester { - std::shared_ptr get_object() const { return m_obj.lock(); } - void set_object(std::shared_ptr obj) { m_obj = obj; } - bool is_expired() { return m_obj.expired(); } - bool is_base_used() { return m_obj.lock()->is_base_used(); } - std::weak_ptr m_obj; +private: + std::weak_ptr wp; }; } // namespace class_sh_trampoline_weak_ptr @@ -44,18 +40,12 @@ struct WpBaseTester { using namespace pybind11_tests::class_sh_trampoline_weak_ptr; TEST_SUBMODULE(class_sh_trampoline_weak_ptr, m) { - // For testing whether a python subclass of a C++ object can be accessed from a C++ weak_ptr - - py::classh(m, "WpBase") + py::classh(m, "VirtBase") .def(py::init<>()) - .def(py::init([](int) { return std::make_shared(); })) - .def("is_base_used", &WpBase::is_base_used) - .def("has_python_instance", &WpBase::has_python_instance); + .def("get_code", &VirtBase::get_code); - py::classh(m, "WpBaseTester") + py::classh(m, "WpOwner") .def(py::init<>()) - .def("get_object", &WpBaseTester::get_object) - .def("set_object", &WpBaseTester::set_object) - .def("is_expired", &WpBaseTester::is_expired) - .def("is_base_used", &WpBaseTester::is_base_used); + .def("set_wp", &WpOwner::set_wp) + .def("get_code", &WpOwner::get_code); } diff --git a/tests/test_class_sh_trampoline_weak_ptr.py b/tests/test_class_sh_trampoline_weak_ptr.py index 545c1ad2e..0f24f0158 100644 --- a/tests/test_class_sh_trampoline_weak_ptr.py +++ b/tests/test_class_sh_trampoline_weak_ptr.py @@ -6,31 +6,22 @@ import env # noqa: F401 import pybind11_tests.class_sh_trampoline_weak_ptr as m -@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC") -def test_weak_ptr_base(): - tester = m.WpBaseTester() - - obj = m.WpBase() - - tester.set_object(obj) - - assert tester.is_expired() is False - assert tester.is_base_used() is True - assert tester.get_object().is_base_used() is True +class PyDrvd(m.VirtBase): + def get_code(self): + return 200 @pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC") -def test_weak_ptr_child(): - class PyChild(m.WpBase): - def is_base_used(self): - return False +@pytest.mark.parametrize(("vtype", "expected_code"), [(m.VirtBase, 100), (PyDrvd, 200)]) +def test_weak_ptr_base(vtype, expected_code): + wpo = m.WpOwner() + assert wpo.get_code() == -999 - tester = m.WpBaseTester() + obj = vtype() + assert obj.get_code() == expected_code - obj = PyChild() + wpo.set_wp(obj) + assert wpo.get_code() == expected_code - tester.set_object(obj) - - assert tester.is_expired() is False - assert tester.is_base_used() is False - assert tester.get_object().is_base_used() is False + del obj + assert wpo.get_code() == -999