Adds setuptools/pip upgrade in python3 virtualenv
[arvados-dev.git] / jenkins / run-tests.sh
1 #!/bin/bash
2
3 . `dirname "$(readlink -f "$0")"`/libcloud-pin
4
5 read -rd "\000" helpmessage <<EOF
6 $(basename $0): Install and test Arvados components.
7
8 Exit non-zero if any tests fail.
9
10 Syntax:
11         $(basename $0) WORKSPACE=/path/to/arvados [options]
12
13 Options:
14
15 --skip FOO     Do not test the FOO component.
16 --only FOO     Do not test anything except the FOO component.
17 --leave-temp   Do not remove GOPATH, virtualenv, and other temp dirs at exit.
18                Instead, show which directories were used this time so they
19                can be reused in subsequent invocations.
20 --skip-install Do not run any install steps. Just run tests.
21                You should provide GOPATH, GEMHOME, and VENVDIR options
22                from a previous invocation if you use this option.
23 --only-install Run specific install step
24 WORKSPACE=path Arvados source tree to test.
25 CONFIGSRC=path Dir with api server config files to copy into source tree.
26                (If none given, leave config files alone in source tree.)
27 services/api_test="TEST=test/functional/arvados/v1/collections_controller_test.rb"
28                Restrict apiserver tests to the given file
29 sdk/python_test="--test-suite test.test_keep_locator"
30                Restrict Python SDK tests to the given class
31 apps/workbench_test="TEST=test/integration/pipeline_instances_test.rb"
32                Restrict Workbench tests to the given file
33 services/arv-git-httpd_test="-check.vv"
34                Show all log messages, even when tests pass (also works
35                with services/keepstore_test etc.)
36 ARVADOS_DEBUG=1
37                Print more debug messages
38 envvar=value   Set \$envvar to value. Primarily useful for WORKSPACE,
39                *_test, and other examples shown above.
40
41 Assuming --skip-install is not given, all components are installed
42 into \$GOPATH, \$VENDIR, and \$GEMHOME before running any tests. Many
43 test suites depend on other components being installed, and installing
44 everything tends to be quicker than debugging dependencies.
45
46 As a special concession to the current CI server config, CONFIGSRC
47 defaults to $HOME/arvados-api-server if that directory exists.
48
49 More information and background:
50
51 https://arvados.org/projects/arvados/wiki/Running_tests
52
53 Available tests:
54
55 apps/workbench
56 apps/workbench_benchmark
57 apps/workbench_profile
58 doc
59 services/api
60 services/crunchstat
61 services/dockercleaner
62 services/fuse
63 services/keepproxy
64 services/keepstore
65 services/login-sync
66 services/nodemanager
67 services/arv-git-httpd
68 sdk/cli
69 sdk/pam
70 sdk/python
71 sdk/ruby
72 sdk/go/arvadosclient
73 sdk/go/keepclient
74 sdk/go/streamer
75
76 EOF
77
78 # First make sure to remove any ARVADOS_ variables from the calling
79 # environment that could interfere with the tests.
80 unset $(env | cut -d= -f1 | grep \^ARVADOS_)
81
82 # Reset other variables that could affect our [tests'] behavior by
83 # accident.
84 GITDIR=
85 GOPATH=
86 VENVDIR=
87 VENV3DIR=
88 PYTHONPATH=
89 GEMHOME=
90 PERLINSTALLBASE=
91
92 COLUMNS=80
93
94 leave_temp=
95 skip_install=
96
97 declare -A leave_temp
98 clear_temp() {
99     leaving=""
100     for var in VENVDIR VENV3DIR GOPATH GITDIR GEMHOME PERLINSTALLBASE
101     do
102         if [[ -z "${leave_temp[$var]}" ]]
103         then
104             if [[ -n "${!var}" ]]
105             then
106                 rm -rf "${!var}"
107             fi
108         else
109             leaving+=" $var=\"${!var}\""
110         fi
111     done
112     if [[ -n "$leaving" ]]; then
113         echo "Leaving behind temp dirs: $leaving"
114     fi
115 }
116
117 fatal() {
118     clear_temp
119     echo >&2 "Fatal: $* (encountered in ${FUNCNAME[1]} at ${BASH_SOURCE[1]} line ${BASH_LINENO[0]})"
120     exit 1
121 }
122
123 report_outcomes() {
124     for x in "${successes[@]}"
125     do
126         echo "Pass: $x"
127     done
128
129     if [[ ${#failures[@]} == 0 ]]
130     then
131         echo "All test suites passed."
132     else
133         echo "Failures (${#failures[@]}):"
134         for x in "${failures[@]}"
135         do
136             echo "Fail: $x"
137         done
138     fi
139 }
140
141 exit_cleanly() {
142     trap - INT
143     create-plot-data-from-log.sh $BUILD_NUMBER "$WORKSPACE/apps/workbench/log/test.log" "$WORKSPACE/apps/workbench/log/"
144     rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
145     stop_services
146     rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
147     report_outcomes
148     clear_temp
149     exit ${#failures}
150 }
151
152 sanity_checks() {
153     ( [[ -n "$WORKSPACE" ]] && [[ -d "$WORKSPACE/services" ]] ) \
154         || fatal "WORKSPACE environment variable not set to a source directory (see: $0 --help)"
155     echo Checking dependencies:
156     echo -n 'virtualenv: '
157     virtualenv --version \
158         || fatal "No virtualenv. Try: apt-get install virtualenv"
159     echo -n 'go: '
160     go version \
161         || fatal "No go binary. See http://golang.org/doc/install"
162     echo -n 'gcc: '
163     gcc --version | egrep ^gcc \
164         || fatal "No gcc. Try: apt-get install build-essential"
165     echo -n 'fuse.h: '
166     find /usr/include -wholename '*fuse/fuse.h' \
167         || fatal "No fuse/fuse.h. Try: apt-get install libfuse-dev"
168     echo -n 'pyconfig.h: '
169     find /usr/include -name pyconfig.h | egrep --max-count=1 . \
170         || fatal "No pyconfig.h. Try: apt-get install python-dev"
171     echo -n 'nginx: '
172     PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" nginx -v \
173         || fatal "No nginx. Try: apt-get install nginx"
174     echo -n 'perl: '
175     perl -v | grep version \
176         || fatal "No perl. Try: apt-get install perl"
177     for mod in ExtUtils::MakeMaker JSON LWP Net::SSL; do
178         echo -n "perl $mod: "
179         perl -e "use $mod; print \"\$$mod::VERSION\\n\"" \
180             || fatal "No $mod. Try: apt-get install perl-modules libcrypt-ssleay-perl libjson-perl"
181     done
182     echo -n 'gitolite: '
183     which gitolite \
184         || fatal "No gitolite. Try: apt-get install gitolite3"
185 }
186
187 rotate_logfile() {
188   # i.e.  rotate_logfile "$WORKSPACE/apps/workbench/log/" "test.log"
189   # $BUILD_NUMBER is set by Jenkins if this script is being called as part of a Jenkins run
190   if [[ -f "$1/$2" ]]; then
191     THEDATE=`date +%Y%m%d%H%M%S`
192     mv "$1/$2" "$1/$THEDATE-$BUILD_NUMBER-$2"
193     gzip "$1/$THEDATE-$BUILD_NUMBER-$2"
194   fi
195 }
196
197 declare -a failures
198 declare -A skip
199 declare -A testargs
200 skip[apps/workbench_profile]=1
201
202 while [[ -n "$1" ]]
203 do
204     arg="$1"; shift
205     case "$arg" in
206         --help)
207             echo >&2 "$helpmessage"
208             echo >&2
209             exit 1
210             ;;
211         --skip)
212             skipwhat="$1"; shift
213             skip[$skipwhat]=1
214             ;;
215         --only)
216             only="$1"; skip[$1]=""; shift
217             ;;
218         --skip-install)
219             skip_install=1
220             ;;
221         --only-install)
222             skip_install=1
223             only_install="$1"; shift
224             ;;
225         --leave-temp)
226             leave_temp[VENVDIR]=1
227             leave_temp[VENV3DIR]=1
228             leave_temp[GOPATH]=1
229             leave_temp[GEMHOME]=1
230             leave_temp[PERLINSTALLBASE]=1
231             ;;
232         --retry)
233             retry=1
234             ;;
235         *_test=*)
236             suite="${arg%%_test=*}"
237             args="${arg#*=}"
238             testargs["$suite"]="$args"
239             ;;
240         *=*)
241             eval export $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
242             ;;
243         *)
244             echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
245             exit 1
246             ;;
247     esac
248 done
249
250 start_api() {
251     echo 'Starting API server...'
252     cd "$WORKSPACE" \
253         && eval $(python sdk/python/tests/run_test_server.py start --auth admin) \
254         && export ARVADOS_TEST_API_HOST="$ARVADOS_API_HOST" \
255         && export ARVADOS_TEST_API_INSTALLED="$$" \
256         && (env | egrep ^ARVADOS)
257 }
258
259 start_nginx_proxy_services() {
260     echo 'Starting keepproxy, arv-git-httpd, and nginx ssl proxy...'
261     cd "$WORKSPACE" \
262         && python sdk/python/tests/run_test_server.py start_keep_proxy \
263         && python sdk/python/tests/run_test_server.py start_arv-git-httpd \
264         && python sdk/python/tests/run_test_server.py start_nginx \
265         && export ARVADOS_TEST_PROXY_SERVICES=1
266 }
267
268 stop_services() {
269     if [[ -n "$ARVADOS_TEST_PROXY_SERVICES" ]]; then
270         unset ARVADOS_TEST_PROXY_SERVICES
271         cd "$WORKSPACE" \
272             && python sdk/python/tests/run_test_server.py stop_nginx \
273             && python sdk/python/tests/run_test_server.py stop_arv-git-httpd \
274             && python sdk/python/tests/run_test_server.py stop_keep_proxy
275     fi
276     if [[ -n "$ARVADOS_TEST_API_HOST" ]]; then
277         unset ARVADOS_TEST_API_HOST
278         cd "$WORKSPACE" \
279             && python sdk/python/tests/run_test_server.py stop
280     fi
281 }
282
283 interrupt() {
284     failures+=("($(basename $0) interrupted)")
285     exit_cleanly
286 }
287 trap interrupt INT
288
289 sanity_checks
290
291 echo "WORKSPACE=$WORKSPACE"
292
293 if [[ -z "$CONFIGSRC" ]] && [[ -d "$HOME/arvados-api-server" ]]; then
294     # Jenkins expects us to use this by default.
295     CONFIGSRC="$HOME/arvados-api-server"
296 fi
297
298 # Clean up .pyc files that may exist in the workspace
299 cd "$WORKSPACE"
300 find -name '*.pyc' -delete
301
302 # Set up temporary install dirs (unless existing dirs were supplied)
303 for tmpdir in VENVDIR VENV3DIR GOPATH GEMHOME PERLINSTALLBASE
304 do
305     if [[ -n "${!tmpdir}" ]]; then
306         leave_temp[$tmpdir]=1
307         mkdir -p "${!tmpdir}"
308     else
309         eval "$tmpdir"='$(mktemp -d)'
310     fi
311 done
312
313 setup_ruby_environment() {
314     if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
315       source "$HOME/.rvm/scripts/rvm"
316       using_rvm=true
317     elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
318       source "/usr/local/rvm/scripts/rvm"
319       using_rvm=true
320     else
321       using_rvm=false
322     fi
323
324     if [[ "$using_rvm" == true ]]; then
325         # If rvm is in use, we can't just put separate "dependencies"
326         # and "gems-under-test" paths to GEM_PATH: passenger resets
327         # the environment to the "current gemset", which would lose
328         # our GEM_PATH and prevent our test suites from running ruby
329         # programs (for example, the Workbench test suite could not
330         # boot an API server or run arv). Instead, we have to make an
331         # rvm gemset and use it for everything.
332
333         [[ `type rvm | head -n1` == "rvm is a function" ]] \
334             || fatal 'rvm check'
335
336         # Put rvm's favorite path back in first place (overriding
337         # virtualenv, which just put itself there). Ignore rvm's
338         # complaint about not being in first place already.
339         rvm use @default 2>/dev/null
340
341         # Create (if needed) and switch to an @arvados-tests
342         # gemset. (Leave the choice of ruby to the caller.)
343         rvm use @arvados-tests --create \
344             || fatal 'rvm gemset setup'
345
346         rvm env
347     else
348         # When our "bundle install"s need to install new gems to
349         # satisfy dependencies, we want them to go where "gem install
350         # --user-install" would put them. (However, if the caller has
351         # already set GEM_HOME, we assume that's where dependencies
352         # should be installed, and we should leave it alone.)
353
354         if [ -z "$GEM_HOME" ]; then
355             user_gempath="$(gem env gempath)"
356             export GEM_HOME="${user_gempath%%:*}"
357         fi
358         PATH="$(gem env gemdir)/bin:$PATH"
359
360         # When we build and install our own gems, we install them in our
361         # $GEMHOME tmpdir, and we want them to be at the front of GEM_PATH and
362         # PATH so integration tests prefer them over other versions that
363         # happen to be installed in $user_gempath, system dirs, etc.
364
365         tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
366         PATH="$tmpdir_gem_home/bin:$PATH"
367         export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
368
369         echo "Will install dependencies to $(gem env gemdir)"
370         echo "Will install arvados gems to $tmpdir_gem_home"
371         echo "Gem search path is GEM_PATH=$GEM_PATH"
372     fi
373 }
374
375 with_test_gemset() {
376     if [[ "$using_rvm" == true ]]; then
377         "$@"
378     else
379         GEM_HOME="$tmpdir_gem_home" GEM_PATH="$tmpdir_gem_home" "$@"
380     fi
381 }
382
383 gem_uninstall_if_exists() {
384     if gem list "$1\$" | egrep '^\w'; then
385         gem uninstall --force --all --executables "$1"
386     fi
387 }
388
389 export PERLINSTALLBASE
390 export PERLLIB="$PERLINSTALLBASE/lib/perl5:${PERLLIB:+$PERLLIB}"
391
392 export GOPATH
393 mkdir -p "$GOPATH/src/git.curoverse.com"
394 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
395     || fatal "symlink failed"
396
397 if ! [[ -e "$VENVDIR/bin/activate" ]] || ! [[ -e "$VENVDIR/bin/pip" ]]; then
398     virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
399 fi
400 . "$VENVDIR/bin/activate"
401
402 if (pip install setuptools | grep setuptools-0) || [ "$($VENVDIR/bin/easy_install --version | cut -d\  -f2 | cut -d. -f1)" -lt 18 ]; then
403     pip install --upgrade setuptools pip
404 fi
405
406 # Needed for run_test_server.py which is used by certain (non-Python) tests.
407 pip freeze 2>/dev/null | egrep ^PyYAML= \
408     || pip install PyYAML >/dev/null \
409     || fatal "pip install PyYAML failed"
410
411 # Preinstall forked version of libcloud, because nodemanager "pip install"
412 # won't pick it up by default.
413 pip freeze 2>/dev/null | egrep ^apache-libcloud==$LIBCLOUD_PIN \
414     || pip install --pre --ignore-installed https://github.com/curoverse/libcloud/archive/apache-libcloud-$LIBCLOUD_PIN.zip >/dev/null \
415     || fatal "pip install apache-libcloud failed"
416
417 # Deactivate Python 2 virtualenv
418 deactivate
419
420 # If Python 3 is available, set up its virtualenv in $VENV3DIR.
421 # Otherwise, skip dependent tests.
422 PYTHON3=$(which python3)
423 if [ "0" = "$?" ]; then
424     virtualenv --python "$PYTHON3" --setuptools "$VENV3DIR" \
425         || fatal "python3 virtualenv $VENV3DIR failed"
426
427     . "$VENV3DIR/bin/activate"
428
429     if (pip install setuptools | grep setuptools-0) || [ "$($VENV3DIR/bin/easy_install --version | cut -d\  -f2 | cut -d. -f1)" -lt 18 ]; then
430         pip install --upgrade setuptools pip
431     fi
432
433     # Deactivate Python 3 virtualenv
434     deactivate
435 else
436     PYTHON3=
437     skip[services/dockercleaner]=1
438     cat >&2 <<EOF
439
440 Warning: python3 could not be found
441 services/dockercleaner install and tests will be skipped
442
443 EOF
444 fi
445
446 # Reactivate Python 2 virtualenv
447 . "$VENVDIR/bin/activate"
448
449 # Note: this must be the last time we change PATH, otherwise rvm will
450 # whine a lot.
451 setup_ruby_environment
452
453 echo "PATH is $PATH"
454
455 if ! which bundler >/dev/null
456 then
457     gem install --user-install bundler || fatal 'Could not install bundler'
458 fi
459
460 checkexit() {
461     if [[ "$1" != "0" ]]; then
462         title "!!!!!! $2 FAILED !!!!!!"
463         failures+=("$2 (`timer`)")
464     else
465         successes+=("$2 (`timer`)")
466     fi
467 }
468
469 timer_reset() {
470     t0=$SECONDS
471 }
472
473 timer() {
474     echo -n "$(($SECONDS - $t0))s"
475 }
476
477 do_test() {
478     while ! do_test_once ${@} && [[ "$retry" == 1 ]]
479     do
480         read -p 'Try again? [Y/n] ' x
481         if [[ "$x" != "y" ]] && [[ "$x" != "" ]]
482         then
483             break
484         fi
485     done
486 }
487
488 do_test_once() {
489     unset result
490     if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
491     then
492         title "Running $1 tests"
493         timer_reset
494         if [[ "$2" == "go" ]]
495         then
496             covername="coverage-$(echo "$1" | sed -e 's/\//_/g')"
497             coverflags=("-covermode=count" "-coverprofile=$WORKSPACE/tmp/.$covername.tmp")
498             if [[ -n "${testargs[$1]}" ]]
499             then
500                 # "go test -check.vv giturl" doesn't work, but this
501                 # does:
502                 cd "$WORKSPACE/$1" && go test ${coverflags[@]} ${testargs[$1]}
503             else
504                 # The above form gets verbose even when testargs is
505                 # empty, so use this form in such cases:
506                 go test ${coverflags[@]} "git.curoverse.com/arvados.git/$1"
507             fi
508             result="$?"
509             go tool cover -html="$WORKSPACE/tmp/.$covername.tmp" -o "$WORKSPACE/tmp/$covername.html"
510             rm "$WORKSPACE/tmp/.$covername.tmp"
511         elif [[ "$2" == "pip" ]]
512         then
513             # $3 can name a path directory for us to use, including trailing
514             # slash; e.g., the bin/ subdirectory of a virtualenv.
515             cd "$WORKSPACE/$1" \
516                 && "${3}python" setup.py test ${testargs[$1]}
517         elif [[ "$2" != "" ]]
518         then
519             "test_$2"
520         else
521             "test_$1"
522         fi
523         result=${result:-$?}
524         checkexit $result "$1 tests"
525         title "End of $1 tests (`timer`)"
526         return $result
527     else
528         title "Skipping $1 tests"
529     fi
530 }
531
532 do_install() {
533     if [[ -z "$skip_install" || (-n "$only_install" && "$only_install" == "$1") ]]
534     then
535         title "Running $1 install"
536         timer_reset
537         if [[ "$2" == "go" ]]
538         then
539             go get -t "git.curoverse.com/arvados.git/$1"
540         elif [[ "$2" == "pip" ]]
541         then
542             # $3 can name a path directory for us to use, including trailing
543             # slash; e.g., the bin/ subdirectory of a virtualenv.
544
545             # Need to change to a different directory after creating
546             # the source dist package to avoid a pip bug.
547             # see https://arvados.org/issues/5766 for details.
548
549             # Also need to install twice, because if it believes the package is
550             # already installed, pip it won't install it.  So the first "pip
551             # install" ensures that the dependencies are met, the second "pip
552             # install" ensures that we've actually installed the local package
553             # we just built.
554             cd "$WORKSPACE/$1" \
555                 && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
556                 && cd "$WORKSPACE" \
557                 && "${3}pip" install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
558                 && "${3}pip" install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
559         elif [[ "$2" != "" ]]
560         then
561             "install_$2"
562         else
563             "install_$1"
564         fi
565         checkexit $? "$1 install"
566         title "End of $1 install (`timer`)"
567     else
568         title "Skipping $1 install"
569     fi
570 }
571
572 title () {
573     txt="********** $1 **********"
574     printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
575 }
576
577 bundle_install_trylocal() {
578     (
579         set -e
580         echo "(Running bundle install --local. 'could not find package' messages are OK.)"
581         if ! bundle install --local --no-deployment; then
582             echo "(Running bundle install again, without --local.)"
583             bundle install --no-deployment
584         fi
585         bundle package --all
586     )
587 }
588
589 install_doc() {
590     cd "$WORKSPACE/doc" \
591         && bundle_install_trylocal \
592         && rm -rf .site
593 }
594 do_install doc
595
596 install_gem() {
597     gemname=$1
598     srcpath=$2
599     with_test_gemset gem_uninstall_if_exists "$gemname" \
600         && cd "$WORKSPACE/$srcpath" \
601         && bundle_install_trylocal \
602         && gem build "$gemname.gemspec" \
603         && with_test_gemset gem install --no-ri --no-rdoc $(ls -t "$gemname"-*.gem|head -n1)
604 }
605
606 install_ruby_sdk() {
607     install_gem arvados sdk/ruby
608 }
609 do_install sdk/ruby ruby_sdk
610
611 install_perl_sdk() {
612     cd "$WORKSPACE/sdk/perl" \
613         && perl Makefile.PL INSTALL_BASE="$PERLINSTALLBASE" \
614         && make install INSTALLDIRS=perl
615 }
616 do_install sdk/perl perl_sdk
617
618 install_cli() {
619     install_gem arvados-cli sdk/cli
620 }
621 do_install sdk/cli cli
622
623 install_login-sync() {
624     install_gem arvados-login-sync services/login-sync
625 }
626 do_install services/login-sync login-sync
627
628 # Install the Python SDK early. Various other test suites (like
629 # keepproxy) bring up run_test_server.py, which imports the arvados
630 # module. We can't actually *test* the Python SDK yet though, because
631 # its own test suite brings up some of those other programs (like
632 # keepproxy).
633 declare -a pythonstuff
634 pythonstuff=(
635     sdk/pam
636     sdk/python
637     services/fuse
638     services/nodemanager
639     )
640 for p in "${pythonstuff[@]}"
641 do
642     do_install "$p" pip
643 done
644 if [ -n "$PYTHON3" ]; then
645     do_install services/dockercleaner pip "$VENV3DIR/bin/"
646 fi
647
648 install_apiserver() {
649     cd "$WORKSPACE/services/api" \
650         && RAILS_ENV=test bundle_install_trylocal
651
652     rm -f config/environments/test.rb
653     cp config/environments/test.rb.example config/environments/test.rb
654
655     if [ -n "$CONFIGSRC" ]
656     then
657         for f in database.yml application.yml
658         do
659             cp "$CONFIGSRC/$f" config/ || fatal "$f"
660         done
661     fi
662
663     # Fill in a random secret_token and blob_signing_key for testing
664     SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
665     BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
666
667     sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
668     sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
669
670     # Set up empty git repo (for git tests)
671     GITDIR=$(mktemp -d)
672     sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
673
674     rm -rf $GITDIR
675     mkdir -p $GITDIR/test
676     cd $GITDIR/test \
677         && git init \
678         && git config user.email "jenkins@ci.curoverse.com" \
679         && git config user.name "Jenkins, CI" \
680         && touch tmp \
681         && git add tmp \
682         && git commit -m 'initial commit'
683
684     # Clear out any lingering postgresql connections to the test
685     # database, so that we can drop it. This assumes the current user
686     # is a postgresql superuser.
687     cd "$WORKSPACE/services/api" \
688         && test_database=$(python -c "import yaml; print yaml.load(file('config/database.yml'))['test']['database']") \
689         && 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
690
691     cd "$WORKSPACE/services/api" \
692         && RAILS_ENV=test bundle exec rake db:drop \
693         && RAILS_ENV=test bundle exec rake db:setup \
694         && RAILS_ENV=test bundle exec rake db:fixtures:load
695 }
696 do_install services/api apiserver
697
698 declare -a gostuff
699 gostuff=(
700     services/arv-git-httpd
701     services/crunchstat
702     services/keepstore
703     services/keepproxy
704     services/datamanager/summary
705     services/datamanager/collection
706     sdk/go/arvadosclient
707     sdk/go/keepclient
708     sdk/go/streamer
709     )
710 for g in "${gostuff[@]}"
711 do
712     do_install "$g" go
713 done
714
715 install_workbench() {
716     cd "$WORKSPACE/apps/workbench" \
717         && mkdir -p tmp/cache \
718         && RAILS_ENV=test bundle_install_trylocal
719 }
720 do_install apps/workbench workbench
721
722 test_doclinkchecker() {
723     (
724         set -e
725         cd "$WORKSPACE/doc"
726         ARVADOS_API_HOST=qr1hi.arvadosapi.com
727         # Make sure python-epydoc is installed or the next line won't
728         # do much good!
729         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
730     )
731 }
732 do_test doc doclinkchecker
733
734 stop_services
735
736 test_apiserver() {
737     cd "$WORKSPACE/services/api" \
738         && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[services/api]}
739 }
740 do_test services/api apiserver
741
742 # Shortcut for when we're only running apiserver tests. This saves a bit of time,
743 # because we don't need to start up the api server for subsequent tests.
744 if [ ! -z "$only" ] && [ "$only" == "services/api" ]; then
745   rotate_logfile "$WORKSPACE/services/api/log/" "test.log"
746   exit_cleanly
747 fi
748
749 start_api
750
751 test_ruby_sdk() {
752     cd "$WORKSPACE/sdk/ruby" \
753         && bundle exec rake test TESTOPTS=-v ${testargs[sdk/ruby]}
754 }
755 do_test sdk/ruby ruby_sdk
756
757 test_cli() {
758     cd "$WORKSPACE/sdk/cli" \
759         && mkdir -p /tmp/keep \
760         && KEEP_LOCAL_STORE=/tmp/keep bundle exec rake test TESTOPTS=-v ${testargs[sdk/cli]}
761 }
762 do_test sdk/cli cli
763
764 test_login-sync() {
765     cd "$WORKSPACE/services/login-sync" \
766         && bundle exec rake test TESTOPTS=-v ${testargs[services/login-sync]}
767 }
768 do_test services/login-sync login-sync
769
770 for p in "${pythonstuff[@]}"
771 do
772     do_test "$p" pip
773 done
774 do_test services/dockercleaner pip "$VENV3DIR/bin/"
775
776 for g in "${gostuff[@]}"
777 do
778     do_test "$g" go
779 done
780
781 test_workbench() {
782     start_nginx_proxy_services \
783         && cd "$WORKSPACE/apps/workbench" \
784         && RAILS_ENV=test bundle exec rake test TESTOPTS=-v ${testargs[apps/workbench]}
785 }
786 do_test apps/workbench workbench
787
788 test_workbench_benchmark() {
789     start_nginx_proxy_services \
790         && cd "$WORKSPACE/apps/workbench" \
791         && RAILS_ENV=test bundle exec rake test:benchmark ${testargs[apps/workbench_benchmark]}
792 }
793 do_test apps/workbench_benchmark workbench_benchmark
794
795 test_workbench_profile() {
796     start_nginx_proxy_services \
797         && cd "$WORKSPACE/apps/workbench" \
798         && RAILS_ENV=test bundle exec rake test:profile ${testargs[apps/workbench_profile]}
799 }
800 do_test apps/workbench_profile workbench_profile
801
802 exit_cleanly