• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![cfg(feature = "invocation")]
2 
3 use std::{sync::Arc, thread::spawn};
4 
5 use jni::{
6     errors::{Error, JniError},
7     Executor, JavaVM,
8 };
9 
10 mod util;
11 use util::jvm;
12 
13 /// Checks if nested attaches are working properly and threads detach themselves
14 /// on exit.
15 #[test]
nested_attach()16 fn nested_attach() {
17     let executor = Executor::new(jvm().clone());
18 
19     assert_eq!(jvm().threads_attached(), 0);
20     let thread = spawn(|| {
21         assert_eq!(jvm().threads_attached(), 0);
22         check_nested_attach(jvm(), executor);
23         assert_eq!(jvm().threads_attached(), 1);
24     });
25     thread.join().unwrap();
26     assert_eq!(jvm().threads_attached(), 0);
27 }
28 
29 /// Checks if nested `with_attached` calls does not detach the thread before the outer-most
30 /// call is finished.
check_nested_attach(vm: &Arc<JavaVM>, executor: Executor)31 fn check_nested_attach(vm: &Arc<JavaVM>, executor: Executor) {
32     check_detached(vm);
33     executor
34         .with_attached(|_| {
35             check_attached(vm);
36             executor.with_attached(|_| {
37                 check_attached(vm);
38                 Ok(())
39             })?;
40             check_attached(vm);
41             Ok(())
42         })
43         .unwrap();
44 }
45 
check_attached(vm: &JavaVM)46 fn check_attached(vm: &JavaVM) {
47     assert!(is_attached(vm));
48 }
49 
check_detached(vm: &JavaVM)50 fn check_detached(vm: &JavaVM) {
51     assert!(!is_attached(vm));
52 }
53 
is_attached(vm: &JavaVM) -> bool54 fn is_attached(vm: &JavaVM) -> bool {
55     vm.get_env()
56         .map(|_| true)
57         .or_else(|jni_err| match jni_err {
58             Error::JniCall(JniError::ThreadDetached) => Ok(false),
59             _ => Err(jni_err),
60         })
61         .expect("An unexpected JNI error occurred")
62 }
63