diff options
Diffstat (limited to 'tools/partest-ack')
-rwxr-xr-x | tools/partest-ack | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/tools/partest-ack b/tools/partest-ack new file mode 100755 index 0000000000..ab722e3b1c --- /dev/null +++ b/tools/partest-ack @@ -0,0 +1,131 @@ +#!/usr/bin/env bash +# +# wrapper around partest for fine-grained test selection via ack + +declare quiet failed update partest_debug +declare cotouched since sortCommand +declare -a ack_args partest_args scalac_args +declare -r standard_ack_args="--noenv -s --java --scala --type-add=scala:ext:flags,check --files-with-matches" + +partest_args=( --show-diff ) +bindir="$(cd "$(dirname "$0")" && pwd)" +base="$bindir/.." +cd "$base" || { echo "Could not change to base directory $base" && exit 1; } +filesdir="test/files" +sortCommand="sort -u" +partestPaths="$bindir/partest-paths" + +[[ -x "$partestPaths" ]] || { echo "Cannot find partest-paths in $partestPaths" && exit 1; } + +[[ $# -gt 0 ]] || { + cat <<EOM +Usage: $0 <regex> [-dfquvp] [ack options] + + -f pass --failed to partest + -q pass --terse to partest + -u pass --update-check to partest + -p <path> select tests appearing in commits where <path> was also modified + -s <time> select tests touched since <time> (git format, e.g. 1.month.ago) + -r run tests in random order + +Given a regular expression (and optionally, any arguments accepted by ack) +runs all the tests for which any associated file matches the regex. Associated +files include .check and .flags files. Tests in directories will match if any +file matches. A file can match the regex by its contents or by its name. + +You must have ack version 2.12+ installed: http://beyondgrep.com/ack-2.12-single-file + +Examples: + + > tools/partest-ack 'case (class|object) Baz' + % testsWithMatchingPaths ... 0 + % testsWithMatchingCode ... 3 + # 3 tests to run. + + > tools/partest-ack -s 12.hours.ago + % testsTouchedSinceGitTime ... 33 + # 33 tests to run. + + > tools/partest-ack -p src/library/scala/Enumeration.scala + % testsModifiedInSameCommit ... 80 + # 80 tests to run. + + > tools/partest-ack -f + % tests-which-failed ... 42 + # 42 tests to run. + + > tools/partest-ack "kinds of the type arguments" + % testsWithMatchingPaths ... 0 + % testsWithMatchingCode ... 6 + # 6 tests to run. +EOM + + exit 0 +} + +while getopts :fuvdrp:s: opt; do + case $opt in + f) failed=true && partest_args+=" --failed" ;; + p) cotouched="$cotouched $OPTARG" ;; + r) sortCommand="randomSort" ;; + s) since="$OPTARG" ;; + q) partest_args+=" --terse" ;; + u) partest_args+=" --update-check" ;; + v) partest_args+=" --verbose" ;; + :) echo "Option -$OPTARG requires an argument." >&2 ;; + *) ack_args+="-$OPTARG" ;; # don't drop unknown args, assume they're for ack + esac +done + +shift $((OPTIND-1)) +ack_args=( "${ack_args[@]}" "$@" ) + +# These methods all just create paths which may or may not be tests +# all are filtered through partest-paths which limits the output to actual tests +regexPathTests () { find "$filesdir" | ack --noenv "$@"; } +failedTests () { for p in $(find "$filesdir" -name '*.log'); do p1=${p%.log} && p2=${p1%-*} && echo "$p2"; done; } +sinceTests() { git log --since="$@" --name-only --pretty="format:" -- "$filesdir"; } +regexCodeTests () { ack $standard_ack_args "$@" -- "$filesdir"; } +sameCommitTests() { for rev in $(git rev-list HEAD -- "$@"); do git --no-pager show --pretty="format:" --name-only "$rev" -- "$filesdir"; done; } + +countStdout () { + local -i count=0 + while read line; do + printf "$line\n" && count+=1 + done + + printf >&2 " $count\n" +} + +randomSort () { + sort -u | while read line; do echo "$RANDOM $line"; done | sort | sed -E 's/^[0-9]+ //' +} + +testRun () { + local description="$1" && shift + printf >&2 "%% tests %-25s ... " "$description" + "$@" | "$partestPaths" | countStdout | egrep -v '^[ ]*$' +} + +allMatches() { + [[ -n $ack_args ]] && testRun "with matching paths" regexPathTests "${ack_args[@]}" + [[ -n $ack_args ]] && testRun "with matching code" regexCodeTests "${ack_args[@]}" + [[ -n $cotouched ]] && testRun "modified in same commit" sameCommitTests $cotouched + [[ -n $since ]] && testRun "modified since time" sinceTests "$since" + [[ -n $failed ]] && testRun "failed on last run" failedTests +} + +paths=$(allMatches | $sortCommand) + +[[ -z $paths ]] && [[ -z $failed ]] && echo >&2 "No matching tests." && exit 0; + +count=$(echo $(echo "$paths" | wc -w)) +[[ "$count" -eq 0 ]] && echo >&2 "No tests to run." && exit 0; + +# Output a command line which will re-run these same tests. +echo "# $count tests to run." +printf "%-52s %s\n" "$base/test/partest ${partest_args[*]}" "\\" +for path in $paths; do printf " %-50s %s\n" "$path" "\\"; done +echo "" + +test/partest ${partest_args[*]} $paths |