47 /// from rust-cpython |
49 /// from rust-cpython |
48 fn mutate_string<'py>( |
50 fn mutate_string<'py>( |
49 owner: &'py Bound<'py, Owner>, |
51 owner: &'py Bound<'py, Owner>, |
50 f: impl FnOnce(&mut String), |
52 f: impl FnOnce(&mut String), |
51 ) -> () { |
53 ) -> () { |
52 let cell = &owner.borrow_mut().string; |
54 let shareable = &owner.borrow_mut().string; |
53 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
55 let shared_ref = unsafe { shareable.borrow_with_owner(owner) }; |
54 f(&mut shared_ref.write()); |
56 f(&mut shared_ref.write()); |
55 } |
57 } |
56 |
58 |
57 #[test] |
59 #[test] |
58 fn test_leaked_borrow() -> PyResult<()> { |
60 fn test_shared_borrow() -> PyResult<()> { |
59 with_setup(|py, owner| { |
61 with_setup(|py, owner| { |
60 let leaked = leak_string(owner); |
62 let shared = share_string(owner); |
61 let leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); |
63 let shared_ref = unsafe { shared.try_borrow(py) }.unwrap(); |
62 assert_eq!(*leaked_ref, "new"); |
64 assert_eq!(*shared_ref, "new"); |
63 Ok(()) |
65 Ok(()) |
64 }) |
66 }) |
65 } |
67 } |
66 |
68 |
67 #[test] |
69 #[test] |
68 fn test_leaked_borrow_mut() -> PyResult<()> { |
70 fn test_shared_borrow_mut() -> PyResult<()> { |
69 with_setup(|py, owner| { |
71 with_setup(|py, owner| { |
70 let leaked = leak_string(owner); |
72 let shared = share_string(owner); |
71 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
73 let mut shared_iter = unsafe { shared.map(py, |s| s.chars()) }; |
72 let mut leaked_ref = |
74 let mut shared_ref = |
73 unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); |
75 unsafe { shared_iter.try_borrow_mut(py) }.unwrap(); |
74 assert_eq!(leaked_ref.next(), Some('n')); |
76 assert_eq!(shared_ref.next(), Some('n')); |
75 assert_eq!(leaked_ref.next(), Some('e')); |
77 assert_eq!(shared_ref.next(), Some('e')); |
76 assert_eq!(leaked_ref.next(), Some('w')); |
78 assert_eq!(shared_ref.next(), Some('w')); |
77 assert_eq!(leaked_ref.next(), None); |
79 assert_eq!(shared_ref.next(), None); |
78 Ok(()) |
80 Ok(()) |
79 }) |
81 }) |
80 } |
82 } |
81 |
83 |
82 #[test] |
84 #[test] |
83 fn test_leaked_borrow_after_mut() -> PyResult<()> { |
85 fn test_shared_borrow_after_mut() -> PyResult<()> { |
84 with_setup(|py, owner| { |
86 with_setup(|py, owner| { |
85 let leaked = leak_string(owner); |
87 let shared = share_string(owner); |
86 mutate_string(owner, String::clear); |
88 mutate_string(owner, String::clear); |
87 assert!(unsafe { leaked.try_borrow(py) }.is_err()); |
89 assert!(unsafe { shared.try_borrow(py) }.is_err()); |
88 Ok(()) |
90 Ok(()) |
89 }) |
91 }) |
90 } |
92 } |
91 |
93 |
92 #[test] |
94 #[test] |
93 fn test_leaked_borrow_mut_after_mut() -> PyResult<()> { |
95 fn test_shared_borrow_mut_after_mut() -> PyResult<()> { |
94 with_setup(|py, owner| { |
96 with_setup(|py, owner| { |
95 let leaked = leak_string(owner); |
97 let shared = share_string(owner); |
96 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
98 let mut shared_iter = unsafe { shared.map(py, |s| s.chars()) }; |
97 |
99 |
98 mutate_string(owner, String::clear); |
100 mutate_string(owner, String::clear); |
99 assert!(unsafe { leaked_iter.try_borrow_mut(py) }.is_err()); |
101 assert!(unsafe { shared_iter.try_borrow_mut(py) }.is_err()); |
100 Ok(()) |
102 Ok(()) |
101 }) |
103 }) |
102 } |
104 } |
103 |
105 |
104 #[test] |
106 #[test] |
105 #[should_panic(expected = "map() over invalidated shared reference")] |
107 #[should_panic(expected = "map() over invalidated shared reference")] |
106 fn test_leaked_map_after_mut() { |
108 fn test_shared_map_after_mut() { |
107 with_setup(|py, owner| { |
109 with_setup(|py, owner| { |
108 let leaked = leak_string(owner); |
110 let shared = share_string(owner); |
109 mutate_string(owner, String::clear); |
111 mutate_string(owner, String::clear); |
110 let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
112 let _shared_iter = unsafe { shared.map(py, |s| s.chars()) }; |
111 Ok(()) |
113 Ok(()) |
112 }) |
114 }) |
113 .expect("should already have panicked") |
115 .expect("should already have panicked") |
114 } |
116 } |
115 |
117 |
116 /// run `try_borrow_mut` on the `string` field and assert it is not an error |
118 /// run `try_borrow_mut` on the `string` field and assert it is not an error |
117 /// |
119 /// |
118 /// Simply returning the `Result` is not possible, because that is |
120 /// Simply returning the `Result` is not possible, because that is |
119 /// returning a reference to data owned by the function |
121 /// returning a reference to data owned by the function |
120 fn assert_try_write_string_ok(owner: &Bound<'_, Owner>) { |
122 fn assert_try_write_string_ok(owner: &Bound<'_, Owner>) { |
121 let cell = &owner.borrow().string; |
123 let shareable = &owner.borrow().string; |
122 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
124 let shared_ref = unsafe { shareable.borrow_with_owner(owner) }; |
123 assert!(shared_ref.try_write().is_ok()); |
125 assert!(shared_ref.try_write().is_ok()); |
124 } |
126 } |
125 |
127 |
126 fn assert_try_write_string_err(owner: &Bound<'_, Owner>) { |
128 fn assert_try_write_string_err(owner: &Bound<'_, Owner>) { |
127 let cell = &owner.borrow().string; |
129 let shareable = &owner.borrow().string; |
128 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
130 let shared_ref = unsafe { shareable.borrow_with_owner(owner) }; |
129 assert!(shared_ref.try_write().is_err()); |
131 assert!(shared_ref.try_write().is_err()); |
130 } |
132 } |
131 |
133 |
132 fn assert_try_read_string_err(owner: &Bound<'_, Owner>) { |
134 fn assert_try_read_string_err(owner: &Bound<'_, Owner>) { |
133 let cell = &owner.borrow().string; |
135 let shareable = &owner.borrow().string; |
134 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
136 let shared_ref = unsafe { shareable.borrow_with_owner(owner) }; |
135 assert!(shared_ref.try_read().is_err()); |
137 assert!(shared_ref.try_read().is_err()); |
136 } |
138 } |
137 |
139 |
138 #[test] |
140 #[test] |
139 fn test_try_write_while_leaked_ref() -> PyResult<()> { |
141 fn test_try_write_while_shared_ref() -> PyResult<()> { |
140 with_setup(|py, owner| { |
142 with_setup(|py, owner| { |
141 assert_try_write_string_ok(owner); |
143 assert_try_write_string_ok(owner); |
142 let leaked = leak_string(owner); |
144 let shared = share_string(owner); |
143 { |
145 { |
144 let _leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); |
146 let _shared_ref = unsafe { shared.try_borrow(py) }.unwrap(); |
145 assert_try_write_string_err(owner); |
147 assert_try_write_string_err(owner); |
146 { |
148 { |
147 let _leaked_ref2 = unsafe { leaked.try_borrow(py) }.unwrap(); |
149 let _shared_ref2 = unsafe { shared.try_borrow(py) }.unwrap(); |
148 assert_try_write_string_err(owner); |
150 assert_try_write_string_err(owner); |
149 } |
151 } |
150 assert_try_write_string_err(owner); |
152 assert_try_write_string_err(owner); |
151 } |
153 } |
152 assert_try_write_string_ok(owner); |
154 assert_try_write_string_ok(owner); |
153 Ok(()) |
155 Ok(()) |
154 }) |
156 }) |
155 } |
157 } |
156 |
158 |
157 #[test] |
159 #[test] |
158 fn test_try_write_while_leaked_ref_mut() -> PyResult<()> { |
160 fn test_try_write_while_shared_ref_mut() -> PyResult<()> { |
159 with_setup(|py, owner| { |
161 with_setup(|py, owner| { |
160 assert_try_write_string_ok(owner); |
162 assert_try_write_string_ok(owner); |
161 let leaked = leak_string(owner); |
163 let shared = share_string(owner); |
162 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
164 let mut shared_iter = unsafe { shared.map(py, |s| s.chars()) }; |
163 { |
165 { |
164 let _leaked_ref = |
166 let _shared_ref = |
165 unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); |
167 unsafe { shared_iter.try_borrow_mut(py) }.unwrap(); |
166 assert_try_write_string_err(owner); |
168 assert_try_write_string_err(owner); |
167 } |
169 } |
168 assert_try_write_string_ok(owner); |
170 assert_try_write_string_ok(owner); |
169 Ok(()) |
171 Ok(()) |
170 }) |
172 }) |
171 } |
173 } |
172 |
174 |
173 #[test] |
175 #[test] |
174 fn test_try_leak_while_write() -> PyResult<()> { |
176 fn test_try_share_while_write() -> PyResult<()> { |
175 with_setup(|_py, owner| { |
177 with_setup(|_py, owner| { |
176 let cell = &owner.borrow().string; |
178 let shareable = &owner.borrow().string; |
177 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
179 let shared_ref = unsafe { shareable.borrow_with_owner(owner) }; |
178 let _mut_ref = shared_ref.write(); |
180 let _mut_ref = shared_ref.write(); |
179 |
181 |
180 assert!(try_leak_string(owner).is_err()); |
182 assert!(try_share_string(owner).is_err()); |
181 Ok(()) |
183 Ok(()) |
182 }) |
184 }) |
183 } |
185 } |
184 |
186 |
185 #[test] |
187 #[test] |
186 #[should_panic(expected = "already mutably borrowed")] |
188 #[should_panic(expected = "already mutably borrowed")] |
187 fn test_leak_while_write() { |
189 fn test_share_while_write() { |
188 with_setup(|_py, owner| { |
190 with_setup(|_py, owner| { |
189 let cell = &owner.borrow().string; |
191 let shareable = &owner.borrow().string; |
190 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
192 let shared_ref = unsafe { shareable.borrow_with_owner(owner) }; |
191 let _mut_ref = shared_ref.write(); |
193 let _mut_ref = shared_ref.write(); |
192 |
194 |
193 leak_string(owner); |
195 share_string(owner); |
194 Ok(()) |
196 Ok(()) |
195 }) |
197 }) |
196 .expect("should already have panicked") |
198 .expect("should already have panicked") |
197 } |
199 } |
198 |
200 |
199 #[test] |
201 #[test] |
200 fn test_try_write_while_borrow() -> PyResult<()> { |
202 fn test_try_write_while_borrow() -> PyResult<()> { |
201 with_setup(|_py, owner| { |
203 with_setup(|_py, owner| { |
202 let cell = &owner.borrow().string; |
204 let shareable = &owner.borrow().string; |
203 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
205 let shared_ref = unsafe { shareable.borrow_with_owner(owner) }; |
204 let _ref = shared_ref.read(); |
206 let _ref = shared_ref.read(); |
205 |
207 |
206 assert_try_write_string_err(owner); |
208 assert_try_write_string_err(owner); |
207 Ok(()) |
209 Ok(()) |
208 }) |
210 }) |