def test_to_python(): mat = m.Matrix(5, 5) assert memoryview(mat).shape == (5, 5) assert mat[2, 3] == 0 mat[2, 3] = 4 assert mat[2, 3] == 4 mat2 = np.array(mat, copy=False) assert mat2.shape == (5, 5) assert abs(mat2).sum() == 4 assert mat2[2, 3] == 4 mat2[2, 3] = 5 assert mat2[2, 3] == 5 cstats = ConstructorStats.get(m.Matrix) assert cstats.alive() == 1 del mat pytest.gc_collect() assert cstats.alive() == 1 del mat2 # holds a mat reference pytest.gc_collect() assert cstats.alive() == 0 assert cstats.values() == ["5x5 matrix"] assert cstats.copy_constructions == 0 # assert cstats.move_constructions >= 0 # Don't invoke any assert cstats.copy_assignments == 0 assert cstats.move_assignments == 0
def test_alias_delay_initialization1(capture): """ A only initializes its trampoline class when we inherit from it; if we just create and use an A instance directly, the trampoline initialization is bypassed and we only initialize an A() instead (for performance reasons). """ from pybind11_tests import A, call_f class B(A): def __init__(self): super(B, self).__init__() def f(self): print("In python f()") # C++ version with capture: a = A() call_f(a) del a pytest.gc_collect() assert capture == "A.f()" # Python version with capture: b = B() call_f(b) del b pytest.gc_collect() assert capture == """
def test_alias_delay_initialization2(capture): """A2, unlike the above, is configured to always initialize the alias; while the extra initialization and extra class layer has small virtual dispatch performance penalty, it also allows us to do more things with the trampoline class such as defining local variables and performing construction/destruction. """ from pybind11_tests import A2, call_f class B2(A2): def __init__(self): super(B2, self).__init__() def f(self): print("In python B2.f()") # No python subclass version with capture: a2 = A2() call_f(a2) del a2 pytest.gc_collect() assert capture == """ PyA2.PyA2() PyA2.f() A2.f() PyA2.~PyA2() """ # Python subclass version with capture: b2 = B2() call_f(b2) del b2 pytest.gc_collect() assert capture == """
def test_alias_delay_initialization1(capture): """`A` only initializes its trampoline class when we inherit from it If we just create and use an A instance directly, the trampoline initialization is bypassed and we only initialize an A() instead (for performance reasons). """ class B(m.A): def __init__(self): super(B, self).__init__() def f(self): print("In python f()") # C++ version with capture: a = m.A() m.call_f(a) del a pytest.gc_collect() assert capture == "A.f()" # Python version with capture: b = B() m.call_f(b) del b pytest.gc_collect() assert capture == """
def test_no_placement_new(capture): """Prior to 2.2, `py::init<...>` relied on the type supporting placement new; this tests a class without placement new support.""" with capture: a = m.NoPlacementNew(123) found = re.search(r'^operator new called, returning (\d+)\n$', str(capture)) assert found assert a.i == 123 with capture: del a pytest.gc_collect() assert capture == "operator delete called on " + found.group(1) with capture: b = m.NoPlacementNew() found = re.search(r'^operator new called, returning (\d+)\n$', str(capture)) assert found assert b.i == 100 with capture: del b pytest.gc_collect() assert capture == "operator delete called on " + found.group(1)
def test_alias_delay_initialization1(capture): """`A` only initializes its trampoline class when we inherit from it If we just create and use an A instance directly, the trampoline initialization is bypassed and we only initialize an A() instead (for performance reasons). """ class B(m.A): def __init__(self): super(B, self).__init__() def f(self): print("In python f()") # C++ version with capture: a = m.A() m.call_f(a) del a pytest.gc_collect() assert capture == "A.f()" # Python version with capture: b = B() m.call_f(b) del b pytest.gc_collect() assert (capture == """ PyA.PyA() PyA.f() In python f() PyA.~PyA() """)
def test_to_python(): m = Matrix(5, 5) assert m[2, 3] == 0 m[2, 3] = 4 assert m[2, 3] == 4 m2 = np.array(m, copy=False) assert m2.shape == (5, 5) assert abs(m2).sum() == 4 assert m2[2, 3] == 4 m2[2, 3] = 5 assert m2[2, 3] == 5 cstats = ConstructorStats.get(Matrix) assert cstats.alive() == 1 del m pytest.gc_collect() assert cstats.alive() == 1 del m2 # holds an m reference pytest.gc_collect() assert cstats.alive() == 0 assert cstats.values() == ["5x5 matrix"] assert cstats.copy_constructions == 0 # assert cstats.move_constructions >= 0 # Don't invoke any assert cstats.copy_assignments == 0 assert cstats.move_assignments == 0
def test_to_python(): mat = m.Matrix(5, 4) assert memoryview(mat).shape == (5, 4) assert mat[2, 3] == 0 mat[2, 3] = 4.0 mat[3, 2] = 7.0 assert mat[2, 3] == 4 assert mat[3, 2] == 7 assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7, ) assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4, ) mat2 = np.array(mat, copy=False) assert mat2.shape == (5, 4) assert abs(mat2).sum() == 11 assert mat2[2, 3] == 4 and mat2[3, 2] == 7 mat2[2, 3] = 5 assert mat2[2, 3] == 5 cstats = ConstructorStats.get(m.Matrix) assert cstats.alive() == 1 del mat pytest.gc_collect() assert cstats.alive() == 1 del mat2 # holds a mat reference pytest.gc_collect() assert cstats.alive() == 0 assert cstats.values() == ["5x4 matrix"] assert cstats.copy_constructions == 0 # assert cstats.move_constructions >= 0 # Don't invoke any assert cstats.copy_assignments == 0 assert cstats.move_assignments == 0
def test_weakref(create_weakref, create_weakref_with_callback): from weakref import getweakrefcount # Apparently, you cannot weakly reference an object() class WeaklyReferenced(object): pass def callback(wr): # No `nonlocal` in Python 2 callback.called = True obj = WeaklyReferenced() assert getweakrefcount(obj) == 0 wr = create_weakref(obj) assert getweakrefcount(obj) == 1 obj = WeaklyReferenced() assert getweakrefcount(obj) == 0 callback.called = False wr = create_weakref_with_callback(obj, callback) # noqa: F841 assert getweakrefcount(obj) == 1 assert not callback.called del obj pytest.gc_collect() assert callback.called
def test_shared_ptr_gc(): """#187: issue involving std::shared_ptr<> return value policy & garbage collection""" el = m.ElementList() for i in range(10): el.add(m.ElementA(i)) pytest.gc_collect() for i, v in enumerate(el.get()): assert i == v.value()
def test_str_leak(): from sys import getrefcount fmt = "f4" pytest.gc_collect() start = getrefcount(fmt) d = m.dtype_wrapper(fmt) assert d is np.dtype("f4") del d pytest.gc_collect() assert getrefcount(fmt) == start
def test_shared_ptr_gc(): """// #187: issue involving std::shared_ptr<> return value policy & garbage collection""" from pybind11_tests.issues import ElementList, ElementA el = ElementList() for i in range(10): el.add(ElementA(i)) pytest.gc_collect() for i, v in enumerate(el.get()): assert i == v.value()
def test_shared_ptr_gc(): """#187: issue involving std::shared_ptr<> return value policy & garbage collection""" from pybind11_tests.smart_ptr import ElementList, ElementA el = ElementList() for i in range(10): el.add(ElementA(i)) pytest.gc_collect() for i, v in enumerate(el.get()): assert i == v.value()
def test_reallocation_a(capture, msg): """When the constructor is overloaded, previous overloads can require a preallocated value. This test makes sure that such preallocated values only happen when they might be necessary, and that they are deallocated properly.""" pytest.gc_collect() with capture: create_and_destroy(1) assert msg(capture) == """
def test_capsule(capture): pytest.gc_collect() with capture: a = m.return_capsule_with_destructor() del a pytest.gc_collect() assert capture.unordered == """ creating capsule destructing capsule """ with capture: a = m.return_capsule_with_destructor_2() del a pytest.gc_collect() assert capture.unordered == """ creating capsule destructing capsule: 1234 """ with capture: a = m.return_capsule_with_name_and_destructor() del a pytest.gc_collect() assert capture.unordered == """
def test_keep_alive_return_value(capture): from pybind11_tests import Parent with capture: p = Parent() assert capture == "Allocating parent." with capture: p.returnChild() pytest.gc_collect() assert capture == """ Allocating child. Releasing child. """ with capture: del p pytest.gc_collect() assert capture == "Releasing parent." with capture: p = Parent() assert capture == "Allocating parent." with capture: p.returnChildKeepAlive() pytest.gc_collect() assert capture == "Allocating child." with capture: del p pytest.gc_collect() assert capture == """
def test_return_none(capture): from pybind11_tests import Parent with capture: p = Parent() if capture != "Allocating parent.": raise AssertionError with capture: p.returnNullChildKeepAliveChild() pytest.gc_collect() if capture != "": raise AssertionError with capture: del p pytest.gc_collect() if capture != "Releasing parent.": raise AssertionError with capture: p = Parent() if capture != "Allocating parent.": raise AssertionError with capture: p.returnNullChildKeepAliveParent() pytest.gc_collect() if capture != "": raise AssertionError with capture: del p pytest.gc_collect() if capture != "Releasing parent.": raise AssertionError
def test_return_none(capture): from pybind11_tests import Parent with capture: p = Parent() assert capture == "Allocating parent." with capture: p.returnNullChildKeepAliveChild() pytest.gc_collect() assert capture == "" with capture: del p pytest.gc_collect() assert capture == "Releasing parent." with capture: p = Parent() assert capture == "Allocating parent." with capture: p.returnNullChildKeepAliveParent() pytest.gc_collect() assert capture == "" with capture: del p pytest.gc_collect() assert capture == "Releasing parent."
def test_capsule(capture): pytest.gc_collect() with capture: a = m.return_capsule_with_destructor() del a pytest.gc_collect() assert (capture.unordered == """ creating capsule destructing capsule """) with capture: a = m.return_capsule_with_destructor_2() del a pytest.gc_collect() assert (capture.unordered == """ creating capsule destructing capsule: 1234 """) with capture: a = m.return_capsule_with_name_and_destructor() del a pytest.gc_collect() assert (capture.unordered == """ created capsule (1234, 'pointer type description') destructing capsule (1234, 'pointer type description') """)
def test_keep_alive_argument(capture): from pybind11_tests import Parent, Child with capture: p = Parent() assert capture == "Allocating parent." with capture: p.addChild(Child()) pytest.gc_collect() assert capture == """ Allocating child. Releasing child. """ with capture: del p pytest.gc_collect() assert capture == "Releasing parent." with capture: p = Parent() assert capture == "Allocating parent." with capture: p.addChildKeepAlive(Child()) pytest.gc_collect() assert capture == "Allocating child." with capture: del p pytest.gc_collect() assert capture == """
def test_capsule_with_destructor(capture): import pybind11_tests as m with capture: a = m.return_capsule_with_destructor() del a pytest.gc_collect() assert capture.unordered == """ creating capsule destructing capsule """ with capture: a = m.return_capsule_with_destructor_2() del a pytest.gc_collect() assert capture.unordered == """
def test_operator_new_delete(capture): """Tests that class-specific operator new/delete functions are invoked""" class SubAliased(m.AliasedHasOpNewDelSize): pass with capture: a = m.HasOpNewDel() b = m.HasOpNewDelSize() d = m.HasOpNewDelBoth() assert capture == """ A new 8 B new 4 D new 32 """ sz_alias = str(m.AliasedHasOpNewDelSize.size_alias) sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias) with capture: c = m.AliasedHasOpNewDelSize() c2 = SubAliased() assert capture == ( "C new " + sz_noalias + "\n" + "C new " + sz_alias + "\n" ) with capture: del a pytest.gc_collect() del b pytest.gc_collect() del d pytest.gc_collect() assert capture == """ A delete B delete 4 D delete """ with capture: del c pytest.gc_collect() del c2 pytest.gc_collect() assert capture == ( "C delete " + sz_noalias + "\n" + "C delete " + sz_alias + "\n" )
def test_operator_new_delete(capture): """Tests that class-specific operator new/delete functions are invoked""" class SubAliased(m.AliasedHasOpNewDelSize): pass with capture: a = m.HasOpNewDel() b = m.HasOpNewDelSize() d = m.HasOpNewDelBoth() assert ( capture == """ A new 8 B new 4 D new 32 """ ) sz_alias = str(m.AliasedHasOpNewDelSize.size_alias) sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias) with capture: c = m.AliasedHasOpNewDelSize() c2 = SubAliased() assert capture == ("C new " + sz_noalias + "\n" + "C new " + sz_alias + "\n") with capture: del a pytest.gc_collect() del b pytest.gc_collect() del d pytest.gc_collect() assert ( capture == """ A delete B delete 4 D delete """ ) with capture: del c pytest.gc_collect() del c2 pytest.gc_collect() assert capture == ("C delete " + sz_noalias + "\n" + "C delete " + sz_alias + "\n")
def test_class_refcount(): """Instances must correctly increase/decrease the reference count of their types (#1029)""" from sys import getrefcount class PyDog(m.Dog): pass for cls in m.Dog, PyDog: refcount_1 = getrefcount(cls) molly = [cls("Molly") for _ in range(10)] refcount_2 = getrefcount(cls) del molly pytest.gc_collect() refcount_3 = getrefcount(cls) assert refcount_1 == refcount_3 assert refcount_2 > refcount_1
def test_to_python(): m = Matrix(5, 5) if m[2, 3] != 0: raise AssertionError m[2, 3] = 4 if m[2, 3] != 4: raise AssertionError m2 = np.array(m, copy=False) if m2.shape != (5, 5): raise AssertionError if abs(m2).sum() != 4: raise AssertionError if m2[2, 3] != 4: raise AssertionError m2[2, 3] = 5 if m2[2, 3] != 5: raise AssertionError cstats = ConstructorStats.get(Matrix) if cstats.alive() != 1: raise AssertionError del m pytest.gc_collect() if cstats.alive() != 1: raise AssertionError del m2 # holds an m reference pytest.gc_collect() if cstats.alive() != 0: raise AssertionError if cstats.values() != ["5x5 matrix"]: raise AssertionError if cstats.copy_constructions != 0: raise AssertionError # assert cstats.move_constructions >= 0 # Don't invoke any if cstats.copy_assignments != 0: raise AssertionError if cstats.move_assignments != 0: raise AssertionError
def test_numpy_view(capture): with capture: ac = m.ArrayClass() ac_view_1 = ac.numpy_view() ac_view_2 = ac.numpy_view() assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32)) del ac pytest.gc_collect() assert (capture == """ ArrayClass() ArrayClass::numpy_view() ArrayClass::numpy_view() """) ac_view_1[0] = 4 ac_view_1[1] = 3 assert ac_view_2[0] == 4 assert ac_view_2[1] == 3 with capture: del ac_view_1 del ac_view_2 pytest.gc_collect() pytest.gc_collect() assert (capture == """ ~ArrayClass() """)
def test_numpy_view(capture): from pybind11_tests.array import ArrayClass with capture: ac = ArrayClass() ac_view_1 = ac.numpy_view() ac_view_2 = ac.numpy_view() assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32)) del ac pytest.gc_collect() assert ( capture == """ ArrayClass() ArrayClass::numpy_view() ArrayClass::numpy_view() """ ) ac_view_1[0] = 4 ac_view_1[1] = 3 assert ac_view_2[0] == 4 assert ac_view_2[1] == 3 with capture: del ac_view_1 del ac_view_2 pytest.gc_collect() pytest.gc_collect() assert ( capture == """ ~ArrayClass() """ )
def test_numpy_view(capture): from pybind11_tests.array import ArrayClass with capture: ac = ArrayClass() ac_view_1 = ac.numpy_view() ac_view_2 = ac.numpy_view() if not np.all(ac_view_1 == np.array([1, 2], dtype=np.int32)): raise AssertionError del ac pytest.gc_collect() if capture != """ ArrayClass() ArrayClass::numpy_view() ArrayClass::numpy_view() """: raise AssertionError ac_view_1[0] = 4 ac_view_1[1] = 3 if ac_view_2[0] != 4: raise AssertionError if ac_view_2[1] != 3: raise AssertionError with capture: del ac_view_1 del ac_view_2 pytest.gc_collect() pytest.gc_collect() if capture != """ ~ArrayClass() """: raise AssertionError
def test_nested(): """ #328: first member in a class can't be used in operators""" from pybind11_tests.issues import NestA, NestB, NestC, get_NestA, get_NestB, get_NestC a = NestA() b = NestB() c = NestC() a += 10 if get_NestA(a) != 13: raise AssertionError b.a += 100 if get_NestA(b.a) != 103: raise AssertionError c.b.a += 1000 if get_NestA(c.b.a) != 1003: raise AssertionError b -= 1 if get_NestB(b) != 3: raise AssertionError c.b -= 3 if get_NestB(c.b) != 1: raise AssertionError c *= 7 if get_NestC(c) != 35: raise AssertionError abase = a.as_base() if abase.value != -2: raise AssertionError a.as_base().value += 44 if abase.value != 42: raise AssertionError if c.b.a.as_base().value != -2: raise AssertionError c.b.a.as_base().value += 44 if c.b.a.as_base().value != 42: raise AssertionError del c pytest.gc_collect() del a # Should't delete while abase is still alive pytest.gc_collect() if abase.value != 42: raise AssertionError del abase, b pytest.gc_collect()
def test_keep_alive_argument(capture): from pybind11_tests import Parent, Child with capture: p = Parent() if capture != "Allocating parent.": raise AssertionError with capture: p.addChild(Child()) pytest.gc_collect() if capture != """ Allocating child. Releasing child. """: raise AssertionError with capture: del p pytest.gc_collect() if capture != "Releasing parent.": raise AssertionError with capture: p = Parent() if capture != "Allocating parent.": raise AssertionError with capture: p.addChildKeepAlive(Child()) pytest.gc_collect() if capture != "Allocating child.": raise AssertionError with capture: del p pytest.gc_collect() if capture != """ Releasing parent. Releasing child. """: raise AssertionError
def test_keep_alive_return_value(capture): from pybind11_tests import Parent with capture: p = Parent() if capture != "Allocating parent.": raise AssertionError with capture: p.returnChild() pytest.gc_collect() if capture != """ Allocating child. Releasing child. """: raise AssertionError with capture: del p pytest.gc_collect() if capture != "Releasing parent.": raise AssertionError with capture: p = Parent() if capture != "Allocating parent.": raise AssertionError with capture: p.returnChildKeepAlive() pytest.gc_collect() if capture != "Allocating child.": raise AssertionError with capture: del p pytest.gc_collect() if capture != """ Releasing parent. Releasing child. """: raise AssertionError
def test_numpy_view(capture): with capture: ac = m.ArrayClass() ac_view_1 = ac.numpy_view() ac_view_2 = ac.numpy_view() assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32)) del ac pytest.gc_collect() assert capture == """ ArrayClass() ArrayClass::numpy_view() ArrayClass::numpy_view() """ ac_view_1[0] = 4 ac_view_1[1] = 3 assert ac_view_2[0] == 4 assert ac_view_2[1] == 3 with capture: del ac_view_1 del ac_view_2 pytest.gc_collect() pytest.gc_collect() assert capture == """
def test_nested(): """#328: first member in a class can't be used in operators""" from pybind11_tests.operators import NestA, NestB, NestC, get_NestA, get_NestB, get_NestC a = NestA() b = NestB() c = NestC() a += 10 assert get_NestA(a) == 13 b.a += 100 assert get_NestA(b.a) == 103 c.b.a += 1000 assert get_NestA(c.b.a) == 1003 b -= 1 assert get_NestB(b) == 3 c.b -= 3 assert get_NestB(c.b) == 1 c *= 7 assert get_NestC(c) == 35 abase = a.as_base() assert abase.value == -2 a.as_base().value += 44 assert abase.value == 42 assert c.b.a.as_base().value == -2 c.b.a.as_base().value += 44 assert c.b.a.as_base().value == 42 del c pytest.gc_collect() del a # Should't delete while abase is still alive pytest.gc_collect() assert abase.value == 42 del abase, b pytest.gc_collect()
def test_nested(): """ #328: first member in a class can't be used in operators""" from pybind11_tests.issues import NestA, NestB, NestC, get_NestA, get_NestB, get_NestC a = NestA() b = NestB() c = NestC() a += 10 assert get_NestA(a) == 13 b.a += 100 assert get_NestA(b.a) == 103 c.b.a += 1000 assert get_NestA(c.b.a) == 1003 b -= 1 assert get_NestB(b) == 3 c.b -= 3 assert get_NestB(c.b) == 1 c *= 7 assert get_NestC(c) == 35 abase = a.as_base() assert abase.value == -2 a.as_base().value += 44 assert abase.value == 42 assert c.b.a.as_base().value == -2 c.b.a.as_base().value += 44 assert c.b.a.as_base().value == 42 del c pytest.gc_collect() del a # Should't delete while abase is still alive pytest.gc_collect() assert abase.value == 42 del abase, b pytest.gc_collect()
def test_nested(): """#328: first member in a class can't be used in operators""" a = m.NestA() b = m.NestB() c = m.NestC() a += 10 assert m.get_NestA(a) == 13 b.a += 100 assert m.get_NestA(b.a) == 103 c.b.a += 1000 assert m.get_NestA(c.b.a) == 1003 b -= 1 assert m.get_NestB(b) == 3 c.b -= 3 assert m.get_NestB(c.b) == 1 c *= 7 assert m.get_NestC(c) == 35 abase = a.as_base() assert abase.value == -2 a.as_base().value += 44 assert abase.value == 42 assert c.b.a.as_base().value == -2 c.b.a.as_base().value += 44 assert c.b.a.as_base().value == 42 del c pytest.gc_collect() del a # Shouldn't delete while abase is still alive pytest.gc_collect() assert abase.value == 42 del abase, b pytest.gc_collect()
def test_numpy_view(capture): from pybind11_tests.array import ArrayClass with capture: ac = ArrayClass() ac_view_1 = ac.numpy_view() ac_view_2 = ac.numpy_view() assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32)) del ac pytest.gc_collect() assert capture == """ ArrayClass() ArrayClass::numpy_view() ArrayClass::numpy_view() """ ac_view_1[0] = 4 ac_view_1[1] = 3 assert ac_view_2[0] == 4 assert ac_view_2[1] == 3 with capture: del ac_view_1 del ac_view_2 pytest.gc_collect() pytest.gc_collect() assert capture == """
def create_and_destroy(*args): a = m.NoisyAlloc(*args) print("---") del a pytest.gc_collect()
def test_reallocations(capture, msg): """When the constructor is overloaded, previous overloads can require a preallocated value. This test makes sure that such preallocated values only happen when they might be necessary, and that they are deallocated properly""" pytest.gc_collect() with capture: create_and_destroy(1) assert msg(capture) == """ noisy new noisy placement new NoisyAlloc(int 1) --- ~NoisyAlloc() noisy delete """ with capture: create_and_destroy(1.5) assert msg(capture) == strip_comments(""" noisy new # allocation required to attempt first overload noisy delete # have to dealloc before considering factory init overload noisy new # pointer factory calling "new", part 1: allocation NoisyAlloc(double 1.5) # ... part two, invoking constructor --- ~NoisyAlloc() # Destructor noisy delete # operator delete """) with capture: create_and_destroy(2, 3) assert msg(capture) == strip_comments(""" noisy new # pointer factory calling "new", allocation NoisyAlloc(int 2) # constructor --- ~NoisyAlloc() # Destructor noisy delete # operator delete """) with capture: create_and_destroy(2.5, 3) assert msg(capture) == strip_comments(""" NoisyAlloc(double 2.5) # construction (local func variable: operator_new not called) noisy new # return-by-value "new" part 1: allocation ~NoisyAlloc() # moved-away local func variable destruction --- ~NoisyAlloc() # Destructor noisy delete # operator delete """) with capture: create_and_destroy(3.5, 4.5) assert msg(capture) == strip_comments(""" noisy new # preallocation needed before invoking placement-new overload noisy placement new # Placement new NoisyAlloc(double 3.5) # construction --- ~NoisyAlloc() # Destructor noisy delete # operator delete """) with capture: create_and_destroy(4, 0.5) assert msg(capture) == strip_comments(""" noisy new # preallocation needed before invoking placement-new overload noisy delete # deallocation of preallocated storage noisy new # Factory pointer allocation NoisyAlloc(int 4) # factory pointer construction --- ~NoisyAlloc() # Destructor noisy delete # operator delete """) with capture: create_and_destroy(5, "hi") assert msg(capture) == strip_comments(""" noisy new # preallocation needed before invoking first placement new noisy delete # delete before considering new-style constructor noisy new # preallocation for second placement new noisy placement new # Placement new in the second placement new overload NoisyAlloc(int 5) # construction --- ~NoisyAlloc() # Destructor noisy delete # operator delete """)