@@ -44,23 +44,23 @@ func init() {
4444 flag .StringVar (& evmSingleBinaryPath , "evm-binary" , "evm" , "evm binary" )
4545}
4646
47- // getAvailablePort finds an available TCP port on localhost
48- func getAvailablePort () (int , error ) {
47+ // getAvailablePort finds an available TCP port on localhost and returns the listener.
48+ func getAvailablePort () (int , net. Listener , error ) {
4949 listener , err := net .Listen ("tcp" , "127.0.0.1:0" )
5050 if err != nil {
51- return 0 , err
51+ return 0 , nil , err
5252 }
53- defer listener .Close ()
54-
5553 addr := listener .Addr ().(* net.TCPAddr )
56- return addr .Port , nil
54+ return addr .Port , listener , nil
5755}
5856
5957// same as getAvailablePort but fails test if not successful
6058func mustGetAvailablePort (t * testing.T ) int {
6159 t .Helper ()
62- port , err := getAvailablePort ()
60+ port , listener , err := getAvailablePort ()
6361 require .NoError (t , err )
62+ // Helper only: close immediately as race conditions are handled by caller if needed.
63+ listener .Close ()
6464 return port
6565}
6666
@@ -132,33 +132,49 @@ func (te *TestEndpoints) GetFullNodeP2PAddress() string {
132132 return "/ip4/127.0.0.1/tcp/" + te .FullNodeP2PPort
133133}
134134
135- // generateTestEndpoints creates a set of unique ports for a test instance
136- // Only generates ports for rollkit components; EVM engine ports will be set dynamically
135+ // generateTestEndpoints creates a set of unique ports for a test instance.
136+ // Holds listeners open until all ports are assigned to prevent OS reuse.
137137func generateTestEndpoints () (* TestEndpoints , error ) {
138138 endpoints := & TestEndpoints {}
139+ var listeners []net.Listener
140+
141+ defer func () {
142+ for _ , l := range listeners {
143+ l .Close ()
144+ }
145+ }()
146+
147+ getPort := func () (int , error ) {
148+ port , listener , err := getAvailablePort ()
149+ if err != nil {
150+ return 0 , err
151+ }
152+ listeners = append (listeners , listener )
153+ return port , nil
154+ }
139155
140156 // Generate unique ports for DA and rollkit components
141- daPort , err := getAvailablePort ()
157+ daPort , err := getPort ()
142158 if err != nil {
143159 return nil , fmt .Errorf ("failed to get DA port: %w" , err )
144160 }
145161
146- rollkitRPCPort , err := getAvailablePort ()
162+ rollkitRPCPort , err := getPort ()
147163 if err != nil {
148164 return nil , fmt .Errorf ("failed to get rollkit RPC port: %w" , err )
149165 }
150166
151- rollkitP2PPort , err := getAvailablePort ()
167+ rollkitP2PPort , err := getPort ()
152168 if err != nil {
153169 return nil , fmt .Errorf ("failed to get rollkit P2P port: %w" , err )
154170 }
155171
156- fullNodeP2PPort , err := getAvailablePort ()
172+ fullNodeP2PPort , err := getPort ()
157173 if err != nil {
158174 return nil , fmt .Errorf ("failed to get full node P2P port: %w" , err )
159175 }
160176
161- fullNodeRPCPort , err := getAvailablePort ()
177+ fullNodeRPCPort , err := getPort ()
162178 if err != nil {
163179 return nil , fmt .Errorf ("failed to get full node RPC port: %w" , err )
164180 }
0 commit comments