parlov 0.4.0

HTTP oracle detection tool — systematic probing for RFC-compliant information leakage.
Documentation
//! Sanity-check tests for the RFC-compliant PATCH test server.
//!
//! Each test spawns an isolated server instance, sends a PATCH request with a
//! known or unknown ID, and asserts the expected status code. No oracle types
//! are used — raw reqwest only.

#![deny(clippy::all)]

mod fixtures {
    pub mod patch_server;
}

use fixtures::patch_server::spawn;
use serde_json::json;

// --- /resource/{id} ---

#[tokio::test]
async fn patch_resource_known_id_returns_422() {
    let addr = spawn().await;
    let resp = reqwest::Client::new()
        .patch(format!("http://{addr}/resource/42"))
        .json(&json!({"role": "invalid_role"}))
        .send()
        .await
        .expect("request failed");
    assert_eq!(resp.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
}

#[tokio::test]
async fn patch_resource_unknown_id_returns_404() {
    let addr = spawn().await;
    let resp = reqwest::Client::new()
        .patch(format!("http://{addr}/resource/999"))
        .json(&json!({"role": "invalid_role"}))
        .send()
        .await
        .expect("request failed");
    assert_eq!(resp.status(), reqwest::StatusCode::NOT_FOUND);
}

// --- /creating/{id} ---

#[tokio::test]
async fn patch_creating_known_id_returns_422() {
    let addr = spawn().await;
    let resp = reqwest::Client::new()
        .patch(format!("http://{addr}/creating/42"))
        .json(&json!({"role": "invalid_role"}))
        .send()
        .await
        .expect("request failed");
    assert_eq!(resp.status(), reqwest::StatusCode::UNPROCESSABLE_ENTITY);
}

#[tokio::test]
async fn patch_creating_unknown_id_returns_201() {
    let addr = spawn().await;
    let resp = reqwest::Client::new()
        .patch(format!("http://{addr}/creating/999"))
        .json(&json!({"role": "invalid_role"}))
        .send()
        .await
        .expect("request failed");
    assert_eq!(resp.status(), reqwest::StatusCode::CREATED);
}

// --- /normalized/{id} (negative case — always 404) ---

#[tokio::test]
async fn patch_normalized_returns_404() {
    let addr = spawn().await;
    let resp = reqwest::Client::new()
        .patch(format!("http://{addr}/normalized/42"))
        .json(&json!({"role": "invalid_role"}))
        .send()
        .await
        .expect("request failed");
    assert_eq!(resp.status(), reqwest::StatusCode::NOT_FOUND);
}