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
59 services/dockercleaner
65 services/arv-git-httpd
76 # First make sure to remove any ARVADOS_ variables from the calling
77 # environment that could interfere with the tests.
78 unset $(env | cut -d= -f1 | grep \^ARVADOS_)
80 # Reset other variables that could affect our [tests'] behavior by
98 for var in VENVDIR VENV3DIR GOPATH GITDIR GEMHOME PERLINSTALLBASE
100 if [[ -z "${leave_temp[$var]}" ]]
102 if [[ -n "${!var}" ]]
107 leaving+=" $var=\"${!var}\""
110 if [[ -n "$leaving" ]]; then
111 echo "Leaving behind temp dirs: $leaving"
117 echo >&2 "Fatal: $* (encountered in ${FUNCNAME[1]} at ${BASH_SOURCE[1]} line ${BASH_LINENO[0]})"
122 for x in "${successes[@]}"
127 if [[ ${#failures[@]} == 0 ]]
129 echo "All test suites passed."
131 echo "Failures (${#failures[@]}):"
132 for x in "${failures[@]}"
141 create-plot-data-from-log.sh $BUILD_NUMBER "$WORKSPACE/apps/workbench/log/test.log" "$WORKSPACE/apps/workbench/log/"
142 rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
144 rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
151 ( [[ -n "$WORKSPACE" ]] && [[ -d "$WORKSPACE/services" ]] ) \
152 || fatal "WORKSPACE environment variable not set to a source directory (see: $0 --help)"
153 echo Checking dependencies:
154 echo -n 'virtualenv: '
155 virtualenv --version \
156 || fatal "No virtualenv. Try: apt-get install virtualenv"
159 || fatal "No go binary. See http://golang.org/doc/install"
161 gcc --version | egrep ^gcc \
162 || fatal "No gcc. Try: apt-get install build-essential"
164 find /usr/include -wholename '*fuse/fuse.h' \
165 || fatal "No fuse/fuse.h. Try: apt-get install libfuse-dev"
166 echo -n 'pyconfig.h: '
167 find /usr/include -name pyconfig.h | egrep --max-count=1 . \
168 || fatal "No pyconfig.h. Try: apt-get install python-dev"
170 PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" nginx -v \
171 || fatal "No nginx. Try: apt-get install nginx"
173 perl -v | grep version \
174 || fatal "No perl. Try: apt-get install perl"
175 for mod in ExtUtils::MakeMaker JSON LWP Net::SSL; do
176 echo -n "perl $mod: "
177 perl -e "use $mod; print \"\$$mod::VERSION\\n\"" \
178 || fatal "No $mod. Try: apt-get install perl-modules libcrypt-ssleay-perl libjson-perl"
183 # i.e. rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
184 # $BUILD_NUMBER is set by Jenkins if this script is being called as part of a Jenkins run
185 if [[ -f "$1/$2" ]]; then
186 THEDATE=`date +%Y%m%d%H%M%S`
187 mv "$1/$2" "$1/$THEDATE-$BUILD_NUMBER-$2"
188 gzip "$1/$THEDATE-$BUILD_NUMBER-$2"
195 skip[apps/workbench_profile]=1
202 echo >&2 "$helpmessage"
211 only="$1"; skip[$1]=""; shift
218 only_install="$1"; shift
221 leave_temp[VENVDIR]=1
222 leave_temp[VENV3DIR]=1
224 leave_temp[GEMHOME]=1
225 leave_temp[PERLINSTALLBASE]=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 VENV3DIR GOPATH GEMHOME PERLINSTALLBASE
300 if [[ -n "${!tmpdir}" ]]; then
301 leave_temp[$tmpdir]=1
302 mkdir -p "${!tmpdir}"
304 eval "$tmpdir"='$(mktemp -d)'
308 setup_ruby_environment() {
309 if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
310 source "$HOME/.rvm/scripts/rvm"
312 elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
313 source "/usr/local/rvm/scripts/rvm"
319 if [[ "$using_rvm" == true ]]; then
320 # If rvm is in use, we can't just put separate "dependencies"
321 # and "gems-under-test" paths to GEM_PATH: passenger resets
322 # the environment to the "current gemset", which would lose
323 # our GEM_PATH and prevent our test suites from running ruby
324 # programs (for example, the Workbench test suite could not
325 # boot an API server or run arv). Instead, we have to make an
326 # rvm gemset and use it for everything.
328 [[ `type rvm | head -n1` == "rvm is a function" ]] \
331 # Put rvm's favorite path back in first place (overriding
332 # virtualenv, which just put itself there). Ignore rvm's
333 # complaint about not being in first place already.
334 rvm use @default 2>/dev/null
336 # Create (if needed) and switch to an @arvados-tests
337 # gemset. (Leave the choice of ruby to the caller.)
338 rvm use @arvados-tests --create \
339 || fatal 'rvm gemset setup'
343 # When our "bundle install"s need to install new gems to
344 # satisfy dependencies, we want them to go where "gem install
345 # --user-install" would put them. (However, if the caller has
346 # already set GEM_HOME, we assume that's where dependencies
347 # should be installed, and we should leave it alone.)
349 if [ -z "$GEM_HOME" ]; then
350 user_gempath="$(gem env gempath)"
351 export GEM_HOME="${user_gempath%%:*}"
353 PATH="$(gem env gemdir)/bin:$PATH"
355 # When we build and install our own gems, we install them in our
356 # $GEMHOME tmpdir, and we want them to be at the front of GEM_PATH and
357 # PATH so integration tests prefer them over other versions that
358 # happen to be installed in $user_gempath, system dirs, etc.
360 tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
361 PATH="$tmpdir_gem_home/bin:$PATH"
362 export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
364 echo "Will install dependencies to $(gem env gemdir)"
365 echo "Will install arvados gems to $tmpdir_gem_home"
366 echo "Gem search path is GEM_PATH=$GEM_PATH"
371 if [[ "$using_rvm" == true ]]; then
374 GEM_HOME="$tmpdir_gem_home" GEM_PATH="$tmpdir_gem_home" "$@"
378 gem_uninstall_if_exists() {
379 if gem list "$1\$" | egrep '^\w'; then
380 gem uninstall --force --all --executables "$1"
384 export PERLINSTALLBASE
385 export PERLLIB="$PERLINSTALLBASE/lib/perl5:${PERLLIB:+$PERLLIB}"
388 mkdir -p "$GOPATH/src/git.curoverse.com"
389 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
390 || fatal "symlink failed"
392 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
393 . "$VENVDIR/bin/activate"
395 if (pip install setuptools | grep setuptools-0) || [ "$($VENVDIR/bin/easy_install --version | cut -d\ -f2 | cut -d. -f1)" -lt 18 ]; then
396 pip install --upgrade setuptools
399 # Note: this must be the last time we change PATH, otherwise rvm will
401 setup_ruby_environment
405 if ! which bundler >/dev/null
407 gem install --user-install bundler || fatal 'Could not install bundler'
410 # Needed for run_test_server.py which is used by certain (non-Python) tests.
411 pip freeze 2>/dev/null | egrep ^PyYAML= \
412 || pip install PyYAML >/dev/null \
413 || fatal "pip install PyYAML failed"
415 # Preinstall forked version of libcloud, because nodemanager "pip install"
416 # won't pick it up by default.
417 pip freeze 2>/dev/null | egrep ^apache-libcloud==0.18.1.dev1 \
418 || pip install --pre --ignore-installed https://github.com/curoverse/libcloud/archive/apache-libcloud-0.18.1.dev1.zip >/dev/null \
419 || fatal "pip install apache-libcloud failed"
421 # If Python 3 is available, set up its virtualenv in $VENV3DIR.
422 # Otherwise, skip dependent tests.
423 PYTHON3=$(which python3)
424 if [ "0" = "$?" ]; then
425 virtualenv --python "$PYTHON3" --setuptools "$VENV3DIR" \
426 || fatal "python3 virtualenv $VENV3DIR failed"
429 skip[services/dockercleaner]=1
432 Warning: python3 could not be found
433 services/dockercleaner install and tests will be skipped
439 if [[ "$1" != "0" ]]; then
440 title "!!!!!! $2 FAILED !!!!!!"
441 failures+=("$2 (`timer`)")
443 successes+=("$2 (`timer`)")
452 echo -n "$(($SECONDS - $t0))s"
456 while ! do_test_once ${@} && [[ "$retry" == 1 ]]
458 read -p 'Try again? [Y/n] ' x
459 if [[ "$x" != "y" ]] && [[ "$x" != "" ]]
467 if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
469 title "Running $1 tests"
471 if [[ "$2" == "go" ]]
473 if [[ -n "${testargs[$1]}" ]]
475 # "go test -check.vv giturl" doesn't work, but this
477 cd "$WORKSPACE/$1" && go test ${testargs[$1]}
479 # The above form gets verbose even when testargs is
480 # empty, so use this form in such cases:
481 go test "git.curoverse.com/arvados.git/$1"
483 elif [[ "$2" == "pip" ]]
485 # $3 can name a path directory for us to use, including trailing
486 # slash; e.g., the bin/ subdirectory of a virtualenv.
488 && "${3}python" setup.py test ${testargs[$1]}
489 elif [[ "$2" != "" ]]
496 checkexit $result "$1 tests"
497 title "End of $1 tests (`timer`)"
500 title "Skipping $1 tests"
505 if [[ -z "$skip_install" || (-n "$only_install" && "$only_install" == "$1") ]]
507 title "Running $1 install"
509 if [[ "$2" == "go" ]]
511 go get -t "git.curoverse.com/arvados.git/$1"
512 elif [[ "$2" == "pip" ]]
514 # $3 can name a path directory for us to use, including trailing
515 # slash; e.g., the bin/ subdirectory of a virtualenv.
517 # Need to change to a different directory after creating
518 # the source dist package to avoid a pip bug.
519 # see https://arvados.org/issues/5766 for details.
521 # Also need to install twice, because if it believes the package is
522 # already installed, pip it won't install it. So the first "pip
523 # install" ensures that the dependencies are met, the second "pip
524 # install" ensures that we've actually installed the local package
527 && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
529 && "${3}pip" install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
530 && "${3}pip" install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
531 elif [[ "$2" != "" ]]
537 checkexit $? "$1 install"
538 title "End of $1 install (`timer`)"
540 title "Skipping $1 install"
545 txt="********** $1 **********"
546 printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
549 bundle_install_trylocal() {
552 echo "(Running bundle install --local. 'could not find package' messages are OK.)"
553 if ! bundle install --local --no-deployment; then
554 echo "(Running bundle install again, without --local.)"
555 bundle install --no-deployment
562 cd "$WORKSPACE/doc" \
563 && bundle_install_trylocal \
571 with_test_gemset gem_uninstall_if_exists "$gemname" \
572 && cd "$WORKSPACE/$srcpath" \
573 && bundle_install_trylocal \
574 && gem build "$gemname.gemspec" \
575 && with_test_gemset gem install --no-ri --no-rdoc $(ls -t "$gemname"-*.gem|head -n1)
579 install_gem arvados sdk/ruby
581 do_install sdk/ruby ruby_sdk
584 cd "$WORKSPACE/sdk/perl" \
585 && perl Makefile.PL INSTALL_BASE="$PERLINSTALLBASE" \
586 && make install INSTALLDIRS=perl
588 do_install sdk/perl perl_sdk
591 install_gem arvados-cli sdk/cli
593 do_install sdk/cli cli
595 install_login-sync() {
596 install_gem arvados-login-sync services/login-sync
598 do_install services/login-sync login-sync
600 # Install the Python SDK early. Various other test suites (like
601 # keepproxy) bring up run_test_server.py, which imports the arvados
602 # module. We can't actually *test* the Python SDK yet though, because
603 # its own test suite brings up some of those other programs (like
605 declare -a pythonstuff
612 for p in "${pythonstuff[@]}"
616 if [ -n "$PYTHON3" ]; then
617 do_install services/dockercleaner pip "$VENV3DIR/bin/"
620 install_apiserver() {
621 cd "$WORKSPACE/services/api" \
622 && RAILS_ENV=test bundle_install_trylocal
624 rm -f config/environments/test.rb
625 cp config/environments/test.rb.example config/environments/test.rb
627 if [ -n "$CONFIGSRC" ]
629 for f in database.yml application.yml
631 cp "$CONFIGSRC/$f" config/ || fatal "$f"
635 # Fill in a random secret_token and blob_signing_key for testing
636 SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
637 BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
639 sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
640 sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
642 # Set up empty git repo (for git tests)
644 sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
647 mkdir -p $GITDIR/test
650 && git config user.email "jenkins@ci.curoverse.com" \
651 && git config user.name "Jenkins, CI" \
654 && git commit -m 'initial commit'
656 # Clear out any lingering postgresql connections to the test
657 # database, so that we can drop it. This assumes the current user
658 # is a postgresql superuser.
659 cd "$WORKSPACE/services/api" \
660 && test_database=$(python -c "import yaml; print yaml.load(file('config/database.yml'))['test']['database']") \
661 && 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
663 cd "$WORKSPACE/services/api" \
664 && RAILS_ENV=test bundle exec rake db:drop \
665 && RAILS_ENV=test bundle exec rake db:setup \
666 && RAILS_ENV=test bundle exec rake db:fixtures:load
668 do_install services/api apiserver
672 services/arv-git-httpd
676 services/datamanager/summary
677 services/datamanager/collection
682 for g in "${gostuff[@]}"
687 install_workbench() {
688 cd "$WORKSPACE/apps/workbench" \
689 && mkdir -p tmp/cache \
690 && RAILS_ENV=test bundle_install_trylocal
692 do_install apps/workbench workbench
694 test_doclinkchecker() {
698 ARVADOS_API_HOST=qr1hi.arvadosapi.com
699 # Make sure python-epydoc is installed or the next line won't
701 PYTHONPATH=$WORKSPACE/sdk/python/ bundle exec rake linkchecker baseurl=file://$WORKSPACE/doc/.site/ arvados_workbench_host=https://workbench.$ARVADOS_API_HOST arvados_api_host=$ARVADOS_API_HOST
704 do_test doc doclinkchecker
709 cd "$WORKSPACE/services/api" \
710 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[services/api]}
712 do_test services/api apiserver
714 # Shortcut for when we're only running apiserver tests. This saves a bit of time,
715 # because we don't need to start up the api server for subsequent tests.
716 if [ ! -z "$only" ] && [ "$only" == "services/api" ]; then
717 rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
724 cd "$WORKSPACE/sdk/ruby" \
725 && bundle exec rake test TESTOPTS=-v ${testargs[sdk/ruby]}
727 do_test sdk/ruby ruby_sdk
730 cd "$WORKSPACE/sdk/cli" \
731 && mkdir -p /tmp/keep \
732 && KEEP_LOCAL_STORE=/tmp/keep bundle exec rake test TESTOPTS=-v ${testargs[sdk/cli]}
737 cd "$WORKSPACE/services/login-sync" \
738 && bundle exec rake test TESTOPTS=-v ${testargs[services/login-sync]}
740 do_test services/login-sync login-sync
742 for p in "${pythonstuff[@]}"
746 do_test services/dockercleaner pip "$VENV3DIR/bin/"
748 for g in "${gostuff[@]}"
754 start_nginx_proxy_services \
755 && cd "$WORKSPACE/apps/workbench" \
756 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[apps/workbench]}
758 do_test apps/workbench workbench
760 test_workbench_benchmark() {
761 start_nginx_proxy_services \
762 && cd "$WORKSPACE/apps/workbench" \
763 && RAILS_ENV=test bundle exec rake test:benchmark ${testargs[apps/workbench_benchmark]}
765 do_test apps/workbench_benchmark workbench_benchmark
767 test_workbench_profile() {
768 start_nginx_proxy_services \
769 && cd "$WORKSPACE/apps/workbench" \
770 && RAILS_ENV=test bundle exec rake test:profile ${testargs[apps/workbench_profile]}
772 do_test apps/workbench_profile workbench_profile