blob: b11c699dfa4892a4ad8d647088ce71d5ed71933e [file] [log] [blame]
Dean Moldovana0c1ccf2016-08-12 13:50:00 +02001import pytest
Wenzel Jakob1ffce742016-08-25 01:43:33 +02002import pybind11_tests
Dean Moldovana0c1ccf2016-08-12 13:50:00 +02003from pybind11_tests import ConstructorStats
4
5
6def test_override(capture, msg):
7 from pybind11_tests import (ExampleVirt, runExampleVirt, runExampleVirtVirtual,
8 runExampleVirtBool)
9
10 class ExtendedExampleVirt(ExampleVirt):
11 def __init__(self, state):
12 super(ExtendedExampleVirt, self).__init__(state + 1)
13 self.data = "Hello world"
14
15 def run(self, value):
16 print('ExtendedExampleVirt::run(%i), calling parent..' % value)
17 return super(ExtendedExampleVirt, self).run(value + 1)
18
19 def run_bool(self):
20 print('ExtendedExampleVirt::run_bool()')
21 return False
22
Jason Rhinelander7dfb9322016-09-08 14:49:43 -040023 def get_string1(self):
24 return "override1"
25
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020026 def pure_virtual(self):
27 print('ExtendedExampleVirt::pure_virtual(): %s' % self.data)
28
Jason Rhinelander7dfb9322016-09-08 14:49:43 -040029 class ExtendedExampleVirt2(ExtendedExampleVirt):
30 def __init__(self, state):
31 super(ExtendedExampleVirt2, self).__init__(state + 1)
32
33 def get_string2(self):
34 return "override2"
35
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020036 ex12 = ExampleVirt(10)
37 with capture:
38 assert runExampleVirt(ex12, 20) == 30
Dean Moldovan76e993a2016-12-13 00:59:28 +010039 assert capture == """
40 Original implementation of ExampleVirt::run(state=10, value=20, str1=default1, str2=default2)
41 """ # noqa: E501 line too long
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020042
43 with pytest.raises(RuntimeError) as excinfo:
44 runExampleVirtVirtual(ex12)
45 assert msg(excinfo.value) == 'Tried to call pure virtual function "ExampleVirt::pure_virtual"'
46
47 ex12p = ExtendedExampleVirt(10)
48 with capture:
49 assert runExampleVirt(ex12p, 20) == 32
50 assert capture == """
51 ExtendedExampleVirt::run(20), calling parent..
Jason Rhinelander7dfb9322016-09-08 14:49:43 -040052 Original implementation of ExampleVirt::run(state=11, value=21, str1=override1, str2=default2)
Dean Moldovan76e993a2016-12-13 00:59:28 +010053 """ # noqa: E501 line too long
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020054 with capture:
55 assert runExampleVirtBool(ex12p) is False
56 assert capture == "ExtendedExampleVirt::run_bool()"
57 with capture:
58 runExampleVirtVirtual(ex12p)
59 assert capture == "ExtendedExampleVirt::pure_virtual(): Hello world"
60
Jason Rhinelander7dfb9322016-09-08 14:49:43 -040061 ex12p2 = ExtendedExampleVirt2(15)
62 with capture:
63 assert runExampleVirt(ex12p2, 50) == 68
64 assert capture == """
65 ExtendedExampleVirt::run(50), calling parent..
66 Original implementation of ExampleVirt::run(state=17, value=51, str1=override1, str2=override2)
Dean Moldovan76e993a2016-12-13 00:59:28 +010067 """ # noqa: E501 line too long
Jason Rhinelander7dfb9322016-09-08 14:49:43 -040068
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020069 cstats = ConstructorStats.get(ExampleVirt)
Jason Rhinelander7dfb9322016-09-08 14:49:43 -040070 assert cstats.alive() == 3
71 del ex12, ex12p, ex12p2
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020072 assert cstats.alive() == 0
Jason Rhinelander7dfb9322016-09-08 14:49:43 -040073 assert cstats.values() == ['10', '11', '17']
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020074 assert cstats.copy_constructions == 0
75 assert cstats.move_constructions >= 0
76
77
Dean Moldovan99dbdc12016-08-19 13:45:36 +020078def test_inheriting_repeat():
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020079 from pybind11_tests import A_Repeat, B_Repeat, C_Repeat, D_Repeat, A_Tpl, B_Tpl, C_Tpl, D_Tpl
80
Dean Moldovanbad17402016-11-20 21:21:54 +010081 class AR(A_Repeat):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020082 def unlucky_number(self):
83 return 99
84
Dean Moldovanbad17402016-11-20 21:21:54 +010085 class AT(A_Tpl):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020086 def unlucky_number(self):
87 return 999
88
Dean Moldovanbad17402016-11-20 21:21:54 +010089 obj = AR()
Dean Moldovan99dbdc12016-08-19 13:45:36 +020090 assert obj.say_something(3) == "hihihi"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020091 assert obj.unlucky_number() == 99
Jason Rhinelander20978262016-08-29 18:16:46 -040092 assert obj.say_everything() == "hi 99"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020093
Dean Moldovanbad17402016-11-20 21:21:54 +010094 obj = AT()
Dean Moldovan99dbdc12016-08-19 13:45:36 +020095 assert obj.say_something(3) == "hihihi"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020096 assert obj.unlucky_number() == 999
Jason Rhinelander20978262016-08-29 18:16:46 -040097 assert obj.say_everything() == "hi 999"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020098
99 for obj in [B_Repeat(), B_Tpl()]:
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200100 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200101 assert obj.unlucky_number() == 13
102 assert obj.lucky_number() == 7.0
Jason Rhinelander20978262016-08-29 18:16:46 -0400103 assert obj.say_everything() == "B says hi 1 times 13"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200104
105 for obj in [C_Repeat(), C_Tpl()]:
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200106 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200107 assert obj.unlucky_number() == 4444
108 assert obj.lucky_number() == 888.0
Jason Rhinelander20978262016-08-29 18:16:46 -0400109 assert obj.say_everything() == "B says hi 1 times 4444"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200110
Dean Moldovanbad17402016-11-20 21:21:54 +0100111 class CR(C_Repeat):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200112 def lucky_number(self):
113 return C_Repeat.lucky_number(self) + 1.25
114
Dean Moldovanbad17402016-11-20 21:21:54 +0100115 obj = CR()
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200116 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200117 assert obj.unlucky_number() == 4444
118 assert obj.lucky_number() == 889.25
Jason Rhinelander20978262016-08-29 18:16:46 -0400119 assert obj.say_everything() == "B says hi 1 times 4444"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200120
Dean Moldovanbad17402016-11-20 21:21:54 +0100121 class CT(C_Tpl):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200122 pass
123
Dean Moldovanbad17402016-11-20 21:21:54 +0100124 obj = CT()
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200125 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200126 assert obj.unlucky_number() == 4444
127 assert obj.lucky_number() == 888.0
Jason Rhinelander20978262016-08-29 18:16:46 -0400128 assert obj.say_everything() == "B says hi 1 times 4444"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200129
Dean Moldovanbad17402016-11-20 21:21:54 +0100130 class CCR(CR):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200131 def lucky_number(self):
Dean Moldovanbad17402016-11-20 21:21:54 +0100132 return CR.lucky_number(self) * 10
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200133
Dean Moldovanbad17402016-11-20 21:21:54 +0100134 obj = CCR()
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200135 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200136 assert obj.unlucky_number() == 4444
137 assert obj.lucky_number() == 8892.5
Jason Rhinelander20978262016-08-29 18:16:46 -0400138 assert obj.say_everything() == "B says hi 1 times 4444"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200139
Dean Moldovanbad17402016-11-20 21:21:54 +0100140 class CCT(CT):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200141 def lucky_number(self):
Dean Moldovanbad17402016-11-20 21:21:54 +0100142 return CT.lucky_number(self) * 1000
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200143
Dean Moldovanbad17402016-11-20 21:21:54 +0100144 obj = CCT()
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200145 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200146 assert obj.unlucky_number() == 4444
147 assert obj.lucky_number() == 888000.0
Jason Rhinelander20978262016-08-29 18:16:46 -0400148 assert obj.say_everything() == "B says hi 1 times 4444"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200149
Dean Moldovanbad17402016-11-20 21:21:54 +0100150 class DR(D_Repeat):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200151 def unlucky_number(self):
152 return 123
153
154 def lucky_number(self):
155 return 42.0
156
157 for obj in [D_Repeat(), D_Tpl()]:
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200158 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200159 assert obj.unlucky_number() == 4444
160 assert obj.lucky_number() == 888.0
Jason Rhinelander20978262016-08-29 18:16:46 -0400161 assert obj.say_everything() == "B says hi 1 times 4444"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200162
Dean Moldovanbad17402016-11-20 21:21:54 +0100163 obj = DR()
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200164 assert obj.say_something(3) == "B says hi 3 times"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200165 assert obj.unlucky_number() == 123
166 assert obj.lucky_number() == 42.0
Jason Rhinelander20978262016-08-29 18:16:46 -0400167 assert obj.say_everything() == "B says hi 1 times 123"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200168
Dean Moldovanbad17402016-11-20 21:21:54 +0100169 class DT(D_Tpl):
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200170 def say_something(self, times):
Dean Moldovanbad17402016-11-20 21:21:54 +0100171 return "DT says:" + (' quack' * times)
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200172
173 def unlucky_number(self):
174 return 1234
175
176 def lucky_number(self):
177 return -4.25
178
Dean Moldovanbad17402016-11-20 21:21:54 +0100179 obj = DT()
180 assert obj.say_something(3) == "DT says: quack quack quack"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200181 assert obj.unlucky_number() == 1234
182 assert obj.lucky_number() == -4.25
Dean Moldovanbad17402016-11-20 21:21:54 +0100183 assert obj.say_everything() == "DT says: quack 1234"
Jason Rhinelander20978262016-08-29 18:16:46 -0400184
Dean Moldovanbad17402016-11-20 21:21:54 +0100185 class DT2(DT):
Jason Rhinelander20978262016-08-29 18:16:46 -0400186 def say_something(self, times):
Dean Moldovanbad17402016-11-20 21:21:54 +0100187 return "DT2: " + ('QUACK' * times)
Jason Rhinelander20978262016-08-29 18:16:46 -0400188
189 def unlucky_number(self):
190 return -3
191
Dean Moldovanbad17402016-11-20 21:21:54 +0100192 class BT(B_Tpl):
Jason Rhinelander20978262016-08-29 18:16:46 -0400193 def say_something(self, times):
Dean Moldovanbad17402016-11-20 21:21:54 +0100194 return "BT" * times
195
Jason Rhinelander20978262016-08-29 18:16:46 -0400196 def unlucky_number(self):
197 return -7
Dean Moldovanbad17402016-11-20 21:21:54 +0100198
Jason Rhinelander20978262016-08-29 18:16:46 -0400199 def lucky_number(self):
200 return -1.375
201
Dean Moldovanbad17402016-11-20 21:21:54 +0100202 obj = BT()
203 assert obj.say_something(3) == "BTBTBT"
Jason Rhinelander20978262016-08-29 18:16:46 -0400204 assert obj.unlucky_number() == -7
205 assert obj.lucky_number() == -1.375
Dean Moldovanbad17402016-11-20 21:21:54 +0100206 assert obj.say_everything() == "BT -7"
207
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200208
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +0100209# PyPy: Reference count > 1 causes call with noncopyable instance
210# to fail in ncv1.print_nc()
211@pytest.unsupported_on_pypy
Wenzel Jakob69b62462016-08-25 02:20:35 +0200212@pytest.mark.skipif(not hasattr(pybind11_tests, 'NCVirt'),
213 reason="NCVirt test broken on ICPC")
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200214def test_move_support():
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200215 from pybind11_tests import NCVirt, NonCopyable, Movable
216
217 class NCVirtExt(NCVirt):
218 def get_noncopyable(self, a, b):
219 # Constructs and returns a new instance:
Wenzel Jakob69b62462016-08-25 02:20:35 +0200220 nc = NonCopyable(a * a, b * b)
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200221 return nc
222
223 def get_movable(self, a, b):
224 # Return a referenced copy
225 self.movable = Movable(a, b)
226 return self.movable
227
228 class NCVirtExt2(NCVirt):
229 def get_noncopyable(self, a, b):
230 # Keep a reference: this is going to throw an exception
231 self.nc = NonCopyable(a, b)
232 return self.nc
233
234 def get_movable(self, a, b):
235 # Return a new instance without storing it
236 return Movable(a, b)
237
238 ncv1 = NCVirtExt()
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200239 assert ncv1.print_nc(2, 3) == "36"
240 assert ncv1.print_movable(4, 5) == "9"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200241 ncv2 = NCVirtExt2()
Dean Moldovan99dbdc12016-08-19 13:45:36 +0200242 assert ncv2.print_movable(7, 7) == "14"
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200243 # Don't check the exception message here because it differs under debug/non-debug mode
244 with pytest.raises(RuntimeError):
245 ncv2.print_nc(9, 9)
246
247 nc_stats = ConstructorStats.get(NonCopyable)
248 mv_stats = ConstructorStats.get(Movable)
249 assert nc_stats.alive() == 1
250 assert mv_stats.alive() == 1
251 del ncv1, ncv2
252 assert nc_stats.alive() == 0
253 assert mv_stats.alive() == 0
254 assert nc_stats.values() == ['4', '9', '9', '9']
255 assert mv_stats.values() == ['4', '5', '7', '7']
256 assert nc_stats.copy_constructions == 0
257 assert mv_stats.copy_constructions == 1
258 assert nc_stats.move_constructions >= 0
259 assert mv_stats.move_constructions >= 0