rust/pyo3-sharedref/tests/test_sharedref.rs
changeset 52608 d85514a88706
parent 52607 a7d2529ed6dd
child 52609 d1e304025b90
equal deleted inserted replaced
52607:a7d2529ed6dd 52608: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 }