11# -*- coding: utf-8 -*-
22import pytest
33
4- import env # noqa: F401
5-
64import pybind11_tests .class_sh_trampoline_shared_from_this as m
75
8- import gc
9- import weakref
10-
116
127class PySft (m .Sft ):
138 pass
149
1510
16- def test_pass_shared_ptr ():
11+ def test_release_and_immediate_reclaim ():
1712 obj = PySft ("PySft" )
1813 assert obj .history == "PySft"
19- assert obj .use_count () in [ 2 , - 1 ] # TODO: Be smarter/stricter.
20- m .pass_shared_ptr (obj )
14+ assert obj .use_count () == 1
15+ assert m .pass_shared_ptr (obj ) == 2
2116 assert obj .history == "PySft_PassSharedPtr"
22- assert obj .use_count () in [2 , - 1 ]
23- uc = m .pass_shared_ptr (obj )
24- assert uc == 2 # +1 for passed argument, +1 for shared_from_this.
17+ assert obj .use_count () == 1
18+ assert m .pass_shared_ptr (obj ) == 2
2519 assert obj .history == "PySft_PassSharedPtr_PassSharedPtr"
26- assert obj .use_count () in [2 , - 1 ]
20+ assert obj .use_count () == 1
21+
22+ obj = PySft ("" )
23+ while True :
24+ m .pass_shared_ptr (obj )
25+ assert obj .history == ""
26+ assert obj .use_count () == 1
27+ break # Comment out for manual leak checking (use `top` command).
2728
2829
29- def test_pass_shared_ptr_while_stashed ():
30+ def test_release_to_cpp_stash ():
3031 obj = PySft ("PySft" )
31- obj_wr = weakref .ref (obj )
3232 stash1 = m .SftSharedPtrStash (1 )
3333 stash1 .Add (obj )
3434 assert obj .history == "PySft_Stash1Add"
35- assert obj .use_count () in [ 2 , - 1 ]
35+ assert obj .use_count () == 1
3636 assert stash1 .history (0 ) == "PySft_Stash1Add"
3737 assert stash1 .use_count (0 ) == 1 # obj does NOT own the shared_ptr anymore.
38- uc = m .pass_shared_ptr (obj )
39- assert uc == 3 # +1 for passed argument, +1 for shared_from_this.
38+ assert m .pass_shared_ptr (obj ) == 3
4039 assert obj .history == "PySft_Stash1Add_PassSharedPtr"
41- assert obj .use_count () in [ 2 , - 1 ]
40+ assert obj .use_count () == 1
4241 assert stash1 .history (0 ) == "PySft_Stash1Add_PassSharedPtr"
4342 assert stash1 .use_count (0 ) == 1
4443 stash2 = m .SftSharedPtrStash (2 )
4544 stash2 .Add (obj )
4645 assert obj .history == "PySft_Stash1Add_PassSharedPtr_Stash2Add"
47- assert obj .use_count () in [ 3 , - 1 ]
46+ assert obj .use_count () == 2
4847 assert stash2 .history (0 ) == "PySft_Stash1Add_PassSharedPtr_Stash2Add"
4948 assert stash2 .use_count (0 ) == 2
5049 stash2 .Add (obj )
51- assert obj .history == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
52- assert obj .use_count () in [4 , - 1 ]
50+ exp_oh = "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
51+ assert obj .history == exp_oh
52+ assert obj .use_count () == 3
53+ assert stash1 .history (0 ) == exp_oh
5354 assert stash1 .use_count (0 ) == 3
54- assert stash1 .history (0 ) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
55+ assert stash2 .history (0 ) == exp_oh
5556 assert stash2 .use_count (0 ) == 3
56- assert stash2 .history (0 ) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
57+ assert stash2 .history (1 ) == exp_oh
5758 assert stash2 .use_count (1 ) == 3
58- assert stash2 .history (1 ) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
5959 del obj
60+ assert stash2 .history (0 ) == exp_oh
6061 assert stash2 .use_count (0 ) == 3
61- assert stash2 .history (0 ) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
62+ assert stash2 .history (1 ) == exp_oh
6263 assert stash2 .use_count (1 ) == 3
63- assert stash2 .history (1 ) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
6464 del stash2
65- gc .collect ()
66- assert obj_wr () is not None
67- assert stash1 .history (0 ) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
68- del stash1
69- gc .collect ()
70- if not env .PYPY :
71- assert obj_wr () is None
65+ assert stash1 .history (0 ) == exp_oh
66+ assert stash1 .use_count (0 ) == 1
7267
7368
74- def test_pass_shared_ptr_while_stashed_with_shared_from_this ():
69+ def test_release_to_cpp_stash_leak ():
70+ obj = PySft ("" )
71+ while True :
72+ stash1 = m .SftSharedPtrStash (1 )
73+ stash1 .Add (obj )
74+ assert obj .history == ""
75+ assert obj .use_count () == 1
76+ assert stash1 .use_count (0 ) == 1
77+ stash1 .Add (obj )
78+ assert obj .history == ""
79+ assert obj .use_count () == 2
80+ assert stash1 .use_count (0 ) == 2
81+ assert stash1 .use_count (1 ) == 2
82+ break # Comment out for manual leak checking (use `top` command).
83+
84+
85+ def test_release_to_cpp_stash_via_shared_from_this ():
7586 obj = PySft ("PySft" )
76- obj_wr = weakref .ref (obj )
7787 stash1 = m .SftSharedPtrStash (1 )
7888 stash1 .AddSharedFromThis (obj )
7989 assert obj .history == "PySft_Stash1AddSharedFromThis"
@@ -82,11 +92,57 @@ def test_pass_shared_ptr_while_stashed_with_shared_from_this():
8292 assert obj .history == "PySft_Stash1AddSharedFromThis_Stash1AddSharedFromThis"
8393 assert stash1 .use_count (0 ) == 3
8494 assert stash1 .use_count (1 ) == 3
85- del obj
86- del stash1
87- gc .collect ()
88- if not env .PYPY :
89- assert obj_wr () is None
95+
96+
97+ def test_release_to_cpp_stash_via_shared_from_this_leak_1 (): # WIP
98+ m .to_cout ("" )
99+ m .to_cout ("" )
100+ m .to_cout ("Add first" )
101+ obj = PySft ("" )
102+ import weakref
103+
104+ obj_wr = weakref .ref (obj )
105+ while True :
106+ stash1 = m .SftSharedPtrStash (1 )
107+ stash1 .Add (obj )
108+ assert obj .history == ""
109+ assert obj .use_count () == 1
110+ assert stash1 .use_count (0 ) == 1
111+ stash1 .AddSharedFromThis (obj )
112+ assert obj .history == ""
113+ assert obj .use_count () == 2
114+ assert stash1 .use_count (0 ) == 2
115+ assert stash1 .use_count (1 ) == 2
116+ del obj
117+ assert obj_wr () is not None
118+ assert stash1 .use_count (0 ) == 2
119+ assert stash1 .use_count (1 ) == 2
120+ break # Comment out for manual leak checking (use `top` command).
121+
122+
123+ def test_release_to_cpp_stash_via_shared_from_this_leak_2 (): # WIP
124+ m .to_cout ("" )
125+ m .to_cout ("AddSharedFromThis only" )
126+ obj = PySft ("" )
127+ import weakref
128+
129+ obj_wr = weakref .ref (obj )
130+ while True :
131+ stash1 = m .SftSharedPtrStash (1 )
132+ stash1 .AddSharedFromThis (obj )
133+ assert obj .history == ""
134+ assert obj .use_count () == 2
135+ assert stash1 .use_count (0 ) == 2
136+ stash1 .AddSharedFromThis (obj )
137+ assert obj .history == ""
138+ assert obj .use_count () == 3
139+ assert stash1 .use_count (0 ) == 3
140+ assert stash1 .use_count (1 ) == 3
141+ del obj
142+ assert obj_wr () is None # BAD NEEDS FIXING
143+ assert stash1 .use_count (0 ) == 2
144+ assert stash1 .use_count (1 ) == 2
145+ break # Comment out for manual leak checking (use `top` command).
90146
91147
92148def test_pass_released_shared_ptr_as_unique_ptr ():
0 commit comments