comparison rust/pyo3-sharedref/tests/test_sharedref.rs @ 52633:d85514a88706

rust-pyo3-sharedref: reworked constructors We had previously duplicated the `new` associated function on `PySharedRef` with a method on `PySharedRefCell`: in `rust-cpython`, the former was hidden by the accessor defined by the `py_class!` macro, which we did not port yet. On `PySharedRefCell` itself, replacing the `new` associated function by the `From` trait carries all the needed semantics, and has the advantage of less repetititons of the type name, which will help with further refactorings and renamings.
author Georges Racinet <georges.racinet@cloudcrane.io>
date Sun, 15 Dec 2024 14:42:53 +0100
parents a7d2529ed6dd
children d1e304025b90
comparison
equal deleted inserted replaced
52632:a7d2529ed6dd 52633:d85514a88706
8 8
9 #[pymethods] 9 #[pymethods]
10 impl Owner { 10 impl Owner {
11 #[new] 11 #[new]
12 fn new(s: String) -> Self { 12 fn new(s: String) -> Self {
13 Self { 13 Self { string: s.into() }
14 string: PySharedRefCell::new(s),
15 }
16 } 14 }
17 } 15 }
18 16
19 fn with_setup( 17 fn with_setup(
20 test: impl FnOnce(Python<'_>, &Bound<'_, Owner>) -> PyResult<()>, 18 test: impl FnOnce(Python<'_>, &Bound<'_, Owner>) -> PyResult<()>,
28 26
29 /// "leak" in the sense of `UnsafePyLeaked` the `string` data field, 27 /// "leak" in the sense of `UnsafePyLeaked` the `string` data field,
30 /// taking care of all the boilerplate 28 /// taking care of all the boilerplate
31 fn leak_string(owner: &Bound<'_, Owner>) -> UnsafePyLeaked<&'static String> { 29 fn leak_string(owner: &Bound<'_, Owner>) -> UnsafePyLeaked<&'static String> {
32 let cell = &owner.borrow().string; 30 let cell = &owner.borrow().string;
33 let shared_ref = unsafe { cell.borrow(owner) }; 31 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
34 shared_ref.leak_immutable() 32 shared_ref.leak_immutable()
35 } 33 }
36 34
37 fn try_leak_string( 35 fn try_leak_string(
38 owner: &Bound<'_, Owner>, 36 owner: &Bound<'_, Owner>,
39 ) -> Result<UnsafePyLeaked<&'static String>, TryLeakError> { 37 ) -> Result<UnsafePyLeaked<&'static String>, TryLeakError> {
40 let cell = &owner.borrow().string; 38 let cell = &owner.borrow().string;
41 let shared_ref = unsafe { cell.borrow(owner) }; 39 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
42 shared_ref.try_leak_immutable() 40 shared_ref.try_leak_immutable()
43 } 41 }
44 42
45 /// Mutate the `string` field of `owner` as would be done from Python code 43 /// Mutate the `string` field of `owner` as would be done from Python code
46 /// 44 ///
52 fn mutate_string<'py>( 50 fn mutate_string<'py>(
53 owner: &'py Bound<'py, Owner>, 51 owner: &'py Bound<'py, Owner>,
54 f: impl FnOnce(&mut String), 52 f: impl FnOnce(&mut String),
55 ) -> () { 53 ) -> () {
56 let cell = &owner.borrow_mut().string; 54 let cell = &owner.borrow_mut().string;
57 let shared_ref = unsafe { cell.borrow(owner) }; 55 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
58 f(&mut shared_ref.borrow_mut()); 56 f(&mut shared_ref.borrow_mut());
59 } 57 }
60 58
61 #[test] 59 #[test]
62 fn test_leaked_borrow() -> PyResult<()> { 60 fn test_leaked_borrow() -> PyResult<()> {
121 /// 119 ///
122 /// Simply returning the `Result` is not possible, because that is 120 /// Simply returning the `Result` is not possible, because that is
123 /// returning a reference to data owned by the function 121 /// returning a reference to data owned by the function
124 fn assert_try_borrow_string_mut_ok(owner: &Bound<'_, Owner>) { 122 fn assert_try_borrow_string_mut_ok(owner: &Bound<'_, Owner>) {
125 let cell = &owner.borrow().string; 123 let cell = &owner.borrow().string;
126 let shared_ref = unsafe { cell.borrow(owner) }; 124 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
127 assert!(shared_ref.try_borrow_mut().is_ok()); 125 assert!(shared_ref.try_borrow_mut().is_ok());
128 } 126 }
129 127
130 fn assert_try_borrow_string_mut_err(owner: &Bound<'_, Owner>) { 128 fn assert_try_borrow_string_mut_err(owner: &Bound<'_, Owner>) {
131 let cell = &owner.borrow().string; 129 let cell = &owner.borrow().string;
132 let shared_ref = unsafe { cell.borrow(owner) }; 130 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
133 assert!(shared_ref.try_borrow_mut().is_err()); 131 assert!(shared_ref.try_borrow_mut().is_err());
134 } 132 }
135 133
136 fn assert_try_borrow_string_err(owner: &Bound<'_, Owner>) { 134 fn assert_try_borrow_string_err(owner: &Bound<'_, Owner>) {
137 let cell = &owner.borrow().string; 135 let cell = &owner.borrow().string;
138 let shared_ref = unsafe { cell.borrow(owner) }; 136 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
139 assert!(shared_ref.try_borrow().is_err()); 137 assert!(shared_ref.try_borrow().is_err());
140 } 138 }
141 139
142 #[test] 140 #[test]
143 fn test_try_borrow_mut_while_leaked_ref() -> PyResult<()> { 141 fn test_try_borrow_mut_while_leaked_ref() -> PyResult<()> {
176 174
177 #[test] 175 #[test]
178 fn test_try_leak_while_borrow_mut() -> PyResult<()> { 176 fn test_try_leak_while_borrow_mut() -> PyResult<()> {
179 with_setup(|_py, owner| { 177 with_setup(|_py, owner| {
180 let cell = &owner.borrow().string; 178 let cell = &owner.borrow().string;
181 let shared_ref = unsafe { cell.borrow(owner) }; 179 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
182 let _mut_ref = shared_ref.borrow_mut(); 180 let _mut_ref = shared_ref.borrow_mut();
183 181
184 assert!(try_leak_string(owner).is_err()); 182 assert!(try_leak_string(owner).is_err());
185 Ok(()) 183 Ok(())
186 }) 184 })
189 #[test] 187 #[test]
190 #[should_panic(expected = "already mutably borrowed")] 188 #[should_panic(expected = "already mutably borrowed")]
191 fn test_leak_while_borrow_mut() { 189 fn test_leak_while_borrow_mut() {
192 with_setup(|_py, owner| { 190 with_setup(|_py, owner| {
193 let cell = &owner.borrow().string; 191 let cell = &owner.borrow().string;
194 let shared_ref = unsafe { cell.borrow(owner) }; 192 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
195 let _mut_ref = shared_ref.borrow_mut(); 193 let _mut_ref = shared_ref.borrow_mut();
196 194
197 leak_string(owner); 195 leak_string(owner);
198 Ok(()) 196 Ok(())
199 }) 197 })
202 200
203 #[test] 201 #[test]
204 fn test_try_borrow_mut_while_borrow() -> PyResult<()> { 202 fn test_try_borrow_mut_while_borrow() -> PyResult<()> {
205 with_setup(|_py, owner| { 203 with_setup(|_py, owner| {
206 let cell = &owner.borrow().string; 204 let cell = &owner.borrow().string;
207 let shared_ref = unsafe { cell.borrow(owner) }; 205 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
208 let _ref = shared_ref.borrow(); 206 let _ref = shared_ref.borrow();
209 207
210 assert_try_borrow_string_mut_err(owner); 208 assert_try_borrow_string_mut_err(owner);
211 Ok(()) 209 Ok(())
212 }) 210 })
215 #[test] 213 #[test]
216 #[should_panic(expected = "already borrowed")] 214 #[should_panic(expected = "already borrowed")]
217 fn test_borrow_mut_while_borrow() { 215 fn test_borrow_mut_while_borrow() {
218 with_setup(|_py, owner| { 216 with_setup(|_py, owner| {
219 let cell = &owner.borrow().string; 217 let cell = &owner.borrow().string;
220 let shared_ref = unsafe { cell.borrow(owner) }; 218 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
221 let _ref = shared_ref.borrow(); 219 let _ref = shared_ref.borrow();
222 220
223 let shared_ref2 = unsafe { cell.borrow(owner) }; 221 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) };
224 let _mut_ref = shared_ref2.borrow_mut(); 222 let _mut_ref = shared_ref2.borrow_mut();
225 Ok(()) 223 Ok(())
226 }) 224 })
227 .expect("should already have panicked") 225 .expect("should already have panicked")
228 } 226 }
229 227
230 #[test] 228 #[test]
231 fn test_try_borrow_while_borrow_mut() -> PyResult<()> { 229 fn test_try_borrow_while_borrow_mut() -> PyResult<()> {
232 with_setup(|_py, owner| { 230 with_setup(|_py, owner| {
233 let cell = &owner.borrow().string; 231 let cell = &owner.borrow().string;
234 let shared_ref = unsafe { cell.borrow(owner) }; 232 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
235 let _mut_ref = shared_ref.borrow_mut(); 233 let _mut_ref = shared_ref.borrow_mut();
236 234
237 assert_try_borrow_string_err(owner); 235 assert_try_borrow_string_err(owner);
238 Ok(()) 236 Ok(())
239 }) 237 })
242 #[test] 240 #[test]
243 #[should_panic(expected = "already mutably borrowed")] 241 #[should_panic(expected = "already mutably borrowed")]
244 fn test_borrow_while_borrow_mut() { 242 fn test_borrow_while_borrow_mut() {
245 with_setup(|_py, owner| { 243 with_setup(|_py, owner| {
246 let cell = &owner.borrow().string; 244 let cell = &owner.borrow().string;
247 let shared_ref = unsafe { cell.borrow(owner) }; 245 let shared_ref = unsafe { cell.borrow_with_owner(owner) };
248 let _mut_ref = shared_ref.borrow_mut(); 246 let _mut_ref = shared_ref.borrow_mut();
249 247
250 let shared_ref2 = unsafe { cell.borrow(owner) }; 248 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) };
251 let _ref = shared_ref2.borrow(); 249 let _ref = shared_ref2.borrow();
252 Ok(()) 250 Ok(())
253 }) 251 })
254 .expect("should already have panicked") 252 .expect("should already have panicked")
255 } 253 }