diff --git a/tests/test_unique_ptr_member.cpp b/tests/test_unique_ptr_member.cpp index 96edf77c5..316dac44e 100644 --- a/tests/test_unique_ptr_member.cpp +++ b/tests/test_unique_ptr_member.cpp @@ -1,15 +1,23 @@ #include "pybind11_tests.h" +#include #include namespace pybind11_tests { namespace unique_ptr_member { +inline void to_cout(std::string text) { std::cout << text << std::endl; } + class pointee { // NOT copyable. public: pointee() = default; - int get_int() const { return 213; } + int get_int() const { + to_cout("pointee::get_int()"); + return 213; + } + + ~pointee() { to_cout("~pointee()"); } private: pointee(const pointee &) = delete; @@ -18,35 +26,64 @@ class pointee { // NOT copyable. pointee &operator=(pointee &&) = delete; }; +inline std::unique_ptr make_unique_pointee() { + return std::unique_ptr(new pointee); +} + class ptr_owner { public: explicit ptr_owner(std::unique_ptr ptr) : ptr_(std::move(ptr)) {} + bool is_owner() const { return bool(ptr_); } + + std::unique_ptr give_up_ownership_via_unique_ptr() { + return std::move(ptr_); + } + std::shared_ptr give_up_ownership_via_shared_ptr() { + return std::move(ptr_); + } + private: std::unique_ptr ptr_; }; // Just to have a minimal example of a typical C++ pattern. inline int cpp_pattern() { - auto obj = std::unique_ptr(new pointee); - int result = (obj ? 10 : 0); + auto obj = make_unique_pointee(); + int result = (obj ? 1 : 8); + obj->get_int(); ptr_owner owner(std::move(obj)); - result += (obj ? 1 : 0); + result = result * 10 + (obj ? 8 : 1); + result = result * 10 + (owner.is_owner() ? 1 : 8); + to_cout("before give up"); + auto reclaimed = owner.give_up_ownership_via_shared_ptr(); + to_cout("after give up"); + result = result * 10 + (owner.is_owner() ? 8 : 1); + result = result * 10 + (reclaimed ? 1 : 8); + reclaimed.reset(); + to_cout("after del"); + result = result * 10 + (reclaimed ? 8 : 1); return result; } TEST_SUBMODULE(unique_ptr_member, m) { - m.def("cpp_pattern", cpp_pattern); + m.def("to_cout", to_cout); - py::class_(m, "pointee") + py::class_>(m, "pointee") .def(py::init<>()) .def("get_int", &pointee::get_int); + m.def("make_unique_pointee", make_unique_pointee); + py::class_(m, "ptr_owner") -#ifdef FEAT_UNIQUE_PTR_ARG - .def(py::init>(), py::arg("ptr")) -#endif - ; + //.def(py::init>(), py::arg("ptr")) + .def("is_owner", &ptr_owner::is_owner) + .def("give_up_ownership_via_unique_ptr", + &ptr_owner::give_up_ownership_via_unique_ptr) + .def("give_up_ownership_via_shared_ptr", + &ptr_owner::give_up_ownership_via_shared_ptr); + + m.def("cpp_pattern", cpp_pattern); } } // namespace unique_ptr_member diff --git a/tests/test_unique_ptr_member.py b/tests/test_unique_ptr_member.py index 121b8ef05..85b07f609 100644 --- a/tests/test_unique_ptr_member.py +++ b/tests/test_unique_ptr_member.py @@ -4,15 +4,35 @@ import pytest from pybind11_tests import unique_ptr_member as m -def test_cpp_pattern(): - res = m.cpp_pattern() - assert res == 10 +def test_make_unique_pointee(): + m.to_cout("") + obj = m.make_unique_pointee() + assert obj.get_int() == 213 + m.to_cout("") def test_pointee_and_ptr_owner(): + m.to_cout("") obj = m.pointee() assert obj.get_int() == 213 - m.ptr_owner(obj) - with pytest.raises(ValueError) as exc_info: + owner = m.ptr_owner(obj) + with pytest.raises(RuntimeError) as exc_info: obj.get_int() - assert str(exc_info.value).startswith("Missing value for wrapped C++ type ") + assert str(exc_info.value) == "Invalid object instance" + assert owner.is_owner() + m.to_cout("before give up") + reclaimed = owner.give_up_ownership_via_shared_ptr() + m.to_cout("after give up") + assert not owner.is_owner() + # assert reclaimed.get_int() == 213 + del reclaimed + m.to_cout("after del") + m.to_cout("3") + m.to_cout("") + + +def test_cpp_pattern(): + m.to_cout("") + res = m.cpp_pattern() + assert res == 111111 + m.to_cout("")