Clean up and exit on SIGINT.
[arvados-dev.git] / jenkins / run-tests.sh
index 612f208ad8ea6275512cf49587af9a6349f0e3f7..b87a7f5b4e81f01c436e9530c6d912df1490d805 100755 (executable)
@@ -20,11 +20,12 @@ Options:
                from a previous invocation if you use this option.
 WORKSPACE=path Arvados source tree to test.
 CONFIGSRC=path Dir with api server config files to copy into source tree.
                from a previous invocation if you use this option.
 WORKSPACE=path Arvados source tree to test.
 CONFIGSRC=path Dir with api server config files to copy into source tree.
-apiserver_test="TEST=test/functional/arvados/v1/collections_test.rb"
+               (If none given, leave config files alone in source tree.)
+services/api_test="TEST=test/functional/arvados/v1/collections_controller_test.rb"
                Restrict apiserver tests to the given file
                Restrict apiserver tests to the given file
-python_sdk_test="--test-suite test.test_keep_locator"
+sdk/python_test="--test-suite test.test_keep_locator"
                Restrict Python SDK tests to the given class
                Restrict Python SDK tests to the given class
-workbench_test="TEST=test/integration/pipeline_instances_test.rb"
+apps/workbench_test="TEST=test/integration/pipeline_instances_test.rb"
                Restrict Workbench tests to the given file
 ARVADOS_DEBUG=1
                Print more debug messages
                Restrict Workbench tests to the given file
 ARVADOS_DEBUG=1
                Print more debug messages
@@ -36,9 +37,32 @@ into \$GOPATH, \$VENDIR, and \$GEMHOME before running any tests. Many
 test suites depend on other components being installed, and installing
 everything tends to be quicker than debugging dependencies.
 
 test suites depend on other components being installed, and installing
 everything tends to be quicker than debugging dependencies.
 
+As a special concession to the current CI server config, CONFIGSRC
+defaults to $HOME/arvados-api-server if that directory exists.
+
 More information and background:
 
 https://arvados.org/projects/arvados/wiki/Running_tests
 More information and background:
 
 https://arvados.org/projects/arvados/wiki/Running_tests
+
+Available tests:
+
+apps/workbench
+apps/workbench_benchmark
+apps/workbench_profile
+doc
+services/api
+services/crunchstat
+services/fuse
+services/keepproxy
+services/keepstore
+services/nodemanager
+sdk/cli
+sdk/python
+sdk/ruby
+sdk/go/arvadosclient
+sdk/go/keepclient
+sdk/go/streamer
+
 EOF
 
 # First make sure to remove any ARVADOS_ variables from the calling
 EOF
 
 # First make sure to remove any ARVADOS_ variables from the calling
@@ -55,20 +79,9 @@ GEMHOME=
 
 COLUMNS=80
 
 
 COLUMNS=80
 
-cli_test=
-workbench_test=
-apiserver_test=
-python_sdk_test=
-ruby_sdk_test=
-fuse_test=
 leave_temp=
 skip_install=
 
 leave_temp=
 skip_install=
 
-if [[ -f /etc/profile.d/rvm.sh ]]
-then
-    source /etc/profile.d/rvm.sh
-fi
-
 declare -A leave_temp
 clear_temp() {
     leaving=""
 declare -A leave_temp
 clear_temp() {
     leaving=""
@@ -84,7 +97,7 @@ clear_temp() {
             leaving+=" $var=\"${!var}\""
         fi
     done
             leaving+=" $var=\"${!var}\""
         fi
     done
-    if [[ -z "$leaving" ]]; then
+    if [[ -n "$leaving" ]]; then
         echo "Leaving behind temp dirs: $leaving"
     fi
 }
         echo "Leaving behind temp dirs: $leaving"
     fi
 }
@@ -112,11 +125,71 @@ report_outcomes() {
         done
     fi
 }
         done
     fi
 }
+
+exit_cleanly() {
+    trap - INT
+    rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
+    stop_api
+    rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
+    report_outcomes
+    clear_temp
+    exit ${#failures}
+}
+
+sanity_checks() {
+  # Make sure WORKSPACE is set
+  if ! [[ -n "$WORKSPACE" ]]; then
+    echo >&2 "$helpmessage"
+    echo >&2
+    echo >&2 "Error: WORKSPACE environment variable not set"
+    echo >&2
+    exit 1
+  fi
+
+  # Make sure virtualenv is installed
+  `virtualenv --help >/dev/null 2>&1`
+
+  if [[ "$?" != "0" ]]; then
+    echo >&2
+    echo >&2 "Error: virtualenv could not be found"
+    echo >&2
+    exit 1
+  fi
+
+  # Make sure go is installed
+  `go env >/dev/null 2>&1`
+
+  if [[ "$?" != "0" ]]; then
+    echo >&2
+    echo >&2 "Error: go could not be found"
+    echo >&2
+    exit 1
+  fi
+
+  # Make sure gcc is installed
+  `gcc --help >/dev/null 2>&1`
+
+  if [[ "$?" != "0" ]]; then
+    echo >&2
+    echo >&2 "Error: gcc could not be found"
+    echo >&2
+    exit 1
+  fi
+}
+
+rotate_logfile() {
+  # $BUILD_NUMBER is set by Jenkins if this script is being called as part of a Jenkins run
+  if [[ -f "$1/$2" ]]; then
+    THEDATE=`date +%Y%m%d%H%M%S`
+    mv "$1/$2" "$1/$THEDATE-$BUILD_NUMBER-$2"
+    gzip "$1/$THEDATE-$BUILD_NUMBER-$2"
+  fi
+}
+
 declare -a failures
 declare -A skip
 declare -a failures
 declare -A skip
-
-# Always skip CLI tests. They don't know how to use run_test_server.py.
-skip[cli]=1
+declare -A testargs
+skip[apps/workbench_profile]=1
 
 while [[ -n "$1" ]]
 do
 
 while [[ -n "$1" ]]
 do
@@ -132,7 +205,7 @@ do
             skip[$skipwhat]=1
             ;;
         --only)
             skip[$skipwhat]=1
             ;;
         --only)
-            only="$1"; shift
+            only="$1"; skip[$1]=""; shift
             ;;
         --skip-install)
             skip_install=1
             ;;
         --skip-install)
             skip_install=1
@@ -142,8 +215,13 @@ do
             leave_temp[GOPATH]=1
             leave_temp[GEMHOME]=1
             ;;
             leave_temp[GOPATH]=1
             leave_temp[GEMHOME]=1
             ;;
+        *_test=*)
+            suite="${arg%%_test=*}"
+            args="${arg#*=}"
+            testargs["$suite"]="$args"
+            ;;
         *=*)
         *=*)
-            eval $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
+            eval export $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
             ;;
         *)
             echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
             ;;
         *)
             echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
@@ -152,17 +230,42 @@ do
     esac
 done
 
     esac
 done
 
-# Sanity check
-echo "WORKSPACE=$WORKSPACE"
-[[ -n "$WORKSPACE" ]] || fatal "WORKSPACE not set"
+start_api() {
+    echo 'Starting API server...'
+    cd "$WORKSPACE" \
+        && eval $(python sdk/python/tests/run_test_server.py start --auth admin) \
+        && export ARVADOS_TEST_API_HOST="$ARVADOS_API_HOST" \
+        && export ARVADOS_TEST_API_INSTALLED="$$" \
+        && (env | egrep ^ARVADOS)
+}
 
 
-if [[ -n "$CONFIGSRC" ]]; then
-    if [[ -d "$HOME/arvados-api-server" ]]; then
-        # Jenkins expects us to use this by default.
-        CONFIGSRC="$HOME/arvados-api-server"
+stop_api() {
+    if [[ -n "$ARVADOS_TEST_API_HOST" ]]; then
+        unset ARVADOS_TEST_API_HOST
+        cd "$WORKSPACE" \
+            && python sdk/python/tests/run_test_server.py stop
     fi
     fi
+}
+
+interrupt() {
+    failures+=("($(basename $0) interrupted)")
+    exit_cleanly
+}
+trap interrupt INT
+
+sanity_checks
+
+echo "WORKSPACE=$WORKSPACE"
+
+if [[ -z "$CONFIGSRC" ]] && [[ -d "$HOME/arvados-api-server" ]]; then
+    # Jenkins expects us to use this by default.
+    CONFIGSRC="$HOME/arvados-api-server"
 fi
 
 fi
 
+# Clean up .pyc files that may exist in the workspace
+cd "$WORKSPACE"
+find -name '*.pyc' -delete
+
 # Set up temporary install dirs (unless existing dirs were supplied)
 for tmpdir in VENVDIR GOPATH GEMHOME
 do
 # Set up temporary install dirs (unless existing dirs were supplied)
 for tmpdir in VENVDIR GOPATH GEMHOME
 do
@@ -172,14 +275,98 @@ do
         eval $tmpdir=$(mktemp -d)
     fi
 done
         eval $tmpdir=$(mktemp -d)
     fi
 done
-PATH="$GEMHOME/.gem/ruby/2.1.0/bin:$PATH"
+
+setup_ruby_environment() {
+    if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
+      source "$HOME/.rvm/scripts/rvm"
+      using_rvm=true
+    elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
+      source "/usr/local/rvm/scripts/rvm"
+      using_rvm=true
+    else
+      using_rvm=false
+    fi
+
+    if [[ "$using_rvm" == true ]]; then
+        # If rvm is in use, we can't just put separate "dependencies"
+        # and "gems-under-test" paths to GEM_PATH: passenger resets
+        # the environment to the "current gemset", which would lose
+        # our GEM_PATH and prevent our test suites from running ruby
+        # programs (for example, the Workbench test suite could not
+        # boot an API server or run arv). Instead, we have to make an
+        # rvm gemset and use it for everything.
+
+        [[ `type rvm | head -n1` == "rvm is a function" ]] \
+            || fatal 'rvm check'
+
+        # Put rvm's favorite path back in first place (overriding
+        # virtualenv, which just put itself there). Ignore rvm's
+        # complaint about not being in first place already.
+        rvm use @default 2>/dev/null
+
+        # Create (if needed) and switch to an @arvados-tests
+        # gemset. (Leave the choice of ruby to the caller.)
+        rvm use @arvados-tests --create \
+            || fatal 'rvm gemset setup'
+
+        rvm env
+    else
+        # When our "bundle install"s need to install new gems to
+        # satisfy dependencies, we want them to go where "gem install
+        # --user-install" would put them. (However, if the caller has
+        # already set GEM_HOME, we assume that's where dependencies
+        # should be installed, and we should leave it alone.)
+
+        if [ -z "$GEM_HOME" ]; then
+            user_gempath="$(gem env gempath)"
+            export GEM_HOME="${user_gempath%%:*}"
+        fi
+        PATH="$(gem env gemdir)/bin:$PATH"
+
+        # When we build and install our own gems, we install them in our
+        # $GEMHOME tmpdir, and we want them to be at the front of GEM_PATH and
+        # PATH so integration tests prefer them over other versions that
+        # happen to be installed in $user_gempath, system dirs, etc.
+
+        tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
+        PATH="$tmpdir_gem_home/bin:$PATH"
+        export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
+
+        echo "Will install dependencies to $(gem env gemdir)"
+        echo "Will install arvados gems to $tmpdir_gem_home"
+        echo "Gem search path is GEM_PATH=$GEM_PATH"
+    fi
+}
+
+with_test_gemset() {
+    if [[ "$using_rvm" == true ]]; then
+        "$@"
+    else
+        GEM_HOME="$tmpdir_gem_home" "$@"
+    fi
+}
+
 export GOPATH
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
     || fatal "symlink failed"
 
 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
 export GOPATH
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
     || fatal "symlink failed"
 
 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
-PATH="$VENVDIR/bin:$PATH"
+. "$VENVDIR/bin/activate"
+
+# Note: this must be the last time we change PATH, otherwise rvm will
+# whine a lot.
+setup_ruby_environment
+
+echo "PATH is $PATH"
+
+if ! which bundler >/dev/null
+then
+    gem install --user-install bundler || fatal 'Could not install bundler'
+fi
+
+# Needed for run_test_server.py which is used by certain (non-Python) tests.
+pip install PyYAML || fatal "pip install PyYAML failed"
 
 checkexit() {
     if [[ "$?" != "0" ]]; then
 
 checkexit() {
     if [[ "$?" != "0" ]]; then
@@ -205,7 +392,14 @@ do_test() {
         timer_reset
         if [[ "$2" == "go" ]]
         then
         timer_reset
         if [[ "$2" == "go" ]]
         then
-            go test "git.curoverse.com/arvados.git/$1"
+            go test ${testargs[$1]} "git.curoverse.com/arvados.git/$1"
+        elif [[ "$2" == "pip" ]]
+        then
+           cd "$WORKSPACE/$1" \
+                && python setup.py test ${testargs[$1]}
+        elif [[ "$2" != "" ]]
+        then
+            "test_$2"
         else
             "test_$1"
         fi
         else
             "test_$1"
         fi
@@ -224,6 +418,14 @@ do_install() {
         if [[ "$2" == "go" ]]
         then
             go get -t "git.curoverse.com/arvados.git/$1"
         if [[ "$2" == "go" ]]
         then
             go get -t "git.curoverse.com/arvados.git/$1"
+        elif [[ "$2" == "pip" ]]
+        then
+            cd "$WORKSPACE/$1" \
+                && python setup.py sdist rotate --keep=1 --match .tar.gz \
+                && pip install --upgrade dist/*.tar.gz
+        elif [[ "$2" != "" ]]
+        then
+            "install_$2"
         else
             "install_$1"
         fi
         else
             "install_$1"
         fi
@@ -239,56 +441,62 @@ title () {
     printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
 }
 
     printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
 }
 
-install_docs() {
-    cd "$WORKSPACE/doc"
-    HOME="$GEMHOME" bundle install --no-deployment
-    rm -rf .site
-    # Make sure python-epydoc is installed or the next line won't do much good!
-    ARVADOS_API_HOST=qr1hi.arvadosapi.com
-    PYTHONPATH=$WORKSPACE/sdk/python/ HOME="$GEMHOME" bundle exec rake generate baseurl=file://$WORKSPACE/doc/.site/ arvados_workbench_host=workbench.$ARVADOS_API_HOST arvados_api_host=$ARVADOS_API_HOST
-    unset ARVADOS_API_HOST
+bundle_install_trylocal() {
+    (
+        set -e
+        echo "(Running bundle install --local. 'could not find package' messages are OK.)"
+        if ! bundle install --local --no-deployment; then
+            echo "(Running bundle install again, without --local.)"
+            bundle install --no-deployment
+        fi
+        bundle package --all
+    )
+}
+
+install_doc() {
+    cd "$WORKSPACE/doc" \
+        && bundle_install_trylocal \
+        && rm -rf .site
 }
 }
-do_install docs
+do_install doc
 
 install_ruby_sdk() {
 
 install_ruby_sdk() {
-    cd "$WORKSPACE/sdk/ruby" \
-        && HOME="$GEMHOME" bundle install --no-deployment \
+    with_test_gemset gem uninstall --force --all --executables arvados \
+        && cd "$WORKSPACE/sdk/ruby" \
+        && bundle_install_trylocal \
         && gem build arvados.gemspec \
         && gem build arvados.gemspec \
-        && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
+        && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
 }
 }
-do_install ruby_sdk
+do_install sdk/ruby ruby_sdk
 
 install_cli() {
 
 install_cli() {
-    cd "$WORKSPACE/sdk/cli" \
+    with_test_gemset gem uninstall --force --all --executables arvados-cli \
+        && cd "$WORKSPACE/sdk/cli" \
+        && bundle_install_trylocal \
         && gem build arvados-cli.gemspec \
         && gem build arvados-cli.gemspec \
-        && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
-}
-do_install cli
-
-install_python_sdk() {
-    # Install the Python SDK early. Various other test suites (like
-    # keepproxy) bring up run_test_server.py, which imports the arvados
-    # module. We can't actually *test* the Python SDK yet though, because
-    # its own test suite brings up some of those other programs (like
-    # keepproxy).
-
-    cd "$WORKSPACE/sdk/python" \
-        && python setup.py egg_info -b ".$(git log --first-parent --format=format:%ct.%h -n1 . | cut -c 1-4,6-7,9-10,12-13,15-16,18-19,26-33)" sdist rotate --keep=1 --match .tar.gz \
-        && pip install dist/arvados-python-client-0.1.*.tar.gz
+        && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
 }
 }
-do_install python_sdk
-
-install_fuse() {
-    cd "$WORKSPACE/services/fuse" \
-        && python setup.py egg_info -b ".$(git log --format=format:%ct.%h -n1 .)" sdist rotate --keep=1 --match .tar.gz \
-        && pip install dist/arvados_fuse-0.1.*.tar.gz
-}
-do_install fuse
+do_install sdk/cli cli
+
+# Install the Python SDK early. Various other test suites (like
+# keepproxy) bring up run_test_server.py, which imports the arvados
+# module. We can't actually *test* the Python SDK yet though, because
+# its own test suite brings up some of those other programs (like
+# keepproxy).
+declare -a pythonstuff
+pythonstuff=(
+    sdk/python
+    services/fuse
+    services/nodemanager
+    )
+for p in "${pythonstuff[@]}"
+do
+    do_install "$p" pip
+done
 
 install_apiserver() {
 
 install_apiserver() {
-    cd "$WORKSPACE/services/api"
-    export RAILS_ENV=test
-    HOME="$GEMHOME" bundle install --no-deployment
+    cd "$WORKSPACE/services/api" \
+        && RAILS_ENV=test bundle_install_trylocal
 
     rm -f config/environments/test.rb
     cp config/environments/test.rb.example config/environments/test.rb
 
     rm -f config/environments/test.rb
     cp config/environments/test.rb.example config/environments/test.rb
@@ -327,14 +535,15 @@ install_apiserver() {
     psql arvados_test -c "SELECT pg_terminate_backend (pg_stat_activity.procpid::int) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'arvados_test';" 2>/dev/null
 
     cd "$WORKSPACE/services/api" \
     psql arvados_test -c "SELECT pg_terminate_backend (pg_stat_activity.procpid::int) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'arvados_test';" 2>/dev/null
 
     cd "$WORKSPACE/services/api" \
-        && HOME="$GEMHOME" bundle exec rake db:drop \
-        && HOME="$GEMHOME" bundle exec rake db:create \
-        && HOME="$GEMHOME" bundle exec rake db:setup
+        && RAILS_ENV=test bundle exec rake db:drop \
+        && RAILS_ENV=test bundle exec rake db:setup \
+        && RAILS_ENV=test bundle exec rake db:fixtures:load
 }
 }
-do_install apiserver
+do_install services/api apiserver
 
 declare -a gostuff
 gostuff=(
 
 declare -a gostuff
 gostuff=(
+    services/crunchstat
     services/keepstore
     services/keepproxy
     sdk/go/arvadosclient
     services/keepstore
     services/keepproxy
     sdk/go/arvadosclient
@@ -346,58 +555,52 @@ do
     do_install "$g" go
 done
 
     do_install "$g" go
 done
 
+install_workbench() {
+    cd "$WORKSPACE/apps/workbench" \
+        && mkdir -p tmp/cache \
+        && RAILS_ENV=test bundle_install_trylocal
+}
+do_install apps/workbench workbench
+
 test_doclinkchecker() {
 test_doclinkchecker() {
-    cd "$WORKSPACE/doc"
-    HOME="$GEMHOME" bundle exec rake linkchecker baseurl=file://$WORKSPACE/doc/.site/
+    (
+        set -e
+        cd "$WORKSPACE/doc"
+        ARVADOS_API_HOST=qr1hi.arvadosapi.com
+        # Make sure python-epydoc is installed or the next line won't
+        # do much good!
+        PYTHONPATH=$WORKSPACE/sdk/python/ bundle exec rake linkchecker baseurl=file://$WORKSPACE/doc/.site/ arvados_workbench_host=workbench.$ARVADOS_API_HOST arvados_api_host=$ARVADOS_API_HOST
+    )
+}
+do_test doc doclinkchecker
+
+stop_api
+
+test_apiserver() {
+    cd "$WORKSPACE/services/api" \
+        && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[services/api]}
 }
 }
-do_test doclinkchecker
+do_test services/api apiserver
+
+start_api
 
 test_ruby_sdk() {
     cd "$WORKSPACE/sdk/ruby" \
 
 test_ruby_sdk() {
     cd "$WORKSPACE/sdk/ruby" \
-        && HOME="$GEMHOME" bundle install --no-deployment \
-        && HOME="$GEMHOME" bundle exec rake test
+        && bundle exec rake test TESTOPTS=-v ${testargs[sdk/ruby]}
 }
 }
-do_test ruby_sdk
+do_test sdk/ruby ruby_sdk
 
 test_cli() {
 
 test_cli() {
-    title "Starting SDK CLI tests"
     cd "$WORKSPACE/sdk/cli" \
     cd "$WORKSPACE/sdk/cli" \
-        && HOME="$GEMHOME" bundle install --no-deployment \
         && mkdir -p /tmp/keep \
         && mkdir -p /tmp/keep \
-        && KEEP_LOCAL_STORE=/tmp/keep HOME="$GEMHOME" bundle exec rake test $cli_test
+        && KEEP_LOCAL_STORE=/tmp/keep bundle exec rake test TESTOPTS=-v ${testargs[sdk/cli]}
 }
 }
-do_test cli
+do_test sdk/cli cli
 
 
-test_apiserver() {
-    cd "$WORKSPACE/services/api"
-    HOME="$GEMHOME" bundle exec rake test $apiserver_test
-}
-do_test apiserver
-
-test_python_sdk() {
-    # Python SDK. We test this before testing keepproxy: keepproxy runs
-    # run_test_server.py, which depends on the yaml package, which is in
-    # tests_require but not install_requires, and therefore does not get
-    # installed by setuptools until we run "setup.py test" *and* install
-    # the .egg files that setup.py downloads.
-
-    cd "$WORKSPACE/sdk/python" \
-        && python setup.py test $python_sdk_test
-    r=$?
-    easy_install *.egg
-    return $r
-}
-do_test python_sdk
-
-test_fuse() {
-    # Install test dependencies here too, in case run_test_server needs them.
-    cd "$WORKSPACE/services/fuse" \
-        && python setup.py test $fuse_test
-    r=$?
-    easy_install *.egg
-    return $r
-}
-do_test fuse
+for p in "${pythonstuff[@]}"
+do
+    do_test "$p" pip
+done
 
 for g in "${gostuff[@]}"
 do
 
 for g in "${gostuff[@]}"
 do
@@ -406,12 +609,20 @@ done
 
 test_workbench() {
     cd "$WORKSPACE/apps/workbench" \
 
 test_workbench() {
     cd "$WORKSPACE/apps/workbench" \
-        && HOME="$GEMHOME" bundle install --no-deployment \
-        && HOME="$GEMHOME" bundle exec rake test $workbench_test
+        && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[apps/workbench]}
+}
+do_test apps/workbench workbench
+
+test_workbench_benchmark() {
+    cd "$WORKSPACE/apps/workbench" \
+        && RAILS_ENV=test bundle exec rake test:benchmark ${testargs[apps/workbench_benchmark]}
 }
 }
-do_test workbench
+do_test apps/workbench_benchmark workbench_benchmark
 
 
-report_outcomes
-clear_temp
+test_workbench_profile() {
+    cd "$WORKSPACE/apps/workbench" \
+        && RAILS_ENV=test bundle exec rake test:profile ${testargs[apps/workbench_profile]}
+}
+do_test apps/workbench_profile workbench_profile
 
 
-exit ${#failures}
+exit_cleanly