use crate::tests::*;
use android_logger::{Config, FilterBuilder};
use backtrace::Backtrace;
use jni::errors::Result as JniResult;
use jni::objects::{Global, JClass, JObject, JString};
use jni::vm::JavaVM;
use jni::{jni_sig, jni_str, Env, EnvUnowned};
use log::*;
use std::panic;
use std::path::{Path, PathBuf};
#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_com_keyring_1manager_keyring_1android_1test_MainActivity_run_1tests(
mut env: EnvUnowned,
_class: JClass,
ctx: JObject,
) {
android_logger::init_once(
Config::default()
.with_max_level(LevelFilter::Trace)
.with_tag("keyring_manager_android_tests")
.with_filter(FilterBuilder::new().parse("keyring=trace").build()),
);
panic::set_hook(Box::new(|panic_info| {
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
println!("panic occurred: {:?}", s);
} else {
println!("panic occurred");
}
let bt = Backtrace::new();
println!("Backtrace:\n{:?}", bt);
}));
env.with_env(|env| -> JniResult<()> {
let ctx = env.new_global_ref(ctx)?;
let vm = env.get_java_vm()?;
run_tests(vm, ctx);
Ok(())
})
.resolve::<jni::errors::ThrowRuntimeExAndDefault>();
}
pub fn run_tests(vm: JavaVM, ctx: Global<JObject<'static>>) {
info!("Starting unit tests");
std::thread::spawn(move || {
vm.attach_current_thread(|jnienv| {
let insecure_keyring_path_string = jnienv
.with_local_frame(64, |jnienv: &mut Env| -> JniResult<String> {
let file = jnienv
.call_method(
ctx.as_obj(),
jni_str!("getFilesDir"),
jni_sig!("()Ljava/io/File;"),
&[],
)
.unwrap()
.l()
.unwrap();
let path = jnienv
.call_method(
file,
jni_str!("getAbsolutePath"),
jni_sig!("()Ljava/lang/String;"),
&[],
)
.unwrap()
.l()
.unwrap();
let jstr = JString::cast_local(jnienv, path)?;
Ok(jstr.to_string())
})
.unwrap();
let insecure_keyring_path: PathBuf =
Path::new(&insecure_keyring_path_string).join("insecure_keyring");
let android_context = (
jnienv.get_java_vm().unwrap(),
jnienv.new_global_ref(ctx.as_obj()).unwrap(),
);
let platform_keyring_manager =
KeyringManager::new_secure(TEST_APPLICATION, android_context).unwrap();
let insecure_keyring_manager =
KeyringManager::new_insecure(TEST_APPLICATION, &insecure_keyring_path).unwrap();
info!("TEST: secure_test_escaped_password_input");
exec_test_escaped_password_input(&platform_keyring_manager);
info!("TEST: secure_test_add_ascii_password");
exec_test_add_ascii_password(&platform_keyring_manager);
info!("TEST: secure_test_round_trip_ascii_password");
exec_test_round_trip_ascii_password(&platform_keyring_manager);
info!("TEST: secure_test_add_non_ascii_password");
exec_test_add_non_ascii_password(&platform_keyring_manager);
info!("TEST: secure_test_round_trip_non_ascii_password");
exec_test_round_trip_non_ascii_password(&platform_keyring_manager);
info!("TEST: secure_test_multiple");
exec_test_multiple(&platform_keyring_manager);
info!("TEST: insecure_test_escaped_password_input");
exec_test_escaped_password_input(&insecure_keyring_manager);
info!("TEST: insecure_test_add_ascii_password");
exec_test_add_ascii_password(&insecure_keyring_manager);
info!("TEST: insecure_test_round_trip_ascii_password");
exec_test_round_trip_ascii_password(&insecure_keyring_manager);
info!("TEST: insecure_test_add_non_ascii_password");
exec_test_add_non_ascii_password(&insecure_keyring_manager);
info!("TEST: insecure_test_round_trip_non_ascii_password");
exec_test_round_trip_non_ascii_password(&insecure_keyring_manager);
info!("TEST: insecure_test_multiple");
exec_test_multiple(&insecure_keyring_manager);
JniResult::Ok(())
})
.unwrap();
})
.join()
.unwrap();
info!("Finished unit tests");
}