systemd-resolved-rs 0.1.1

A compatibility-oriented reimplementation of systemd-resolved
#[cfg(test)]
mod test_10_proxy_mode_synthesis {
    use super::*;
    use std::net::UdpSocket;
    use std::thread;

    fn upstream_response(response: impl FnOnce(&[u8]) -> Vec<u8> + Send + 'static) -> SocketAddr {
        let socket = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).expect("bind DNS server");
        let address = socket.local_addr().expect("DNS server address");
        thread::spawn(move || {
            let mut packet = [0; 512];
            let (length, peer) = socket.recv_from(&mut packet).expect("receive query");
            let reply = response(&packet[..length]);
            socket.send_to(&reply, peer).expect("send response");
        });
        address
    }

    #[test]
    fn proxy_mode_synthesizes_localhost_without_servers() {
        let mut config = Config::default();
        config.upstreams.clear();
        config.fallback_upstreams.clear();
        let resolver = Resolver::new(config);
        let query = make_query("localhost", TYPE_A, 55).expect("query");
        let response = resolver
            .query(&query, QueryMode::Proxy)
            .expect("synthetic response");
        assert_eq!(
            wire::extract_addresses(&response, Some(2)).expect("address"),
            vec![IpAddr::V4(Ipv4Addr::LOCALHOST)]
        );
    }

    #[test]
    fn proxy_mode_synthesizes_localhost_after_nxdomain() {
        let server = upstream_response(|query| wire::nxdomain_for(query).expect("NXDOMAIN"));
        let resolver = Resolver::new(Config {
            upstreams: vec![server],
            fallback_upstreams: Vec::new(),
            ..Config::default()
        });
        let query = make_query("localhost", TYPE_A, 56).expect("query");
        let response = resolver
            .query(&query, QueryMode::Proxy)
            .expect("synthetic response");
        assert_eq!(Header::parse(&response).expect("header").response_code(), 0);
        assert_eq!(
            wire::extract_addresses(&response, Some(2)).expect("address"),
            vec![IpAddr::V4(Ipv4Addr::LOCALHOST)]
        );
    }

    #[test]
    fn proxy_mode_preserves_successful_network_answer() {
        let server = upstream_response(|query| {
            local_response(
                query,
                &[crate::wire::LocalRecord::A(Ipv4Addr::new(192, 0, 2, 1))],
                30,
            )
            .expect("answer")
        });
        let resolver = Resolver::new(Config {
            upstreams: vec![server],
            fallback_upstreams: Vec::new(),
            ..Config::default()
        });
        let query = make_query("localhost", TYPE_A, 57).expect("query");
        let response = resolver
            .query(&query, QueryMode::Proxy)
            .expect("network response");
        assert_eq!(
            wire::extract_addresses(&response, Some(2)).expect("address"),
            vec![IpAddr::V4(Ipv4Addr::new(192, 0, 2, 1))]
        );
    }
}