#!/usr/bin/env bash # Usage: script/test [file] [adapter]... -- [test/unit options] # Runs the test suite against a local server spawned automatically in a # thread. After tests are done, the server is shut down. # # If filename arguments are given, only those files are run. If arguments given # are not filenames, they are taken as words that filter the list of files to run. # # Examples: # # $ script/test # $ script/test test/env_test.rb # $ script/test excon typhoeus # # # Run only tests matching /ssl/ for the net_http adapter, with SSL enabled. # $ SSL=yes script/test net_http -- -n /ssl/ # # # Run against multiple rbenv versions # $ RBENV_VERSIONS="1.9.3-p194 ree-1.8.7-2012.02" script/test set -e if [[ "$RUBYOPT" != *"bundler/setup"* ]]; then export RUBYOPT="-rbundler/setup $RUBYOPT" fi port=3999 proxy_port=3998 scheme=http if [ "$SSL" = "yes" ]; then scheme=https if [ -z "$SSL_KEY" ] || [ -z "$SSL_FILE" ]; then eval "$(script/generate_certs -s)" fi fi find_test_files() { find "$1" -name '*_test.rb' } filter_matching() { pattern="$1" shift for line in "$@"; do [[ $line == *"$pattern"* ]] && echo "$line" done } start_server() { mkdir -p log script/server -p $port >log/test.log 2>&1 & echo $! } start_proxy() { mkdir -p log script/proxy-server -p $proxy_port -u "faraday@test.local:there is cake" >log/proxy.log 2>&1 & echo $! } server_started() { lsof -i :${1?} >/dev/null } timestamp() { date +%s } wait_for_server() { timeout=$(( `timestamp` + $1 )) while true; do if server_started "$2"; then break elif [ `timestamp` -gt "$timeout" ]; then echo "timed out after $1 seconds" >&2 return 1 fi done } filtered= IFS=$'\n' test_files=($(find_test_files "test")) declare -a explicit_files # Process filter arguments: # - test filenames as taken as-is # - other words are taken as pattern to match the list of known files against # - arguments after "--" are forwarded to the ruby process while [ $# -gt 0 ]; do arg="$1" shift if [ "$arg" = "--" ]; then break elif [ -f "$arg" ]; then filtered=true explicit_files[${#explicit_files[@]}+1]="$arg" else filtered=true IFS=$'\n' explicit_files=( ${explicit_files[@]} $(filter_matching "$arg" "${test_files[@]}" || true) ) fi done # If there were filter args, replace test files list with the results if [ -n "$filtered" ]; then if [ ${#explicit_files[@]} -eq 0 ]; then echo "Error: no test files match" >&2 exit 1 else test_files=(${explicit_files[@]}) echo running "${test_files[@]}" fi fi # If there are any adapter tests, spin up the HTTP server if [ -n "$(filter_matching "adapters" "${test_files[@]}")" ]; then if server_started $port; then echo "aborted: another instance of server running on $port" >&2 exit 1 fi server_pid=$(start_server) proxy_pid=$(start_proxy) wait_for_server 30 $port || { cat log/test.log kill "$server_pid" kill "$proxy_pid" exit 1 } wait_for_server 5 $proxy_port cleanup() { if [ $? -ne 0 ] && [ -n "$TRAVIS" ]; then cat log/test.log fi kill "$server_pid" kill "$proxy_pid" } trap cleanup INT EXIT export LIVE="${scheme}://localhost:${port}" export LIVE_PROXY="http://faraday%40test.local:there%20is%20cake@localhost:${proxy_port}" fi warnings="${TMPDIR:-/tmp}/faraday-warnings.$$" run_test_files() { # Save warnings on stderr to a separate file RUBYOPT="$RUBYOPT -w" ruby -e 'while f=ARGV.shift and f!="--"; load f; end' "${test_files[@]}" -- "$@" \ 2> >(tee >(grep 'warning:' >"$warnings") | grep -v 'warning:') } check_warnings() { # Display Ruby warnings from this project's source files. Abort if any were found. num="$(grep -F "$PWD" "$warnings" | grep -v "${PWD}/bundle" | sort | uniq -c | sort -rn | tee /dev/stderr | wc -l)" rm -f "$warnings" if [ "$num" -gt 0 ]; then echo "FAILED: this test suite doesn't tolerate Ruby syntax warnings!" >&2 exit 1 fi } if [ -n "$RBENV_VERSIONS" ]; then IFS=' ' versions=($RBENV_VERSIONS) for version in "${versions[@]}"; do echo "[${version}]" RBENV_VERSION="$version" run_test_files "$@" done else run_test_files "$@" fi check_warnings