Skip to content

Commit f88515a

Browse files
committed
Adding test_class_sh_disowning_mi.cpp (multiple inheritance).
1 parent 08339d6 commit f88515a

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-0
lines changed

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ set(PYBIND11_TEST_FILES
103103
test_class.cpp
104104
test_class_sh_basic.cpp
105105
test_class_sh_disowning.cpp
106+
test_class_sh_disowning_mi.cpp
106107
test_class_sh_factory_constructors.cpp
107108
test_class_sh_inheritance.cpp
108109
test_class_sh_trampoline_shared_ptr_cpp_arg.cpp

tests/test_class_sh_disowning_mi.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include "pybind11_tests.h"
2+
3+
#include <pybind11/smart_holder.h>
4+
5+
#include <memory>
6+
7+
namespace pybind11_tests {
8+
namespace class_sh_disowning_mi {
9+
10+
// Diamond inheritance (copied from test_multiple_inheritance.cpp).
11+
struct B {
12+
int val_b = 10;
13+
B() = default;
14+
B(const B &) = default;
15+
virtual ~B() = default;
16+
};
17+
18+
struct C0 : public virtual B {
19+
int val_c0 = 20;
20+
};
21+
22+
struct C1 : public virtual B {
23+
int val_c1 = 21;
24+
};
25+
26+
struct D : public C0, public C1 {
27+
int val_d = 30;
28+
};
29+
30+
void disown(std::unique_ptr<B>) {}
31+
32+
} // namespace class_sh_disowning_mi
33+
} // namespace pybind11_tests
34+
35+
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::B)
36+
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::C0)
37+
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::C1)
38+
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_disowning_mi::D)
39+
40+
TEST_SUBMODULE(class_sh_disowning_mi, m) {
41+
using namespace pybind11_tests::class_sh_disowning_mi;
42+
43+
py::classh<B>(m, "B")
44+
.def(py::init<>())
45+
.def_readonly("val_b", &D::val_b)
46+
.def("b", [](B *self) { return self; })
47+
.def("get", [](const B &self) { return self.val_b; });
48+
49+
py::classh<C0, B>(m, "C0")
50+
.def(py::init<>())
51+
.def_readonly("val_c0", &D::val_c0)
52+
.def("c0", [](C0 *self) { return self; })
53+
.def("get", [](const C0 &self) { return self.val_b * 100 + self.val_c0; });
54+
55+
py::classh<C1, B>(m, "C1")
56+
.def(py::init<>())
57+
.def_readonly("val_c1", &D::val_c1)
58+
.def("c1", [](C1 *self) { return self; })
59+
.def("get", [](const C1 &self) { return self.val_b * 100 + self.val_c1; });
60+
61+
py::classh<D, C0, C1>(m, "D")
62+
.def(py::init<>())
63+
.def_readonly("val_d", &D::val_d)
64+
.def("d", [](D *self) { return self; })
65+
.def("get", [](const D &self) {
66+
return self.val_b * 1000000 + self.val_c0 * 10000 + self.val_c1 * 100 + self.val_d;
67+
});
68+
69+
m.def("disown", disown);
70+
}

tests/test_class_sh_disowning_mi.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from pybind11_tests import class_sh_disowning_mi as m
4+
5+
6+
def test_diamond_inheritance():
7+
# Very similar to test_multiple_inheritance.py:test_diamond_inheritance.
8+
d = m.D()
9+
assert d is d.d()
10+
assert d is d.c0()
11+
assert d is d.c1()
12+
assert d is d.b()
13+
assert d is d.c0().b()
14+
assert d is d.c1().b()
15+
assert d is d.c0().c1().b().c0().b()
16+
17+
18+
def was_disowned(obj):
19+
try:
20+
obj.get()
21+
except ValueError as e:
22+
assert (
23+
str(e)
24+
== "Missing value for wrapped C++ type: Python instance was disowned."
25+
)
26+
return True
27+
return False
28+
29+
30+
def test_disown_b():
31+
b = m.B()
32+
assert b.get() == 10
33+
m.disown(b)
34+
assert was_disowned(b)
35+
36+
37+
def test_disown_c0():
38+
c0 = m.C0()
39+
assert c0.get() == 1020
40+
b = c0.b()
41+
m.disown(c0)
42+
assert was_disowned(c0)
43+
assert was_disowned(b)
44+
45+
46+
def test_disown_c1():
47+
c1 = m.C1()
48+
assert c1.get() == 1021
49+
b = c1.b()
50+
m.disown(c1)
51+
assert was_disowned(c1)
52+
assert was_disowned(b)
53+
54+
55+
def test_disown_d():
56+
d = m.D()
57+
assert d.get() == 10202130
58+
b = d.b()
59+
c0 = d.c0()
60+
c1 = d.c1()
61+
m.disown(d)
62+
assert was_disowned(d)
63+
assert was_disowned(c1)
64+
assert was_disowned(c0)
65+
assert was_disowned(b)

0 commit comments

Comments
 (0)