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