From 3b343920c54a28a4655a989fc563b71747644b69 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 18 Dec 2020 15:36:12 -0800 Subject: [PATCH] Copying tests as-is from xxx_value_ptr_xxx_holder branch. https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder Systematically exercising casting between shared_ptr, shared_ptr. --- tests/test_smart_ptr_base_derived.cpp | 160 ++++++++++++++++++++++++++ tests/test_smart_ptr_base_derived.py | 40 +++++++ 2 files changed, 200 insertions(+) create mode 100644 tests/test_smart_ptr_base_derived.cpp create mode 100644 tests/test_smart_ptr_base_derived.py diff --git a/tests/test_smart_ptr_base_derived.cpp b/tests/test_smart_ptr_base_derived.cpp new file mode 100644 index 00000000000..844bbd0517f --- /dev/null +++ b/tests/test_smart_ptr_base_derived.cpp @@ -0,0 +1,160 @@ +#include "pybind11_tests.h" + +#include +#include + +namespace pybind11_tests { +namespace smart_ptr_base_derived { + +inline void to_cout(std::string text) { std::cout << text << std::endl; } + +class cbase { + public: + int get_int() const { return 90146438; } +}; + +class cderived : public cbase { + public: + // Printing from constructor & destructor for simple external validation. + cderived() { + std::cout << std::endl << "cderived+" << std::endl; + } + ~cderived() { + std::cout << std::endl << "cderived-" << std::endl; + } + int get_int() const { return 31607978; } + int base_get_int(const cbase& base) { return get_int() + base.get_int(); } +}; + +class vbase { + public: + virtual ~vbase() {} + virtual int get_int() const = 0; +}; + +class vderived : public vbase { + public: + // Printing from constructor & destructor for simple external validation. + vderived() { + std::cout << std::endl << "vderived+" << std::endl; + } + ~vderived() { + std::cout << std::endl << "vderived-" << std::endl; + } + int get_int() const override { return 29852452; } + int base_get_int(const vbase& base) { return get_int() + base.get_int(); } +}; + +class vrederived : public vderived {}; + +inline std::unique_ptr +make_unique_cderived_up_cast() { + // Undefined Behavior (pure C++ problem, NOT a pybind11 problem): + // cderived destructor does not run. + return std::unique_ptr(new cderived); +} + +inline std::shared_ptr +make_shared_cderived(bool use_custom_deleter = false) { + if (use_custom_deleter) { + return std::shared_ptr( + new cderived, [](cderived *p) { delete p; }); + } + return std::shared_ptr(new cderived); +} + +inline std::shared_ptr +make_shared_cderived_up_cast(bool use_custom_deleter = false) { + return make_shared_cderived(use_custom_deleter); +} + +inline int pass_unique_cbase(std::unique_ptr cb) { + return cb->get_int(); +} + +inline int pass_shared_cbase(std::shared_ptr cb) { + return cb->get_int(); +} + +inline int pass_shared_cderived(std::shared_ptr cd) { + return cd->get_int(); +} + +inline std::unique_ptr +make_unique_vderived_up_cast() { + // Well-defined behavior because vderived has a virtual destructor. + return std::unique_ptr(new vderived); +} + +inline std::shared_ptr +make_shared_vderived(bool use_custom_deleter = false) { + if (use_custom_deleter) { + return std::shared_ptr( + new vderived, [](vderived *p) { delete p; }); + } + return std::shared_ptr(new vderived); +} + +inline std::shared_ptr +make_shared_vderived_up_cast(bool use_custom_deleter = false) { + return make_shared_vderived(use_custom_deleter); +} + +inline int pass_unique_vbase(std::unique_ptr vb) { + return vb->get_int(); +} + +inline int pass_shared_vbase(std::shared_ptr vb) { + return vb->get_int(); +} + +inline int pass_shared_vderived(std::shared_ptr vd) { + return vd->get_int(); +} + +inline int pass_shared_vrederived(std::shared_ptr vr) { + return vr->get_int(); +} + +TEST_SUBMODULE(smart_ptr_base_derived, m) { + m.def("to_cout", to_cout); + + py::class_>(m, "cbase") + .def(py::init<>()) + .def("get_int", &cbase::get_int); + + py::class_>(m, "cderived") + .def(py::init<>()) + .def("get_int", &cderived::get_int); + + py::class_>(m, "vbase") + .def("get_int", &vbase::get_int); + + py::class_>(m, "vderived") + .def(py::init<>()); + + py::class_>(m, "vrederived") + .def(py::init<>()); + + m.def("make_shared_cderived", + make_shared_cderived, + py::arg("use_custom_deleter") = false); + m.def("make_shared_cderived_up_cast", + make_shared_cderived_up_cast, + py::arg("use_custom_deleter") = false); + m.def("pass_shared_cbase", pass_shared_cbase); + m.def("pass_shared_cderived", pass_shared_cderived); + + m.def("make_shared_vderived", + make_shared_vderived, + py::arg("use_custom_deleter") = false); + m.def("make_shared_vderived_up_cast", + make_shared_vderived_up_cast, + py::arg("use_custom_deleter") = false); + m.def("pass_shared_vbase", pass_shared_vbase); + m.def("pass_shared_vderived", pass_shared_vderived); + m.def("pass_shared_vrederived", pass_shared_vrederived); +} + +} // namespace smart_ptr_base_derived +} // namespace pybind11_tests diff --git a/tests/test_smart_ptr_base_derived.py b/tests/test_smart_ptr_base_derived.py new file mode 100644 index 00000000000..b57c364da88 --- /dev/null +++ b/tests/test_smart_ptr_base_derived.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +import pytest + +from pybind11_tests import smart_ptr_base_derived as m + +CBASE_GET_INT_RESULT = 90146438 +CDERIVED_GET_INT_RESULT = 31607978 +VDERIVED_GET_INT_RESULT = 29852452 + +def test_concrete(): + m.to_cout("") + m.to_cout("") + m.to_cout("make_shared_cderived") + cd = m.make_shared_cderived() + assert cd.get_int() == CDERIVED_GET_INT_RESULT + m.pass_shared_cderived(cd) + m.pass_shared_cbase(cd) + cb = m.make_shared_cderived_up_cast() + assert cb.get_int() == CBASE_GET_INT_RESULT + m.pass_shared_cbase(cb) + with pytest.raises(TypeError): + m.pass_shared_cderived(cb) + m.to_cout("") + +def test_virtual(): + m.to_cout("") + m.to_cout("") + m.to_cout("make_shared_vderived") + vd = m.make_shared_vderived() + assert vd.get_int() == VDERIVED_GET_INT_RESULT + m.pass_shared_vderived(vd) + m.pass_shared_vbase(vd) + vd_uc = m.make_shared_vderived_up_cast() + assert vd_uc.get_int() == VDERIVED_GET_INT_RESULT + assert isinstance(vd_uc, m.vderived) # pybind11 un-did upcast. + m.pass_shared_vbase(vd_uc) + m.pass_shared_vderived(vd_uc) + with pytest.raises(TypeError): + m.pass_shared_vrederived(vd_uc) + m.to_cout("")