Future-proof against potential Prelude.foldl' (backport #8960) (#9265)
[cabal.git] / validate.sh
blobb23989a2c13f78cfb801df0ae4ed6fbdc5118ab0
1 #!/bin/sh
2 # shellcheck disable=SC2086
4 # default config
5 #######################################################################
7 # We use the default ghc in PATH as default
8 # Use the ghc-x.y.z trigger several errors in windows:
9 # * It triggers the max path length issue:
10 # See https://github.com/haskell/cabal/issues/6271#issuecomment-1065102255
11 # * It triggers a `createProcess: does not exist` error in units tests
12 # See https://github.com/haskell/cabal/issues/8049
13 HC=ghc
14 CABAL=cabal
15 CABALPLAN=cabal-plan
16 JOBS=4
17 LIBTESTS=true
18 CLITESTS=true
19 CABALSUITETESTS=true
20 LIBONLY=false
21 DEPSONLY=false
22 DOCTEST=false
23 BENCHMARKS=false
24 VERBOSE=false
25 HACKAGETESTSALL=false
27 TARGETS=""
28 STEPS=""
29 EXTRAHCS=""
31 LISTSTEPS=false
33 # Help
34 #######################################################################
36 show_usage() {
37 cat <<EOF
38 ./validate.sh - build & test
40 Usage: ./validate.sh [options]
41 A script which runs all the tests.
43 Available options:
44 -j, --jobs JOBS cabal v2-build -j argument (default: $JOBS)
45 --libonly Test only Cabal-the-library
46 --cli Test both Cabal-the-library and cabal-install
47 --(no-)run-lib-tests Run library tests
48 --(no-)run-cli-tests Run client tests
49 --(no-)run-lib-suite Run cabal-testsuite with library
50 --(no-)run-cli-suite Run cabal-testsuite with client
51 -w, --with-compiler HC With compiler
52 --with-cabal CABAL With cabal-install
53 --with-cabal-plan CABALPLAN With cabal-plan
54 --extra-hc HC Extra compiler to run test-suite with
55 --(no-)doctest Run doctest on library
56 --(no-)solver-benchmarks Build and trial run solver-benchmarks
57 --complete-hackage-tests Run hackage-tests on complete Hackage data
58 --partial-hackage-tests Run hackage-tests on parts of Hackage data
59 -v, --verbose Verbose output
60 -q, --quiet Less output
61 -s, --step STEP Run only specific step (can be specified multiple times)
62 --list-steps List steps and build-targets and exit
63 --help Print this message and exit
64 EOF
67 # "library"
68 #######################################################################
70 OUTPUT=$(mktemp)
72 RED='\033[0;31m'
73 GREEN='\033[0;32m'
74 BLUE='\033[0;34m'
75 CYAN='\033[0;96m'
76 RESET='\033[0m' # No Color
78 JOB_START_TIME=$(date +%s)
80 timed() {
81 PRETTYCMD=$(echo "$@" | sed -E 's/\/home[^ ]*\/([^\/])/**\/\1/g')
82 echo "$BLUE>>> $PRETTYCMD $RESET"
83 start_time=$(date +%s)
85 if $VERBOSE; then
86 "$@" 2>&1
87 else
88 "$@" > "$OUTPUT" 2>&1
90 # echo "MOCK" > "$OUTPUT"
91 RET=$?
93 end_time=$(date +%s)
94 duration=$((end_time - start_time))
95 tduration=$((end_time - JOB_START_TIME))
97 if [ $RET -eq 0 ]; then
98 if ! $VERBOSE; then
99 # if output is relatively short, show everything
100 if [ "$(wc -l < "$OUTPUT")" -le 50 ]; then
101 cat "$OUTPUT"
102 else
103 echo "..."
104 tail -n 20 "$OUTPUT"
107 rm -f "$OUTPUT"
110 echo "$GREEN<<< $PRETTYCMD $RESET ($duration/$tduration sec)"
112 # bottom-margin
113 echo ""
114 else
115 if ! $VERBOSE; then
116 cat "$OUTPUT"
119 echo "$RED<<< $PRETTYCMD $RESET ($duration/$tduration sec, $RET)"
120 echo "$RED<<< $* $RESET ($duration/$tduration sec, $RET)"
121 rm -f "$OUTPUT"
122 exit 1
126 print_header() {
127 TITLE=$1
128 TITLEPAT="$(echo "$TITLE"|sed 's:.:=:g')"
129 echo "$CYAN===X============================================================ $(date +%T) ===$RESET" \
130 | sed "s#X$TITLEPAT=# $TITLE #"
134 # getopt
135 #######################################################################
137 while [ $# -gt 0 ]; do
138 arg=$1
139 case $arg in
140 --help)
141 show_usage
142 exit
144 -j|--jobs)
145 JOBS="$2"
146 shift
147 shift
149 --lib-only)
150 LIBONLY=true
151 shift
153 --cli)
154 LIBONLY=false
155 shift
157 --run-lib-tests)
158 LIBTESTS=true
159 shift
161 --no-run-lib-tests)
162 LIBTESTS=false
163 shift
165 --run-cli-tests)
166 CLITESTS=true
167 shift
169 --no-run-cli-tests)
170 CLITESTS=false
171 shift
173 --run-lib-suite)
174 LIBSUITE=true
175 shift
177 --no-run-lib-suite)
178 LIBSUITE=false
179 shift
181 --run-cli-suite)
182 CLISUITE=true
183 shift
185 --no-run-cli-suite)
186 CLISUITE=false
187 shift
189 -w|--with-compiler)
190 HC=$2
191 shift
192 shift
194 --with-cabal)
195 CABAL=$2
196 shift
197 shift
199 --with-cabal-plan)
200 CABALPLAN=$2
201 shift
202 shift
204 --extra-hc)
205 EXTRAHCS="$EXTRAHCS $2"
206 shift
207 shift
209 --doctest)
210 DOCTEST=true
211 shift
213 --no-doctest)
214 DOCTEST=false
215 shift
217 --solver-benchmarks)
218 BENCHMARKS=true
219 shift
221 --no-solver-benchmarks)
222 BENCHMARKS=false
223 shift
225 --complete-hackage-tests)
226 HACKAGETESTSALL=true
227 shift
229 --partial-hackage-tests)
230 HACKAGETESTSALL=false
231 shift
233 -v|--verbose)
234 VERBOSE=true
235 shift
237 -q|--quiet)
238 VERBOSE=false
239 shift
241 -s|--step)
242 STEPS="$STEPS $2"
243 shift
244 shift
246 --list-steps)
247 LISTSTEPS=true
248 shift
251 echo "Unknown option $arg"
252 exit 1
253 esac
254 done
256 # calculate steps and build targets
257 #######################################################################
259 # If there are no explicit steps given calculate them
260 if $LIBONLY; then
261 CLITESTS=false
262 CLISUITE=false
263 BENCHMARKS=false
266 if [ -z "$STEPS" ]; then
267 STEPS="print-config print-tool-versions"
268 STEPS="$STEPS build"
269 if $DOCTEST; then STEPS="$STEPS doctest"; fi
270 if $LIBTESTS; then STEPS="$STEPS lib-tests"; fi
271 if $LIBSUITE; then STEPS="$STEPS lib-suite"; fi
272 if $LIBSUITE && [ -n "$EXTRAHCS" ];
273 then STEPS="$STEPS lib-suite-extras"; fi
274 if $CLITESTS; then STEPS="$STEPS cli-tests"; fi
275 if $CLISUITE; then STEPS="$STEPS cli-suite"; fi
276 if $BENCHMARKS; then STEPS="$STEPS solver-benchmarks-tests solver-benchmarks-run"; fi
277 STEPS="$STEPS time-summary"
280 TARGETS="Cabal cabal-testsuite Cabal-tests Cabal-QuickCheck Cabal-tree-diff Cabal-described"
281 if ! $LIBONLY; then TARGETS="$TARGETS cabal-install cabal-install-solver cabal-benchmarks"; fi
282 if $BENCHMARKS; then TARGETS="$TARGETS solver-benchmarks"; fi
284 if $LISTSTEPS; then
285 echo "Targets: $TARGETS"
286 echo "Steps: $STEPS"
287 exit
290 # Adjust runtime configuration
291 #######################################################################
293 TESTSUITEJOBS="-j$JOBS"
294 JOBS="-j$JOBS"
296 # assume compiler is GHC
297 RUNHASKELL=$(echo $HC | sed -E 's/ghc(-[0-9.]*)$/runghc\1/')
299 if [ "$OSTYPE" = "msys" ]; then
300 ARCH="x86_64-windows"
301 elif [ "$(uname)" = "Linux" ]; then
302 ARCH="x86_64-linux"
303 else
304 ARCH="x86_64-osx"
307 if $LIBONLY; then
308 PROJECTFILE=cabal.project.validate.libonly
309 else
310 PROJECTFILE=cabal.project.validate
313 BASEHC=ghc-$($HC --numeric-version)
314 BUILDDIR=dist-newstyle-validate-$BASEHC
315 CABAL_TESTSUITE_BDIR="$(pwd)/$BUILDDIR/build/$ARCH/$BASEHC/cabal-testsuite-3"
317 CABALNEWBUILD="${CABAL} v2-build $JOBS -w $HC --builddir=$BUILDDIR --project-file=$PROJECTFILE"
318 CABALPLANLISTBIN="${CABALPLAN} list-bin --builddir=$BUILDDIR"
320 # header
321 #######################################################################
323 step_print_config() {
324 print_header print-config
326 cat <<EOF
327 compiler: $HC
328 runhaskell: $RUNHASKELL
329 cabal-install: $CABAL
330 cabal-plan: $CABALPLAN
331 jobs: $JOBS
332 Cabal tests: $LIBTESTS
333 cabal-install tests: $CLITESTS
334 cabal-testsuite: $CABALSUITETESTS
335 library only: $LIBONLY
336 dependencies only: $DEPSONLY
337 doctest: $DOCTEST
338 benchmarks: $BENCHMARKS
339 verbose: $VERBOSE
340 extra compilers: $EXTRAHCS
345 step_print_tool_versions() {
346 print_header print-tool-versions
348 timed $HC --version
349 timed $CABAL --version
350 timed $CABALPLAN --version
352 for EXTRAHC in $EXTRAHCS; do
353 timed $EXTRAHC --version
354 done
357 step_time_summary() {
358 print_header END
360 JOB_END_TIME=$(date +%s)
361 tduration=$((JOB_END_TIME - JOB_START_TIME))
363 echo "$CYAN!!! Validation took $tduration seconds. $RESET"
366 # build
367 #######################################################################
369 step_build() {
370 print_header "build"
371 timed $CABALNEWBUILD $TARGETS --dry-run || exit 1
372 $CABALPLAN topo --builddir=$BUILDDIR || exit 1
373 timed $CABALNEWBUILD $TARGETS || exit 1
376 # Cabal lib
377 #######################################################################
379 step_doctest() {
380 print_header "Cabal: doctest"
381 cabal-env --name doctest-Cabal --transitive QuickCheck
382 cabal-env --name doctest-Cabal array bytestring containers deepseq directory filepath pretty process time binary unix text parsec mtl
383 timed doctest -package-env=doctest-Cabal --fast Cabal/Distribution Cabal/Language
386 step_lib_tests() {
387 print_header "Cabal: tests"
389 CMD="$($CABALPLANLISTBIN Cabal-tests:test:unit-tests) $TESTSUITEJOBS --hide-successes --with-ghc=$HC"
390 (cd Cabal-tests && timed $CMD) || exit 1
392 CMD="$($CABALPLANLISTBIN Cabal-tests:test:check-tests) $TESTSUITEJOBS --hide-successes"
393 (cd Cabal-tests && timed $CMD) || exit 1
395 CMD="$($CABALPLANLISTBIN Cabal-tests:test:parser-tests) $TESTSUITEJOBS --hide-successes"
396 (cd Cabal-tests && timed $CMD) || exit 1
398 CMD="$($CABALPLANLISTBIN Cabal-tests:test:rpmvercmp) $TESTSUITEJOBS --hide-successes"
399 (cd Cabal-tests && timed $CMD) || exit 1
401 CMD="$($CABALPLANLISTBIN Cabal-tests:test:no-thunks-test) $TESTSUITEJOBS --hide-successes"
402 (cd Cabal-tests && timed $CMD) || exit 1
404 CMD=$($CABALPLANLISTBIN Cabal-tests:test:hackage-tests)
405 (cd Cabal-tests && timed $CMD read-fields) || exit 1
406 if $HACKAGETESTSALL; then
407 (cd Cabal-tests && timed $CMD parsec) || exit 1
408 (cd Cabal-tests && timed $CMD roundtrip) || exit 1
409 else
410 (cd Cabal-tests && timed $CMD parsec d) || exit 1
411 (cd Cabal-tests && timed $CMD roundtrip k) || exit 1
415 # Cabal cabal-testsuite
416 #######################################################################
418 step_lib_suite() {
419 print_header "Cabal: cabal-testsuite"
421 CMD="$($CABALPLANLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR $TESTSUITEJOBS --with-ghc=$HC --hide-successes"
422 (cd cabal-testsuite && timed $CMD) || exit 1
425 step_lib_suite_extras() {
426 for EXTRAHC in $EXTRAHCS; do
428 CMD="$($CABALPLANLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR $TESTSUITEJOBS --with-ghc=$EXTRAHC --hide-successes"
429 (cd cabal-testsuite && timed $CMD) || exit 1
431 done
434 # cabal-install
435 #######################################################################
437 step_cli_tests() {
438 print_header "cabal-install: tests"
440 # this are sorted in asc time used, quicker tests first.
441 CMD="$($CABALPLANLISTBIN cabal-install:test:long-tests) $TESTSUITEJOBS --hide-successes"
442 (cd cabal-install && timed $CMD) || exit 1
444 # This doesn't work in parallel either
445 CMD="$($CABALPLANLISTBIN cabal-install:test:unit-tests) -j1 --hide-successes"
446 (cd cabal-install && timed $CMD) || exit 1
448 # Only single job, otherwise we fail with "Heap exhausted"
449 CMD="$($CABALPLANLISTBIN cabal-install:test:mem-use-tests) -j1 --hide-successes"
450 (cd cabal-install && timed $CMD) || exit 1
452 # This test-suite doesn't like concurrency
453 CMD="$($CABALPLANLISTBIN cabal-install:test:integration-tests2) -j1 --hide-successes --with-ghc=$HC"
454 (cd cabal-install && timed $CMD) || exit 1
457 # cabal-install cabal-testsuite
458 #######################################################################
460 step_cli_suite() {
461 print_header "cabal-install: cabal-testsuite"
463 CMD="$($CABALPLANLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR --with-cabal=$($CABALPLANLISTBIN cabal-install:exe:cabal) $TESTSUITEJOBS --with-ghc=$HC --hide-successes"
464 (cd cabal-testsuite && timed $CMD) || exit 1
467 # solver-benchmarks
468 #######################################################################
470 step_solver_benchmarks_tests() {
471 print_header "solver-benchmarks: test"
473 CMD="$($CABALPLANLISTBIN solver-benchmarks:test:unit-tests)"
474 (cd Cabal && timed $CMD) || exit 1
477 step_solver_benchmarks_run() {
478 print_header "solver-benchmarks: run"
480 SOLVEPKG=Chart-diagrams
481 CMD="$($CABALPLANLISTBIN solver-benchmarks:exe:hackage-benchmark) --cabal1=$CABAL --cabal2=$($CABALPLANLISTBIN cabal-install:exe:cabal) --trials=5 --packages=$SOLVEPKG --print-trials"
482 (cd Cabal && timed $CMD) || exit 1
485 # Steps dispatcher
486 #######################################################################
488 for step in $STEPS; do
489 case $step in
490 print-config) step_print_config ;;
491 print-tool-versions) step_print_tool_versions ;;
492 build) step_build ;;
493 doctest) step_doctest ;;
494 lib-tests) step_lib_tests ;;
495 cli-tests) step_cli_tests ;;
496 lib-suite) step_lib_suite ;;
497 lib-suite-extras) step_lib_suite_extras ;;
498 cli-suite) step_cli_suite ;;
499 solver-benchmarks-tests) step_solver_benchmarks_tests ;;
500 solver-benchmarks-run) step_solver_benchmarks_run ;;
501 time-summary) step_time_summary ;;
503 echo "Invalid step $step"
504 exit 1
506 esac
507 done
509 #######################################################################