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"
182 || fatal "No gitolite. Try: apt-get install gitolite3"
186 # i.e. rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
187 # $BUILD_NUMBER is set by Jenkins if this script is being called as part of a Jenkins run
188 if [[ -f "$1/$2" ]]; then
189 THEDATE=`date +%Y%m%d%H%M%S`
190 mv "$1/$2" "$1/$THEDATE-$BUILD_NUMBER-$2"
191 gzip "$1/$THEDATE-$BUILD_NUMBER-$2"
198 skip[apps/workbench_profile]=1
205 echo >&2 "$helpmessage"
214 only="$1"; skip[$1]=""; shift
221 only_install="$1"; shift
224 leave_temp[VENVDIR]=1
225 leave_temp[VENV3DIR]=1
227 leave_temp[GEMHOME]=1
228 leave_temp[PERLINSTALLBASE]=1
234 suite="${arg%%_test=*}"
236 testargs["$suite"]="$args"
239 eval export $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
242 echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
249 echo 'Starting API server...'
251 && eval $(python sdk/python/tests/run_test_server.py start --auth admin) \
252 && export ARVADOS_TEST_API_HOST="$ARVADOS_API_HOST" \
253 && export ARVADOS_TEST_API_INSTALLED="$$" \
254 && (env | egrep ^ARVADOS)
257 start_nginx_proxy_services() {
258 echo 'Starting keepproxy, arv-git-httpd, and nginx ssl proxy...'
260 && python sdk/python/tests/run_test_server.py start_keep_proxy \
261 && python sdk/python/tests/run_test_server.py start_arv-git-httpd \
262 && python sdk/python/tests/run_test_server.py start_nginx \
263 && export ARVADOS_TEST_PROXY_SERVICES=1
267 if [[ -n "$ARVADOS_TEST_PROXY_SERVICES" ]]; then
268 unset ARVADOS_TEST_PROXY_SERVICES
270 && python sdk/python/tests/run_test_server.py stop_nginx \
271 && python sdk/python/tests/run_test_server.py stop_arv-git-httpd \
272 && python sdk/python/tests/run_test_server.py stop_keep_proxy
274 if [[ -n "$ARVADOS_TEST_API_HOST" ]]; then
275 unset ARVADOS_TEST_API_HOST
277 && python sdk/python/tests/run_test_server.py stop
282 failures+=("($(basename $0) interrupted)")
289 echo "WORKSPACE=$WORKSPACE"
291 if [[ -z "$CONFIGSRC" ]] && [[ -d "$HOME/arvados-api-server" ]]; then
292 # Jenkins expects us to use this by default.
293 CONFIGSRC="$HOME/arvados-api-server"
296 # Clean up .pyc files that may exist in the workspace
298 find -name '*.pyc' -delete
300 # Set up temporary install dirs (unless existing dirs were supplied)
301 for tmpdir in VENVDIR VENV3DIR GOPATH GEMHOME PERLINSTALLBASE
303 if [[ -n "${!tmpdir}" ]]; then
304 leave_temp[$tmpdir]=1
305 mkdir -p "${!tmpdir}"
307 eval "$tmpdir"='$(mktemp -d)'
311 setup_ruby_environment() {
312 if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
313 source "$HOME/.rvm/scripts/rvm"
315 elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
316 source "/usr/local/rvm/scripts/rvm"
322 if [[ "$using_rvm" == true ]]; then
323 # If rvm is in use, we can't just put separate "dependencies"
324 # and "gems-under-test" paths to GEM_PATH: passenger resets
325 # the environment to the "current gemset", which would lose
326 # our GEM_PATH and prevent our test suites from running ruby
327 # programs (for example, the Workbench test suite could not
328 # boot an API server or run arv). Instead, we have to make an
329 # rvm gemset and use it for everything.
331 [[ `type rvm | head -n1` == "rvm is a function" ]] \
334 # Put rvm's favorite path back in first place (overriding
335 # virtualenv, which just put itself there). Ignore rvm's
336 # complaint about not being in first place already.
337 rvm use @default 2>/dev/null
339 # Create (if needed) and switch to an @arvados-tests
340 # gemset. (Leave the choice of ruby to the caller.)
341 rvm use @arvados-tests --create \
342 || fatal 'rvm gemset setup'
346 # When our "bundle install"s need to install new gems to
347 # satisfy dependencies, we want them to go where "gem install
348 # --user-install" would put them. (However, if the caller has
349 # already set GEM_HOME, we assume that's where dependencies
350 # should be installed, and we should leave it alone.)
352 if [ -z "$GEM_HOME" ]; then
353 user_gempath="$(gem env gempath)"
354 export GEM_HOME="${user_gempath%%:*}"
356 PATH="$(gem env gemdir)/bin:$PATH"
358 # When we build and install our own gems, we install them in our
359 # $GEMHOME tmpdir, and we want them to be at the front of GEM_PATH and
360 # PATH so integration tests prefer them over other versions that
361 # happen to be installed in $user_gempath, system dirs, etc.
363 tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
364 PATH="$tmpdir_gem_home/bin:$PATH"
365 export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
367 echo "Will install dependencies to $(gem env gemdir)"
368 echo "Will install arvados gems to $tmpdir_gem_home"
369 echo "Gem search path is GEM_PATH=$GEM_PATH"
374 if [[ "$using_rvm" == true ]]; then
377 GEM_HOME="$tmpdir_gem_home" GEM_PATH="$tmpdir_gem_home" "$@"
381 gem_uninstall_if_exists() {
382 if gem list "$1\$" | egrep '^\w'; then
383 gem uninstall --force --all --executables "$1"
387 export PERLINSTALLBASE
388 export PERLLIB="$PERLINSTALLBASE/lib/perl5:${PERLLIB:+$PERLLIB}"
391 mkdir -p "$GOPATH/src/git.curoverse.com"
392 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
393 || fatal "symlink failed"
395 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
396 . "$VENVDIR/bin/activate"
398 if (pip install setuptools | grep setuptools-0) || [ "$($VENVDIR/bin/easy_install --version | cut -d\ -f2 | cut -d. -f1)" -lt 18 ]; then
399 pip install --upgrade setuptools
402 # Note: this must be the last time we change PATH, otherwise rvm will
404 setup_ruby_environment
408 if ! which bundler >/dev/null
410 gem install --user-install bundler || fatal 'Could not install bundler'
413 # Needed for run_test_server.py which is used by certain (non-Python) tests.
414 pip freeze 2>/dev/null | egrep ^PyYAML= \
415 || pip install PyYAML >/dev/null \
416 || fatal "pip install PyYAML failed"
418 # Preinstall forked version of libcloud, because nodemanager "pip install"
419 # won't pick it up by default.
420 pip freeze 2>/dev/null | egrep ^apache-libcloud==0.18.1.dev1 \
421 || pip install --pre --ignore-installed https://github.com/curoverse/libcloud/archive/apache-libcloud-0.18.1.dev1.zip >/dev/null \
422 || fatal "pip install apache-libcloud failed"
424 # If Python 3 is available, set up its virtualenv in $VENV3DIR.
425 # Otherwise, skip dependent tests.
426 PYTHON3=$(which python3)
427 if [ "0" = "$?" ]; then
428 virtualenv --python "$PYTHON3" --setuptools "$VENV3DIR" \
429 || fatal "python3 virtualenv $VENV3DIR failed"
432 skip[services/dockercleaner]=1
435 Warning: python3 could not be found
436 services/dockercleaner install and tests will be skipped
442 if [[ "$1" != "0" ]]; then
443 title "!!!!!! $2 FAILED !!!!!!"
444 failures+=("$2 (`timer`)")
446 successes+=("$2 (`timer`)")
455 echo -n "$(($SECONDS - $t0))s"
459 while ! do_test_once ${@} && [[ "$retry" == 1 ]]
461 read -p 'Try again? [Y/n] ' x
462 if [[ "$x" != "y" ]] && [[ "$x" != "" ]]
470 if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
472 title "Running $1 tests"
474 if [[ "$2" == "go" ]]
476 if [[ -n "${testargs[$1]}" ]]
478 # "go test -check.vv giturl" doesn't work, but this
480 cd "$WORKSPACE/$1" && go test ${testargs[$1]}
482 # The above form gets verbose even when testargs is
483 # empty, so use this form in such cases:
484 go test "git.curoverse.com/arvados.git/$1"
486 elif [[ "$2" == "pip" ]]
488 # $3 can name a path directory for us to use, including trailing
489 # slash; e.g., the bin/ subdirectory of a virtualenv.
491 && "${3}python" setup.py test ${testargs[$1]}
492 elif [[ "$2" != "" ]]
499 checkexit $result "$1 tests"
500 title "End of $1 tests (`timer`)"
503 title "Skipping $1 tests"
508 if [[ -z "$skip_install" || (-n "$only_install" && "$only_install" == "$1") ]]
510 title "Running $1 install"
512 if [[ "$2" == "go" ]]
514 go get -t "git.curoverse.com/arvados.git/$1"
515 elif [[ "$2" == "pip" ]]
517 # $3 can name a path directory for us to use, including trailing
518 # slash; e.g., the bin/ subdirectory of a virtualenv.
520 # Need to change to a different directory after creating
521 # the source dist package to avoid a pip bug.
522 # see https://arvados.org/issues/5766 for details.
524 # Also need to install twice, because if it believes the package is
525 # already installed, pip it won't install it. So the first "pip
526 # install" ensures that the dependencies are met, the second "pip
527 # install" ensures that we've actually installed the local package
530 && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
532 && "${3}pip" install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
533 && "${3}pip" install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
534 elif [[ "$2" != "" ]]
540 checkexit $? "$1 install"
541 title "End of $1 install (`timer`)"
543 title "Skipping $1 install"
548 txt="********** $1 **********"
549 printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
552 bundle_install_trylocal() {
555 echo "(Running bundle install --local. 'could not find package' messages are OK.)"
556 if ! bundle install --local --no-deployment; then
557 echo "(Running bundle install again, without --local.)"
558 bundle install --no-deployment
565 cd "$WORKSPACE/doc" \
566 && bundle_install_trylocal \
574 with_test_gemset gem_uninstall_if_exists "$gemname" \
575 && cd "$WORKSPACE/$srcpath" \
576 && bundle_install_trylocal \
577 && gem build "$gemname.gemspec" \
578 && with_test_gemset gem install --no-ri --no-rdoc $(ls -t "$gemname"-*.gem|head -n1)
582 install_gem arvados sdk/ruby
584 do_install sdk/ruby ruby_sdk
587 cd "$WORKSPACE/sdk/perl" \
588 && perl Makefile.PL INSTALL_BASE="$PERLINSTALLBASE" \
589 && make install INSTALLDIRS=perl
591 do_install sdk/perl perl_sdk
594 install_gem arvados-cli sdk/cli
596 do_install sdk/cli cli
598 install_login-sync() {
599 install_gem arvados-login-sync services/login-sync
601 do_install services/login-sync login-sync
603 # Install the Python SDK early. Various other test suites (like
604 # keepproxy) bring up run_test_server.py, which imports the arvados
605 # module. We can't actually *test* the Python SDK yet though, because
606 # its own test suite brings up some of those other programs (like
608 declare -a pythonstuff
615 for p in "${pythonstuff[@]}"
619 if [ -n "$PYTHON3" ]; then
620 do_install services/dockercleaner pip "$VENV3DIR/bin/"
623 install_apiserver() {
624 cd "$WORKSPACE/services/api" \
625 && RAILS_ENV=test bundle_install_trylocal
627 rm -f config/environments/test.rb
628 cp config/environments/test.rb.example config/environments/test.rb
630 if [ -n "$CONFIGSRC" ]
632 for f in database.yml application.yml
634 cp "$CONFIGSRC/$f" config/ || fatal "$f"
638 # Fill in a random secret_token and blob_signing_key for testing
639 SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
640 BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
642 sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
643 sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
645 # Set up empty git repo (for git tests)
647 sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
650 mkdir -p $GITDIR/test
653 && git config user.email "jenkins@ci.curoverse.com" \
654 && git config user.name "Jenkins, CI" \
657 && git commit -m 'initial commit'
659 # Clear out any lingering postgresql connections to the test
660 # database, so that we can drop it. This assumes the current user
661 # is a postgresql superuser.
662 cd "$WORKSPACE/services/api" \
663 && test_database=$(python -c "import yaml; print yaml.load(file('config/database.yml'))['test']['database']") \
664 && 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
666 cd "$WORKSPACE/services/api" \
667 && RAILS_ENV=test bundle exec rake db:drop \
668 && RAILS_ENV=test bundle exec rake db:setup \
669 && RAILS_ENV=test bundle exec rake db:fixtures:load
671 do_install services/api apiserver
675 services/arv-git-httpd
679 services/datamanager/summary
680 services/datamanager/collection
685 for g in "${gostuff[@]}"
690 install_workbench() {
691 cd "$WORKSPACE/apps/workbench" \
692 && mkdir -p tmp/cache \
693 && RAILS_ENV=test bundle_install_trylocal
695 do_install apps/workbench workbench
697 test_doclinkchecker() {
701 ARVADOS_API_HOST=qr1hi.arvadosapi.com
702 # Make sure python-epydoc is installed or the next line won't
704 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
707 do_test doc doclinkchecker
712 cd "$WORKSPACE/services/api" \
713 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[services/api]}
715 do_test services/api apiserver
717 # Shortcut for when we're only running apiserver tests. This saves a bit of time,
718 # because we don't need to start up the api server for subsequent tests.
719 if [ ! -z "$only" ] && [ "$only" == "services/api" ]; then
720 rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
727 cd "$WORKSPACE/sdk/ruby" \
728 && bundle exec rake test TESTOPTS=-v ${testargs[sdk/ruby]}
730 do_test sdk/ruby ruby_sdk
733 cd "$WORKSPACE/sdk/cli" \
734 && mkdir -p /tmp/keep \
735 && KEEP_LOCAL_STORE=/tmp/keep bundle exec rake test TESTOPTS=-v ${testargs[sdk/cli]}
740 cd "$WORKSPACE/services/login-sync" \
741 && bundle exec rake test TESTOPTS=-v ${testargs[services/login-sync]}
743 do_test services/login-sync login-sync
745 for p in "${pythonstuff[@]}"
749 do_test services/dockercleaner pip "$VENV3DIR/bin/"
751 for g in "${gostuff[@]}"
757 start_nginx_proxy_services \
758 && cd "$WORKSPACE/apps/workbench" \
759 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[apps/workbench]}
761 do_test apps/workbench workbench
763 test_workbench_benchmark() {
764 start_nginx_proxy_services \
765 && cd "$WORKSPACE/apps/workbench" \
766 && RAILS_ENV=test bundle exec rake test:benchmark ${testargs[apps/workbench_benchmark]}
768 do_test apps/workbench_benchmark workbench_benchmark
770 test_workbench_profile() {
771 start_nginx_proxy_services \
772 && cd "$WORKSPACE/apps/workbench" \
773 && RAILS_ENV=test bundle exec rake test:profile ${testargs[apps/workbench_profile]}
775 do_test apps/workbench_profile workbench_profile