@@ -373,54 +373,19 @@ fn url_port(url: &Url) -> Option<u16> {
373373mod tests {
374374 use std:: net:: { Ipv4Addr , Ipv6Addr } ;
375375
376- use iroh_dns:: dns:: { BoxIter , DnsError , DnsResolver , Resolver , TxtRecordData } ;
377- use n0_future:: boxed:: BoxFuture ;
378376 use tokio:: net:: TcpListener ;
379377
380- use super :: * ;
381-
382- /// Resolver that hands out fixed IPv4 and IPv6 addresses for every host.
383- #[ derive( Debug , Clone ) ]
384- struct StaticResolver {
385- v4 : Vec < Ipv4Addr > ,
386- v6 : Vec < Ipv6Addr > ,
387- }
388-
389- impl Resolver for StaticResolver {
390- fn lookup_ipv4 ( & self , _host : String ) -> BoxFuture < Result < BoxIter < Ipv4Addr > , DnsError > > {
391- let addrs: BoxIter < _ > = Box :: new ( self . v4 . clone ( ) . into_iter ( ) ) ;
392- Box :: pin ( std:: future:: ready ( Ok ( addrs) ) )
393- }
394-
395- fn lookup_ipv6 ( & self , _host : String ) -> BoxFuture < Result < BoxIter < Ipv6Addr > , DnsError > > {
396- let addrs: BoxIter < _ > = Box :: new ( self . v6 . clone ( ) . into_iter ( ) ) ;
397- Box :: pin ( std:: future:: ready ( Ok ( addrs) ) )
398- }
378+ use crate :: test_utils:: StaticResolver ;
399379
400- fn lookup_txt ( & self , _host : String ) -> BoxFuture < Result < BoxIter < TxtRecordData > , DnsError > > {
401- let records: BoxIter < _ > = Box :: new ( std:: iter:: empty ( ) ) ;
402- Box :: pin ( std:: future:: ready ( Ok ( records) ) )
403- }
404-
405- fn clear_cache ( & self ) { }
406-
407- fn reset ( & self ) -> Box < dyn Resolver > {
408- Box :: new ( self . clone ( ) )
409- }
410- }
411-
412- fn resolver ( v4 : Vec < Ipv4Addr > , v6 : Vec < Ipv6Addr > ) -> DnsResolver {
413- DnsResolver :: custom ( StaticResolver { v4, v6 } )
414- }
380+ use super :: * ;
415381
416382 fn relay_url ( port : u16 ) -> Url {
417383 format ! ( "http://relay.test:{port}" )
418384 . parse ( )
419385 . expect ( "valid url" )
420386 }
421387
422- /// An unreachable IPv4 address (RFC 5737 TEST-NET-1): a connection attempt to
423- /// it never succeeds, modelling a stale or dead record.
388+ /// An unreachable IPv4 address (RFC 5737 TEST-NET-1).
424389 fn dead_v4 ( n : u8 ) -> Ipv4Addr {
425390 Ipv4Addr :: new ( 192 , 0 , 2 , n)
426391 }
@@ -430,85 +395,46 @@ mod tests {
430395 Ipv6Addr :: new ( 0x2001 , 0xdb8 , 0 , 0 , 0 , 0 , 0 , n)
431396 }
432397
433- /// Runs the dialer against `relay.test` on `port`. An attempt to an
434- /// unreachable address is capped by [`DIAL_ENDPOINT_TIMEOUT`] internally, so
435- /// the dialer always makes progress; the outer timeout only guards against a
436- /// true hang.
437- async fn dial (
438- resolver : & DnsResolver ,
439- port : u16 ,
440- prefer_ipv6 : bool ,
441- ) -> Result < TcpStream , DialError > {
442- time:: timeout (
443- time:: Duration :: from_secs ( 10 ) ,
444- dial_happy_eyeballs ( resolver, & relay_url ( port) , prefer_ipv6) ,
445- )
446- . await
447- . expect ( "dialer finishes in time" )
448- }
449-
450- #[ tokio:: test]
451- async fn connects_to_the_resolved_address ( ) {
452- let listener = TcpListener :: bind ( ( Ipv4Addr :: LOCALHOST , 0 ) ) . await . unwrap ( ) ;
453- let port = listener. local_addr ( ) . unwrap ( ) . port ( ) ;
454-
455- let stream = dial ( & resolver ( vec ! [ Ipv4Addr :: LOCALHOST ] , vec ! [ ] ) , port, false )
456- . await
457- . expect ( "connects to the listener" ) ;
458- assert_eq ! (
459- stream. peer_addr( ) . unwrap( ) ,
460- ( Ipv4Addr :: LOCALHOST , port) . into( )
461- ) ;
462- }
463-
398+ /// Tests that all addresses are tried until one succeeds.
464399 #[ tokio:: test]
465400 async fn tries_addresses_until_one_connects ( ) {
466401 let listener = TcpListener :: bind ( ( Ipv4Addr :: LOCALHOST , 0 ) ) . await . unwrap ( ) ;
467402 let port = listener. local_addr ( ) . unwrap ( ) . port ( ) ;
468403
469- // Vary the number of unreachable addresses preceding the reachable one:
470- // the dialer should skip the dead ones and still connect.
471- for dead in [ 0u8 , 1 , 3 ] {
472- let v4 = ( 1 ..=dead)
473- . map ( dead_v4)
474- . chain ( [ Ipv4Addr :: LOCALHOST ] )
475- . collect ( ) ;
476- let stream = dial ( & resolver ( v4, vec ! [ ] ) , port, false )
477- . await
478- . unwrap_or_else ( |err| panic ! ( "connects with {dead} dead addresses: {err:#}" ) ) ;
479- assert_eq ! ( stream. peer_addr( ) . unwrap( ) . ip( ) , Ipv4Addr :: LOCALHOST ) ;
480- }
404+ let addrs = ( 1 ..5 ) . map ( dead_v4) . chain ( [ Ipv4Addr :: LOCALHOST ] ) . collect ( ) ;
405+ let resolver = StaticResolver :: new ( addrs, vec ! [ ] ) ;
406+ let stream = dial_happy_eyeballs ( & resolver, & relay_url ( port) , false )
407+ . await
408+ . expect ( "should skip the invalid addrs and still connect" ) ;
409+ assert_eq ! ( stream. peer_addr( ) . unwrap( ) . ip( ) , Ipv4Addr :: LOCALHOST ) ;
481410 }
482411
412+ /// Tests if the preferred family is unreachable the non-preferred family is used.
483413 #[ tokio:: test]
484414 async fn falls_back_from_unreachable_preferred_family ( ) {
485- // IPv6 is preferred but every IPv6 address is unreachable; the dialer must
486- // interleave across families and fall back to the reachable IPv4 address.
487415 let listener = TcpListener :: bind ( ( Ipv4Addr :: LOCALHOST , 0 ) ) . await . unwrap ( ) ;
488416 let port = listener. local_addr ( ) . unwrap ( ) . port ( ) ;
489- let resolver = resolver ( vec ! [ Ipv4Addr :: LOCALHOST ] , vec ! [ dead_v6( 1 ) , dead_v6( 2 ) ] ) ;
417+ let resolver = StaticResolver :: new ( vec ! [ Ipv4Addr :: LOCALHOST ] , vec ! [ dead_v6( 1 ) , dead_v6( 2 ) ] ) ;
490418
491- let stream = dial ( & resolver, port, true )
419+ let stream = dial_happy_eyeballs ( & resolver, & relay_url ( port) , true )
492420 . await
493421 . expect ( "falls back to IPv4" ) ;
494422 assert ! ( stream. peer_addr( ) . unwrap( ) . is_ipv4( ) ) ;
495423 }
496424
497425 #[ tokio:: test]
498426 async fn errors_when_all_addresses_unreachable ( ) {
499- let resolver = resolver ( vec ! [ dead_v4( 1 ) , dead_v4( 2 ) ] , vec ! [ dead_v6( 1 ) ] ) ;
500- let err = dial ( & resolver, 8080 , true )
427+ let resolver = StaticResolver :: new ( vec ! [ dead_v4( 1 ) , dead_v4( 2 ) ] , vec ! [ dead_v6( 1 ) ] ) ;
428+ let err = dial_happy_eyeballs ( & resolver, & relay_url ( 80 ) , true )
501429 . await
502430 . expect_err ( "nothing reachable" ) ;
503- assert ! ( matches!(
504- err,
505- DialError :: Io { .. } | DialError :: Timeout { .. }
506- ) ) ;
431+ assert ! ( matches!( err, DialError :: Io { .. } ) ) ;
507432 }
508433
509434 #[ tokio:: test]
510435 async fn errors_when_nothing_resolves ( ) {
511- let err = dial_happy_eyeballs ( & resolver ( vec ! [ ] , vec ! [ ] ) , & relay_url ( 80 ) , false )
436+ let resolver = StaticResolver :: new ( vec ! [ ] , vec ! [ ] ) ;
437+ let err = dial_happy_eyeballs ( & resolver, & relay_url ( 80 ) , false )
512438 . await
513439 . expect_err ( "no addresses to dial" ) ;
514440 assert ! ( matches!( err, DialError :: Dns { .. } ) ) ;
0 commit comments