@@ -29,6 +29,13 @@ test_dir=$1 # parse the first argument
2929# It can be set through the env variable TEST_TIMEOUT and defaults to 1200 seconds.
3030test_timeout=" ${TEST_TIMEOUT:- 1200} "
3131
32+ # Base port to start assigning from (default: 12000)
33+ last_used_port=" ${BASE_PORT:- 12000} "
34+
35+ # Port spacing between attempts (default: 20)
36+ port_margin=" ${PORT_MARGIN:- 20} "
37+
38+
3239# Temporary file to store the collected tests
3340COLLECTED_TESTS_FILE=" collected_tests.txt"
3441
@@ -96,6 +103,43 @@ report=() # final report
96103pids=() # array of PID for running tests
97104test_ids=() # array of indexes of running tests
98105failed_tests=() # array of failed tests
106+ used_ports=() # array of used ports
107+
108+ # --- helper functions ---
109+
110+ get_available_port () {
111+ preferred_port=" $1 "
112+
113+ # Check the preferred port first
114+ if nc -z localhost " $preferred_port " 2> /dev/null; then
115+ # Preferred port is busy, grab an ephemeral one
116+ port=$( python3 -c " import socket as s; sock=s.socket(); sock.bind(('',0)); print(sock.getsockname()[1]); sock.close()" )
117+ echo " $port "
118+ else
119+ # Preferred port is free
120+ echo " $preferred_port "
121+ fi
122+ }
123+
124+ contains () {
125+ local element=" $1 "
126+ shift
127+ local array=(" $@ " )
128+
129+ for item in " ${array[@]} " ; do
130+ if [[ " $item " == " $element " ]]; then
131+ echo " true"
132+ return 0
133+ fi
134+ done
135+
136+ echo " false"
137+ return 1
138+ }
139+
140+
141+ # --- Start running tests in parallel batches ---
142+
99143printf " Running $test_count tests in batches of $test_batch_size :\n"
100144for i in " ${! tests[@]} " ; do
101145 test=${tests[$i]}
@@ -108,12 +152,28 @@ for i in "${!tests[@]}"; do
108152 # add the pytest cli to the test command
109153 cli_test=" ${cli_test} ${cli_pytest} "
110154
111- printf " \e[95m* Running test $(( i+ 1 )) /$test_count : $cli_test $test \e[0m\n"
155+ # get the next available unique port based on last_used_port and port_margin
156+ (( last_used_port+= port_margin))
157+ available_port=$( get_available_port $last_used_port )
158+
159+ # ensure the port is unique among used ports
160+ while [[ $( contains $available_port " ${used_ports[@]} " ) == " true" ]]; do
161+ # get the next available unique port
162+ (( last_used_port+= port_margin))
163+ available_port=$( get_available_port $last_used_port )
164+ done
165+
166+ # mark the port as used
167+ used_ports+=($available_port )
168+
169+ test_command=" env STANDALONE_PORT=${available_port} ${cli_test} $test "
170+
171+ printf " \e[95m* Running test $(( i+ 1 )) /$test_count : $test_command \e[0m\n"
112172
113173 # execute the test in the background
114174 # redirect to a log file that buffers test output. since the tests will run in the background,
115175 # we cannot let them output to std{out,err} because the outputs would be garbled together
116- ${cli_test} " $test " & > " parallel_test_output-$i .txt" &
176+ $test_command & > " parallel_test_output-$i .txt" &
117177 test_ids+=($i ) # save the test's id in an array with running tests
118178 pids+=($! ) # save the PID in an array with running tests
119179
0 commit comments