waddling-errors-macros 0.7.3

Procedural macros for structured error codes with compile-time validation and taxonomy enforcement
Documentation
//! Debug test to understand the three different hash computations
//!
//! We have three different hash values:
//! 1. Macro-generated: Ram7k
//! 2. Library compute_hash(): YxQs2
//! 3. Manual computation: ETtpS (or others)
//!
//! This test will trace through each step to find where they diverge.

#![allow(non_upper_case_globals)] // Intentional: testing various naming patterns
#![allow(clippy::print_literal)] // Intentional: alignment formatting in debug output

use waddling_errors_macros::{diag, setup};
use xxhash_rust::xxh3::xxh3_64;

// Define test components
pub mod components {
    use waddling_errors_macros::component;

    component! {
        pub enum Component {
            Auth {
                docs: "Authentication",
                tags: [],
            },
        }
    }
}

pub mod primaries {
    use waddling_errors_macros::primary;

    primary! {
        Token {
            docs: "Token operations",
        },
    }
}

pub mod sequences {
    use waddling_errors_macros::sequence;

    sequence! {
        DEBUGTEST(1) {
            description: "Debug test sequence",
            typical_severity: "Error",
        },
    }
}

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

// Define a diagnostic
diag! {
    E.AUTH.TOKEN.DEBUGTEST: {
        message: "Test error for debugging",
        fields: [],
        'R role: "Public",
    },
}

/// Test 1: Check what the macro generated
#[test]
fn test_1_macro_output() {
    println!("\n╔════════════════════════════════════════╗");
    println!("║   TEST 1: MACRO-GENERATED HASH         ║");
    println!("╚════════════════════════════════════════╝\n");

    let macro_hash = E_AUTH_TOKEN_DEBUGTEST_HASH;
    println!("Macro-generated hash: {}", macro_hash);
    println!("Length: {} characters", macro_hash.len());

    // Check if it's valid base62
    let all_base62 = macro_hash
        .chars()
        .all(|c| c.is_ascii_digit() || c.is_ascii_alphabetic());
    println!("Valid base62: {}", all_base62);

    println!("\n");
}

/// Test 2: Check library compute_hash()
#[test]
fn test_2_library_computation() {
    use waddling_errors_hash::{WDP_SEED, compute_hash};

    println!("\n╔════════════════════════════════════════╗");
    println!("║   TEST 2: LIBRARY compute_hash()      ║");
    println!("╚════════════════════════════════════════╝\n");

    // Test various input formats
    let test_inputs = vec![
        "E.AUTH.TOKEN.1",
        "E.AUTH.TOKEN.001",
        "E.AUTH.TOKEN.DEBUGTEST",
        "E.Auth.Token.1",
        "e.auth.token.1",
    ];

    println!("Testing library compute_hash() with different inputs:\n");
    println!("{:<30} {}", "Input", "Hash");
    println!("{}", "-".repeat(40));

    for input in test_inputs {
        let hash = compute_hash(input);
        println!("{:<30} {}", input, hash);
    }

    // Display WDP seed
    println!("\nWDP_SEED = {}", WDP_SEED);
    println!("WDP_SEED = 0x{:x}\n", WDP_SEED);
}

/// Test 3: Manual computation with correct seed conversion
#[test]
fn test_3_manual_with_correct_seed() {
    use waddling_errors_hash::WDP_SEED;

    println!("\n╔════════════════════════════════════════╗");
    println!("║   TEST 3: MANUAL (CORRECT SEED)        ║");
    println!("╚════════════════════════════════════════╝\n");

    // Use the WDP seed constant
    println!("Using WDP_SEED: {}", WDP_SEED);

    let test_inputs = vec![
        "E.AUTH.TOKEN.1",
        "E.AUTH.TOKEN.001",
        "E.AUTH.TOKEN.DEBUGTEST",
    ];

    println!("\nManual xxHash3 computation:\n");
    println!("{:<30} {:<20} {}", "Input", "Raw Hash (u64)", "Base62");
    println!("{}", "-".repeat(70));

    for input in test_inputs {
        let raw_hash = xxh3_64(input.as_bytes());
        let base62 = manual_base62(raw_hash);
        println!("{:<30} {:<20} {}", input, raw_hash, base62);
    }

    println!("\n");
}

/// Test 4: Check library's base62 encoding
#[test]
fn test_4_base62_encoding_comparison() {
    use waddling_errors_hash::u64_to_base62;

    println!("\n╔════════════════════════════════════════╗");
    println!("║   TEST 4: BASE62 ENCODING              ║");
    println!("╚════════════════════════════════════════╝\n");

    let input = "E.AUTH.TOKEN.1";
    let raw_hash = xxh3_64(input.as_bytes());

    println!("Input: {}", input);
    println!("Raw hash (u64): {}", raw_hash);
    println!("Raw hash (hex): 0x{:016x}", raw_hash);
    println!();

    // Compare base62 encodings
    let library_base62 = u64_to_base62(raw_hash);
    let manual_base62 = manual_base62(raw_hash);

    println!("Library u64_to_base62(): {}", library_base62);
    println!("Manual base62:           {}", manual_base62);
    println!("Match: {}", library_base62 == manual_base62);

    // Show byte breakdown
    println!("\nByte breakdown of u64:");
    for i in (0..8).rev() {
        let byte = (raw_hash >> (i * 8)) as u8;
        println!("  Byte {}: 0x{:02x} ({})", 7 - i, byte, byte);
    }

    println!("\n");
}

/// Test 5: Trace through library compute_hash step by step
#[test]
fn test_5_trace_library_steps() {
    use waddling_errors_hash::{WDP_SEED, u64_to_base62};

    println!("\n╔════════════════════════════════════════╗");
    println!("║   TEST 5: TRACE LIBRARY STEPS          ║");
    println!("╚════════════════════════════════════════╝\n");

    let input = "E.AUTH.TOKEN.1";

    println!("Step 1: Input string");
    println!("  Input: '{}'", input);
    println!("  Bytes: {:?}", input.as_bytes());
    println!();

    println!("Step 2: WDP Seed");
    println!("  WDP_SEED = {}", WDP_SEED);
    println!("  Hex: 0x{:016x}", WDP_SEED);
    println!();

    println!("Step 3: xxHash3 computation");
    let hash = xxh3_64(input.as_bytes());
    println!("  xxh3_64(input) = {}", hash);
    println!("  Hex: 0x{:016x}", hash);
    println!();

    println!("Step 4: Base62 encoding");
    let base62 = u64_to_base62(hash);
    println!("  u64_to_base62(hash) = '{}'", base62);
    println!();

    // Compare with library compute_hash
    use waddling_errors_hash::compute_hash;
    let library_result = compute_hash(input);
    println!("Library compute_hash('{}') = '{}'", input, library_result);
    println!("Our traced result = '{}'", base62);
    println!("Match: {}", library_result == base62);

    println!("\n");
}

/// Test 6: Find what format matches the macro
#[test]
fn test_6_find_macro_format() {
    use waddling_errors_hash::compute_hash;

    println!("\n╔════════════════════════════════════════╗");
    println!("║   TEST 6: FIND MACRO FORMAT            ║");
    println!("╚════════════════════════════════════════╝\n");

    let macro_hash = E_AUTH_TOKEN_DEBUGTEST_HASH;
    println!("Target (macro hash): {}\n", macro_hash);

    // Comprehensive list of possibilities
    let candidates = vec![
        // Integer formats
        ("E.AUTH.TOKEN.1", "Simple integer"),
        ("E.AUTH.TOKEN.01", "2-digit padding"),
        ("E.AUTH.TOKEN.001", "3-digit padding"),
        ("E.AUTH.TOKEN.0001", "4-digit padding"),
        // Sequence name
        ("E.AUTH.TOKEN.DEBUGTEST", "Sequence name (uppercase)"),
        ("E.AUTH.TOKEN.debugtest", "Sequence name (lowercase)"),
        ("E.AUTH.TOKEN.DebugTest", "Sequence name (PascalCase)"),
        // Component/Primary variations
        ("E.Auth.Token.1", "PascalCase components"),
        ("E.auth.token.1", "Lowercase components"),
        // Without dots
        ("EAUTHTOKEN1", "No separators"),
        ("E_AUTH_TOKEN_1", "Underscore separators"),
        // With component names vs values
        ("E.Auth.Token.DEBUGTEST", "Names (not values)"),
    ];

    println!("{:<35} {:<30} {}", "Input Format", "Description", "Hash");
    println!("{}", "-".repeat(75));

    let mut found = false;
    for (input, description) in candidates {
        let hash = compute_hash(input);
        let match_marker = if hash == macro_hash {
            found = true;
            " ← ✓ MATCH!"
        } else {
            ""
        };
        println!("{:<35} {:<30} {}{}", input, description, hash, match_marker);
    }

    if !found {
        println!("\n❌ No exact match found!");
        println!("The macro may be using a format not tested above.");
    } else {
        println!("\n✓ Found matching format!");
    }

    println!("\n");
}

/// Test 7: Compare all three directly
#[test]
fn test_7_three_way_comparison() {
    use waddling_errors_hash::compute_hash;

    println!("\n╔════════════════════════════════════════╗");
    println!("║   TEST 7: THREE-WAY COMPARISON         ║");
    println!("╚════════════════════════════════════════╝\n");

    let macro_hash = E_AUTH_TOKEN_DEBUGTEST_HASH;

    // Test all reasonable formats
    let formats = vec![
        "E.AUTH.TOKEN.1",
        "E.AUTH.TOKEN.001",
        "E.AUTH.TOKEN.DEBUGTEST",
    ];

    println!("Macro hash: {}\n", macro_hash);
    println!(
        "{:<30} {:<10} {:<15}",
        "Format", "Lib Hash", "Matches Macro?"
    );
    println!("{}", "-".repeat(60));

    for format in formats {
        let lib_hash = compute_hash(format);
        let matches = if lib_hash == macro_hash {
            "✓ YES"
        } else {
            "✗ No"
        };
        println!("{:<30} {:<10} {:<15}", format, lib_hash, matches);
    }

    println!("\n📊 Summary:");
    println!("   Macro:   {}", macro_hash);
    println!("   Library: (varies by input)");
    println!("\nConclusion: Need to identify which input format the macro uses.");

    println!("\n");
}

// Helper function: Manual base62 encoding
// This logic mirrors the library's u64_to_base62 and to_base62 functions.
fn manual_base62(num: u64) -> String {
    const BASE62_CHARS: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    const BASE: u64 = 62;

    let mut result_chars = [0u8; 5];
    let mut n = num;

    for i in (0..5).rev() {
        result_chars[i] = BASE62_CHARS[(n % BASE) as usize];
        n /= BASE;
    }

    String::from_utf8(result_chars.to_vec()).unwrap()
}

/// Run all tests in sequence
#[test]
fn run_all_debug_tests() {
    test_1_macro_output();
    test_2_library_computation();
    test_3_manual_with_correct_seed();
    test_4_base62_encoding_comparison();
    test_5_trace_library_steps();
    test_6_find_macro_format();
    test_7_three_way_comparison();

    println!("\n╔════════════════════════════════════════╗");
    println!("║   ALL DEBUG TESTS COMPLETED            ║");
    println!("╚════════════════════════════════════════╝\n");
}