Skip to content

Commit 3b34392

Browse files
committed
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<base>, shared_ptr<derived>.
1 parent b63f0c6 commit 3b34392

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed

tests/test_smart_ptr_base_derived.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#include "pybind11_tests.h"
2+
3+
#include <iostream>
4+
#include <memory>
5+
6+
namespace pybind11_tests {
7+
namespace smart_ptr_base_derived {
8+
9+
inline void to_cout(std::string text) { std::cout << text << std::endl; }
10+
11+
class cbase {
12+
public:
13+
int get_int() const { return 90146438; }
14+
};
15+
16+
class cderived : public cbase {
17+
public:
18+
// Printing from constructor & destructor for simple external validation.
19+
cderived() {
20+
std::cout << std::endl << "cderived+" << std::endl;
21+
}
22+
~cderived() {
23+
std::cout << std::endl << "cderived-" << std::endl;
24+
}
25+
int get_int() const { return 31607978; }
26+
int base_get_int(const cbase& base) { return get_int() + base.get_int(); }
27+
};
28+
29+
class vbase {
30+
public:
31+
virtual ~vbase() {}
32+
virtual int get_int() const = 0;
33+
};
34+
35+
class vderived : public vbase {
36+
public:
37+
// Printing from constructor & destructor for simple external validation.
38+
vderived() {
39+
std::cout << std::endl << "vderived+" << std::endl;
40+
}
41+
~vderived() {
42+
std::cout << std::endl << "vderived-" << std::endl;
43+
}
44+
int get_int() const override { return 29852452; }
45+
int base_get_int(const vbase& base) { return get_int() + base.get_int(); }
46+
};
47+
48+
class vrederived : public vderived {};
49+
50+
inline std::unique_ptr<cbase>
51+
make_unique_cderived_up_cast() {
52+
// Undefined Behavior (pure C++ problem, NOT a pybind11 problem):
53+
// cderived destructor does not run.
54+
return std::unique_ptr<cderived>(new cderived);
55+
}
56+
57+
inline std::shared_ptr<cderived>
58+
make_shared_cderived(bool use_custom_deleter = false) {
59+
if (use_custom_deleter) {
60+
return std::shared_ptr<cderived>(
61+
new cderived, [](cderived *p) { delete p; });
62+
}
63+
return std::shared_ptr<cderived>(new cderived);
64+
}
65+
66+
inline std::shared_ptr<cbase>
67+
make_shared_cderived_up_cast(bool use_custom_deleter = false) {
68+
return make_shared_cderived(use_custom_deleter);
69+
}
70+
71+
inline int pass_unique_cbase(std::unique_ptr<cbase> cb) {
72+
return cb->get_int();
73+
}
74+
75+
inline int pass_shared_cbase(std::shared_ptr<cbase> cb) {
76+
return cb->get_int();
77+
}
78+
79+
inline int pass_shared_cderived(std::shared_ptr<cderived> cd) {
80+
return cd->get_int();
81+
}
82+
83+
inline std::unique_ptr<vbase>
84+
make_unique_vderived_up_cast() {
85+
// Well-defined behavior because vderived has a virtual destructor.
86+
return std::unique_ptr<vderived>(new vderived);
87+
}
88+
89+
inline std::shared_ptr<vderived>
90+
make_shared_vderived(bool use_custom_deleter = false) {
91+
if (use_custom_deleter) {
92+
return std::shared_ptr<vderived>(
93+
new vderived, [](vderived *p) { delete p; });
94+
}
95+
return std::shared_ptr<vderived>(new vderived);
96+
}
97+
98+
inline std::shared_ptr<vbase>
99+
make_shared_vderived_up_cast(bool use_custom_deleter = false) {
100+
return make_shared_vderived(use_custom_deleter);
101+
}
102+
103+
inline int pass_unique_vbase(std::unique_ptr<vbase> vb) {
104+
return vb->get_int();
105+
}
106+
107+
inline int pass_shared_vbase(std::shared_ptr<vbase> vb) {
108+
return vb->get_int();
109+
}
110+
111+
inline int pass_shared_vderived(std::shared_ptr<vderived> vd) {
112+
return vd->get_int();
113+
}
114+
115+
inline int pass_shared_vrederived(std::shared_ptr<vrederived> vr) {
116+
return vr->get_int();
117+
}
118+
119+
TEST_SUBMODULE(smart_ptr_base_derived, m) {
120+
m.def("to_cout", to_cout);
121+
122+
py::class_<cbase, std::shared_ptr<cbase>>(m, "cbase")
123+
.def(py::init<>())
124+
.def("get_int", &cbase::get_int);
125+
126+
py::class_<cderived, cbase, std::shared_ptr<cderived>>(m, "cderived")
127+
.def(py::init<>())
128+
.def("get_int", &cderived::get_int);
129+
130+
py::class_<vbase, std::shared_ptr<vbase>>(m, "vbase")
131+
.def("get_int", &vbase::get_int);
132+
133+
py::class_<vderived, vbase, std::shared_ptr<vderived>>(m, "vderived")
134+
.def(py::init<>());
135+
136+
py::class_<vrederived, vderived, std::shared_ptr<vrederived>>(m, "vrederived")
137+
.def(py::init<>());
138+
139+
m.def("make_shared_cderived",
140+
make_shared_cderived,
141+
py::arg("use_custom_deleter") = false);
142+
m.def("make_shared_cderived_up_cast",
143+
make_shared_cderived_up_cast,
144+
py::arg("use_custom_deleter") = false);
145+
m.def("pass_shared_cbase", pass_shared_cbase);
146+
m.def("pass_shared_cderived", pass_shared_cderived);
147+
148+
m.def("make_shared_vderived",
149+
make_shared_vderived,
150+
py::arg("use_custom_deleter") = false);
151+
m.def("make_shared_vderived_up_cast",
152+
make_shared_vderived_up_cast,
153+
py::arg("use_custom_deleter") = false);
154+
m.def("pass_shared_vbase", pass_shared_vbase);
155+
m.def("pass_shared_vderived", pass_shared_vderived);
156+
m.def("pass_shared_vrederived", pass_shared_vrederived);
157+
}
158+
159+
} // namespace smart_ptr_base_derived
160+
} // namespace pybind11_tests

tests/test_smart_ptr_base_derived.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# -*- coding: utf-8 -*-
2+
import pytest
3+
4+
from pybind11_tests import smart_ptr_base_derived as m
5+
6+
CBASE_GET_INT_RESULT = 90146438
7+
CDERIVED_GET_INT_RESULT = 31607978
8+
VDERIVED_GET_INT_RESULT = 29852452
9+
10+
def test_concrete():
11+
m.to_cout("")
12+
m.to_cout("")
13+
m.to_cout("make_shared_cderived")
14+
cd = m.make_shared_cderived()
15+
assert cd.get_int() == CDERIVED_GET_INT_RESULT
16+
m.pass_shared_cderived(cd)
17+
m.pass_shared_cbase(cd)
18+
cb = m.make_shared_cderived_up_cast()
19+
assert cb.get_int() == CBASE_GET_INT_RESULT
20+
m.pass_shared_cbase(cb)
21+
with pytest.raises(TypeError):
22+
m.pass_shared_cderived(cb)
23+
m.to_cout("")
24+
25+
def test_virtual():
26+
m.to_cout("")
27+
m.to_cout("")
28+
m.to_cout("make_shared_vderived")
29+
vd = m.make_shared_vderived()
30+
assert vd.get_int() == VDERIVED_GET_INT_RESULT
31+
m.pass_shared_vderived(vd)
32+
m.pass_shared_vbase(vd)
33+
vd_uc = m.make_shared_vderived_up_cast()
34+
assert vd_uc.get_int() == VDERIVED_GET_INT_RESULT
35+
assert isinstance(vd_uc, m.vderived) # pybind11 un-did upcast.
36+
m.pass_shared_vbase(vd_uc)
37+
m.pass_shared_vderived(vd_uc)
38+
with pytest.raises(TypeError):
39+
m.pass_shared_vrederived(vd_uc)
40+
m.to_cout("")

0 commit comments

Comments
 (0)