1*055d4590SKeyi Gui#!/bin/bash 2*055d4590SKeyi Gui# 3*055d4590SKeyi Gui# Copyright (C) 2007 The Android Open Source Project 4*055d4590SKeyi Gui# 5*055d4590SKeyi Gui# Licensed under the Apache License, Version 2.0 (the "License"); 6*055d4590SKeyi Gui# you may not use this file except in compliance with the License. 7*055d4590SKeyi Gui# You may obtain a copy of the License at 8*055d4590SKeyi Gui# 9*055d4590SKeyi Gui# http://www.apache.org/licenses/LICENSE-2.0 10*055d4590SKeyi Gui# 11*055d4590SKeyi Gui# Unless required by applicable law or agreed to in writing, software 12*055d4590SKeyi Gui# distributed under the License is distributed on an "AS IS" BASIS, 13*055d4590SKeyi Gui# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*055d4590SKeyi Gui# See the License for the specific language governing permissions and 15*055d4590SKeyi Gui# limitations under the License. 16*055d4590SKeyi Gui 17*055d4590SKeyi Gui# Set up prog to be the path of this script, including following symlinks, 18*055d4590SKeyi Gui# and set up progdir to be the fully-qualified pathname of its directory. 19*055d4590SKeyi Guiprog="$0" 20*055d4590SKeyi Guiwhile [ -h "${prog}" ]; do 21*055d4590SKeyi Gui newProg=`/bin/ls -ld "${prog}"` 22*055d4590SKeyi Gui newProg=`expr "${newProg}" : ".* -> \(.*\)$"` 23*055d4590SKeyi Gui if expr "x${newProg}" : 'x/' >/dev/null; then 24*055d4590SKeyi Gui prog="${newProg}" 25*055d4590SKeyi Gui else 26*055d4590SKeyi Gui progdir=`dirname "${prog}"` 27*055d4590SKeyi Gui prog="${progdir}/${newProg}" 28*055d4590SKeyi Gui fi 29*055d4590SKeyi Guidone 30*055d4590SKeyi Guioldwd=`pwd` 31*055d4590SKeyi Guiprogdir=`dirname "${prog}"` 32*055d4590SKeyi Guicd "${progdir}" 33*055d4590SKeyi Guiprogdir=`pwd` 34*055d4590SKeyi Guiprog="${progdir}"/`basename "${prog}"` 35*055d4590SKeyi Gui 36*055d4590SKeyi Guiskip_tests="115-merge 127-merge-stress 129-numthread-deterministic 130-numthread-multidex-deterministic 143-interface-methods" 37*055d4590SKeyi Gui 38*055d4590SKeyi Gui# Command-line options 39*055d4590SKeyi Guisequential="no" 40*055d4590SKeyi Guiusage="no" 41*055d4590SKeyi Guiwhile [[ "$1" == "-"* ]]; do 42*055d4590SKeyi Gui case $1 in 43*055d4590SKeyi Gui --seq) sequential="yes" ;; 44*055d4590SKeyi Gui --skip) skip_tests="$2 $skip_tests" 45*055d4590SKeyi Gui shift ;; 46*055d4590SKeyi Gui *) usage="yes" ;; 47*055d4590SKeyi Gui esac 48*055d4590SKeyi Gui shift 49*055d4590SKeyi Guidone 50*055d4590SKeyi Gui 51*055d4590SKeyi Guiif [ $usage = "yes" ]; then 52*055d4590SKeyi Gui prog=`basename $prog` 53*055d4590SKeyi Gui cat 1>&2 <<END_USAGE 54*055d4590SKeyi GuiUsage: 55*055d4590SKeyi Gui $prog [options] Run all tests with given options. 56*055d4590SKeyi GuiOptions: 57*055d4590SKeyi Gui --seq Run tests sequentially (default: parallel) 58*055d4590SKeyi Gui --skip <test> Skip running specified test 59*055d4590SKeyi GuiEND_USAGE 60*055d4590SKeyi Gui exit 1 61*055d4590SKeyi Guifi 62*055d4590SKeyi Gui 63*055d4590SKeyi Gui# Globals for tracking numbers of successes and failures and their names. 64*055d4590SKeyi Guipassed=() 65*055d4590SKeyi Guisurprised=() 66*055d4590SKeyi Guiignored=() 67*055d4590SKeyi Guifailed=() 68*055d4590SKeyi Guiskipped=() 69*055d4590SKeyi Gui 70*055d4590SKeyi Gui# Tests failing and require attention (e.g. 115-merge) 71*055d4590SKeyi Guiknown_bad="100-local-mismatch 115-merge 119-merge-conflict" 72*055d4590SKeyi Gui 73*055d4590SKeyi Guifunction display_results { 74*055d4590SKeyi Gui printf "\n\nTest Results\n" 75*055d4590SKeyi Gui printf -- "----------------------------\n" 76*055d4590SKeyi Gui printf "Pass: % 4d\n" ${#passed[@]} 77*055d4590SKeyi Gui printf "Surprise pass: % 4d\n" ${#surprised[@]} 78*055d4590SKeyi Gui printf "Known failures: % 4d\n" ${#ignored[@]} 79*055d4590SKeyi Gui printf "Failures: % 4d\n" ${#failed[@]} 80*055d4590SKeyi Gui printf "Skipped: % 4d\n" ${#skipped[@]} 81*055d4590SKeyi Gui printf -- "----------------------------\n" 82*055d4590SKeyi Gui printf "Elapsed time(s): % 4d\n" $SECONDS 83*055d4590SKeyi Gui 84*055d4590SKeyi Gui list_files "Unexpected successes" ${surprised[@]} 85*055d4590SKeyi Gui list_files "Known failures" ${ignored[@]} 86*055d4590SKeyi Gui list_files "Failures" ${failed[@]} 87*055d4590SKeyi Gui list_files "Skipped" ${skipped[@]} 88*055d4590SKeyi Gui 89*055d4590SKeyi Gui needing_attention=$(( ${#failed[@]} + ${#surprised[@]} )) 90*055d4590SKeyi Gui exit ${needing_attention} 91*055d4590SKeyi Gui} 92*055d4590SKeyi Gui 93*055d4590SKeyi Guifunction list_files { 94*055d4590SKeyi Gui # Arguments: Title test_name0 test_name1 ... test_nameN 95*055d4590SKeyi Gui echo "$1:" 96*055d4590SKeyi Gui shift 97*055d4590SKeyi Gui if [[ "$1" = "" ]]; then 98*055d4590SKeyi Gui echo " NONE" 99*055d4590SKeyi Gui return 100*055d4590SKeyi Gui fi 101*055d4590SKeyi Gui while [[ "$1" != "" ]]; do 102*055d4590SKeyi Gui echo " $1" 103*055d4590SKeyi Gui shift 104*055d4590SKeyi Gui done 105*055d4590SKeyi Gui} 106*055d4590SKeyi Gui 107*055d4590SKeyi Guifunction update_result { 108*055d4590SKeyi Gui local -r test_name=$1 109*055d4590SKeyi Gui local -r output=$2 110*055d4590SKeyi Gui local -r result=$3 111*055d4590SKeyi Gui local expectFail 112*055d4590SKeyi Gui 113*055d4590SKeyi Gui if [[ "$known_bad" == *"$test_name"* ]]; then 114*055d4590SKeyi Gui expectFail=1 115*055d4590SKeyi Gui else 116*055d4590SKeyi Gui expectFail=0 117*055d4590SKeyi Gui fi 118*055d4590SKeyi Gui if [ $result = 0 ]; then 119*055d4590SKeyi Gui if [[ $expectFail = 0 ]]; then 120*055d4590SKeyi Gui passed+=(${test_name}) 121*055d4590SKeyi Gui else 122*055d4590SKeyi Gui echo "Failing on unexpected success of $test_name" 123*055d4590SKeyi Gui surprised+=(${test_name}) 124*055d4590SKeyi Gui fi 125*055d4590SKeyi Gui else 126*055d4590SKeyi Gui if [[ $expectFail = 0 ]]; then 127*055d4590SKeyi Gui failed+=(${test_name}) 128*055d4590SKeyi Gui else 129*055d4590SKeyi Gui echo "Ignoring expected failure of $test_name" 130*055d4590SKeyi Gui ignored+=(${test_name}) 131*055d4590SKeyi Gui # Clean up when we expect a test to fail. 132*055d4590SKeyi Gui # run-test only does this on success. 133*055d4590SKeyi Gui rm -rf "$output" 134*055d4590SKeyi Gui fi 135*055d4590SKeyi Gui fi 136*055d4590SKeyi Gui} 137*055d4590SKeyi Gui 138*055d4590SKeyi Guifunction run_one_test_with_flock { 139*055d4590SKeyi Gui local -r output_dir=$1 140*055d4590SKeyi Gui local -r test_name=$2 141*055d4590SKeyi Gui local -r lock_file=$3 142*055d4590SKeyi Gui 143*055d4590SKeyi Gui # Wait for the lock and run the test when acquired 144*055d4590SKeyi Gui flock "${lock_file}" ./run-test --output_dir "${output_dir}" "${test_name}" 145*055d4590SKeyi Gui} 146*055d4590SKeyi Gui 147*055d4590SKeyi Guifunction run_tests { 148*055d4590SKeyi Gui readonly test_root=$(mktemp -d) 149*055d4590SKeyi Gui trap "rm -rf ${test_root}" EXIT 150*055d4590SKeyi Gui if [[ "$sequential" = "yes" ]]; then 151*055d4590SKeyi Gui for test_name in *; do 152*055d4590SKeyi Gui if [[ "$skip_tests" = *"$test_name"* ]]; then 153*055d4590SKeyi Gui skipped+=(${test_name}) 154*055d4590SKeyi Gui continue 155*055d4590SKeyi Gui fi 156*055d4590SKeyi Gui if [ -d "$test_name" -a -r "$test_name" ]; then 157*055d4590SKeyi Gui output="${test_root}/${test_name}" 158*055d4590SKeyi Gui ./run-test --output_dir "${output}" "${test_name}" 159*055d4590SKeyi Gui update_result "${test_name}" "${output}" $? 160*055d4590SKeyi Gui fi 161*055d4590SKeyi Gui done 162*055d4590SKeyi Gui else 163*055d4590SKeyi Gui readonly num_workers=4 164*055d4590SKeyi Gui local i=0 165*055d4590SKeyi Gui for test_name in *; do 166*055d4590SKeyi Gui if [[ "$skip_tests" = *"$test_name"* ]]; then 167*055d4590SKeyi Gui skipped+=(${test_name}) 168*055d4590SKeyi Gui continue 169*055d4590SKeyi Gui fi 170*055d4590SKeyi Gui local lock_file=${test_root}/lock.$((i % num_workers)) 171*055d4590SKeyi Gui if [ -d "${test_name}" -a -r "${test_name}" ]; then 172*055d4590SKeyi Gui output="${test_root}/${test_name}" 173*055d4590SKeyi Gui run_one_test_with_flock "$output" "$test_name" "$lock_file" & 174*055d4590SKeyi Gui test_pids[i]=$! 175*055d4590SKeyi Gui test_names[test_pids[i]]="$test_name" 176*055d4590SKeyi Gui test_outputs[test_pids[i]]="output" 177*055d4590SKeyi Gui let i+=1 178*055d4590SKeyi Gui fi 179*055d4590SKeyi Gui done 180*055d4590SKeyi Gui 181*055d4590SKeyi Gui for pid in ${test_pids[@]}; do 182*055d4590SKeyi Gui wait $pid 183*055d4590SKeyi Gui update_result ${test_names[$pid]} ${test_outputs[$pid]} $? 184*055d4590SKeyi Gui done 185*055d4590SKeyi Gui fi 186*055d4590SKeyi Gui} 187*055d4590SKeyi Gui 188*055d4590SKeyi Guifunction handle_interrupt { 189*055d4590SKeyi Gui trap INT 190*055d4590SKeyi Gui display_results 191*055d4590SKeyi Gui if [ ! -z "${test_pids}" ]; then 192*055d4590SKeyi Gui killall ${test_pids} 193*055d4590SKeyi Gui fi 194*055d4590SKeyi Gui} 195*055d4590SKeyi Gui 196*055d4590SKeyi Guitrap handle_interrupt INT 197*055d4590SKeyi Guirun_tests 198*055d4590SKeyi Guidisplay_results 199