4156: Do not use --user-install -- just install to the GEM_HOME we selected.
[arvados-dev.git] / jenkins / run-tests.sh
1 #!/bin/bash
2
3 read -rd "\000" helpmessage <<EOF
4 $(basename $0): Install and test Arvados components.
5
6 Exit non-zero if any tests fail.
7
8 Syntax:
9         $(basename $0) WORKSPACE=/path/to/arvados [options]
10
11 Options:
12
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 WORKSPACE=path Arvados source tree to test.
22 CONFIGSRC=path Dir with api server config files to copy into source tree.
23                (If none given, leave config files alone in source tree.)
24 apiserver_test="TEST=test/functional/arvados/v1/collections_controller_test.rb"
25                Restrict apiserver tests to the given file
26 sdk/python_test="--test-suite test.test_keep_locator"
27                Restrict Python SDK tests to the given class
28 workbench_test="TEST=test/integration/pipeline_instances_test.rb"
29                Restrict Workbench tests to the given file
30 ARVADOS_DEBUG=1
31                Print more debug messages
32 envvar=value   Set \$envvar to value. Primarily useful for WORKSPACE,
33                *_test, and other examples shown above.
34
35 Assuming --skip-install is not given, all components are installed
36 into \$GOPATH, \$VENDIR, and \$GEMHOME before running any tests. Many
37 test suites depend on other components being installed, and installing
38 everything tends to be quicker than debugging dependencies.
39
40 As a special concession to the current CI server config, CONFIGSRC
41 defaults to $HOME/arvados-api-server if that directory exists.
42
43 More information and background:
44
45 https://arvados.org/projects/arvados/wiki/Running_tests
46 EOF
47
48 # First make sure to remove any ARVADOS_ variables from the calling
49 # environment that could interfere with the tests.
50 unset $(env | cut -d= -f1 | grep \^ARVADOS_)
51
52 # Reset other variables that could affect our [tests'] behavior by
53 # accident.
54 GITDIR=
55 GOPATH=
56 VENVDIR=
57 PYTHONPATH=
58 GEMHOME=
59
60 COLUMNS=80
61
62 leave_temp=
63 skip_install=
64
65 if [[ -f /etc/profile.d/rvm.sh ]]
66 then
67     source /etc/profile.d/rvm.sh
68 fi
69
70 declare -A leave_temp
71 clear_temp() {
72     leaving=""
73     for var in VENVDIR GOPATH GITDIR GEMHOME
74     do
75         if [[ -z "${leave_temp[$var]}" ]]
76         then
77             if [[ -n "${!var}" ]]
78             then
79                 rm -rf "${!var}"
80             fi
81         else
82             leaving+=" $var=\"${!var}\""
83         fi
84     done
85     if [[ -n "$leaving" ]]; then
86         echo "Leaving behind temp dirs: $leaving"
87     fi
88 }
89
90 fatal() {
91     clear_temp
92     echo >&2 "Fatal: $* in ${FUNCNAME[1]} at ${BASH_SOURCE[1]} line ${BASH_LINENO[0]}"
93     exit 1
94 }
95
96 report_outcomes() {
97     for x in "${successes[@]}"
98     do
99         echo "Pass: $x"
100     done
101
102     if [[ ${#failures[@]} == 0 ]]
103     then
104         echo "All test suites passed."
105     else
106         echo "Failures (${#failures[@]}):"
107         for x in "${failures[@]}"
108         do
109             echo "Fail: $x"
110         done
111     fi
112 }
113 declare -a failures
114 declare -A skip
115 declare -A testargs
116
117 while [[ -n "$1" ]]
118 do
119     arg="$1"; shift
120     case "$arg" in
121         --help)
122             echo >&2 "$helpmessage"
123             echo >&2
124             exit 1
125             ;;
126         --skip)
127             skipwhat="$1"; shift
128             skip[$skipwhat]=1
129             ;;
130         --only)
131             only="$1"; shift
132             ;;
133         --skip-install)
134             skip_install=1
135             ;;
136         --leave-temp)
137             leave_temp[VENVDIR]=1
138             leave_temp[GOPATH]=1
139             leave_temp[GEMHOME]=1
140             ;;
141         *_test=*)
142             suite="${arg%%_test=*}"
143             args="${arg#*=}"
144             testargs["$suite"]="$args"
145             ;;
146         *=*)
147             eval export $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
148             ;;
149         *)
150             echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
151             exit 1
152             ;;
153     esac
154 done
155
156 # Sanity check
157 if ! [[ -n "$WORKSPACE" ]]; then
158   echo >&2 "$helpmessage"
159   echo >&2
160   echo >&2 "Error: WORKSPACE environment variable not set"
161   echo >&2
162   exit 1
163 fi
164
165 echo "WORKSPACE=$WORKSPACE"
166
167 if [[ -z "$CONFIGSRC" ]] && [[ -d "$HOME/arvados-api-server" ]]; then
168     # Jenkins expects us to use this by default.
169     CONFIGSRC="$HOME/arvados-api-server"
170 fi
171
172 # Clean up .pyc files that may exist in the workspace
173 cd "$WORKSPACE"
174 find -name '*.pyc' -delete
175
176 # Set up temporary install dirs (unless existing dirs were supplied)
177 for tmpdir in VENVDIR GOPATH GEMHOME
178 do
179     if [[ -n "${!tmpdir}" ]]; then
180         leave_temp[$tmpdir]=1
181     else
182         eval $tmpdir=$(mktemp -d)
183     fi
184 done
185
186 # When our "bundle install"s need to install new gems to satisfy
187 # dependencies, we want them to go where "gem install --user-install"
188 # would put them. If rvm is in use (or something else has set
189 # GEM_HOME) we assume "bundle install" already does something
190 # reasonable.
191
192 if [ -z "$GEM_HOME" ]; then
193     user_gempath="$(gem env gempath)"
194     export GEM_HOME="${user_gempath%%:*}"
195 fi
196 PATH="$(gem env gemdir)/bin:$PATH"
197
198 # When we build and install our own gems, we install them in our
199 # $GEMHOME tmpdir, and we want them to be at the front of GEM_PATH and
200 # PATH so integration tests prefer them over other versions that
201 # happen to be installed in $user_gempath, system dirs, etc.
202
203 tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
204 PATH="${tmpdir_gem_home%%:*}/bin:$PATH"
205 export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
206
207 echo "PATH=$PATH"
208 echo "Will install dependencies to $GEM_HOME"
209 echo "Will install arvados gems to $tmpdir_gem_home"
210 echo "Gem search path is GEM_PATH=$GEM_PATH"
211
212 if ! which bundler >/dev/null
213 then
214     gem install --user-install bundler || fatal 'Could not install bundler'
215 fi
216
217 export GOPATH
218 mkdir -p "$GOPATH/src/git.curoverse.com"
219 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
220     || fatal "symlink failed"
221
222 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
223 . "$VENVDIR/bin/activate"
224
225 # Needed for run_test_server.py which is used by certain (non-Python) tests.
226 pip install PyYAML
227
228 checkexit() {
229     if [[ "$?" != "0" ]]; then
230         title "!!!!!! $1 FAILED !!!!!!"
231         failures+=("$1 (`timer`)")
232     else
233         successes+=("$1 (`timer`)")
234     fi
235 }
236
237 timer_reset() {
238     t0=$SECONDS
239 }
240
241 timer() {
242     echo -n "$(($SECONDS - $t0))s"
243 }
244
245 do_test() {
246     if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
247     then
248         title "Running $1 tests"
249         timer_reset
250         if [[ "$2" == "go" ]]
251         then
252             go test "git.curoverse.com/arvados.git/$1"
253         elif [[ "$2" == "pip" ]]
254         then
255            # Other test suites can depend on tests_require
256            # dependencies of this package. For example, keepproxy runs
257            # run_test_server.py, which depends on the yaml package,
258            # which is in sdk/python's tests_require but not
259            # install_requires, and therefore does not get installed by
260            # setuptools until we run "setup.py test" *and* install the
261            # .egg files that setup.py downloads.
262            cd "$WORKSPACE/$1" \
263                 && python setup.py test ${testargs[$1]} \
264                 && (easy_install *.egg || true)
265         else
266             "test_$1"
267         fi
268         checkexit "$1 tests"
269         title "End of $1 tests (`timer`)"
270     else
271         title "Skipping $1 tests"
272     fi
273 }
274
275 do_install() {
276     if [[ -z "$skip_install" ]]
277     then
278         title "Running $1 install"
279         timer_reset
280         if [[ "$2" == "go" ]]
281         then
282             go get -t "git.curoverse.com/arvados.git/$1"
283         elif [[ "$2" == "pip" ]]
284         then
285             cd "$WORKSPACE/$1" \
286                 && python setup.py sdist rotate --keep=1 --match .tar.gz \
287                 && pip install --upgrade dist/*.tar.gz
288         else
289             "install_$1"
290         fi
291         checkexit "$1 install"
292         title "End of $1 install (`timer`)"
293     else
294         title "Skipping $1 install"
295     fi
296 }
297
298 title () {
299     txt="********** $1 **********"
300     printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
301 }
302
303 install_docs() {
304     cd "$WORKSPACE/doc"
305     bundle install --no-deployment
306     rm -rf .site
307     # Make sure python-epydoc is installed or the next line won't do much good!
308     ARVADOS_API_HOST=qr1hi.arvadosapi.com
309     PYTHONPATH=$WORKSPACE/sdk/python/ bundle exec rake generate baseurl=file://$WORKSPACE/doc/.site/ arvados_workbench_host=workbench.$ARVADOS_API_HOST arvados_api_host=$ARVADOS_API_HOST
310     unset ARVADOS_API_HOST
311 }
312 do_install docs
313
314 install_ruby_sdk() {
315     cd "$WORKSPACE/sdk/ruby" \
316         && bundle install --no-deployment \
317         && gem build arvados.gemspec \
318         && GEM_HOME="$tmpdir_gem_home" gem install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
319 }
320 do_install ruby_sdk
321
322 install_cli() {
323     cd "$WORKSPACE/sdk/cli" \
324         && bundle install --no-deployment \
325         && gem build arvados-cli.gemspec \
326         && GEM_HOME="$tmpdir_gem_home" gem install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
327 }
328 do_install cli
329
330 # Install the Python SDK early. Various other test suites (like
331 # keepproxy) bring up run_test_server.py, which imports the arvados
332 # module. We can't actually *test* the Python SDK yet though, because
333 # its own test suite brings up some of those other programs (like
334 # keepproxy).
335 declare -a pythonstuff
336 pythonstuff=(
337     sdk/python
338     services/fuse
339     services/nodemanager
340     )
341 for p in "${pythonstuff[@]}"
342 do
343     do_install "$p" pip
344 done
345
346 install_apiserver() {
347     cd "$WORKSPACE/services/api"
348     export RAILS_ENV=test
349     bundle install --no-deployment
350
351     rm -f config/environments/test.rb
352     cp config/environments/test.rb.example config/environments/test.rb
353
354     if [ -n "$CONFIGSRC" ]
355     then
356         for f in database.yml application.yml
357         do
358             cp "$CONFIGSRC/$f" config/ || fatal "$f"
359         done
360     fi
361
362     # Fill in a random secret_token and blob_signing_key for testing
363     SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
364     BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
365
366     sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
367     sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
368
369     # Set up empty git repo (for git tests)
370     GITDIR=$(mktemp -d)
371     sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
372
373     rm -rf $GITDIR
374     mkdir -p $GITDIR/test
375     cd $GITDIR/test \
376         && git init \
377         && git config user.email "jenkins@ci.curoverse.com" \
378         && git config user.name "Jenkins, CI" \
379         && touch tmp \
380         && git add tmp \
381         && git commit -m 'initial commit'
382
383     # Clear out any lingering postgresql connections to arvados_test, so that we can drop it
384     # This assumes the current user is a postgresql superuser
385     psql arvados_test -c "SELECT pg_terminate_backend (pg_stat_activity.procpid::int) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'arvados_test';" 2>/dev/null
386
387     cd "$WORKSPACE/services/api" \
388         && bundle exec rake db:drop \
389         && bundle exec rake db:create \
390         && bundle exec rake db:setup
391 }
392 do_install apiserver
393
394 declare -a gostuff
395 gostuff=(
396     services/crunchstat
397     services/keepstore
398     services/keepproxy
399     sdk/go/arvadosclient
400     sdk/go/keepclient
401     sdk/go/streamer
402     )
403 for g in "${gostuff[@]}"
404 do
405     do_install "$g" go
406 done
407
408 test_doclinkchecker() {
409     cd "$WORKSPACE/doc"
410     bundle exec rake linkchecker baseurl=file://$WORKSPACE/doc/.site/
411 }
412 do_test doclinkchecker
413
414 test_ruby_sdk() {
415     cd "$WORKSPACE/sdk/ruby" \
416         && bundle install --no-deployment \
417         && bundle exec rake test ${testargs[sdk/ruby]}
418 }
419 do_test ruby_sdk
420
421 test_cli() {
422     title "Starting SDK CLI tests"
423     cd "$WORKSPACE/sdk/cli" \
424         && bundle install --no-deployment \
425         && mkdir -p /tmp/keep \
426         && KEEP_LOCAL_STORE=/tmp/keep bundle exec rake test ${testargs[sdk/cli]}
427 }
428 do_test cli
429
430 test_apiserver() {
431     cd "$WORKSPACE/services/api"
432     bundle exec rake test ${testargs[apiserver]}
433 }
434 do_test apiserver
435
436 # We must test sdk/python before testing services/keepproxy, because
437 # keepproxy depends on sdk/python's test dependencies.
438 for p in "${pythonstuff[@]}"
439 do
440     do_test "$p" pip
441 done
442
443 for g in "${gostuff[@]}"
444 do
445     do_test "$g" go
446 done
447
448 test_workbench() {
449     cd "$WORKSPACE/apps/workbench" \
450         && bundle install --no-deployment \
451         && bundle exec rake test ${testargs[workbench]}
452 }
453 do_test workbench
454
455 report_outcomes
456 clear_temp
457
458 exit ${#failures}