123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- # -*- coding: utf-8 -*-
- import pytest
- import env # noqa: F401
- from pybind11_tests import call_policies as m
- from pybind11_tests import ConstructorStats
- @pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
- def test_keep_alive_argument(capture):
- n_inst = ConstructorStats.detail_reg_inst()
- with capture:
- p = m.Parent()
- assert capture == "Allocating parent."
- with capture:
- p.addChild(m.Child())
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
- assert (
- capture
- == """
- Allocating child.
- Releasing child.
- """
- )
- with capture:
- del p
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == "Releasing parent."
- with capture:
- p = m.Parent()
- assert capture == "Allocating parent."
- with capture:
- p.addChildKeepAlive(m.Child())
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
- assert capture == "Allocating child."
- with capture:
- del p
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert (
- capture
- == """
- Releasing parent.
- Releasing child.
- """
- )
- def test_keep_alive_return_value(capture):
- n_inst = ConstructorStats.detail_reg_inst()
- with capture:
- p = m.Parent()
- assert capture == "Allocating parent."
- with capture:
- p.returnChild()
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
- assert (
- capture
- == """
- Allocating child.
- Releasing child.
- """
- )
- with capture:
- del p
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == "Releasing parent."
- with capture:
- p = m.Parent()
- assert capture == "Allocating parent."
- with capture:
- p.returnChildKeepAlive()
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
- assert capture == "Allocating child."
- with capture:
- del p
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert (
- capture
- == """
- Releasing parent.
- Releasing child.
- """
- )
- # https://foss.heptapod.net/pypy/pypy/-/issues/2447
- @pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
- def test_alive_gc(capture):
- n_inst = ConstructorStats.detail_reg_inst()
- p = m.ParentGC()
- p.addChildKeepAlive(m.Child())
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
- lst = [p]
- lst.append(lst) # creates a circular reference
- with capture:
- del p, lst
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert (
- capture
- == """
- Releasing parent.
- Releasing child.
- """
- )
- def test_alive_gc_derived(capture):
- class Derived(m.Parent):
- pass
- n_inst = ConstructorStats.detail_reg_inst()
- p = Derived()
- p.addChildKeepAlive(m.Child())
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
- lst = [p]
- lst.append(lst) # creates a circular reference
- with capture:
- del p, lst
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert (
- capture
- == """
- Releasing parent.
- Releasing child.
- """
- )
- def test_alive_gc_multi_derived(capture):
- class Derived(m.Parent, m.Child):
- def __init__(self):
- m.Parent.__init__(self)
- m.Child.__init__(self)
- n_inst = ConstructorStats.detail_reg_inst()
- p = Derived()
- p.addChildKeepAlive(m.Child())
- # +3 rather than +2 because Derived corresponds to two registered instances
- assert ConstructorStats.detail_reg_inst() == n_inst + 3
- lst = [p]
- lst.append(lst) # creates a circular reference
- with capture:
- del p, lst
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert (
- capture
- == """
- Releasing parent.
- Releasing child.
- Releasing child.
- """
- )
- def test_return_none(capture):
- n_inst = ConstructorStats.detail_reg_inst()
- with capture:
- p = m.Parent()
- assert capture == "Allocating parent."
- with capture:
- p.returnNullChildKeepAliveChild()
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
- assert capture == ""
- with capture:
- del p
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == "Releasing parent."
- with capture:
- p = m.Parent()
- assert capture == "Allocating parent."
- with capture:
- p.returnNullChildKeepAliveParent()
- assert ConstructorStats.detail_reg_inst() == n_inst + 1
- assert capture == ""
- with capture:
- del p
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == "Releasing parent."
- def test_keep_alive_constructor(capture):
- n_inst = ConstructorStats.detail_reg_inst()
- with capture:
- p = m.Parent(m.Child())
- assert ConstructorStats.detail_reg_inst() == n_inst + 2
- assert (
- capture
- == """
- Allocating child.
- Allocating parent.
- """
- )
- with capture:
- del p
- assert ConstructorStats.detail_reg_inst() == n_inst
- assert (
- capture
- == """
- Releasing parent.
- Releasing child.
- """
- )
- def test_call_guard():
- assert m.unguarded_call() == "unguarded"
- assert m.guarded_call() == "guarded"
- assert m.multiple_guards_correct_order() == "guarded & guarded"
- assert m.multiple_guards_wrong_order() == "unguarded & guarded"
- if hasattr(m, "with_gil"):
- assert m.with_gil() == "GIL held"
- assert m.without_gil() == "GIL released"
|