@@ -9,36 +9,95 @@ const assert = require('assert');
99const net = require ( 'net' ) ;
1010const http = require ( 'http' ) ;
1111const { internalBinding } = require ( 'internal/test/binding' ) ;
12- const { UV_ENETUNREACH } = internalBinding ( 'uv' ) ;
12+ const { UV_ENETUNREACH , UV_EADDRINUSE } = internalBinding ( 'uv' ) ;
1313const {
1414 newAsyncId,
1515 symbols : { async_id_symbol }
1616} = require ( 'internal/async_hooks' ) ;
1717
18- const agent = new http . Agent ( ) ;
19- agent . createConnection = common . mustCall ( ( cfg ) => {
20- const sock = new net . Socket ( ) ;
18+ const config = {
19+ host : 'http://example.com' ,
20+ // We need to specify 'family' in both items of the array so 'internalConnectMultiple' is invoked
21+ connectMultiple : [ { address : '192.4.4.4' , family : 4 } , { address : '200::1' , family : 6 } ] ,
22+ connectSolo : { address : '192.4.4.4' , family : 4 } ,
23+ } ;
2124
22- // Fake the handle so we can enforce returning an immediate error
23- sock . _handle = {
24- connect : common . mustCall ( ( req , addr , port ) => {
25- return UV_ENETUNREACH ;
26- } ) ,
27- readStart ( ) { } ,
28- close ( ) { }
29- } ;
25+ function agentFactory ( handle , count ) {
26+ const agent = new http . Agent ( ) ;
27+ agent . createConnection = common . mustCall ( ( cfg ) => {
28+ const sock = new net . Socket ( ) ;
3029
31- // Simulate just enough socket handle initialization
32- sock [ async_id_symbol ] = newAsyncId ( ) ;
30+ // Fake the handle so we can enforce returning an immediate error
31+ sock . _handle = handle ;
3332
34- sock . connect ( cfg ) ;
35- return sock ;
36- } ) ;
33+ // Simulate just enough socket handle initialization
34+ sock [ async_id_symbol ] = newAsyncId ( ) ;
35+
36+ sock . connect ( cfg ) ;
37+ return sock ;
38+ } , count ) ;
39+
40+ return agent ;
41+ } ;
42+
43+ const handleWithoutBind = {
44+ connect : common . mustCall ( ( req , addr , port ) => {
45+ return UV_ENETUNREACH ;
46+ } , 3 ) , // Because two tests will use this
47+ readStart ( ) { } ,
48+ close ( ) { } ,
49+ } ;
50+
51+ const handleWithBind = {
52+ readStart ( ) { } ,
53+ close ( ) { } ,
54+ bind : common . mustCall ( ( ) => UV_EADDRINUSE , 2 ) , // Because two tests will use this handle
55+ } ;
56+
57+ const agentWithoutBind = agentFactory ( handleWithoutBind , 3 ) ;
58+ const agentWithBind = agentFactory ( handleWithBind , 2 ) ;
3759
3860http . get ( {
3961 host : '127.0.0.1' ,
4062 port : 1 ,
41- agent
63+ agent : agentWithoutBind ,
4264} ) . on ( 'error' , common . mustCall ( ( err ) => {
4365 assert . strictEqual ( err . code , 'ENETUNREACH' ) ;
4466} ) ) ;
67+
68+ http . request ( config . host , {
69+ agent : agentWithoutBind ,
70+ lookup ( _0 , _1 , cb ) {
71+ cb ( null , config . connectMultiple ) ;
72+ } ,
73+ } ) . on ( 'error' , common . mustCall ( ( err ) => {
74+ assert . strictEqual ( err . code , 'ENETUNREACH' ) ;
75+ } ) ) ;
76+
77+ http . request ( config . host , {
78+ agent : agentWithoutBind ,
79+ lookup ( _0 , _1 , cb ) {
80+ cb ( null , config . connectSolo . address , config . connectSolo . family ) ;
81+ } ,
82+ family : 4 ,
83+ } ) . on ( 'error' , common . mustCall ( ( err ) => {
84+ assert . strictEqual ( err . code , 'ENETUNREACH' ) ;
85+ } ) ) ;
86+
87+ http . request ( config . host , {
88+ agent : agentWithBind ,
89+ family : 4 , // We specify 'family' so 'internalConnect' is invoked
90+ localPort : 2222 // Required to trigger _handle.bind()
91+ } ) . on ( 'error' , common . mustCall ( ( err ) => {
92+ assert . strictEqual ( err . code , 'EADDRINUSE' ) ;
93+ } ) ) ;
94+
95+ http . request ( config . host , {
96+ agent : agentWithBind ,
97+ lookup ( _0 , _1 , cb ) {
98+ cb ( null , config . connectMultiple ) ;
99+ } ,
100+ localPort : 2222 , // Required to trigger _handle.bind()
101+ } ) . on ( 'error' , common . mustCall ( ( err ) => {
102+ assert . strictEqual ( err . code , 'EADDRINUSE' ) ;
103+ } ) ) ;
0 commit comments