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