From 1c4e21f625a826cefe4407fcab8f7b017b62e5f9 Mon Sep 17 00:00:00 2001 From: oiupoyt Date: Tue, 29 Sep 2026 22:14:25 +0530 Subject: [PATCH] test(jni): implement JNI_OnLoad and ANativeActivity end-to-end integration test --- .../molotov-core/tests/jni_lifecycle_test.rs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 crates/molotov-core/tests/jni_lifecycle_test.rs diff --git a/crates/molotov-core/tests/jni_lifecycle_test.rs b/crates/molotov-core/tests/jni_lifecycle_test.rs new file mode 100644 index 0000000..3c8140f --- /dev/null +++ b/crates/molotov-core/tests/jni_lifecycle_test.rs @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +use molotov_core::jni::activity::{ANativeActivity, ActivityRunner}; +use molotov_core::jni::types::{JavaVMPtr, JNI_VERSION_1_6}; + +// Simulated JNI_OnLoad exported by libroblox.so +unsafe extern "C" fn mock_jni_onload(vm: JavaVMPtr, _reserved: *mut ()) -> i32 { + let mut env = std::ptr::null_mut(); + let res = (**vm).GetEnv.unwrap()(vm, &mut env, JNI_VERSION_1_6); + if res == 0 && !env.is_null() { + JNI_VERSION_1_6 + } else { + -1 + } +} + +// Simulated ANativeActivity_onCreate exported by libroblox.so +unsafe extern "C" fn mock_native_activity_on_create( + activity: *mut ANativeActivity, + _saved_state: *mut (), + _saved_state_size: usize, +) { + if let Some(act) = activity.as_mut() { + if let Some(cbs) = act.callbacks.as_mut() { + cbs.onResume = Some(mock_on_resume); + } + } +} + +static mut RESUME_CALLED: bool = false; +unsafe extern "C" fn mock_on_resume(_activity: *mut ANativeActivity) { + RESUME_CALLED = true; +} + +#[test] +fn test_jni_onload_and_native_activity_lifecycle() { + let mut runner = ActivityRunner::new(); + + // 1. Simulate JNI_OnLoad execution + unsafe { + let ver = mock_jni_onload(runner.activity.vm, std::ptr::null_mut()); + assert_eq!(ver, JNI_VERSION_1_6, "JNI_OnLoad must return JNI_VERSION_1_6"); + + // 2. Simulate ANativeActivity_onCreate + mock_native_activity_on_create(&mut *runner.activity, std::ptr::null_mut(), 0); + + // 3. Trigger Resume callback registered by the engine + runner.trigger_resume(); + assert!(RESUME_CALLED, "Registered onResume callback must be invoked"); + } +}