From f88515a557da91d0b18b8651f8dfba8afaf26040 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 23 Mar 2021 15:45:34 -0700 Subject: [PATCH] Adding test_class_sh_disowning_mi.cpp (multiple inheritance). --- tests/CMakeLists.txt | 1 + tests/test_class_sh_disowning_mi.cpp | 70 ++++++++++++++++++++++++++++ tests/test_class_sh_disowning_mi.py | 65 ++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 tests/test_class_sh_disowning_mi.cpp create mode 100644 tests/test_class_sh_disowning_mi.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 19ba6399bf..acc9efb172 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -103,6 +103,7 @@ set(PYBIND11_TEST_FILES test_class.cpp test_class_sh_basic.cpp test_class_sh_disowning.cpp + test_class_sh_disowning_mi.cpp test_class_sh_factory_constructors.cpp test_class_sh_inheritance.cpp test_class_sh_trampoline_shared_ptr_cpp_arg.cpp diff --git a/tests/test_class_sh_disowning_mi.cpp b/tests/test_class_sh_disowning_mi.cpp new file mode 100644 index 0000000000..1858320bb0 --- /dev/null +++ b/tests/test_class_sh_disowning_mi.cpp @@ -0,0 +1,70 @@ +#include "pybind11_tests.h" + +#include + +#include + +namespace pybind11_tests { +namespace class_sh_disowning_mi { + +// Diamond inheritance (copied from test_multiple_inheritance.cpp). +struct B { + int val_b = 10; + B() = default; + B(const B &) = default; + virtual ~B() = default; +}; + +struct C0 : public virtual B { + int val_c0 = 20; +}; + +struct C1 : public virtual B { + int val_c1 = 21; +}; + +struct D : public C0, public C1 { + int val_d = 30; +}; + +void disown(std::unique_ptr) {} + +} // namespace class_sh_disowning_mi +} // namespace pybind11_tests + +PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::B) +PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::C0) +PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::C1) +PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::D) + +TEST_SUBMODULE(class_sh_disowning_mi, m) { + using namespace pybind11_tests::class_sh_disowning_mi; + + py::classh(m, "B") + .def(py::init<>()) + .def_readonly("val_b", &D::val_b) + .def("b", [](B *self) { return self; }) + .def("get", [](const B &self) { return self.val_b; }); + + py::classh(m, "C0") + .def(py::init<>()) + .def_readonly("val_c0", &D::val_c0) + .def("c0", [](C0 *self) { return self; }) + .def("get", [](const C0 &self) { return self.val_b * 100 + self.val_c0; }); + + py::classh(m, "C1") + .def(py::init<>()) + .def_readonly("val_c1", &D::val_c1) + .def("c1", [](C1 *self) { return self; }) + .def("get", [](const C1 &self) { return self.val_b * 100 + self.val_c1; }); + + py::classh(m, "D") + .def(py::init<>()) + .def_readonly("val_d", &D::val_d) + .def("d", [](D *self) { return self; }) + .def("get", [](const D &self) { + return self.val_b * 1000000 + self.val_c0 * 10000 + self.val_c1 * 100 + self.val_d; + }); + + m.def("disown", disown); +} diff --git a/tests/test_class_sh_disowning_mi.py b/tests/test_class_sh_disowning_mi.py new file mode 100644 index 0000000000..bb0ea23efa --- /dev/null +++ b/tests/test_class_sh_disowning_mi.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +from pybind11_tests import class_sh_disowning_mi as m + + +def test_diamond_inheritance(): + # Very similar to test_multiple_inheritance.py:test_diamond_inheritance. + d = m.D() + assert d is d.d() + assert d is d.c0() + assert d is d.c1() + assert d is d.b() + assert d is d.c0().b() + assert d is d.c1().b() + assert d is d.c0().c1().b().c0().b() + + +def was_disowned(obj): + try: + obj.get() + except ValueError as e: + assert ( + str(e) + == "Missing value for wrapped C++ type: Python instance was disowned." + ) + return True + return False + + +def test_disown_b(): + b = m.B() + assert b.get() == 10 + m.disown(b) + assert was_disowned(b) + + +def test_disown_c0(): + c0 = m.C0() + assert c0.get() == 1020 + b = c0.b() + m.disown(c0) + assert was_disowned(c0) + assert was_disowned(b) + + +def test_disown_c1(): + c1 = m.C1() + assert c1.get() == 1021 + b = c1.b() + m.disown(c1) + assert was_disowned(c1) + assert was_disowned(b) + + +def test_disown_d(): + d = m.D() + assert d.get() == 10202130 + b = d.b() + c0 = d.c0() + c1 = d.c1() + m.disown(d) + assert was_disowned(d) + assert was_disowned(c1) + assert was_disowned(c0) + assert was_disowned(b)