use jvmrs::interpreter::Interpreter;
use jvmrs::inline_cache::{InlineCacheManager, CallSiteCache, InlineCacheEntry};
use jvmrs::class_file::{ClassFile, MethodInfo};
#[test]
fn test_inline_cache_functionality() {
let mut interpreter = Interpreter::new();
let cache_manager = InlineCacheManager::new(true);
assert!(cache_manager.is_enabled());
let cache = cache_manager.get_cache("TestClass", "method", "()V", 100);
assert!(cache.is_none());
}
#[test]
fn test_call_site_cache_basic_operations() {
let mut cache = CallSiteCache::new(4);
let entry = InlineCacheEntry {
receiver_class: "java/lang/String".to_string(),
method_name: "toString".to_string(),
descriptor: "()Ljava/lang/String;".to_string(),
resolved_class: "java/lang/String".to_string(),
method: std::sync::Arc::new(create_test_method()),
hit_count: 0,
};
cache.update(entry.clone());
let found = cache.lookup("java/lang/String", "toString", "()Ljava/lang/String;");
assert!(found.is_some());
assert_eq!(found.unwrap().receiver_class, "java/lang/String");
let stats = cache.stats();
assert_eq!(stats.total_lookups, 1);
assert_eq!(stats.cache_hits, 0); assert_eq!(stats.entry_count, 1);
}
#[test]
fn test_call_site_cache_lru_eviction() {
let mut cache = CallSiteCache::new(2);
let entry1 = create_test_entry("Class1", "method1", "()V");
let entry2 = create_test_entry("Class2", "method2", "()V");
cache.update(entry1.clone());
cache.update(entry2.clone());
assert_eq!(cache.stats().entry_count, 2);
let entry3 = create_test_entry("Class3", "method3", "()V");
cache.update(entry3.clone());
assert_eq!(cache.stats().entry_count, 2);
let stats1 = cache.lookup("Class1", "method1", "()V");
let stats2 = cache.lookup("Class2", "method2", "()V");
let stats3 = cache.lookup("Class3", "method3", "()V");
let found_original = stats1.is_some() || stats2.is_some();
let new_entry = stats3.is_some();
assert!(found_original);
assert!(new_entry);
}
#[test]
fn test_cache_hit_scenarios() {
let mut cache = CallSiteCache::new(4);
let entry = create_test_entry("TestClass", "testMethod", "()I");
cache.update(entry.clone());
let stats = cache.stats();
assert_eq!(stats.total_lookups, 1);
assert_eq!(stats.cache_hits, 0);
cache.update(entry.clone());
let stats = cache.stats();
assert_eq!(stats.total_lookups, 2);
assert_eq!(stats.cache_hits, 1);
assert!(stats.hit_rate > 0.0);
}
#[test]
fn test_cache_disabled_operations() {
let cache_manager = InlineCacheManager::new(false);
assert!(!cache_manager.is_enabled());
let cache = cache_manager.get_cache("TestClass", "method", "()V", 100);
assert!(cache.is_none());
let entry = create_test_entry("TestClass", "method", "()V");
cache_manager.update_cache("TestClass", "method", "()V", 100, entry);
let stats = cache_manager.get_stats();
assert!(stats.is_empty());
}
#[test]
fn test_cache_performance_characteristics() {
let mut cache = CallSiteCache::new(8);
let entry = create_test_entry("Test", "method", "()V");
for i in 0..1000 {
cache.update(entry.clone());
}
let stats = cache.stats();
assert_eq!(stats.total_lookups, 1000);
assert_eq!(stats.cache_hits, 999); assert!(stats.hit_rate > 0.9);
assert_eq!(stats.entry_count, 1); }
#[test]
fn test_cache_concurrent_access() {
let cache_manager = InlineCacheManager::new(true);
let entry = create_test_entry("ConcurrentTest", "method", "()V");
for i in 0..10 {
cache_manager.update_cache("ConcurrentTest", "method", "()V", i, entry.clone());
}
let stats = cache_manager.get_stats();
assert!(!stats.is_empty());
assert!(stats.len() > 0);
}
fn create_test_method() -> MethodInfo {
MethodInfo {
access_flags: 0,
name_index: 0,
descriptor_index: 0,
attributes: vec![],
}
}
fn create_test_entry(class: &str, method: &str, descriptor: &str) -> InlineCacheEntry {
InlineCacheEntry {
receiver_class: class.to_string(),
method_name: method.to_string(),
descriptor: descriptor.to_string(),
resolved_class: class.to_string(),
method: std::sync::Arc::new(create_test_method()),
hit_count: 0,
}
}