3 read -rd "\000" helpmessage <<EOF
4 $(basename $0): Install and test Arvados components.
6 Exit non-zero if any tests fail.
9 $(basename $0) WORKSPACE=/path/to/arvados [options]
13 --skip FOO Do not test the FOO component.
14 --only FOO Do not test anything except the FOO component.
15 --leave-temp Do not remove GOPATH, virtualenv, and other temp dirs at exit.
16 Instead, show which directories were used this time so they
17 can be reused in subsequent invocations.
18 --skip-install Do not run any install steps. Just run tests.
19 You should provide GOPATH, GEMHOME, and VENVDIR options
20 from a previous invocation if you use this option.
21 --only-install Run specific install step
22 WORKSPACE=path Arvados source tree to test.
23 CONFIGSRC=path Dir with api server config files to copy into source tree.
24 (If none given, leave config files alone in source tree.)
25 services/api_test="TEST=test/functional/arvados/v1/collections_controller_test.rb"
26 Restrict apiserver tests to the given file
27 sdk/python_test="--test-suite test.test_keep_locator"
28 Restrict Python SDK tests to the given class
29 apps/workbench_test="TEST=test/integration/pipeline_instances_test.rb"
30 Restrict Workbench tests to the given file
31 services/arv-git-httpd_test="-check.vv"
32 Show all log messages, even when tests pass (also works
33 with services/keepstore_test etc.)
35 Print more debug messages
36 envvar=value Set \$envvar to value. Primarily useful for WORKSPACE,
37 *_test, and other examples shown above.
39 Assuming --skip-install is not given, all components are installed
40 into \$GOPATH, \$VENDIR, and \$GEMHOME before running any tests. Many
41 test suites depend on other components being installed, and installing
42 everything tends to be quicker than debugging dependencies.
44 As a special concession to the current CI server config, CONFIGSRC
45 defaults to $HOME/arvados-api-server if that directory exists.
47 More information and background:
49 https://arvados.org/projects/arvados/wiki/Running_tests
54 apps/workbench_benchmark
55 apps/workbench_profile
63 services/arv-git-httpd
73 # First make sure to remove any ARVADOS_ variables from the calling
74 # environment that could interfere with the tests.
75 unset $(env | cut -d= -f1 | grep \^ARVADOS_)
77 # Reset other variables that could affect our [tests'] behavior by
93 for var in VENVDIR GOPATH GITDIR GEMHOME
95 if [[ -z "${leave_temp[$var]}" ]]
102 leaving+=" $var=\"${!var}\""
105 if [[ -n "$leaving" ]]; then
106 echo "Leaving behind temp dirs: $leaving"
112 echo >&2 "Fatal: $* in ${FUNCNAME[1]} at ${BASH_SOURCE[1]} line ${BASH_LINENO[0]}"
117 for x in "${successes[@]}"
122 if [[ ${#failures[@]} == 0 ]]
124 echo "All test suites passed."
126 echo "Failures (${#failures[@]}):"
127 for x in "${failures[@]}"
136 rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
138 rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
145 # Make sure WORKSPACE is set
146 if ! [[ -n "$WORKSPACE" ]]; then
147 echo >&2 "$helpmessage"
149 echo >&2 "Error: WORKSPACE environment variable not set"
154 # Make sure virtualenv is installed
155 `virtualenv --help >/dev/null 2>&1`
157 if [[ "$?" != "0" ]]; then
159 echo >&2 "Error: virtualenv could not be found"
164 # Make sure go is installed
165 `go env >/dev/null 2>&1`
167 if [[ "$?" != "0" ]]; then
169 echo >&2 "Error: go could not be found"
174 # Make sure gcc is installed
175 `gcc --help >/dev/null 2>&1`
177 if [[ "$?" != "0" ]]; then
179 echo >&2 "Error: gcc could not be found"
186 # $BUILD_NUMBER is set by Jenkins if this script is being called as part of a Jenkins run
187 if [[ -f "$1/$2" ]]; then
188 THEDATE=`date +%Y%m%d%H%M%S`
189 mv "$1/$2" "$1/$THEDATE-$BUILD_NUMBER-$2"
190 gzip "$1/$THEDATE-$BUILD_NUMBER-$2"
197 skip[apps/workbench_profile]=1
204 echo >&2 "$helpmessage"
213 only="$1"; skip[$1]=""; shift
220 only_install="$1"; shift
223 leave_temp[VENVDIR]=1
225 leave_temp[GEMHOME]=1
231 suite="${arg%%_test=*}"
233 testargs["$suite"]="$args"
236 eval export $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
239 echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
246 echo 'Starting API server...'
248 && eval $(python sdk/python/tests/run_test_server.py start --auth admin) \
249 && export ARVADOS_TEST_API_HOST="$ARVADOS_API_HOST" \
250 && export ARVADOS_TEST_API_INSTALLED="$$" \
251 && (env | egrep ^ARVADOS)
254 start_nginx_proxy_services() {
255 echo 'Starting keepproxy, arv-git-httpd, and nginx ssl proxy...'
257 && python sdk/python/tests/run_test_server.py start_keep_proxy \
258 && python sdk/python/tests/run_test_server.py start_arv-git-httpd \
259 && python sdk/python/tests/run_test_server.py start_nginx \
260 && export ARVADOS_TEST_PROXY_SERVICES=1
264 if [[ -n "$ARVADOS_TEST_PROXY_SERVICES" ]]; then
265 unset ARVADOS_TEST_PROXY_SERVICES
267 && python sdk/python/tests/run_test_server.py stop_nginx \
268 && python sdk/python/tests/run_test_server.py stop_arv-git-httpd \
269 && python sdk/python/tests/run_test_server.py stop_keep_proxy
271 if [[ -n "$ARVADOS_TEST_API_HOST" ]]; then
272 unset ARVADOS_TEST_API_HOST
274 && python sdk/python/tests/run_test_server.py stop
279 failures+=("($(basename $0) interrupted)")
286 echo "WORKSPACE=$WORKSPACE"
288 if [[ -z "$CONFIGSRC" ]] && [[ -d "$HOME/arvados-api-server" ]]; then
289 # Jenkins expects us to use this by default.
290 CONFIGSRC="$HOME/arvados-api-server"
293 # Clean up .pyc files that may exist in the workspace
295 find -name '*.pyc' -delete
297 # Set up temporary install dirs (unless existing dirs were supplied)
298 for tmpdir in VENVDIR GOPATH GEMHOME
300 if [[ -n "${!tmpdir}" ]]; then
301 leave_temp[$tmpdir]=1
303 eval $tmpdir=$(mktemp -d)
307 setup_ruby_environment() {
308 if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
309 source "$HOME/.rvm/scripts/rvm"
311 elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
312 source "/usr/local/rvm/scripts/rvm"
318 if [[ "$using_rvm" == true ]]; then
319 # If rvm is in use, we can't just put separate "dependencies"
320 # and "gems-under-test" paths to GEM_PATH: passenger resets
321 # the environment to the "current gemset", which would lose
322 # our GEM_PATH and prevent our test suites from running ruby
323 # programs (for example, the Workbench test suite could not
324 # boot an API server or run arv). Instead, we have to make an
325 # rvm gemset and use it for everything.
327 [[ `type rvm | head -n1` == "rvm is a function" ]] \
330 # Put rvm's favorite path back in first place (overriding
331 # virtualenv, which just put itself there). Ignore rvm's
332 # complaint about not being in first place already.
333 rvm use @default 2>/dev/null
335 # Create (if needed) and switch to an @arvados-tests
336 # gemset. (Leave the choice of ruby to the caller.)
337 rvm use @arvados-tests --create \
338 || fatal 'rvm gemset setup'
342 # When our "bundle install"s need to install new gems to
343 # satisfy dependencies, we want them to go where "gem install
344 # --user-install" would put them. (However, if the caller has
345 # already set GEM_HOME, we assume that's where dependencies
346 # should be installed, and we should leave it alone.)
348 if [ -z "$GEM_HOME" ]; then
349 user_gempath="$(gem env gempath)"
350 export GEM_HOME="${user_gempath%%:*}"
352 PATH="$(gem env gemdir)/bin:$PATH"
354 # When we build and install our own gems, we install them in our
355 # $GEMHOME tmpdir, and we want them to be at the front of GEM_PATH and
356 # PATH so integration tests prefer them over other versions that
357 # happen to be installed in $user_gempath, system dirs, etc.
359 tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
360 PATH="$tmpdir_gem_home/bin:$PATH"
361 export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
363 echo "Will install dependencies to $(gem env gemdir)"
364 echo "Will install arvados gems to $tmpdir_gem_home"
365 echo "Gem search path is GEM_PATH=$GEM_PATH"
370 if [[ "$using_rvm" == true ]]; then
373 GEM_HOME="$tmpdir_gem_home" "$@"
378 mkdir -p "$GOPATH/src/git.curoverse.com"
379 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
380 || fatal "symlink failed"
382 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
383 . "$VENVDIR/bin/activate"
385 # When re-using $VENVDIR, upgrade any packages (except arvados) that are
387 pip install --quiet --upgrade `pip freeze | grep -v arvados | cut -f1 -d=`
389 # Note: this must be the last time we change PATH, otherwise rvm will
391 setup_ruby_environment
395 if ! which bundler >/dev/null
397 gem install --user-install bundler || fatal 'Could not install bundler'
400 # Needed for run_test_server.py which is used by certain (non-Python) tests.
401 echo "pip install -q PyYAML"
402 pip install --quiet PyYAML || fatal "pip install PyYAML failed"
405 if [[ "$1" != "0" ]]; then
406 title "!!!!!! $2 FAILED !!!!!!"
407 failures+=("$2 (`timer`)")
409 successes+=("$2 (`timer`)")
418 echo -n "$(($SECONDS - $t0))s"
422 while ! do_test_once ${@} && [[ "$retry" == 1 ]]
424 read -p 'Try again? [Y/n] ' x
425 if [[ "$x" != "y" ]] && [[ "$x" != "" ]]
433 if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
435 title "Running $1 tests"
437 if [[ "$2" == "go" ]]
439 if [[ -n "${testargs[$1]}" ]]
441 # "go test -check.vv giturl" doesn't work, but this
443 cd "$WORKSPACE/$1" && go test ${testargs[$1]}
445 # The above form gets verbose even when testargs is
446 # empty, so use this form in such cases:
447 go test "git.curoverse.com/arvados.git/$1"
449 elif [[ "$2" == "pip" ]]
452 && python setup.py test ${testargs[$1]}
453 elif [[ "$2" != "" ]]
460 checkexit $result "$1 tests"
461 title "End of $1 tests (`timer`)"
464 title "Skipping $1 tests"
469 if [[ -z "$skip_install" || (-n "$only_install" && "$only_install" == "$1") ]]
471 title "Running $1 install"
473 if [[ "$2" == "go" ]]
475 go get -t "git.curoverse.com/arvados.git/$1"
476 elif [[ "$2" == "pip" ]]
478 # Need to change to a different directory after creating
479 # the source dist package to avoid a pip bug.
480 # see https://arvados.org/issues/5766 for details.
482 # Also need to install twice, because if it belives the package is
483 # already installed, pip it won't install it. So the first "pip
484 # install" ensures that the dependencies are met, the second "pip
485 # install" ensures that we've actually install the local package
488 && python setup.py sdist rotate --keep=1 --match .tar.gz \
490 && pip install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
491 && pip install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
492 elif [[ "$2" != "" ]]
498 checkexit $? "$1 install"
499 title "End of $1 install (`timer`)"
501 title "Skipping $1 install"
506 txt="********** $1 **********"
507 printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
510 bundle_install_trylocal() {
513 echo "(Running bundle install --local. 'could not find package' messages are OK.)"
514 if ! bundle install --local --no-deployment; then
515 echo "(Running bundle install again, without --local.)"
516 bundle install --no-deployment
523 cd "$WORKSPACE/doc" \
524 && bundle_install_trylocal \
530 with_test_gemset gem uninstall --force --all --executables arvados \
531 && cd "$WORKSPACE/sdk/ruby" \
532 && bundle_install_trylocal \
533 && gem build arvados.gemspec \
534 && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
536 do_install sdk/ruby ruby_sdk
539 with_test_gemset gem uninstall --force --all --executables arvados-cli \
540 && cd "$WORKSPACE/sdk/cli" \
541 && bundle_install_trylocal \
542 && gem build arvados-cli.gemspec \
543 && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
545 do_install sdk/cli cli
547 # Install the Python SDK early. Various other test suites (like
548 # keepproxy) bring up run_test_server.py, which imports the arvados
549 # module. We can't actually *test* the Python SDK yet though, because
550 # its own test suite brings up some of those other programs (like
552 declare -a pythonstuff
558 for p in "${pythonstuff[@]}"
563 install_apiserver() {
564 cd "$WORKSPACE/services/api" \
565 && RAILS_ENV=test bundle_install_trylocal
567 rm -f config/environments/test.rb
568 cp config/environments/test.rb.example config/environments/test.rb
570 if [ -n "$CONFIGSRC" ]
572 for f in database.yml application.yml
574 cp "$CONFIGSRC/$f" config/ || fatal "$f"
578 # Fill in a random secret_token and blob_signing_key for testing
579 SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
580 BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
582 sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
583 sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
585 # Set up empty git repo (for git tests)
587 sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
590 mkdir -p $GITDIR/test
593 && git config user.email "jenkins@ci.curoverse.com" \
594 && git config user.name "Jenkins, CI" \
597 && git commit -m 'initial commit'
599 # Clear out any lingering postgresql connections to the test
600 # database, so that we can drop it. This assumes the current user
601 # is a postgresql superuser.
602 test_database=$(python -c "import yaml; print yaml.load(file('config/database.yml'))['test']['database']")
603 psql "$test_database" -c "SELECT pg_terminate_backend (pg_stat_activity.procpid::int) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$test_database';" 2>/dev/null
605 cd "$WORKSPACE/services/api" \
606 && RAILS_ENV=test bundle exec rake db:drop \
607 && RAILS_ENV=test bundle exec rake db:setup \
608 && RAILS_ENV=test bundle exec rake db:fixtures:load
610 do_install services/api apiserver
614 services/arv-git-httpd
622 for g in "${gostuff[@]}"
627 install_workbench() {
628 cd "$WORKSPACE/apps/workbench" \
629 && mkdir -p tmp/cache \
630 && RAILS_ENV=test bundle_install_trylocal
632 do_install apps/workbench workbench
634 test_doclinkchecker() {
638 ARVADOS_API_HOST=qr1hi.arvadosapi.com
639 # Make sure python-epydoc is installed or the next line won't
641 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
644 do_test doc doclinkchecker
649 cd "$WORKSPACE/services/api" \
650 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[services/api]}
652 do_test services/api apiserver
654 # Shortcut for when we're only running apiserver tests. This saves a bit of time,
655 # because we don't need to start up the api server for subsequent tests.
656 if [ ! -z "$only" ] && [ "$only" == "services/api" ]; then
657 rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
664 cd "$WORKSPACE/sdk/ruby" \
665 && bundle exec rake test TESTOPTS=-v ${testargs[sdk/ruby]}
667 do_test sdk/ruby ruby_sdk
670 cd "$WORKSPACE/sdk/cli" \
671 && mkdir -p /tmp/keep \
672 && KEEP_LOCAL_STORE=/tmp/keep bundle exec rake test TESTOPTS=-v ${testargs[sdk/cli]}
676 for p in "${pythonstuff[@]}"
681 for g in "${gostuff[@]}"
687 start_nginx_proxy_services \
688 && cd "$WORKSPACE/apps/workbench" \
689 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[apps/workbench]}
691 do_test apps/workbench workbench
693 test_workbench_benchmark() {
694 start_nginx_proxy_services \
695 && cd "$WORKSPACE/apps/workbench" \
696 && RAILS_ENV=test bundle exec rake test:benchmark ${testargs[apps/workbench_benchmark]}
698 do_test apps/workbench_benchmark workbench_benchmark
700 test_workbench_profile() {
701 start_nginx_proxy_services \
702 && cd "$WORKSPACE/apps/workbench" \
703 && RAILS_ENV=test bundle exec rake test:profile ${testargs[apps/workbench_profile]}
705 do_test apps/workbench_profile workbench_profile