use cpython::{py_class, GILGuard, Python};
py_class!(class Owner |py| {
@shared data string: String;
});
fn prepare_env() -> (GILGuard, Owner) {
let gil = Python::acquire_gil();
let owner = {
let py = gil.python();
Owner::create_instance(py, "new".to_owned()).unwrap()
};
(gil, owner)
}
#[test]
fn test_leaked_borrow() {
let (gil, owner) = prepare_env();
let py = gil.python();
let leaked = owner.string(py).leak_immutable();
let leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap();
assert_eq!(*leaked_ref, "new");
}
#[test]
fn test_leaked_borrow_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let leaked = owner.string(py).leak_immutable();
let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
let mut leaked_ref = unsafe { leaked_iter.try_borrow_mut(py) }.unwrap();
assert_eq!(leaked_ref.next(), Some('n'));
assert_eq!(leaked_ref.next(), Some('e'));
assert_eq!(leaked_ref.next(), Some('w'));
assert_eq!(leaked_ref.next(), None);
}
#[test]
fn test_leaked_borrow_after_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let leaked = owner.string(py).leak_immutable();
owner.string(py).borrow_mut().clear();
assert!(unsafe { leaked.try_borrow(py) }.is_err());
}
#[test]
fn test_leaked_borrow_mut_after_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let leaked = owner.string(py).leak_immutable();
let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
owner.string(py).borrow_mut().clear();
assert!(unsafe { leaked_iter.try_borrow_mut(py) }.is_err());
}
#[test]
#[should_panic(expected = "map() over invalidated leaked reference")]
fn test_leaked_map_after_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let leaked = owner.string(py).leak_immutable();
owner.string(py).borrow_mut().clear();
let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
}
#[test]
fn test_try_borrow_mut_while_leaked_ref() {
let (gil, owner) = prepare_env();
let py = gil.python();
assert!(owner.string(py).try_borrow_mut().is_ok());
let leaked = owner.string(py).leak_immutable();
{
let _leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap();
assert!(owner.string(py).try_borrow_mut().is_err());
{
let _leaked_ref2 = unsafe { leaked.try_borrow(py) }.unwrap();
assert!(owner.string(py).try_borrow_mut().is_err());
}
assert!(owner.string(py).try_borrow_mut().is_err());
}
assert!(owner.string(py).try_borrow_mut().is_ok());
}
#[test]
fn test_try_borrow_mut_while_leaked_ref_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
assert!(owner.string(py).try_borrow_mut().is_ok());
let leaked = owner.string(py).leak_immutable();
let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
{
let _leaked_ref = unsafe { leaked_iter.try_borrow_mut(py) }.unwrap();
assert!(owner.string(py).try_borrow_mut().is_err());
}
assert!(owner.string(py).try_borrow_mut().is_ok());
}
#[test]
fn test_try_leak_while_borrow_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let _mut_ref = owner.string(py).borrow_mut();
assert!(owner.string(py).try_leak_immutable().is_err());
}
#[test]
#[should_panic(expected = "already mutably borrowed")]
fn test_leak_while_borrow_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let _mut_ref = owner.string(py).borrow_mut();
owner.string(py).leak_immutable();
}
#[test]
fn test_try_borrow_mut_while_borrow() {
let (gil, owner) = prepare_env();
let py = gil.python();
let _ref = owner.string(py).borrow();
assert!(owner.string(py).try_borrow_mut().is_err());
}
#[test]
#[should_panic(expected = "already borrowed")]
fn test_borrow_mut_while_borrow() {
let (gil, owner) = prepare_env();
let py = gil.python();
let _ref = owner.string(py).borrow();
owner.string(py).borrow_mut();
}
#[test]
fn test_try_borrow_while_borrow_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let _mut_ref = owner.string(py).borrow_mut();
assert!(owner.string(py).try_borrow().is_err());
}
#[test]
#[should_panic(expected = "already mutably borrowed")]
fn test_borrow_while_borrow_mut() {
let (gil, owner) = prepare_env();
let py = gil.python();
let _mut_ref = owner.string(py).borrow_mut();
owner.string(py).borrow();
}