use folk_runtime_embed::php::{PhpInstance, ZvalValue};
#[test]
fn fatal_error_die_worker_survives() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot failed");
php.request_startup().expect("startup failed");
let result = php.eval("die('fatal');");
assert!(result.is_err(), "die() should return error");
php.request_shutdown();
php.request_startup()
.expect("startup after die should work");
let result = php
.eval(r#"echo "alive";"#)
.expect("eval should work after die");
assert_eq!(result.output, "alive");
php.request_shutdown();
}
#[test]
fn fatal_error_exit_worker_survives() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot failed");
php.request_startup().expect("startup failed");
let result = php.eval("exit(1);");
assert!(result.is_err(), "exit() should return error");
php.request_shutdown();
php.request_startup()
.expect("startup after exit should work");
let result = php.eval(r#"echo "still here";"#).expect("eval should work");
assert_eq!(result.output, "still here");
php.request_shutdown();
}
#[test]
fn fatal_error_undefined_class() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot failed");
php.request_startup().expect("startup failed");
let result = php.eval("new ThisClassDoesNotExistAnywhere();");
assert!(result.is_err(), "undefined class should return error");
php.request_shutdown();
php.request_startup().expect("startup should work");
let result = php.call("strlen", &["test"]).expect("call should work");
assert_eq!(result, ZvalValue::Long(4));
php.request_shutdown();
}
#[test]
fn fatal_error_undefined_function() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot failed");
php.request_startup().expect("startup failed");
let result = php.call("this_function_absolutely_does_not_exist", &[]);
assert!(result.is_err(), "undefined function should return error");
php.request_shutdown();
php.request_startup().expect("startup should work");
let result = php.eval(r#"echo "ok";"#).expect("eval should work");
assert_eq!(result.output, "ok");
php.request_shutdown();
}
#[test]
fn worker_survives_many_fatal_errors() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot failed");
for i in 0..50 {
php.request_startup().expect("startup failed");
if i % 2 == 0 {
let _ = php.eval("die('boom');");
} else {
let result = php
.eval(&format!(r#"echo "ok-{i}";"#))
.expect("eval should work");
assert_eq!(result.output, format!("ok-{i}"));
}
php.request_shutdown();
}
}
#[test]
fn protected_eval_catches_fatal() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot failed");
php.request_startup().expect("startup failed");
let result = php.eval_protected("die('protected');");
assert!(result.is_err());
php.request_shutdown();
php.request_startup().expect("startup should work");
let result = php
.eval_protected(r#"echo "protected ok";"#)
.expect("eval should work");
assert_eq!(result.output, "protected ok");
php.request_shutdown();
}
#[test]
fn protected_call_catches_fatal() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot failed");
php.request_startup().expect("startup failed");
let result = php.call_protected("nonexistent_function_xyz", &[]);
assert!(result.is_err());
php.request_shutdown();
php.request_startup().expect("startup should work");
let result = php
.call_protected("strtoupper", &["hello"])
.expect("call should work");
assert_eq!(result, ZvalValue::String("HELLO".to_string()));
php.request_shutdown();
}
#[test]
fn sapi_name_after_signal_restore() {
let mut php = PhpInstance::boot_custom_sapi().expect("boot with signals failed");
let mut ctx = folk_runtime_embed::php::RequestContext::new("GET", "/");
php.set_request_context(&mut ctx);
php.request_startup().expect("startup failed");
let result = php.eval(r#"echo php_sapi_name();"#).expect("eval failed");
assert_eq!(result.output, "folk-embed");
php.request_shutdown();
}