#![allow(unsafe_code)] #![allow(clippy::print_stdout)]
use cuengine::{CStringPtr, evaluate_cue_package};
use std::ffi::CString;
use std::fs;
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::{Duration, Instant};
use tempfile::TempDir;
#[test]
fn test_cstring_ptr_raii_memory_management() {
let test_strings = vec!["test1", "test2", "test3", "longer test string", ""];
for test_str in test_strings {
let c_string = CString::new(test_str).unwrap();
let ptr = c_string.into_raw();
let wrapper = unsafe { CStringPtr::new(ptr) };
if !wrapper.is_null() {
let converted = unsafe { wrapper.to_str().unwrap() };
assert_eq!(converted, test_str);
}
}
}
#[test]
fn test_concurrent_ffi_access() {
const NUM_THREADS: usize = 8;
const CALLS_PER_THREAD: usize = 10;
let temp_dir = TempDir::new().unwrap();
let cue_content = r#"package cuenv
env: {
THREAD_TEST: "concurrent_value"
THREAD_ID: 1
}
"#;
fs::write(temp_dir.path().join("env.cue"), cue_content).unwrap();
let barrier = Arc::new(Barrier::new(NUM_THREADS));
let temp_path = Arc::new(temp_dir.path().to_path_buf());
let handles: Vec<_> = (0..NUM_THREADS)
.map(|thread_id| {
let barrier = Arc::clone(&barrier);
let temp_path = Arc::clone(&temp_path);
thread::spawn(move || {
barrier.wait();
let mut results = Vec::new();
let mut errors = Vec::new();
for call_id in 0..CALLS_PER_THREAD {
match evaluate_cue_package(&temp_path, "cuenv") {
Ok(json) => {
results.push((thread_id, call_id, json));
}
Err(e) => {
errors.push((thread_id, call_id, e.to_string()));
}
}
thread::sleep(Duration::from_millis(1));
}
(thread_id, results, errors)
})
})
.collect();
let mut total_successes = 0;
let mut total_errors = 0;
for handle in handles {
let (thread_id, results, errors) = handle.join().unwrap();
total_successes += results.len();
total_errors += errors.len();
for (_tid, _call_id, json) in results {
if json.contains("THREAD_TEST") {
assert!(json.contains("concurrent_value"));
}
}
for (_tid, _call_id, error) in errors {
println!("Thread {thread_id} error: {error}");
}
}
println!("Concurrent FFI test: {total_successes} successes, {total_errors} errors");
if total_successes > 0 {
assert!(
total_successes > total_errors,
"If FFI works, most calls should succeed"
);
} else {
println!("FFI appears unavailable in test environment");
}
}
#[test]
fn test_ffi_memory_leak_detection() {
let temp_dir = TempDir::new().unwrap();
for i in 0..3 {
let cue_content = format!(
r#"package cuenv
env: {{
LEAK_TEST: "value_{i}"
DATA: "{}"
}}
"#,
"x".repeat(100 * (i + 1)) );
fs::write(temp_dir.path().join(format!("test_{i}.cue")), cue_content).unwrap();
}
for iteration in 0..50 {
let file_index = iteration % 3;
let _ = fs::remove_file(temp_dir.path().join("env.cue"));
fs::copy(
temp_dir.path().join(format!("test_{file_index}.cue")),
temp_dir.path().join("env.cue"),
)
.unwrap();
match evaluate_cue_package(temp_dir.path(), "cuenv") {
Ok(json) => {
assert!(
json.contains(&format!("value_{file_index}")) || json.contains("env"),
"Expected value_{file_index} or env in JSON: {json}"
);
}
Err(_) => {
if iteration > 5 {
break; }
}
}
}
}
#[test]
fn test_ffi_error_handling_edge_cases() {
let temp_dir = TempDir::new().unwrap();
let long_package_name = "x".repeat(1000);
let test_cases = vec![
("", "Empty package name should be handled"),
(
&long_package_name,
"Very long package name should be handled",
),
("package!@#$%", "Special characters should be handled"),
("definitely_not_a_real_package", "Non-existent package"),
];
for (package_name, description) in test_cases {
let result = evaluate_cue_package(temp_dir.path(), package_name);
match result {
Ok(json) => {
println!("{description}: succeeded with {}", json.len());
}
Err(error) => {
let error_str = error.to_string();
assert!(
!error_str.is_empty(),
"{description}: Error should not be empty"
);
assert!(
error_str.len() > 10,
"{description}: Error should be meaningful"
);
println!("{description}: got expected error: {error_str}");
}
}
}
}
#[test]
fn test_ffi_with_complex_directory_structure() {
let temp_dir = TempDir::new().unwrap();
let nested_dir = temp_dir.path().join("very").join("deeply").join("nested");
fs::create_dir_all(&nested_dir).unwrap();
let cue_content = r#"package cuenv
env: {
NESTED_TEST: "deep_value"
DEPTH: 3
}
"#;
fs::write(nested_dir.join("env.cue"), cue_content).unwrap();
let result = evaluate_cue_package(&nested_dir, "cuenv");
match result {
Ok(json) => {
assert!(json.contains("NESTED_TEST") || json.contains("env"));
assert!(json.contains("deep_value") || json.contains("env"));
println!("Nested directory test succeeded");
}
Err(e) => {
println!("Nested directory test failed (FFI may be unavailable): {e}");
}
}
let unicode_dir = temp_dir.path().join("测试 directory with spaces");
fs::create_dir_all(&unicode_dir).unwrap();
let unicode_cue = r#"package cuenv
env: {
UNICODE_TEST: "unicode_value"
PATH_TYPE: "unicode_with_spaces"
}
"#;
fs::write(unicode_dir.join("env.cue"), unicode_cue).unwrap();
let unicode_result = evaluate_cue_package(&unicode_dir, "cuenv");
match unicode_result {
Ok(json) => {
assert!(json.contains("UNICODE_TEST") || json.contains("env"));
println!("Unicode directory test succeeded");
}
Err(e) => {
println!("Unicode directory test failed: {e}");
}
}
}
#[test]
fn test_ffi_cleanup_on_errors() {
let temp_dir = TempDir::new().unwrap();
let invalid_cue_files = vec![
(
"syntax_error.cue",
"package cuenv\n\nthis is not valid CUE {",
),
("empty.cue", ""), ("wrong_package.cue", "package wrong\nenv: {TEST: \"value\"}"),
("circular.cue", "package cuenv\nenv: {A: env.B, B: env.A}"), ];
for (filename, content) in invalid_cue_files {
let _ = fs::remove_file(temp_dir.path().join("env.cue"));
fs::write(temp_dir.path().join(filename), content).unwrap();
let result = evaluate_cue_package(temp_dir.path(), "cuenv");
match result {
Ok(json) => {
println!("File {filename} unexpectedly succeeded: {json}");
}
Err(error) => {
println!("File {filename} failed as expected: {error}");
assert!(!error.to_string().is_empty());
}
}
let _ = fs::remove_file(temp_dir.path().join(filename));
}
let valid_cue = "package cuenv\nenv: {RECOVERY_TEST: \"recovered\"}";
fs::write(temp_dir.path().join("env.cue"), valid_cue).unwrap();
let recovery_result = evaluate_cue_package(temp_dir.path(), "cuenv");
match recovery_result {
Ok(json) => {
assert!(json.contains("RECOVERY_TEST"));
println!("FFI recovered successfully after errors");
}
Err(e) => {
println!("FFI recovery failed (may be unavailable): {e}");
}
}
}
#[test]
fn test_ffi_performance_characteristics() {
let temp_dir = TempDir::new().unwrap();
let cue_content = r#"package cuenv
env: {
PERF_TEST: "performance_test"
LARGE_DATA: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
NUMBERS: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
NESTED: {
LEVEL1: {
LEVEL2: {
LEVEL3: "deep_value"
}
}
}
}
"#;
fs::write(temp_dir.path().join("env.cue"), cue_content).unwrap();
let mut times = Vec::new();
for i in 0..10 {
let start = Instant::now();
match evaluate_cue_package(temp_dir.path(), "cuenv") {
Ok(json) => {
let duration = start.elapsed();
times.push(duration);
assert!(json.contains("PERF_TEST") || json.contains("env"));
assert!(json.contains("Lorem ipsum") || json.contains("env"));
println!("Call {i}: {:?} (JSON size: {} bytes)", duration, json.len());
}
Err(e) => {
println!("Performance test call {i} failed: {e}");
if i > 2 {
break; }
}
}
}
if times.is_empty() {
println!("FFI performance test skipped (FFI unavailable)");
} else {
let avg_time = times.iter().sum::<Duration>() / u32::try_from(times.len()).unwrap();
let max_time = times.iter().max().unwrap();
let min_time = times.iter().min().unwrap();
println!("FFI Performance: avg={avg_time:?}, min={min_time:?}, max={max_time:?}");
assert!(
max_time < &Duration::from_secs(5),
"No single call should take longer than 5 seconds"
);
assert!(
avg_time < Duration::from_secs(1),
"Average call time should be under 1 second"
);
}
}