waddling-errors-macros 0.7.3

Procedural macros for structured error codes with compile-time validation and taxonomy enforcement
Documentation
//! WDP Compact ID Test Vectors - Conformance Test
//!
//! This example validates that our compile-time hash implementation
//! matches the official WDP specification test vectors from:
//! wdp-specs/test-vectors/data/compact-ids.json
//!
//! ## Test Coverage
//!
//! Tests the following official test vectors:
//! - basic-001: E.AUTH.TOKEN.001 → V6a0B
//! - basic-002: W.DATABASE.CONNECTION.027 → KF52S
//! - basic-003: E.A.B.001 → l3i4I
//! - basic-005: I.HTTP.REQUEST.001 → iBrs6
//! - edge-001: E.AUTH.TOKEN.002 → 35Jkp
//!
//! ## Running
//!
//! ```bash
//! cargo run --example test_compile_time_hash --features metadata,hash
//! ```

#![allow(non_upper_case_globals)]

#[cfg(not(feature = "metadata"))]
compile_error!(
    "\n\n\
    ❌ This example requires the 'metadata' feature!\n\
    \n\
    Run with: cargo run --example test_compile_time_hash --features metadata,hash\n\
    "
);

use waddling_errors_macros::{diag, setup};

// Components from test vectors
pub mod components {
    use waddling_errors_macros::component;

    component! {
        pub enum Component {
            Auth { docs: "Authentication component" },
            Database { docs: "Database component" },
            A { docs: "Minimal component" },
            Http { docs: "HTTP component" },
        }
    }

    pub use Component::*;
}

// Primaries from test vectors
pub mod primaries {
    use waddling_errors_macros::primary;

    primary! {
        pub enum Primary {
            Token { description: "Token operations" },
            Connection { description: "Connection operations" },
            B { description: "Minimal primary" },
            Request { description: "Request operations" },
        }
    }

    pub use Primary::*;
}

// Sequences from test vectors
pub mod sequences {
    use waddling_errors_macros::sequence;

    sequence! {
        // For E.AUTH.TOKEN.001 and E.A.B.001 and I.HTTP.REQUEST.001
        SEQ001(1) {
            description: "Sequence 001",
            typical_severity: "Error",
            hints: ["Test sequence 001"],
        },
        // For E.AUTH.TOKEN.002
        SEQ002(2) {
            description: "Sequence 002",
            typical_severity: "Error",
            hints: ["Test sequence 002"],
        },
        // For W.DATABASE.CONNECTION.027
        SEQ027(27) {
            description: "Sequence 027",
            typical_severity: "Warning",
            hints: ["Test sequence 027"],
        },
    }
}

setup! {
    components = crate::components,
    primaries = crate::primaries,
    sequences = crate::sequences,
}

// Test vectors from wdp-specs/test-vectors/data/compact-ids.json

// basic-001: E.AUTH.TOKEN.001 → V6a0B
diag! {
    strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
    E.Auth.Token.SEQ001: {
        message: "Standard error code",
    }
}

// basic-002: W.DATABASE.CONNECTION.027 → KF52S
diag! {
    strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
    W.Database.Connection.SEQ027: {
        message: "Warning with extended components",
    }
}

// basic-003: E.A.B.001 → l3i4I
diag! {
    strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
    E.A.B.SEQ001: {
        message: "Minimal valid code",
    }
}

// basic-005: I.HTTP.REQUEST.001 → iBrs6
diag! {
    strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
    I.Http.Request.SEQ001: {
        message: "Info severity",
    }
}

// edge-001: E.AUTH.TOKEN.002 → 35Jkp
diag! {
    strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
    E.Auth.Token.SEQ002: {
        message: "Sequential codes produce different hashes",
    }
}

fn main() {
    println!("🦆 WDP Compact ID Test Vectors - Conformance Test");
    println!("====================================================\n");
    println!("Testing against official test vectors from:");
    println!("wdp-specs/test-vectors/data/compact-ids.json\n");

    let mut passed = 0;
    let mut failed = 0;

    // Test case structure: (code, hash_constant, expected, description)
    let test_cases = [
        (
            E_AUTH_TOKEN_SEQ001.code,
            E_AUTH_TOKEN_SEQ001_HASH,
            "V6a0B",
            "basic-001: E.AUTH.TOKEN.001",
        ),
        (
            W_DATABASE_CONNECTION_SEQ027.code,
            W_DATABASE_CONNECTION_SEQ027_HASH,
            "KF52S",
            "basic-002: W.DATABASE.CONNECTION.027",
        ),
        (
            E_A_B_SEQ001.code,
            E_A_B_SEQ001_HASH,
            "l3i4I",
            "basic-003: E.A.B.001",
        ),
        (
            I_HTTP_REQUEST_SEQ001.code,
            I_HTTP_REQUEST_SEQ001_HASH,
            "iBrs6",
            "basic-005: I.HTTP.REQUEST.001",
        ),
        (
            E_AUTH_TOKEN_SEQ002.code,
            E_AUTH_TOKEN_SEQ002_HASH,
            "35Jkp",
            "edge-001: E.AUTH.TOKEN.002",
        ),
    ];

    for (code, compile_time_hash, expected, description) in &test_cases {
        print!("  {} ", description);

        if compile_time_hash == expected {
            println!("✅ PASS");
            println!("    Code: {}", code);
            println!("    Hash: {} (matches expected)\n", compile_time_hash);
            passed += 1;
        } else {
            println!("❌ FAIL");
            println!("    Code: {}", code);
            println!("    Expected: {}", expected);
            println!("    Got:      {}\n", compile_time_hash);
            failed += 1;
        }
    }

    // Also verify runtime hash computation matches
    {
        println!("\n🔍 Verifying runtime hash computation matches compile-time:");
        use waddling_errors_hash::compute_hash;

        // Runtime test vectors with canonical uppercase forms
        let runtime_tests = [
            ("E.AUTH.TOKEN.001", "V6a0B", "basic-001"),
            ("W.DATABASE.CONNECTION.027", "KF52S", "basic-002"),
            ("E.A.B.001", "l3i4I", "basic-003"),
            ("I.HTTP.REQUEST.001", "iBrs6", "basic-005"),
            ("E.AUTH.TOKEN.002", "35Jkp", "edge-001"),
        ];

        for (canonical_code, expected_hash, description) in &runtime_tests {
            let runtime_hash = compute_hash(canonical_code);
            if &runtime_hash == expected_hash {
                println!("{} runtime matches", description);
            } else {
                println!("{} runtime mismatch!", description);
                println!("     Expected: {}", expected_hash);
                println!("     Got:      {}", runtime_hash);
                failed += 1;
            }
        }
    }

    println!("\n====================================================");
    println!("Results: {} passed, {} failed", passed, failed);

    if failed > 0 {
        println!("\n❌ Some tests failed! Hash implementation may not match WDP spec.");
        std::process::exit(1);
    } else {
        println!("\n✅ All test vectors passed! Implementation conforms to WDP spec.");
    }
}