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
64 services/arv-git-httpd
74 # First make sure to remove any ARVADOS_ variables from the calling
75 # environment that could interfere with the tests.
76 unset $(env | cut -d= -f1 | grep \^ARVADOS_)
78 # Reset other variables that could affect our [tests'] behavior by
96 for var in VENVDIR VENV3DIR GOPATH GITDIR GEMHOME PERLINSTALLBASE
98 if [[ -z "${leave_temp[$var]}" ]]
100 if [[ -n "${!var}" ]]
105 leaving+=" $var=\"${!var}\""
108 if [[ -n "$leaving" ]]; then
109 echo "Leaving behind temp dirs: $leaving"
115 echo >&2 "Fatal: $* (encountered in ${FUNCNAME[1]} at ${BASH_SOURCE[1]} line ${BASH_LINENO[0]})"
120 for x in "${successes[@]}"
125 if [[ ${#failures[@]} == 0 ]]
127 echo "All test suites passed."
129 echo "Failures (${#failures[@]}):"
130 for x in "${failures[@]}"
139 create-plot-data-from-log.sh $BUILD_NUMBER "$WORKSPACE/apps/workbench/log/test.log" "$WORKSPACE/apps/workbench/log/"
140 rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
142 rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
149 ( [[ -n "$WORKSPACE" ]] && [[ -d "$WORKSPACE/services" ]] ) \
150 || fatal "WORKSPACE environment variable not set to a source directory (see: $0 --help)"
151 echo Checking dependencies:
152 echo -n 'virtualenv: '
153 virtualenv --version \
154 || fatal "No virtualenv. Try: apt-get install virtualenv"
157 || fatal "No go binary. See http://golang.org/doc/install"
159 gcc --version | egrep ^gcc \
160 || fatal "No gcc. Try: apt-get install build-essential"
162 find /usr/include -wholename '*fuse/fuse.h' \
163 || fatal "No fuse/fuse.h. Try: apt-get install libfuse-dev"
164 echo -n 'pyconfig.h: '
165 find /usr/include -name pyconfig.h | egrep --max-count=1 . \
166 || fatal "No pyconfig.h. Try: apt-get install python-dev"
168 PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" nginx -v \
169 || fatal "No nginx. Try: apt-get install nginx"
171 perl -v | grep version \
172 || fatal "No perl. Try: apt-get install perl"
173 for mod in ExtUtils::MakeMaker JSON LWP Net::SSL; do
174 echo -n "perl $mod: "
175 perl -e "use $mod; print \"\$$mod::VERSION\\n\"" \
176 || fatal "No $mod. Try: apt-get install perl-modules libcrypt-ssleay-perl libjson-perl"
181 # i.e. rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
182 # $BUILD_NUMBER is set by Jenkins if this script is being called as part of a Jenkins run
183 if [[ -f "$1/$2" ]]; then
184 THEDATE=`date +%Y%m%d%H%M%S`
185 mv "$1/$2" "$1/$THEDATE-$BUILD_NUMBER-$2"
186 gzip "$1/$THEDATE-$BUILD_NUMBER-$2"
193 skip[apps/workbench_profile]=1
200 echo >&2 "$helpmessage"
209 only="$1"; skip[$1]=""; shift
216 only_install="$1"; shift
219 leave_temp[VENVDIR]=1
220 leave_temp[VENV3DIR]=1
222 leave_temp[GEMHOME]=1
223 leave_temp[PERLINSTALLBASE]=1
229 suite="${arg%%_test=*}"
231 testargs["$suite"]="$args"
234 eval export $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
237 echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
244 echo 'Starting API server...'
246 && eval $(python sdk/python/tests/run_test_server.py start --auth admin) \
247 && export ARVADOS_TEST_API_HOST="$ARVADOS_API_HOST" \
248 && export ARVADOS_TEST_API_INSTALLED="$$" \
249 && (env | egrep ^ARVADOS)
252 start_nginx_proxy_services() {
253 echo 'Starting keepproxy, arv-git-httpd, and nginx ssl proxy...'
255 && python sdk/python/tests/run_test_server.py start_keep_proxy \
256 && python sdk/python/tests/run_test_server.py start_arv-git-httpd \
257 && python sdk/python/tests/run_test_server.py start_nginx \
258 && export ARVADOS_TEST_PROXY_SERVICES=1
262 if [[ -n "$ARVADOS_TEST_PROXY_SERVICES" ]]; then
263 unset ARVADOS_TEST_PROXY_SERVICES
265 && python sdk/python/tests/run_test_server.py stop_nginx \
266 && python sdk/python/tests/run_test_server.py stop_arv-git-httpd \
267 && python sdk/python/tests/run_test_server.py stop_keep_proxy
269 if [[ -n "$ARVADOS_TEST_API_HOST" ]]; then
270 unset ARVADOS_TEST_API_HOST
272 && python sdk/python/tests/run_test_server.py stop
277 failures+=("($(basename $0) interrupted)")
284 echo "WORKSPACE=$WORKSPACE"
286 if [[ -z "$CONFIGSRC" ]] && [[ -d "$HOME/arvados-api-server" ]]; then
287 # Jenkins expects us to use this by default.
288 CONFIGSRC="$HOME/arvados-api-server"
291 # Clean up .pyc files that may exist in the workspace
293 find -name '*.pyc' -delete
295 # Set up temporary install dirs (unless existing dirs were supplied)
296 for tmpdir in VENVDIR VENV3DIR GOPATH GEMHOME PERLINSTALLBASE
298 if [[ -n "${!tmpdir}" ]]; then
299 leave_temp[$tmpdir]=1
300 mkdir -p "${!tmpdir}"
302 eval "$tmpdir"='$(mktemp -d)'
306 setup_ruby_environment() {
307 if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
308 source "$HOME/.rvm/scripts/rvm"
310 elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
311 source "/usr/local/rvm/scripts/rvm"
317 if [[ "$using_rvm" == true ]]; then
318 # If rvm is in use, we can't just put separate "dependencies"
319 # and "gems-under-test" paths to GEM_PATH: passenger resets
320 # the environment to the "current gemset", which would lose
321 # our GEM_PATH and prevent our test suites from running ruby
322 # programs (for example, the Workbench test suite could not
323 # boot an API server or run arv). Instead, we have to make an
324 # rvm gemset and use it for everything.
326 [[ `type rvm | head -n1` == "rvm is a function" ]] \
329 # Put rvm's favorite path back in first place (overriding
330 # virtualenv, which just put itself there). Ignore rvm's
331 # complaint about not being in first place already.
332 rvm use @default 2>/dev/null
334 # Create (if needed) and switch to an @arvados-tests
335 # gemset. (Leave the choice of ruby to the caller.)
336 rvm use @arvados-tests --create \
337 || fatal 'rvm gemset setup'
341 # When our "bundle install"s need to install new gems to
342 # satisfy dependencies, we want them to go where "gem install
343 # --user-install" would put them. (However, if the caller has
344 # already set GEM_HOME, we assume that's where dependencies
345 # should be installed, and we should leave it alone.)
347 if [ -z "$GEM_HOME" ]; then
348 user_gempath="$(gem env gempath)"
349 export GEM_HOME="${user_gempath%%:*}"
351 PATH="$(gem env gemdir)/bin:$PATH"
353 # When we build and install our own gems, we install them in our
354 # $GEMHOME tmpdir, and we want them to be at the front of GEM_PATH and
355 # PATH so integration tests prefer them over other versions that
356 # happen to be installed in $user_gempath, system dirs, etc.
358 tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
359 PATH="$tmpdir_gem_home/bin:$PATH"
360 export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
362 echo "Will install dependencies to $(gem env gemdir)"
363 echo "Will install arvados gems to $tmpdir_gem_home"
364 echo "Gem search path is GEM_PATH=$GEM_PATH"
369 if [[ "$using_rvm" == true ]]; then
372 GEM_HOME="$tmpdir_gem_home" GEM_PATH="$tmpdir_gem_home" "$@"
376 gem_uninstall_if_exists() {
377 if gem list "$1\$" | egrep '^\w'; then
378 gem uninstall --force --all --executables "$1"
382 export PERLINSTALLBASE
383 export PERLLIB="$PERLINSTALLBASE/lib/perl5:${PERLLIB:+$PERLLIB}"
386 mkdir -p "$GOPATH/src/git.curoverse.com"
387 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
388 || fatal "symlink failed"
390 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
391 . "$VENVDIR/bin/activate"
393 # Note: this must be the last time we change PATH, otherwise rvm will
395 setup_ruby_environment
399 if ! which bundler >/dev/null
401 gem install --user-install bundler || fatal 'Could not install bundler'
404 # Needed for run_test_server.py which is used by certain (non-Python) tests.
405 pip freeze 2>/dev/null | egrep ^PyYAML= \
406 || pip install PyYAML >/dev/null \
407 || fatal "pip install PyYAML failed"
409 # If Python 3 is available, set up its virtualenv in $VENV3DIR.
410 # Otherwise, skip dependent tests.
411 PYTHON3=$(which python3)
412 if [ "0" = "$?" ]; then
413 virtualenv --python "$PYTHON3" --setuptools "$VENV3DIR" \
414 || fatal "python3 virtualenv $VENV3DIR failed"
417 skip[services/dockercleaner]=1
420 Warning: python3 could not be found
421 services/dockercleaner install and tests will be skipped
427 if [[ "$1" != "0" ]]; then
428 title "!!!!!! $2 FAILED !!!!!!"
429 failures+=("$2 (`timer`)")
431 successes+=("$2 (`timer`)")
440 echo -n "$(($SECONDS - $t0))s"
444 while ! do_test_once ${@} && [[ "$retry" == 1 ]]
446 read -p 'Try again? [Y/n] ' x
447 if [[ "$x" != "y" ]] && [[ "$x" != "" ]]
455 if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
457 title "Running $1 tests"
459 if [[ "$2" == "go" ]]
461 if [[ -n "${testargs[$1]}" ]]
463 # "go test -check.vv giturl" doesn't work, but this
465 cd "$WORKSPACE/$1" && go test ${testargs[$1]}
467 # The above form gets verbose even when testargs is
468 # empty, so use this form in such cases:
469 go test "git.curoverse.com/arvados.git/$1"
471 elif [[ "$2" == "pip" ]]
473 # $3 can name a path directory for us to use, including trailing
474 # slash; e.g., the bin/ subdirectory of a virtualenv.
476 && "${3}python" setup.py test ${testargs[$1]}
477 elif [[ "$2" != "" ]]
484 checkexit $result "$1 tests"
485 title "End of $1 tests (`timer`)"
488 title "Skipping $1 tests"
493 if [[ -z "$skip_install" || (-n "$only_install" && "$only_install" == "$1") ]]
495 title "Running $1 install"
497 if [[ "$2" == "go" ]]
499 go get -t "git.curoverse.com/arvados.git/$1"
500 elif [[ "$2" == "pip" ]]
502 # $3 can name a path directory for us to use, including trailing
503 # slash; e.g., the bin/ subdirectory of a virtualenv.
505 # Need to change to a different directory after creating
506 # the source dist package to avoid a pip bug.
507 # see https://arvados.org/issues/5766 for details.
509 # Also need to install twice, because if it belives the package is
510 # already installed, pip it won't install it. So the first "pip
511 # install" ensures that the dependencies are met, the second "pip
512 # install" ensures that we've actually install the local package
515 && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
517 && "${3}pip" install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
518 && "${3}pip" install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
519 elif [[ "$2" != "" ]]
525 checkexit $? "$1 install"
526 title "End of $1 install (`timer`)"
528 title "Skipping $1 install"
533 txt="********** $1 **********"
534 printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
537 bundle_install_trylocal() {
540 echo "(Running bundle install --local. 'could not find package' messages are OK.)"
541 if ! bundle install --local --no-deployment; then
542 echo "(Running bundle install again, without --local.)"
543 bundle install --no-deployment
550 cd "$WORKSPACE/doc" \
551 && bundle_install_trylocal \
557 with_test_gemset gem_uninstall_if_exists arvados \
558 && cd "$WORKSPACE/sdk/ruby" \
559 && bundle_install_trylocal \
560 && gem build arvados.gemspec \
561 && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
563 do_install sdk/ruby ruby_sdk
566 cd "$WORKSPACE/sdk/perl" \
567 && perl Makefile.PL INSTALL_BASE="$PERLINSTALLBASE" \
568 && make install INSTALLDIRS=perl
570 do_install sdk/perl perl_sdk
573 with_test_gemset gem_uninstall_if_exists arvados-cli \
574 && cd "$WORKSPACE/sdk/cli" \
575 && bundle_install_trylocal \
576 && gem build arvados-cli.gemspec \
577 && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
579 do_install sdk/cli cli
581 # Install the Python SDK early. Various other test suites (like
582 # keepproxy) bring up run_test_server.py, which imports the arvados
583 # module. We can't actually *test* the Python SDK yet though, because
584 # its own test suite brings up some of those other programs (like
586 declare -a pythonstuff
592 for p in "${pythonstuff[@]}"
596 if [ -n "$PYTHON3" ]; then
597 do_install services/dockercleaner pip "$VENV3DIR/bin/"
600 install_apiserver() {
601 cd "$WORKSPACE/services/api" \
602 && RAILS_ENV=test bundle_install_trylocal
604 rm -f config/environments/test.rb
605 cp config/environments/test.rb.example config/environments/test.rb
607 if [ -n "$CONFIGSRC" ]
609 for f in database.yml application.yml
611 cp "$CONFIGSRC/$f" config/ || fatal "$f"
615 # Fill in a random secret_token and blob_signing_key for testing
616 SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
617 BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
619 sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
620 sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
622 # Set up empty git repo (for git tests)
624 sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
627 mkdir -p $GITDIR/test
630 && git config user.email "jenkins@ci.curoverse.com" \
631 && git config user.name "Jenkins, CI" \
634 && git commit -m 'initial commit'
636 # Clear out any lingering postgresql connections to the test
637 # database, so that we can drop it. This assumes the current user
638 # is a postgresql superuser.
639 cd "$WORKSPACE/services/api" \
640 && test_database=$(python -c "import yaml; print yaml.load(file('config/database.yml'))['test']['database']") \
641 && 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
643 cd "$WORKSPACE/services/api" \
644 && RAILS_ENV=test bundle exec rake db:drop \
645 && RAILS_ENV=test bundle exec rake db:setup \
646 && RAILS_ENV=test bundle exec rake db:fixtures:load
648 do_install services/api apiserver
652 services/arv-git-httpd
656 services/datamanager/summary
657 services/datamanager/collection
662 for g in "${gostuff[@]}"
667 install_workbench() {
668 cd "$WORKSPACE/apps/workbench" \
669 && mkdir -p tmp/cache \
670 && RAILS_ENV=test bundle_install_trylocal
672 do_install apps/workbench workbench
674 test_doclinkchecker() {
678 ARVADOS_API_HOST=qr1hi.arvadosapi.com
679 # Make sure python-epydoc is installed or the next line won't
681 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
684 do_test doc doclinkchecker
689 cd "$WORKSPACE/services/api" \
690 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[services/api]}
692 do_test services/api apiserver
694 # Shortcut for when we're only running apiserver tests. This saves a bit of time,
695 # because we don't need to start up the api server for subsequent tests.
696 if [ ! -z "$only" ] && [ "$only" == "services/api" ]; then
697 rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
704 cd "$WORKSPACE/sdk/ruby" \
705 && bundle exec rake test TESTOPTS=-v ${testargs[sdk/ruby]}
707 do_test sdk/ruby ruby_sdk
710 cd "$WORKSPACE/sdk/cli" \
711 && mkdir -p /tmp/keep \
712 && KEEP_LOCAL_STORE=/tmp/keep bundle exec rake test TESTOPTS=-v ${testargs[sdk/cli]}
716 for p in "${pythonstuff[@]}"
720 do_test services/dockercleaner pip "$VENV3DIR/bin/"
722 for g in "${gostuff[@]}"
728 start_nginx_proxy_services \
729 && cd "$WORKSPACE/apps/workbench" \
730 && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[apps/workbench]}
732 do_test apps/workbench workbench
734 test_workbench_benchmark() {
735 start_nginx_proxy_services \
736 && cd "$WORKSPACE/apps/workbench" \
737 && RAILS_ENV=test bundle exec rake test:benchmark ${testargs[apps/workbench_benchmark]}
739 do_test apps/workbench_benchmark workbench_benchmark
741 test_workbench_profile() {
742 start_nginx_proxy_services \
743 && cd "$WORKSPACE/apps/workbench" \
744 && RAILS_ENV=test bundle exec rake test:profile ${testargs[apps/workbench_profile]}
746 do_test apps/workbench_profile workbench_profile