diff options
author | Paul Phillips <paulp@improving.org> | 2013-01-31 16:35:35 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-01-31 16:46:51 -0800 |
commit | d2965f8b458a210868f64261093a2372d0ef91d6 (patch) | |
tree | 4acd1a2c043160719ad492cd862fccfb7843056c | |
parent | d499db3800b6460cfd575e650953980211d4026b (diff) | |
download | scala-d2965f8b458a210868f64261093a2372d0ef91d6.tar.gz scala-d2965f8b458a210868f64261093a2372d0ef91d6.tar.bz2 scala-d2965f8b458a210868f64261093a2372d0ef91d6.zip |
Overhaul of tools/partest-ack.
I decided what would be really handy for test selection is
being able to run all the tests which were created or modified
at the same time as something else. Right now that is at file
granularity, though it would be simple enough to generalize it
such that any expression which can be translated to a set of
git commits can also be turned into a selection of tests.
I added some other options as well:
Usage: $0 <regex> [-dfquvp] [ack options]
-d pass --debug to partest
-f pass --failed to partest
-q DON'T pass --show-log and --show-diff to partest
-u pass --update-check to partest
-v pass --verbose to partest
-p <path> select tests appearing in commits where <path> was also modified
Example usage:
> tools/partest-ack -p src/compiler/scala/tools/nsc/typechecker/Checkable.scala
% tests-modified-in-same-commit ... 12
# 12 tests to run.
Testing individual files
testing: [...]/files/pos/t6537.scala [ OK ]
Testing individual files
testing: [...]/files/neg/unchecked-impossible.scala [ OK ]
testing: [...]/files/neg/t1872.scala [ OK ]
testing: [...]/files/neg/t4302.scala [ OK ]
testing: [...]/files/neg/unchecked-knowable.scala [ OK ]
testing: [...]/files/neg/unchecked-abstract.scala [ OK ]
[etc]
-rwxr-xr-x | tools/partest-ack | 156 |
1 files changed, 113 insertions, 43 deletions
diff --git a/tools/partest-ack b/tools/partest-ack index 0c8244257b..f7d5063292 100755 --- a/tools/partest-ack +++ b/tools/partest-ack @@ -2,36 +2,18 @@ # # wrapper around partest for fine-grained test selection via ack -args="$@" - -pathMatches () { - ack --noenv --text --files-with-matches "$@" test/files - - for p in $(find test/files/* -print); do - [[ $p =~ $1 ]] && echo "$p" - done -} - -testIds () { - pathMatches "$@" | \ - perl -pe 's#^(test/files/[^/]+/[^/.]+).*$#$1#' | \ - sort -u -} -testPaths () { - for id in "$@"; do - if [[ -d $id ]]; then - echo $id - elif [[ -f ${id}.scala ]]; then - echo "${id}.scala" - else - echo >&2 "No test corresponds to $id" - fi - done -} +declare quiet failed update partest_debug file_regex partest_args ack_args cotouched [[ $# -gt 0 ]] || { cat <<EOM -Usage: $0 <regex> [ack options] +Usage: $0 <regex> [-dfquvp] [ack options] + + -d pass --debug to partest + -f pass --failed to partest + -q DON'T pass --show-log and --show-diff to partest + -u pass --update-check to partest + -v pass --verbose to partest + -p <path> select tests appearing in commits where <path> was also modified Given a regular expression (and optionally, any arguments accepted by ack) runs all the tests for which any associated file matches the regex. Associated @@ -42,30 +24,118 @@ You must have ack installed: http://betterthangrep.com/ack-standalone Examples: - % tools/partest-ack monad - Found 4 tests matching 'ack monad' + > tools/partest-ack monad + % tests-with-matching-paths ... 2 + % tests-with-matching-code ... 2 + # 4 tests to run. - Testing individual files - testing: [...]/files/pos/tcpoly_boundedmonad.scala [ OK ] - testing: [...]/files/pos/tcpoly_ticket2096.scala [ OK ] - testing: [...]/files/run/tcpoly_monads.scala [ OK ] - testing: [...]/files/presentation/callcc-interpreter [ OK ] + > tools/partest-ack -p src/library/scala/Enumeration.scala + % tests-modified-in-same-commit ... 84 + # 84 tests to run. - % tools/partest-ack monad -i # -i == ignore case - Found 12 tests matching 'ack monad -i' - - Testing individual files - [etc] + > tools/partest-ack -f + % tests-which-failed ... 42 + # 42 tests to run. EOM exit 0 } -paths=$(testPaths $(testIds "$@")) -if [[ -z $paths ]]; then +# The leading : in :achs suppresses some errors. Each letter is a valid +# option. If an option takes an argument, a colon follows it, e.g. +# it would be :ach:s if -h took an argument. +while getopts :fuvdp: opt; do + case $opt in + d) partest_debug=true && partest_args="$partest_args --debug" ;; + f) failed=true && partest_args="$partest_args --failed" ;; + p) cotouched="$cotouched $OPTARG" ;; + q) quiet=true ;; + u) partest_args="$partest_args --update-check" ;; + v) partest_args="$partest_args --verbose" ;; + :) echo "Option -$OPTARG requires an argument." >&2 ;; # this case is called for a missing option argument + *) echo "Unrecognized argument $OPTARG" ;; # this is the catch-all implying an unknown option + esac +done + +shift $((OPTIND-1)) +file_regex="$1" +ack_args="$*" + +tests () { + find test/files -mindepth 2 -maxdepth 2 -name '*.scala' -o -type d +} + +pathsToTests () { + for path in $(perl -pe 's#^(test/files/[^/]+/[^/.]+).*$#$1#'); do + if [[ -d "$path" ]]; then + echo "$path" + elif [[ -f "$path.scala" ]]; then + echo "$path.scala" + fi + done | sort -u +} + +tests-with-matching-paths() { + local re="$1" + for p in $(find test/files -type f); do + [[ $p =~ $re ]] && echo "$p" + done +} + +tests-which-failed () { + for f in $(find test/files -name '*.log'); do + echo ${f%-*} + done +} + +tests-modified-in-same-commit() { + [[ $# -gt 0 ]] && \ + for rev in $(git rev-list HEAD -- "$@"); do + git --no-pager show --pretty="format:" --name-only "$rev" -- test/files + done +} + +tests-with-matching-code() { + ack --noenv --text --files-with-matches "$@" -- test/files +} + +countStdout () { + local -i count=0 + while read line; do + printf "$line\n" + count+=1 + done + + printf >&2 " $count\n" +} + +testRun () { + printf >&2 "%% %-30s ... " "$1" + "$@" | pathsToTests | countStdout +} + +allMatches() { + [[ -n $file_regex ]] && testRun tests-with-matching-paths $file_regex + [[ -n $cotouched ]] && testRun tests-modified-in-same-commit $cotouched + [[ -n $ack_args ]] && testRun tests-with-matching-code $ack_args + [[ -n $failed ]] && testRun tests-which-failed +} + +paths=$(allMatches | sort -u) +[[ -n $quiet ]] || partest_args="--show-diff --show-log $partest_args" + +if [[ -z $paths ]] && [[ -z $failed ]]; then echo >&2 "No matching tests." else count=$(echo $(echo "$paths" | wc -w)) - echo "Found $count tests matching 'ack $@'" - test/partest $paths + + # Output a command line which will re-run these same tests. + echo "# $count tests to run." + printf "%-52s %s\n" "test/partest $partest_args" "\\" + for path in $paths; do + printf " %-50s %s\n" "$path" "\\" + done + echo ' ""' + + test/partest $partest_args $paths fi |