1use std::fmt;
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
3use std::sync::{Arc, Mutex};
4
5use crate::error::Error;
6use crate::eventloop::{EventLoop, EventLoopStopper};
7
8#[cfg(cares1_29)]
9use c_ares::{ServerFailoverOptions, ServerStateFlags};
10
11#[derive(Default)]
13pub struct Options {
14 inner: c_ares::Options,
15}
16
17impl fmt::Debug for Options {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 f.debug_struct("Options").finish_non_exhaustive()
20 }
21}
22
23impl Options {
24 pub fn new() -> Self {
38 Self::default()
39 }
40
41 pub fn set_flags(&mut self, flags: c_ares::Flags) -> &mut Self {
43 self.inner.set_flags(flags);
44 self
45 }
46
47 pub fn set_timeout(&mut self, timeout: std::time::Duration) -> &mut Self {
51 self.inner.set_timeout(timeout);
52 self
53 }
54
55 pub fn set_tries(&mut self, tries: u32) -> &mut Self {
58 self.inner.set_tries(tries);
59 self
60 }
61
62 pub fn set_ndots(&mut self, ndots: u32) -> &mut Self {
66 self.inner.set_ndots(ndots);
67 self
68 }
69
70 pub fn set_udp_port(&mut self, udp_port: u16) -> &mut Self {
73 self.inner.set_udp_port(udp_port);
74 self
75 }
76
77 pub fn set_tcp_port(&mut self, tcp_port: u16) -> &mut Self {
80 self.inner.set_tcp_port(tcp_port);
81 self
82 }
83
84 pub fn set_domains<I, S>(&mut self, domains: I) -> c_ares::Result<&mut Self>
87 where
88 I: IntoIterator<Item = S>,
89 S: AsRef<str>,
90 {
91 self.inner.set_domains(domains)?;
92 Ok(self)
93 }
94
95 pub fn set_lookups(&mut self, lookups: &str) -> c_ares::Result<&mut Self> {
99 self.inner.set_lookups(lookups)?;
100 Ok(self)
101 }
102
103 pub fn set_sock_send_buffer_size(&mut self, size: u32) -> &mut Self {
105 self.inner.set_sock_send_buffer_size(size);
106 self
107 }
108
109 pub fn set_sock_receive_buffer_size(&mut self, size: u32) -> &mut Self {
111 self.inner.set_sock_receive_buffer_size(size);
112 self
113 }
114
115 pub fn set_rotate(&mut self) -> &mut Self {
117 self.inner.set_rotate();
118 self
119 }
120
121 pub fn set_no_rotate(&mut self) -> &mut Self {
123 self.inner.set_no_rotate();
124 self
125 }
126
127 pub fn set_ednspsz(&mut self, size: u32) -> &mut Self {
129 self.inner.set_ednspsz(size);
130 self
131 }
132
133 pub fn set_resolvconf_path(&mut self, resolvconf_path: &str) -> c_ares::Result<&mut Self> {
137 self.inner.set_resolvconf_path(resolvconf_path)?;
138 Ok(self)
139 }
140
141 #[cfg(cares1_19)]
144 pub fn set_hosts_path(&mut self, hosts_path: &str) -> c_ares::Result<&mut Self> {
145 self.inner.set_hosts_path(hosts_path)?;
146 Ok(self)
147 }
148
149 #[cfg(cares1_20)]
154 pub fn set_udp_max_queries(&mut self, udp_max_queries: Option<u32>) -> &mut Self {
155 self.inner.set_udp_max_queries(udp_max_queries);
156 self
157 }
158
159 #[cfg(cares1_22)]
162 pub fn set_max_timeout(&mut self, max_timeout: std::time::Duration) -> &mut Self {
163 self.inner.set_max_timeout(max_timeout);
164 self
165 }
166
167 #[cfg(cares1_23)]
174 pub fn set_query_cache_max_ttl(&mut self, qcache_max_ttl: u32) -> &mut Self {
175 self.inner.set_query_cache_max_ttl(qcache_max_ttl);
176 self
177 }
178
179 #[cfg(cares1_29)]
190 pub fn set_server_failover_options(
191 &mut self,
192 server_failover_options: &ServerFailoverOptions,
193 ) -> &mut Self {
194 self.inner
195 .set_server_failover_options(server_failover_options);
196 self
197 }
198}
199
200pub struct Resolver {
205 ares_channel: Arc<Mutex<c_ares::Channel>>,
206
207 _event_loop_stopper: Option<EventLoopStopper>,
210}
211
212impl fmt::Debug for Resolver {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 f.debug_struct("Resolver").finish_non_exhaustive()
215 }
216}
217
218impl Resolver {
219 pub fn new() -> Result<Self, Error> {
221 let options = Options::default();
222 Self::with_options(options)
223 }
224
225 pub fn with_options(options: Options) -> Result<Self, Error> {
227 let mut inner = options.inner;
228
229 #[cfg(cares1_26)]
231 let event_loop = if c_ares::thread_safety() {
232 inner.set_event_thread(c_ares::EventSys::Default);
233 None
234 } else {
235 Some(EventLoop::new(&mut inner)?)
236 };
237 #[cfg(not(cares1_26))]
238 let event_loop = Some(EventLoop::new(&mut inner)?);
239
240 let ares_channel = Arc::new(Mutex::new(c_ares::Channel::with_options(inner)?));
242
243 let stopper = event_loop.map(|el| el.run(Arc::clone(&ares_channel)));
245
246 Ok(Self {
247 ares_channel,
248 _event_loop_stopper: stopper,
249 })
250 }
251
252 #[cfg(cares1_22)]
254 pub fn reinit(&self) -> c_ares::Result<&Self> {
255 self.ares_channel.lock().unwrap().reinit()?;
256 Ok(self)
257 }
258
259 pub fn set_servers<I, S>(&self, servers: I) -> c_ares::Result<&Self>
265 where
266 I: IntoIterator<Item = S>,
267 S: AsRef<str>,
268 {
269 self.ares_channel.lock().unwrap().set_servers(servers)?;
270 Ok(self)
271 }
272
273 #[cfg(cares1_24)]
278 pub fn servers(&self) -> Vec<String> {
279 self.ares_channel.lock().unwrap().servers()
280 }
281
282 pub fn set_local_ipv4(&self, ipv4: Ipv4Addr) -> &Self {
284 self.ares_channel.lock().unwrap().set_local_ipv4(ipv4);
285 self
286 }
287
288 pub fn set_local_ipv6(&self, ipv6: Ipv6Addr) -> &Self {
290 self.ares_channel.lock().unwrap().set_local_ipv6(ipv6);
291 self
292 }
293
294 pub fn set_local_device(&self, device: &str) -> c_ares::Result<&Self> {
296 self.ares_channel.lock().unwrap().set_local_device(device)?;
297 Ok(self)
298 }
299
300 pub fn set_sortlist<I, S>(&self, sortlist: I) -> c_ares::Result<&Self>
307 where
308 I: IntoIterator<Item = S>,
309 S: AsRef<str>,
310 {
311 self.ares_channel.lock().unwrap().set_sortlist(sortlist)?;
312 Ok(self)
313 }
314
315 #[cfg(cares1_29)]
323 pub fn set_server_state_callback<F>(&self, callback: F) -> &Self
324 where
325 F: Fn(&str, bool, ServerStateFlags) + Send + Sync + 'static,
326 {
327 self.ares_channel
328 .lock()
329 .unwrap()
330 .set_server_state_callback(callback);
331 self
332 }
333
334 pub fn query_a<F>(&self, name: &str, handler: F)
338 where
339 F: FnOnce(c_ares::Result<c_ares::AResults>) + Send + 'static,
340 {
341 self.ares_channel.lock().unwrap().query_a(name, handler);
342 }
343
344 pub fn search_a<F>(&self, name: &str, handler: F)
348 where
349 F: FnOnce(c_ares::Result<c_ares::AResults>) + Send + 'static,
350 {
351 self.ares_channel.lock().unwrap().search_a(name, handler);
352 }
353
354 pub fn query_aaaa<F>(&self, name: &str, handler: F)
358 where
359 F: FnOnce(c_ares::Result<c_ares::AAAAResults>) + Send + 'static,
360 {
361 self.ares_channel.lock().unwrap().query_aaaa(name, handler);
362 }
363
364 pub fn search_aaaa<F>(&self, name: &str, handler: F)
368 where
369 F: FnOnce(c_ares::Result<c_ares::AAAAResults>) + Send + 'static,
370 {
371 self.ares_channel.lock().unwrap().search_aaaa(name, handler);
372 }
373
374 pub fn query_caa<F>(&self, name: &str, handler: F)
378 where
379 F: FnOnce(c_ares::Result<c_ares::CAAResults>) + Send + 'static,
380 {
381 self.ares_channel.lock().unwrap().query_caa(name, handler);
382 }
383
384 pub fn search_caa<F>(&self, name: &str, handler: F)
388 where
389 F: FnOnce(c_ares::Result<c_ares::CAAResults>) + Send + 'static,
390 {
391 self.ares_channel.lock().unwrap().search_caa(name, handler);
392 }
393
394 pub fn query_cname<F>(&self, name: &str, handler: F)
398 where
399 F: FnOnce(c_ares::Result<c_ares::CNameResults>) + Send + 'static,
400 {
401 self.ares_channel.lock().unwrap().query_cname(name, handler);
402 }
403
404 pub fn search_cname<F>(&self, name: &str, handler: F)
408 where
409 F: FnOnce(c_ares::Result<c_ares::CNameResults>) + Send + 'static,
410 {
411 self.ares_channel
412 .lock()
413 .unwrap()
414 .search_cname(name, handler);
415 }
416
417 pub fn query_mx<F>(&self, name: &str, handler: F)
421 where
422 F: FnOnce(c_ares::Result<c_ares::MXResults>) + Send + 'static,
423 {
424 self.ares_channel.lock().unwrap().query_mx(name, handler);
425 }
426
427 pub fn search_mx<F>(&self, name: &str, handler: F)
431 where
432 F: FnOnce(c_ares::Result<c_ares::MXResults>) + Send + 'static,
433 {
434 self.ares_channel.lock().unwrap().search_mx(name, handler);
435 }
436
437 pub fn query_naptr<F>(&self, name: &str, handler: F)
441 where
442 F: FnOnce(c_ares::Result<c_ares::NAPTRResults>) + Send + 'static,
443 {
444 self.ares_channel.lock().unwrap().query_naptr(name, handler);
445 }
446
447 pub fn search_naptr<F>(&self, name: &str, handler: F)
451 where
452 F: FnOnce(c_ares::Result<c_ares::NAPTRResults>) + Send + 'static,
453 {
454 self.ares_channel
455 .lock()
456 .unwrap()
457 .search_naptr(name, handler);
458 }
459
460 pub fn query_ns<F>(&self, name: &str, handler: F)
464 where
465 F: FnOnce(c_ares::Result<c_ares::NSResults>) + Send + 'static,
466 {
467 self.ares_channel.lock().unwrap().query_ns(name, handler);
468 }
469
470 pub fn search_ns<F>(&self, name: &str, handler: F)
474 where
475 F: FnOnce(c_ares::Result<c_ares::NSResults>) + Send + 'static,
476 {
477 self.ares_channel.lock().unwrap().search_ns(name, handler);
478 }
479
480 pub fn query_ptr<F>(&self, name: &str, handler: F)
484 where
485 F: FnOnce(c_ares::Result<c_ares::PTRResults>) + Send + 'static,
486 {
487 self.ares_channel.lock().unwrap().query_ptr(name, handler);
488 }
489
490 pub fn search_ptr<F>(&self, name: &str, handler: F)
494 where
495 F: FnOnce(c_ares::Result<c_ares::PTRResults>) + Send + 'static,
496 {
497 self.ares_channel.lock().unwrap().search_ptr(name, handler);
498 }
499
500 pub fn query_soa<F>(&self, name: &str, handler: F)
504 where
505 F: FnOnce(c_ares::Result<c_ares::SOAResult>) + Send + 'static,
506 {
507 self.ares_channel.lock().unwrap().query_soa(name, handler);
508 }
509
510 pub fn search_soa<F>(&self, name: &str, handler: F)
514 where
515 F: FnOnce(c_ares::Result<c_ares::SOAResult>) + Send + 'static,
516 {
517 self.ares_channel.lock().unwrap().search_soa(name, handler);
518 }
519
520 pub fn query_srv<F>(&self, name: &str, handler: F)
524 where
525 F: FnOnce(c_ares::Result<c_ares::SRVResults>) + Send + 'static,
526 {
527 self.ares_channel.lock().unwrap().query_srv(name, handler);
528 }
529
530 pub fn search_srv<F>(&self, name: &str, handler: F)
534 where
535 F: FnOnce(c_ares::Result<c_ares::SRVResults>) + Send + 'static,
536 {
537 self.ares_channel.lock().unwrap().search_srv(name, handler);
538 }
539
540 pub fn query_txt<F>(&self, name: &str, handler: F)
544 where
545 F: FnOnce(c_ares::Result<c_ares::TXTResults>) + Send + 'static,
546 {
547 self.ares_channel.lock().unwrap().query_txt(name, handler);
548 }
549
550 pub fn search_txt<F>(&self, name: &str, handler: F)
554 where
555 F: FnOnce(c_ares::Result<c_ares::TXTResults>) + Send + 'static,
556 {
557 self.ares_channel.lock().unwrap().search_txt(name, handler);
558 }
559
560 pub fn query_uri<F>(&self, name: &str, handler: F)
564 where
565 F: FnOnce(c_ares::Result<c_ares::URIResults>) + Send + 'static,
566 {
567 self.ares_channel.lock().unwrap().query_uri(name, handler);
568 }
569
570 pub fn search_uri<F>(&self, name: &str, handler: F)
574 where
575 F: FnOnce(c_ares::Result<c_ares::URIResults>) + Send + 'static,
576 {
577 self.ares_channel.lock().unwrap().search_uri(name, handler);
578 }
579
580 pub fn get_host_by_address<F>(&self, address: &IpAddr, handler: F)
584 where
585 F: FnOnce(c_ares::Result<&c_ares::HostResults>) + Send + 'static,
586 {
587 self.ares_channel
588 .lock()
589 .unwrap()
590 .get_host_by_address(address, handler);
591 }
592
593 pub fn get_host_by_name<F>(&self, name: &str, family: c_ares::AddressFamily, handler: F)
597 where
598 F: FnOnce(c_ares::Result<&c_ares::HostResults>) + Send + 'static,
599 {
600 self.ares_channel
601 .lock()
602 .unwrap()
603 .get_host_by_name(name, family, handler);
604 }
605
606 pub fn get_name_info<F>(&self, address: &SocketAddr, flags: c_ares::NIFlags, handler: F)
610 where
611 F: FnOnce(c_ares::Result<c_ares::NameInfoResult>) + Send + 'static,
612 {
613 self.ares_channel
614 .lock()
615 .unwrap()
616 .get_name_info(address, flags, handler);
617 }
618
619 pub fn get_addrinfo<F>(
623 &self,
624 name: &str,
625 service: Option<&str>,
626 hints: &c_ares::AddrInfoHints,
627 handler: F,
628 ) where
629 F: FnOnce(c_ares::Result<c_ares::AddrInfoResults>) + Send + 'static,
630 {
631 self.ares_channel
632 .lock()
633 .unwrap()
634 .get_addrinfo(name, service, hints, handler);
635 }
636
637 pub fn query<F>(&self, name: &str, dns_class: u16, query_type: u16, handler: F)
646 where
647 F: FnOnce(c_ares::Result<&[u8]>) + Send + 'static,
648 {
649 self.ares_channel
650 .lock()
651 .unwrap()
652 .query(name, dns_class, query_type, handler);
653 }
654
655 pub fn search<F>(&self, name: &str, dns_class: u16, query_type: u16, handler: F)
664 where
665 F: FnOnce(c_ares::Result<&[u8]>) + Send + 'static,
666 {
667 self.ares_channel
668 .lock()
669 .unwrap()
670 .search(name, dns_class, query_type, handler);
671 }
672
673 #[cfg(cares1_28)]
677 pub fn send_dnsrec<F>(&self, dnsrec: &c_ares::DnsRecord, handler: F) -> c_ares::Result<u16>
678 where
679 F: FnOnce(c_ares::Result<&c_ares::DnsRecord>) + Send + 'static,
680 {
681 self.ares_channel
682 .lock()
683 .unwrap()
684 .send_dnsrec(dnsrec, handler)
685 }
686
687 #[cfg(cares1_28)]
690 pub fn query_dnsrec<F>(
691 &self,
692 name: &str,
693 dns_class: c_ares::DnsCls,
694 query_type: c_ares::DnsRecordType,
695 handler: F,
696 ) -> c_ares::Result<u16>
697 where
698 F: FnOnce(c_ares::Result<&c_ares::DnsRecord>) + Send + 'static,
699 {
700 self.ares_channel
701 .lock()
702 .unwrap()
703 .query_dnsrec(name, dns_class, query_type, handler)
704 }
705
706 #[cfg(cares1_28)]
709 pub fn search_dnsrec<F>(&self, dnsrec: &c_ares::DnsRecord, handler: F) -> c_ares::Result<()>
710 where
711 F: FnOnce(c_ares::Result<&c_ares::DnsRecord>) + Send + 'static,
712 {
713 self.ares_channel
714 .lock()
715 .unwrap()
716 .search_dnsrec(dnsrec, handler)
717 }
718
719 #[cfg(cares1_27)]
724 pub fn queue_wait_empty(&self, timeout: Option<std::time::Duration>) -> c_ares::Result<()> {
725 let raw = self.ares_channel.lock().unwrap().as_raw();
733 let timeout_ms: core::ffi::c_int = match timeout {
734 None => -1,
735 Some(d) => d.as_millis().try_into().unwrap_or(core::ffi::c_int::MAX),
736 };
737 let rc = unsafe { c_ares_sys::ares_queue_wait_empty(raw, timeout_ms) };
738 c_ares::Error::try_from(rc).map_or(Ok(()), Err)
739 }
740
741 #[cfg(cares1_27)]
743 pub fn queue_active_queries(&self) -> usize {
744 self.ares_channel.lock().unwrap().queue_active_queries()
745 }
746
747 pub fn cancel(&self) {
749 self.ares_channel.lock().unwrap().cancel();
750 }
751}
752
753#[cfg(test)]
754mod tests {
755 use super::*;
756
757 fn assert_send<T: Send>() {}
758 fn assert_sync<T: Sync>() {}
759
760 #[test]
761 fn options_is_send() {
762 assert_send::<Options>();
763 }
764
765 #[test]
766 fn options_is_sync() {
767 assert_sync::<Options>();
768 }
769
770 #[test]
771 fn resolver_is_send() {
772 assert_send::<Resolver>();
773 }
774
775 #[test]
776 fn resolver_is_sync() {
777 assert_sync::<Resolver>();
778 }
779
780 #[test]
781 fn options_new() {
782 let options = Options::new();
783 assert!(std::mem::size_of_val(&options) > 0);
785 }
786
787 #[test]
788 fn options_default() {
789 let options = Options::default();
790 assert!(std::mem::size_of_val(&options) > 0);
791 }
792
793 #[test]
794 fn options_set_flags() {
795 let mut options = Options::new();
796 options.set_flags(c_ares::Flags::STAYOPEN);
797 }
799
800 #[test]
801 fn options_set_timeout() {
802 let mut options = Options::new();
803 let result = options.set_timeout(std::time::Duration::from_secs(1));
804 assert!(std::ptr::eq(result, &raw const options));
805 }
806
807 #[test]
808 fn options_set_tries() {
809 let mut options = Options::new();
810 let result = options.set_tries(3);
811 assert!(std::ptr::eq(result, &raw const options));
812 }
813
814 #[test]
815 fn options_set_ndots() {
816 let mut options = Options::new();
817 let result = options.set_ndots(2);
818 assert!(std::ptr::eq(result, &raw const options));
819 }
820
821 #[test]
822 fn options_set_udp_port() {
823 let mut options = Options::new();
824 let result = options.set_udp_port(5353);
825 assert!(std::ptr::eq(result, &raw const options));
826 }
827
828 #[test]
829 fn options_set_tcp_port() {
830 let mut options = Options::new();
831 let result = options.set_tcp_port(5353);
832 assert!(std::ptr::eq(result, &raw const options));
833 }
834
835 #[test]
836 fn options_set_domains() {
837 let mut options = Options::new();
838 let result = options.set_domains(["example.com", "test.com"]).unwrap();
839 assert!(std::ptr::eq(result, &raw const options));
840 }
841
842 #[test]
843 fn options_set_lookups() {
844 let mut options = Options::new();
845 let result = options.set_lookups("bf").unwrap();
846 assert!(std::ptr::eq(result, &raw const options));
847 }
848
849 #[test]
850 fn options_set_sock_send_buffer_size() {
851 let mut options = Options::new();
852 let result = options.set_sock_send_buffer_size(65536);
853 assert!(std::ptr::eq(result, &raw const options));
854 }
855
856 #[test]
857 fn options_set_sock_receive_buffer_size() {
858 let mut options = Options::new();
859 let result = options.set_sock_receive_buffer_size(65536);
860 assert!(std::ptr::eq(result, &raw const options));
861 }
862
863 #[test]
864 fn options_set_rotate() {
865 let mut options = Options::new();
866 let result = options.set_rotate();
867 assert!(std::ptr::eq(result, &raw const options));
868 }
869
870 #[test]
871 fn options_set_no_rotate() {
872 let mut options = Options::new();
873 let result = options.set_no_rotate();
874 assert!(std::ptr::eq(result, &raw const options));
875 }
876
877 #[test]
878 fn options_set_ednspsz() {
879 let mut options = Options::new();
880 let result = options.set_ednspsz(4096);
881 assert!(std::ptr::eq(result, &raw const options));
882 }
883
884 #[test]
885 fn options_set_resolvconf_path() {
886 let mut options = Options::new();
887 let result = options.set_resolvconf_path("/etc/resolv.conf").unwrap();
888 assert!(std::ptr::eq(result, &raw const options));
889 }
890
891 #[test]
892 #[cfg(cares1_19)]
893 fn options_set_hosts_path() {
894 let mut options = Options::new();
895 let result = options.set_hosts_path("/etc/hosts").unwrap();
896 assert!(std::ptr::eq(result, &raw const options));
897 }
898
899 #[test]
900 #[cfg(cares1_20)]
901 fn options_set_udp_max_queries() {
902 let mut options = Options::new();
903 let result = options.set_udp_max_queries(Some(100));
904 assert!(std::ptr::eq(result, &raw const options));
905 }
906
907 #[test]
908 #[cfg(cares1_22)]
909 fn options_set_max_timeout() {
910 let mut options = Options::new();
911 let result = options.set_max_timeout(std::time::Duration::from_secs(30));
912 assert!(std::ptr::eq(result, &raw const options));
913 }
914
915 #[test]
916 #[cfg(cares1_23)]
917 fn options_set_query_cache_max_ttl() {
918 let mut options = Options::new();
919 let result = options.set_query_cache_max_ttl(3600);
920 assert!(std::ptr::eq(result, &raw const options));
921 }
922
923 #[test]
924 fn resolver_new() {
925 let resolver = Resolver::new();
926 assert!(resolver.is_ok());
927 }
928
929 #[test]
930 fn resolver_with_options() {
931 let options = Options::new();
932 let resolver = Resolver::with_options(options);
933 assert!(resolver.is_ok());
934 }
935
936 #[test]
937 fn resolver_with_custom_options() {
938 let mut options = Options::new();
939 options
940 .set_timeout(std::time::Duration::from_secs(2))
941 .set_tries(2);
942 let resolver = Resolver::with_options(options);
943 assert!(resolver.is_ok());
944 }
945
946 #[test]
947 fn resolver_set_local_ipv4() {
948 let resolver = Resolver::new().unwrap();
949 let result = resolver.set_local_ipv4(Ipv4Addr::LOCALHOST);
950 assert!(std::ptr::eq(result, &raw const resolver));
951 }
952
953 #[test]
954 fn resolver_set_local_ipv6() {
955 let resolver = Resolver::new().unwrap();
956 let ipv6 = Ipv6Addr::LOCALHOST;
957 let result = resolver.set_local_ipv6(ipv6);
958 assert!(std::ptr::eq(result, &raw const resolver));
959 }
960
961 #[test]
962 fn resolver_set_local_device() {
963 let resolver = Resolver::new().unwrap();
964 let result = resolver.set_local_device("lo").unwrap();
965 assert!(std::ptr::eq(result, &raw const resolver));
966 }
967
968 #[test]
969 fn resolver_set_servers_valid() {
970 let resolver = Resolver::new().unwrap();
971 let result = resolver.set_servers(["8.8.8.8", "8.8.4.4"]);
972 assert!(result.is_ok());
973 }
974
975 #[test]
976 fn resolver_set_servers_with_port() {
977 let resolver = Resolver::new().unwrap();
978 let result = resolver.set_servers(["8.8.8.8:53"]);
979 assert!(result.is_ok());
980 }
981
982 #[test]
983 fn resolver_set_servers_ipv6() {
984 let resolver = Resolver::new().unwrap();
985 let result = resolver.set_servers(["[2001:4860:4860::8888]:53"]);
986 assert!(result.is_ok());
987 }
988
989 #[test]
990 fn resolver_set_sortlist_valid() {
991 let resolver = Resolver::new().unwrap();
992 let result = resolver.set_sortlist(["130.155.160.0/255.255.240.0"]);
993 assert!(result.is_ok());
994 }
995
996 #[test]
997 fn resolver_cancel() {
998 let resolver = Resolver::new().unwrap();
999 resolver.cancel(); }
1001
1002 #[test]
1003 #[cfg(cares1_22)]
1004 fn resolver_reinit() {
1005 let resolver = Resolver::new().unwrap();
1006 let result = resolver.reinit();
1007 assert!(result.is_ok());
1008 }
1009
1010 #[test]
1011 #[cfg(cares1_24)]
1012 fn resolver_servers() {
1013 let resolver = Resolver::new().unwrap();
1014 let _ = resolver.set_servers(["8.8.8.8"]);
1015 let servers = resolver.servers();
1016 assert!(!servers.is_empty());
1017 }
1018
1019 #[test]
1020 #[cfg(cares1_29)]
1021 fn resolver_set_server_state_callback() {
1022 let resolver = Resolver::new().unwrap();
1023 let result = resolver.set_server_state_callback(|_server, _success, _flags| {});
1024 assert!(std::ptr::eq(result, &raw const resolver));
1025 }
1026
1027 #[test]
1028 #[cfg(cares1_29)]
1029 fn options_set_server_failover_options() {
1030 let mut options = Options::new();
1031 let failover_opts = c_ares::ServerFailoverOptions::new();
1032 let result = options.set_server_failover_options(&failover_opts);
1033 assert!(std::ptr::eq(result, &raw const options));
1034 }
1035
1036 #[test]
1037 #[cfg(cares1_27)]
1038 fn resolver_queue_active_queries() {
1039 let resolver = Resolver::new().unwrap();
1040 assert_eq!(resolver.queue_active_queries(), 0);
1041 }
1042
1043 #[test]
1044 #[cfg(cares1_27)]
1045 fn resolver_queue_wait_empty() {
1046 let resolver = Resolver::new().unwrap();
1047 let result = resolver.queue_wait_empty(Some(std::time::Duration::ZERO));
1048 assert!(result.is_ok() || result == Err(c_ares::Error::ENOTIMP));
1049 }
1050
1051 #[test]
1052 #[cfg(cares1_27)]
1053 fn resolver_queue_wait_empty_none_timeout() {
1054 let resolver = Resolver::new().unwrap();
1055 let result = resolver.queue_wait_empty(None);
1057 assert!(result.is_ok() || result == Err(c_ares::Error::ENOTIMP));
1058 }
1059
1060 #[test]
1068 #[cfg(cares1_27)]
1069 fn resolver_queue_wait_empty_with_pending_query() {
1070 let mut options = Options::new();
1071 options
1072 .set_timeout(std::time::Duration::from_secs(1))
1073 .set_tries(1);
1074 let resolver = std::sync::Arc::new(Resolver::with_options(options).unwrap());
1075
1076 resolver.set_servers(["192.0.2.1"]).unwrap();
1078 resolver.query_a("example.com", |_| {});
1079
1080 let start = std::time::Instant::now();
1081 let _ = resolver.queue_wait_empty(Some(std::time::Duration::from_secs(5)));
1082 let elapsed = start.elapsed();
1083
1084 assert!(
1086 elapsed < std::time::Duration::from_secs(3),
1087 "queue_wait_empty took {elapsed:.2?}, expected ~1s: event loop likely deadlocked"
1088 );
1089 }
1090
1091 #[test]
1092 fn debug_resolver_options() {
1093 let options = Options::new();
1094 let debug = format!("{options:?}");
1095 assert!(debug.contains("Options"));
1096 }
1097
1098 #[test]
1099 fn debug_resolver() {
1100 let resolver = Resolver::new().unwrap();
1101 let debug = format!("{resolver:?}");
1102 assert!(debug.contains("Resolver"));
1103 }
1104}