folk-plugin-http 0.3.2

HTTP plugin for Folk — accepts connections via hyper and dispatches to PHP workers
Documentation
//! Tests for parsing `[[http.hooks]]` from TOML config.

use folk_plugin_http::config::{HookConfig, HookErrorBehavior, HookMode, HttpConfig};

#[test]
fn hooks_default_empty() {
    let config = HttpConfig::default();
    assert!(config.hooks.is_empty());
}

#[test]
fn hooks_parse_minimal() {
    let toml = r#"
        [[hooks]]
        event = "request.before"
        lua = "scripts/rate_limit.lua"
    "#;
    let config: HttpConfig = toml::from_str(toml).unwrap();
    assert_eq!(config.hooks.len(), 1);
    let h = &config.hooks[0];
    assert_eq!(h.event, "request.before");
    assert_eq!(h.lua.to_str().unwrap(), "scripts/rate_limit.lua");
    assert_eq!(h.mode, HookMode::Sync);
    assert_eq!(h.timeout_ms, 5);
    assert_eq!(h.on_error, HookErrorBehavior::FailOpen);
}

#[test]
fn hooks_parse_full() {
    let toml = r#"
        [[hooks]]
        event = "request.before"
        lua = "scripts/auth.lua"
        mode = "sync"
        timeout_ms = 10
        on_error = "fail_closed"

        [[hooks]]
        event = "request.error"
        lua = "scripts/alert.lua"
        mode = "async"
    "#;
    let config: HttpConfig = toml::from_str(toml).unwrap();
    assert_eq!(config.hooks.len(), 2);

    let h0 = &config.hooks[0];
    assert_eq!(h0.event, "request.before");
    assert_eq!(h0.mode, HookMode::Sync);
    assert_eq!(h0.timeout_ms, 10);
    assert_eq!(h0.on_error, HookErrorBehavior::FailClosed);

    let h1 = &config.hooks[1];
    assert_eq!(h1.event, "request.error");
    assert_eq!(h1.mode, HookMode::Async);
    assert_eq!(h1.on_error, HookErrorBehavior::FailOpen);
}

#[test]
fn hooks_parse_all_events() {
    let toml = r#"
        [[hooks]]
        event = "request.before"
        lua = "a.lua"

        [[hooks]]
        event = "request.error"
        lua = "b.lua"

        [[hooks]]
        event = "response.headers"
        lua = "c.lua"

        [[hooks]]
        event = "response.after"
        lua = "d.lua"
    "#;
    let config: HttpConfig = toml::from_str(toml).unwrap();
    assert_eq!(config.hooks.len(), 4);
    let events: Vec<&str> = config.hooks.iter().map(|h| h.event.as_str()).collect();
    assert_eq!(
        events,
        [
            "request.before",
            "request.error",
            "response.headers",
            "response.after"
        ]
    );
}

#[test]
fn hooks_parse_hook_config_directly() {
    let toml = r#"
        event = "response.headers"
        lua = "cors.lua"
        mode = "sync"
        timeout_ms = 2
        on_error = "fail_open"
    "#;
    let h: HookConfig = toml::from_str(toml).unwrap();
    assert_eq!(h.event, "response.headers");
    assert_eq!(h.mode, HookMode::Sync);
    assert_eq!(h.timeout_ms, 2);
    assert_eq!(h.on_error, HookErrorBehavior::FailOpen);
}

#[test]
fn hooks_no_hooks_section_does_not_break_other_config() {
    let toml = r#"
        listen = "0.0.0.0:9000"
        access_log = true
    "#;
    let config: HttpConfig = toml::from_str(toml).unwrap();
    assert_eq!(config.listen.to_string(), "0.0.0.0:9000");
    assert!(config.access_log);
    assert!(config.hooks.is_empty());
}