1212# NO_BUILD_ONCE : set to non-empty to skip the initial cabal build step
1313#
1414# Test selection:
15- # TEST_PATTERNS : comma-separated list of tasty patterns to run each iteration.
16- # Example: TEST_PATTERNS='open close,bidirectional module dependency with hs-boot'
15+ # TEST_PATTERNS : comma-separated list of entries to run each iteration.
16+ # Each entry can be either a plain tasty pattern, or 'BIN::PATTERN' to select a test binary.
17+ # Examples:
18+ # TEST_PATTERNS='open close'
19+ # TEST_PATTERNS='ghcide-tests::open close,func-test::sends indefinite progress notifications'
1720# If set and non-empty, this takes precedence over PATTERN_FILE.
18- # If unset, defaults to 'open close' to match prior behavior.
19- # PATTERN_FILE : path to a file with one pattern per line (lines starting with # or blank are ignored).
21+ # If unset, defaults to 'ghcide-tests::open close' to match prior behavior.
22+ # PATTERN_FILE : path to a file with one entry per line.
23+ # Lines start with optional 'BIN::', then the tasty pattern. '#' comments and blank lines ignored.
24+ # Examples:
25+ # ghcide-tests::open close
26+ # func-test::sends indefinite progress notifications
2027# Used only if TEST_PATTERNS is empty/unset; otherwise ignored.
2128#
2229# Exit codes:
@@ -54,65 +61,91 @@ BROKEN_PIPE_RE='Broken pipe'
5461TEST_FAILED_RE=' fail|timeout'
5562DEBUG_DETECT=" ${DEBUG_DETECT:- 0} "
5663
57- # Resolve which tasty patterns to run each iteration
58- patterns =()
64+ # Resolve what to run each iteration as pairs of BIN and PATTERN
65+ items =() # each item is 'BIN::PATTERN'
5966if [[ -n " ${TEST_PATTERNS:- } " ]]; then
60- IFS=' ,' read -r -a patterns <<< " ${TEST_PATTERNS}"
61- # trim whitespace and drop empty entries
62- tmp_patterns=()
63- for p in " ${patterns[@]} " ; do
64- # trim leading
65- p= " ${p # ${p %% [![:space:]] * } } "
66- # trim trailing
67- p= " ${p % ${p ##* [![:space:]]} } "
68- [[ -z " $p " ]] && continue
69- tmp_patterns+=( " $p " )
67+ IFS=' ,' read -r -a raw_items <<< " ${TEST_PATTERNS}"
68+ for it in " ${raw_items[@]} " ; do
69+ # trim
70+ it= " ${it # ${it %% [![:space:]] * } } " ; it= " ${it % ${it ##* [![:space:]]} } "
71+ [[ -z " $it " ]] && continue
72+ if [[ " $it " == * " :: " * ]] ; then
73+ items+=( " $it " )
74+ else
75+ items+=( " ghcide-tests:: ${it} " )
76+ fi
7077 done
71- patterns=(" ${tmp_patterns[@]} " )
7278elif [[ -n " ${PATTERN_FILE:- } " && -r " ${PATTERN_FILE} " ]]; then
7379 while IFS= read -r line; do
7480 # trim whitespace, skip comments and blank lines
75- trimmed=" ${line# ${line%% [![:space:]]* } } "
76- trimmed=" ${trimmed% ${trimmed##* [![:space:]]} } "
81+ trimmed=" ${line# ${line%% [![:space:]]* } } " ; trimmed=" ${trimmed% ${trimmed##* [![:space:]]} } "
7782 [[ -z " ${trimmed} " || " ${trimmed} " =~ ^[[:space:]]* # ]] && continue
78- patterns+= (" ${trimmed} " )
83+ if [[ " ${trimmed} " == * " ::" * ]]; then
84+ items+=(" ${trimmed} " )
85+ else
86+ items+=(" ghcide-tests::${trimmed} " )
87+ fi
7988 done < " ${PATTERN_FILE} "
8089else
8190 # default to the original single test
82- patterns += (" open close" )
91+ items += (" ghcide-tests:: open close" )
8392fi
8493
85- if [[ ${# patterns [@]} -eq 0 ]]; then
86- echo " [loop][error] No test patterns provided (via PATTERN_FILE or TEST_PATTERNS)." >&2
94+ if [[ ${# items [@]} -eq 0 ]]; then
95+ echo " [loop][error] No test entries provided (via PATTERN_FILE or TEST_PATTERNS)." >&2
8796 exit 2
8897fi
8998
90- if [[ -z " ${NO_BUILD_ONCE:- } " ]]; then
91- echo " [loop] Building test target ghcide-tests once upfront" >&2
92- cabal build ghcide-tests >&2
93- fi
94-
95- # Locate the built test binary (simple heuristic similar to run_progress_test.sh)
96- if [[ -z " ${TEST_BIN:- } " ]]; then
97- TEST_BIN=$( find dist-newstyle -type f -name ghcide-tests -perm -111 2> /dev/null | head -n1 || true)
99+ # Build required test binaries once upfront (unless NO_BUILD_ONCE is set or TEST_BIN overrides)
100+ if [[ -z " ${NO_BUILD_ONCE:- } " && -z " ${TEST_BIN:- } " ]]; then
101+ # collect unique BIN names
102+ declare -a bins_to_build=()
103+ for it in " ${items[@]} " ; do
104+ bin=" ${it%%::* } " ; seen=0
105+ if (( ${# bins_to_build[@]} > 0 )) ; then
106+ for b in " ${bins_to_build[@]} " ; do [[ " $b " == " $bin " ]] && seen=1 && break ; done
107+ fi
108+ [[ $seen -eq 0 ]] && bins_to_build+=(" $bin " )
109+ done
110+ if (( ${# bins_to_build[@]} > 0 )) ; then
111+ echo " [loop] Building test targets once upfront: ${bins_to_build[*]} " >&2
112+ cabal build " ${bins_to_build[@]} " >&2 || true
113+ fi
98114fi
99115
100- if [[ -z " ${TEST_BIN} " || ! -x " ${TEST_BIN} " ]]; then
101- echo " [loop][error] Could not locate executable test binary 'ghcide-tests'. Set TEST_BIN explicitly or ensure build succeeded." >&2
102- exit 2
103- fi
104- echo " [loop] Using test binary: ${TEST_BIN} " > & 2
116+ # Resolve binary path by name (cache results)
117+ BIN_NAMES= ()
118+ BIN_PATHS= ()
119+ get_bin_path () {
120+ local name=" $1 "
121+ local i
122+ for (( i= 0 ; i< ${# BIN_NAMES[@]} ; i++ )) ; do
123+ if [[ " ${BIN_NAMES[i]} " == " $name " ]]; then
124+ echo " ${BIN_PATHS[i]} " ; return
125+ fi
126+ done
127+ local path=" "
128+ if [[ -n " ${TEST_BIN:- } " ]]; then
129+ path=" ${TEST_BIN} "
130+ else
131+ path=$( find dist-newstyle -type f -name " $name " -perm -111 2> /dev/null | head -n1 || true)
132+ fi
133+ BIN_NAMES+=(" $name " ); BIN_PATHS+=(" $path " )
134+ echo " $path "
135+ }
105136
106137while true ; do
107138 iter=$(( iter+ 1 ))
108139 ts=$( date -Iseconds)
109140 file_num=$(( iter % 100 ))
110141 if [[ ${file_num} -eq 0 ]]; then file_num=100; fi
111142
112- # Run each selected pattern in this iteration
113- for pattern in " ${patterns[@]} " ; do
143+ # Run each selected item (BIN::PATTERN) in this iteration
144+ for item in " ${items[@]} " ; do
145+ bin_name=" ${item%%::* } "
146+ pattern=" ${item#*:: } "
114147 # sanitize pattern for a log slug
115- slug=$( printf ' %s' " ${pattern} " | tr -cs ' A-Za-z0-9._-' ' -' | sed -E ' s/^-+|-+$//g' )
148+ slug=$( printf ' %s' " ${bin_name} - ${ pattern}" | tr -cs ' A-Za-z0-9._-' ' -' | sed -E ' s/^-+|-+$//g' )
116149 [[ -z " ${slug} " ]] && slug=" pattern"
117150 log=" test-logs/${slug} -loop-${file_num} .log"
118151
@@ -127,8 +160,8 @@ while true; do
127160 HLS_TEST_LOG_STDERR=" ${LOG_STDERR} " \
128161 HLS_TEST_HARNESS_STDERR=" ${LOG_STDERR} " \
129162 TASTY_NUM_THREADS=1 \
130- TASTY_PATTERN=" ${pattern} " \
131- " ${TEST_BIN} " > " ${log} " 2>&1
163+ TASTY_PATTERN=" ${pattern} " \
164+ " $( get_bin_path " ${bin_name} " ) " > " ${log} " 2>&1
132165 set -e
133166
134167 if grep -aFiq -- " ${BROKEN_PIPE_RE} " " ${log} " ; then
0 commit comments