112037Sandreas.sandberg@arm.comimport pytest
212391Sjason@lowepower.comfrom pybind11_tests import ConstructorStats
312391Sjason@lowepower.comfrom pybind11_tests import multiple_inheritance as m
411986Sandreas.sandberg@arm.com
511986Sandreas.sandberg@arm.com
611986Sandreas.sandberg@arm.comdef test_multiple_inheritance_cpp():
712391Sjason@lowepower.com    mt = m.MIType(3, 4)
811986Sandreas.sandberg@arm.com
911986Sandreas.sandberg@arm.com    assert mt.foo() == 3
1011986Sandreas.sandberg@arm.com    assert mt.bar() == 4
1111986Sandreas.sandberg@arm.com
1211986Sandreas.sandberg@arm.com
1311986Sandreas.sandberg@arm.comdef test_multiple_inheritance_mix1():
1411986Sandreas.sandberg@arm.com    class Base1:
1511986Sandreas.sandberg@arm.com        def __init__(self, i):
1611986Sandreas.sandberg@arm.com            self.i = i
1711986Sandreas.sandberg@arm.com
1811986Sandreas.sandberg@arm.com        def foo(self):
1911986Sandreas.sandberg@arm.com            return self.i
2011986Sandreas.sandberg@arm.com
2112391Sjason@lowepower.com    class MITypePy(Base1, m.Base2):
2211986Sandreas.sandberg@arm.com        def __init__(self, i, j):
2311986Sandreas.sandberg@arm.com            Base1.__init__(self, i)
2412391Sjason@lowepower.com            m.Base2.__init__(self, j)
2511986Sandreas.sandberg@arm.com
2611986Sandreas.sandberg@arm.com    mt = MITypePy(3, 4)
2711986Sandreas.sandberg@arm.com
2811986Sandreas.sandberg@arm.com    assert mt.foo() == 3
2911986Sandreas.sandberg@arm.com    assert mt.bar() == 4
3011986Sandreas.sandberg@arm.com
3111986Sandreas.sandberg@arm.com
3211986Sandreas.sandberg@arm.comdef test_multiple_inheritance_mix2():
3311986Sandreas.sandberg@arm.com
3411986Sandreas.sandberg@arm.com    class Base2:
3511986Sandreas.sandberg@arm.com        def __init__(self, i):
3611986Sandreas.sandberg@arm.com            self.i = i
3711986Sandreas.sandberg@arm.com
3811986Sandreas.sandberg@arm.com        def bar(self):
3911986Sandreas.sandberg@arm.com            return self.i
4011986Sandreas.sandberg@arm.com
4112391Sjason@lowepower.com    class MITypePy(m.Base1, Base2):
4211986Sandreas.sandberg@arm.com        def __init__(self, i, j):
4312391Sjason@lowepower.com            m.Base1.__init__(self, i)
4411986Sandreas.sandberg@arm.com            Base2.__init__(self, j)
4511986Sandreas.sandberg@arm.com
4611986Sandreas.sandberg@arm.com    mt = MITypePy(3, 4)
4711986Sandreas.sandberg@arm.com
4811986Sandreas.sandberg@arm.com    assert mt.foo() == 3
4911986Sandreas.sandberg@arm.com    assert mt.bar() == 4
5011986Sandreas.sandberg@arm.com
5111986Sandreas.sandberg@arm.com
5212391Sjason@lowepower.comdef test_multiple_inheritance_python():
5312037Sandreas.sandberg@arm.com
5412391Sjason@lowepower.com    class MI1(m.Base1, m.Base2):
5512391Sjason@lowepower.com        def __init__(self, i, j):
5612391Sjason@lowepower.com            m.Base1.__init__(self, i)
5712391Sjason@lowepower.com            m.Base2.__init__(self, j)
5812391Sjason@lowepower.com
5912391Sjason@lowepower.com    class B1(object):
6012391Sjason@lowepower.com        def v(self):
6112391Sjason@lowepower.com            return 1
6212391Sjason@lowepower.com
6312391Sjason@lowepower.com    class MI2(B1, m.Base1, m.Base2):
6412391Sjason@lowepower.com        def __init__(self, i, j):
6512391Sjason@lowepower.com            B1.__init__(self)
6612391Sjason@lowepower.com            m.Base1.__init__(self, i)
6712391Sjason@lowepower.com            m.Base2.__init__(self, j)
6812391Sjason@lowepower.com
6912391Sjason@lowepower.com    class MI3(MI2):
7012391Sjason@lowepower.com        def __init__(self, i, j):
7112391Sjason@lowepower.com            MI2.__init__(self, i, j)
7212391Sjason@lowepower.com
7312391Sjason@lowepower.com    class MI4(MI3, m.Base2):
7412391Sjason@lowepower.com        def __init__(self, i, j):
7512391Sjason@lowepower.com            MI3.__init__(self, i, j)
7612391Sjason@lowepower.com            # This should be ignored (Base2 is already initialized via MI2):
7712391Sjason@lowepower.com            m.Base2.__init__(self, i + 100)
7812391Sjason@lowepower.com
7912391Sjason@lowepower.com    class MI5(m.Base2, B1, m.Base1):
8012391Sjason@lowepower.com        def __init__(self, i, j):
8112391Sjason@lowepower.com            B1.__init__(self)
8212391Sjason@lowepower.com            m.Base1.__init__(self, i)
8312391Sjason@lowepower.com            m.Base2.__init__(self, j)
8412391Sjason@lowepower.com
8512391Sjason@lowepower.com    class MI6(m.Base2, B1):
8612391Sjason@lowepower.com        def __init__(self, i):
8712391Sjason@lowepower.com            m.Base2.__init__(self, i)
8812391Sjason@lowepower.com            B1.__init__(self)
8912391Sjason@lowepower.com
9012391Sjason@lowepower.com    class B2(B1):
9112391Sjason@lowepower.com        def v(self):
9212391Sjason@lowepower.com            return 2
9312391Sjason@lowepower.com
9412391Sjason@lowepower.com    class B3(object):
9512391Sjason@lowepower.com        def v(self):
9612391Sjason@lowepower.com            return 3
9712391Sjason@lowepower.com
9812391Sjason@lowepower.com    class B4(B3, B2):
9912391Sjason@lowepower.com        def v(self):
10012391Sjason@lowepower.com            return 4
10112391Sjason@lowepower.com
10212391Sjason@lowepower.com    class MI7(B4, MI6):
10312391Sjason@lowepower.com        def __init__(self, i):
10412391Sjason@lowepower.com            B4.__init__(self)
10512391Sjason@lowepower.com            MI6.__init__(self, i)
10612391Sjason@lowepower.com
10712391Sjason@lowepower.com    class MI8(MI6, B3):
10812391Sjason@lowepower.com        def __init__(self, i):
10912391Sjason@lowepower.com            MI6.__init__(self, i)
11012391Sjason@lowepower.com            B3.__init__(self)
11112391Sjason@lowepower.com
11212391Sjason@lowepower.com    class MI8b(B3, MI6):
11312391Sjason@lowepower.com        def __init__(self, i):
11412391Sjason@lowepower.com            B3.__init__(self)
11512391Sjason@lowepower.com            MI6.__init__(self, i)
11612391Sjason@lowepower.com
11712391Sjason@lowepower.com    mi1 = MI1(1, 2)
11812391Sjason@lowepower.com    assert mi1.foo() == 1
11912391Sjason@lowepower.com    assert mi1.bar() == 2
12012391Sjason@lowepower.com
12112391Sjason@lowepower.com    mi2 = MI2(3, 4)
12212391Sjason@lowepower.com    assert mi2.v() == 1
12312391Sjason@lowepower.com    assert mi2.foo() == 3
12412391Sjason@lowepower.com    assert mi2.bar() == 4
12512391Sjason@lowepower.com
12612391Sjason@lowepower.com    mi3 = MI3(5, 6)
12712391Sjason@lowepower.com    assert mi3.v() == 1
12812391Sjason@lowepower.com    assert mi3.foo() == 5
12912391Sjason@lowepower.com    assert mi3.bar() == 6
13012391Sjason@lowepower.com
13112391Sjason@lowepower.com    mi4 = MI4(7, 8)
13212391Sjason@lowepower.com    assert mi4.v() == 1
13312391Sjason@lowepower.com    assert mi4.foo() == 7
13412391Sjason@lowepower.com    assert mi4.bar() == 8
13512391Sjason@lowepower.com
13612391Sjason@lowepower.com    mi5 = MI5(10, 11)
13712391Sjason@lowepower.com    assert mi5.v() == 1
13812391Sjason@lowepower.com    assert mi5.foo() == 10
13912391Sjason@lowepower.com    assert mi5.bar() == 11
14012391Sjason@lowepower.com
14112391Sjason@lowepower.com    mi6 = MI6(12)
14212391Sjason@lowepower.com    assert mi6.v() == 1
14312391Sjason@lowepower.com    assert mi6.bar() == 12
14412391Sjason@lowepower.com
14512391Sjason@lowepower.com    mi7 = MI7(13)
14612391Sjason@lowepower.com    assert mi7.v() == 4
14712391Sjason@lowepower.com    assert mi7.bar() == 13
14812391Sjason@lowepower.com
14912391Sjason@lowepower.com    mi8 = MI8(14)
15012391Sjason@lowepower.com    assert mi8.v() == 1
15112391Sjason@lowepower.com    assert mi8.bar() == 14
15212391Sjason@lowepower.com
15312391Sjason@lowepower.com    mi8b = MI8b(15)
15412391Sjason@lowepower.com    assert mi8b.v() == 3
15512391Sjason@lowepower.com    assert mi8b.bar() == 15
15612391Sjason@lowepower.com
15712391Sjason@lowepower.com
15812391Sjason@lowepower.comdef test_multiple_inheritance_python_many_bases():
15912391Sjason@lowepower.com
16012391Sjason@lowepower.com    class MIMany14(m.BaseN1, m.BaseN2, m.BaseN3, m.BaseN4):
16112391Sjason@lowepower.com        def __init__(self):
16212391Sjason@lowepower.com            m.BaseN1.__init__(self, 1)
16312391Sjason@lowepower.com            m.BaseN2.__init__(self, 2)
16412391Sjason@lowepower.com            m.BaseN3.__init__(self, 3)
16512391Sjason@lowepower.com            m.BaseN4.__init__(self, 4)
16612391Sjason@lowepower.com
16712391Sjason@lowepower.com    class MIMany58(m.BaseN5, m.BaseN6, m.BaseN7, m.BaseN8):
16812391Sjason@lowepower.com        def __init__(self):
16912391Sjason@lowepower.com            m.BaseN5.__init__(self, 5)
17012391Sjason@lowepower.com            m.BaseN6.__init__(self, 6)
17112391Sjason@lowepower.com            m.BaseN7.__init__(self, 7)
17212391Sjason@lowepower.com            m.BaseN8.__init__(self, 8)
17312391Sjason@lowepower.com
17412391Sjason@lowepower.com    class MIMany916(m.BaseN9, m.BaseN10, m.BaseN11, m.BaseN12, m.BaseN13, m.BaseN14, m.BaseN15,
17512391Sjason@lowepower.com                    m.BaseN16):
17612391Sjason@lowepower.com        def __init__(self):
17712391Sjason@lowepower.com            m.BaseN9.__init__(self, 9)
17812391Sjason@lowepower.com            m.BaseN10.__init__(self, 10)
17912391Sjason@lowepower.com            m.BaseN11.__init__(self, 11)
18012391Sjason@lowepower.com            m.BaseN12.__init__(self, 12)
18112391Sjason@lowepower.com            m.BaseN13.__init__(self, 13)
18212391Sjason@lowepower.com            m.BaseN14.__init__(self, 14)
18312391Sjason@lowepower.com            m.BaseN15.__init__(self, 15)
18412391Sjason@lowepower.com            m.BaseN16.__init__(self, 16)
18512391Sjason@lowepower.com
18612391Sjason@lowepower.com    class MIMany19(MIMany14, MIMany58, m.BaseN9):
18712391Sjason@lowepower.com        def __init__(self):
18812391Sjason@lowepower.com            MIMany14.__init__(self)
18912391Sjason@lowepower.com            MIMany58.__init__(self)
19012391Sjason@lowepower.com            m.BaseN9.__init__(self, 9)
19112391Sjason@lowepower.com
19212391Sjason@lowepower.com    class MIMany117(MIMany14, MIMany58, MIMany916, m.BaseN17):
19312391Sjason@lowepower.com        def __init__(self):
19412391Sjason@lowepower.com            MIMany14.__init__(self)
19512391Sjason@lowepower.com            MIMany58.__init__(self)
19612391Sjason@lowepower.com            MIMany916.__init__(self)
19712391Sjason@lowepower.com            m.BaseN17.__init__(self, 17)
19812391Sjason@lowepower.com
19912391Sjason@lowepower.com    # Inherits from 4 registered C++ classes: can fit in one pointer on any modern arch:
20012391Sjason@lowepower.com    a = MIMany14()
20112391Sjason@lowepower.com    for i in range(1, 4):
20212391Sjason@lowepower.com        assert getattr(a, "f" + str(i))() == 2 * i
20312391Sjason@lowepower.com
20412391Sjason@lowepower.com    # Inherits from 8: requires 1/2 pointers worth of holder flags on 32/64-bit arch:
20512391Sjason@lowepower.com    b = MIMany916()
20612391Sjason@lowepower.com    for i in range(9, 16):
20712391Sjason@lowepower.com        assert getattr(b, "f" + str(i))() == 2 * i
20812391Sjason@lowepower.com
20912391Sjason@lowepower.com    # Inherits from 9: requires >= 2 pointers worth of holder flags
21012391Sjason@lowepower.com    c = MIMany19()
21112391Sjason@lowepower.com    for i in range(1, 9):
21212391Sjason@lowepower.com        assert getattr(c, "f" + str(i))() == 2 * i
21312391Sjason@lowepower.com
21412391Sjason@lowepower.com    # Inherits from 17: requires >= 3 pointers worth of holder flags
21512391Sjason@lowepower.com    d = MIMany117()
21612391Sjason@lowepower.com    for i in range(1, 17):
21712391Sjason@lowepower.com        assert getattr(d, "f" + str(i))() == 2 * i
21812037Sandreas.sandberg@arm.com
21912037Sandreas.sandberg@arm.com
22011986Sandreas.sandberg@arm.comdef test_multiple_inheritance_virtbase():
22111986Sandreas.sandberg@arm.com
22212391Sjason@lowepower.com    class MITypePy(m.Base12a):
22311986Sandreas.sandberg@arm.com        def __init__(self, i, j):
22412391Sjason@lowepower.com            m.Base12a.__init__(self, i, j)
22511986Sandreas.sandberg@arm.com
22611986Sandreas.sandberg@arm.com    mt = MITypePy(3, 4)
22711986Sandreas.sandberg@arm.com    assert mt.bar() == 4
22812391Sjason@lowepower.com    assert m.bar_base2a(mt) == 4
22912391Sjason@lowepower.com    assert m.bar_base2a_sharedptr(mt) == 4
23012037Sandreas.sandberg@arm.com
23112037Sandreas.sandberg@arm.com
23212037Sandreas.sandberg@arm.comdef test_mi_static_properties():
23312037Sandreas.sandberg@arm.com    """Mixing bases with and without static properties should be possible
23412037Sandreas.sandberg@arm.com     and the result should be independent of base definition order"""
23512037Sandreas.sandberg@arm.com
23612391Sjason@lowepower.com    for d in (m.VanillaStaticMix1(), m.VanillaStaticMix2()):
23712037Sandreas.sandberg@arm.com        assert d.vanilla() == "Vanilla"
23812037Sandreas.sandberg@arm.com        assert d.static_func1() == "WithStatic1"
23912037Sandreas.sandberg@arm.com        assert d.static_func2() == "WithStatic2"
24012037Sandreas.sandberg@arm.com        assert d.static_func() == d.__class__.__name__
24112037Sandreas.sandberg@arm.com
24212391Sjason@lowepower.com        m.WithStatic1.static_value1 = 1
24312391Sjason@lowepower.com        m.WithStatic2.static_value2 = 2
24412037Sandreas.sandberg@arm.com        assert d.static_value1 == 1
24512037Sandreas.sandberg@arm.com        assert d.static_value2 == 2
24612037Sandreas.sandberg@arm.com        assert d.static_value == 12
24712037Sandreas.sandberg@arm.com
24812037Sandreas.sandberg@arm.com        d.static_value1 = 0
24912037Sandreas.sandberg@arm.com        assert d.static_value1 == 0
25012037Sandreas.sandberg@arm.com        d.static_value2 = 0
25112037Sandreas.sandberg@arm.com        assert d.static_value2 == 0
25212037Sandreas.sandberg@arm.com        d.static_value = 0
25312037Sandreas.sandberg@arm.com        assert d.static_value == 0
25412037Sandreas.sandberg@arm.com
25512037Sandreas.sandberg@arm.com
25612037Sandreas.sandberg@arm.com@pytest.unsupported_on_pypy
25712037Sandreas.sandberg@arm.comdef test_mi_dynamic_attributes():
25812037Sandreas.sandberg@arm.com    """Mixing bases with and without dynamic attribute support"""
25912037Sandreas.sandberg@arm.com
26012391Sjason@lowepower.com    for d in (m.VanillaDictMix1(), m.VanillaDictMix2()):
26112037Sandreas.sandberg@arm.com        d.dynamic = 1
26212037Sandreas.sandberg@arm.com        assert d.dynamic == 1
26312391Sjason@lowepower.com
26412391Sjason@lowepower.com
26512391Sjason@lowepower.comdef test_mi_unaligned_base():
26612391Sjason@lowepower.com    """Returning an offset (non-first MI) base class pointer should recognize the instance"""
26712391Sjason@lowepower.com
26812391Sjason@lowepower.com    n_inst = ConstructorStats.detail_reg_inst()
26912391Sjason@lowepower.com
27012391Sjason@lowepower.com    c = m.I801C()
27112391Sjason@lowepower.com    d = m.I801D()
27212391Sjason@lowepower.com    # + 4 below because we have the two instances, and each instance has offset base I801B2
27312391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst + 4
27412391Sjason@lowepower.com    b1c = m.i801b1_c(c)
27512391Sjason@lowepower.com    assert b1c is c
27612391Sjason@lowepower.com    b2c = m.i801b2_c(c)
27712391Sjason@lowepower.com    assert b2c is c
27812391Sjason@lowepower.com    b1d = m.i801b1_d(d)
27912391Sjason@lowepower.com    assert b1d is d
28012391Sjason@lowepower.com    b2d = m.i801b2_d(d)
28112391Sjason@lowepower.com    assert b2d is d
28212391Sjason@lowepower.com
28312391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst + 4  # no extra instances
28412391Sjason@lowepower.com    del c, b1c, b2c
28512391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst + 2
28612391Sjason@lowepower.com    del d, b1d, b2d
28712391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst
28812391Sjason@lowepower.com
28912391Sjason@lowepower.com
29012391Sjason@lowepower.comdef test_mi_base_return():
29112391Sjason@lowepower.com    """Tests returning an offset (non-first MI) base class pointer to a derived instance"""
29212391Sjason@lowepower.com
29312391Sjason@lowepower.com    n_inst = ConstructorStats.detail_reg_inst()
29412391Sjason@lowepower.com
29512391Sjason@lowepower.com    c1 = m.i801c_b1()
29612391Sjason@lowepower.com    assert type(c1) is m.I801C
29712391Sjason@lowepower.com    assert c1.a == 1
29812391Sjason@lowepower.com    assert c1.b == 2
29912391Sjason@lowepower.com
30012391Sjason@lowepower.com    d1 = m.i801d_b1()
30112391Sjason@lowepower.com    assert type(d1) is m.I801D
30212391Sjason@lowepower.com    assert d1.a == 1
30312391Sjason@lowepower.com    assert d1.b == 2
30412391Sjason@lowepower.com
30512391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst + 4
30612391Sjason@lowepower.com
30712391Sjason@lowepower.com    c2 = m.i801c_b2()
30812391Sjason@lowepower.com    assert type(c2) is m.I801C
30912391Sjason@lowepower.com    assert c2.a == 1
31012391Sjason@lowepower.com    assert c2.b == 2
31112391Sjason@lowepower.com
31212391Sjason@lowepower.com    d2 = m.i801d_b2()
31312391Sjason@lowepower.com    assert type(d2) is m.I801D
31412391Sjason@lowepower.com    assert d2.a == 1
31512391Sjason@lowepower.com    assert d2.b == 2
31612391Sjason@lowepower.com
31712391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst + 8
31812391Sjason@lowepower.com
31912391Sjason@lowepower.com    del c2
32012391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst + 6
32112391Sjason@lowepower.com    del c1, d1, d2
32212391Sjason@lowepower.com    assert ConstructorStats.detail_reg_inst() == n_inst
32312391Sjason@lowepower.com
32412391Sjason@lowepower.com    # Returning an unregistered derived type with a registered base; we won't
32512391Sjason@lowepower.com    # pick up the derived type, obviously, but should still work (as an object
32612391Sjason@lowepower.com    # of whatever type was returned).
32712391Sjason@lowepower.com    e1 = m.i801e_c()
32812391Sjason@lowepower.com    assert type(e1) is m.I801C
32912391Sjason@lowepower.com    assert e1.a == 1
33012391Sjason@lowepower.com    assert e1.b == 2
33112391Sjason@lowepower.com
33212391Sjason@lowepower.com    e2 = m.i801e_b2()
33312391Sjason@lowepower.com    assert type(e2) is m.I801B2
33412391Sjason@lowepower.com    assert e2.b == 2
33512391Sjason@lowepower.com
33612391Sjason@lowepower.com
33712391Sjason@lowepower.comdef test_diamond_inheritance():
33812391Sjason@lowepower.com    """Tests that diamond inheritance works as expected (issue #959)"""
33912391Sjason@lowepower.com
34012391Sjason@lowepower.com    # Issue #959: this shouldn't segfault:
34112391Sjason@lowepower.com    d = m.D()
34212391Sjason@lowepower.com
34312391Sjason@lowepower.com    # Make sure all the various distinct pointers are all recognized as registered instances:
34412391Sjason@lowepower.com    assert d is d.c0()
34512391Sjason@lowepower.com    assert d is d.c1()
34612391Sjason@lowepower.com    assert d is d.b()
34712391Sjason@lowepower.com    assert d is d.c0().b()
34812391Sjason@lowepower.com    assert d is d.c1().b()
34912391Sjason@lowepower.com    assert d is d.c0().c1().b().c0().b()
350