technitium 0.4.0

Typed async Rust client for the Technitium DNS Server API
Documentation
mod common;

use std::time::{Duration, Instant};

use technitium::Client;

#[tokio::test]
#[ignore = "requires running Technitium server"]
async fn rate_limiting_paces_requests() {
    let client = Client::builder()
        .base_url(common::server_url())
        .rate_limit(5.0) // 5 requests per second
        .build()
        .expect("build client");

    client
        .login(&common::admin_username(), &common::admin_password())
        .await
        .expect("login");

    let start = Instant::now();
    let mut successes = 0u32;

    for _ in 0..10 {
        let result = client.list_zones().await;
        assert!(
            result.is_ok(),
            "request should succeed (backpressure, not rejection)"
        );
        successes += 1;
    }

    let elapsed = start.elapsed();

    assert_eq!(successes, 10, "all 10 requests should succeed");
    assert!(
        elapsed >= Duration::from_millis(800),
        "10 requests at 5/sec should take ≥0.8s, took {elapsed:?}"
    );
}

#[tokio::test]
#[ignore = "requires running Technitium server"]
async fn no_rate_limit_is_fast() {
    let client = common::build_client();
    client
        .login(&common::admin_username(), &common::admin_password())
        .await
        .expect("login");

    let start = Instant::now();
    for _ in 0..5 {
        client.list_zones().await.expect("list_zones");
    }
    let elapsed = start.elapsed();

    assert!(
        elapsed < Duration::from_secs(3),
        "5 requests without rate limit should be fast, took {elapsed:?}"
    );
}