use folk_runtime_embed::php::{PhpInstance, ZvalValue};
#[test]
fn test_boot_and_eval_echo() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
let result = php.eval(r#"echo "hello from PHP";"#).expect("eval failed");
assert_eq!(result.output, "hello from PHP");
php.request_shutdown();
}
#[test]
fn test_eval_return_value() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
let result = php.eval("return 42;").expect("eval failed");
php.request_shutdown();
}
#[test]
fn test_call_function() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
php.eval(r#"function folk_test_add($a, $b) { return (int)$a + (int)$b; }"#)
.expect("define function failed");
let result = php.call("folk_test_add", &["3", "4"]).expect("call failed");
assert_eq!(result, ZvalValue::Long(7));
php.request_shutdown();
}
#[test]
fn test_call_builtin_strlen() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
let result = php.call("strlen", &["hello world"]).expect("call failed");
assert_eq!(result, ZvalValue::Long(11));
php.request_shutdown();
}
#[test]
fn test_call_strtoupper() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
let result = php.call("strtoupper", &["hello"]).expect("call failed");
assert_eq!(result, ZvalValue::String("HELLO".to_string()));
php.request_shutdown();
}
#[test]
fn test_multiple_request_cycles() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
for i in 0..100 {
php.request_startup().expect("request startup failed");
let code = format!(r#"echo "request {i}";"#);
let result = php.eval(&code).expect("eval failed");
assert_eq!(result.output, format!("request {i}"));
php.request_shutdown();
}
}
#[test]
fn test_no_leaks_10k_requests() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
for _ in 0..10_000 {
php.request_startup().expect("request startup failed");
php.eval(r#"$x = str_repeat("A", 1024); echo strlen($x);"#)
.expect("eval failed");
php.request_shutdown();
}
}
#[test]
fn test_fatal_error_caught() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
let result = php.call("this_function_does_not_exist_at_all", &[]);
assert!(result.is_err(), "calling undefined function should fail");
php.request_shutdown();
php.request_startup()
.expect("request startup should work after error");
let result = php
.call("strlen", &["test"])
.expect("call should work after error");
assert_eq!(result, ZvalValue::Long(4));
php.request_shutdown();
}
#[test]
fn test_output_capture_reset_between_requests() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
php.eval(r#"echo "first";"#).expect("eval failed");
let output1 = php.take_output();
php.request_shutdown();
php.request_startup().expect("request startup failed");
php.eval(r#"echo "second";"#).expect("eval failed");
let output2 = php.take_output();
php.request_shutdown();
assert!(!output2.contains("first"), "output leaked between requests");
assert_eq!(output2, "second");
}
#[test]
fn test_json_encode_decode() {
let mut php = PhpInstance::boot().expect("PHP boot failed");
php.request_startup().expect("request startup failed");
php.eval(
r#"
$data = ['status' => 'ok', 'count' => 42];
echo json_encode($data);
"#,
)
.expect("eval failed");
let output = php.take_output();
assert_eq!(output, r#"{"status":"ok","count":42}"#);
php.request_shutdown();
}