85 lines
2.4 KiB
Rust
85 lines
2.4 KiB
Rust
use std::{
|
|
net::IpAddr,
|
|
sync::{
|
|
Arc,
|
|
atomic::{AtomicU8, Ordering},
|
|
},
|
|
thread::sleep,
|
|
time::Duration,
|
|
};
|
|
|
|
use futures_util::stream::{FuturesUnordered, StreamExt};
|
|
use test_support::{MockNetworkHandler, MockProvider, MockRecord, subscribe};
|
|
|
|
use hickory_net::xfer::{DnsHandle, FirstAnswer, Protocol};
|
|
use hickory_proto::{
|
|
ProtoError,
|
|
op::{DnsRequestOptions, Message, Query, ResponseCode},
|
|
rr::{Name, RecordType},
|
|
};
|
|
use hickory_resolver::{
|
|
NameServer, NameServerPool, PoolContext, TlsConfig,
|
|
config::{NameServerConfig, ResolverOpts},
|
|
};
|
|
|
|
#[tokio::test]
|
|
async fn test_shared_lookup() -> Result<(), ProtoError> {
|
|
subscribe();
|
|
|
|
let query_name = Name::from_ascii("host.hickory-dns.testing.")?;
|
|
let query_ip = IpAddr::from([10, 0, 0, 1]);
|
|
|
|
let responses = vec![MockRecord::a(query_ip, &query_name, query_ip)];
|
|
|
|
let counter = Arc::new(AtomicU8::new(0));
|
|
let counter_copy = counter.clone();
|
|
let mutator = Box::new(
|
|
move |_destination: IpAddr, _protocol: Protocol, _msg: &mut Message| {
|
|
counter_copy.fetch_add(1, Ordering::Relaxed);
|
|
// Ensure the first query is still active when the second is polled
|
|
sleep(Duration::from_millis(250));
|
|
},
|
|
);
|
|
|
|
let handler = MockNetworkHandler::new(responses).with_mutation(mutator);
|
|
|
|
let provider = MockProvider::new(handler);
|
|
let mut opts = ResolverOpts::default();
|
|
opts.case_randomization = true;
|
|
let name_server = Arc::new(NameServer::new(
|
|
[],
|
|
NameServerConfig::udp(query_ip),
|
|
&opts,
|
|
provider,
|
|
));
|
|
let pool = NameServerPool::from_nameservers(
|
|
vec![name_server],
|
|
Arc::new(PoolContext::new(opts, TlsConfig::new().unwrap())),
|
|
);
|
|
|
|
let mut futures = vec![
|
|
pool.lookup(
|
|
Query::query(query_name.clone(), RecordType::A),
|
|
DnsRequestOptions::default(),
|
|
)
|
|
.first_answer(),
|
|
pool.lookup(
|
|
Query::query(query_name.clone(), RecordType::A),
|
|
DnsRequestOptions::default(),
|
|
)
|
|
.first_answer(),
|
|
]
|
|
.into_iter()
|
|
.collect::<FuturesUnordered<_>>();
|
|
|
|
let mut ok_count = 0;
|
|
while let Some(Ok(response)) = futures.next().await {
|
|
assert_eq!(response.response_code, ResponseCode::NoError);
|
|
ok_count += 1;
|
|
}
|
|
|
|
assert_eq!(ok_count, 2);
|
|
assert_eq!(counter.load(Ordering::Relaxed), 1);
|
|
Ok(())
|
|
}
|