[skip ci] Simplify test case.

This commit is contained in:
Ralf W. Grosse-Kunstleve
2025-04-19 00:18:23 -07:00
parent b160f6c2b1
commit 2fe82b2fdf
2 changed files with 40 additions and 59 deletions

View File

@@ -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 <utility>
#include <memory>
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<VirtBase> 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<WpBase> get_object() const { return m_obj.lock(); }
void set_object(std::shared_ptr<WpBase> 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<WpBase> m_obj;
private:
std::weak_ptr<VirtBase> 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<WpBase, PyWpBase>(m, "WpBase")
py::classh<VirtBase, PyVirtBase>(m, "VirtBase")
.def(py::init<>())
.def(py::init([](int) { return std::make_shared<PyWpBase>(); }))
.def("is_base_used", &WpBase::is_base_used)
.def("has_python_instance", &WpBase::has_python_instance);
.def("get_code", &VirtBase::get_code);
py::classh<WpBaseTester>(m, "WpBaseTester")
py::classh<WpOwner>(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);
}

View File

@@ -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