4400: Fix syntax error.
[arvados.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 # Always skip CLI tests. They don't know how to use run_test_server.py.
118 skip[cli]=1
119
120 while [[ -n "$1" ]]
121 do
122     arg="$1"; shift
123     case "$arg" in
124         --help)
125             echo >&2 "$helpmessage"
126             echo >&2
127             exit 1
128             ;;
129         --skip)
130             skipwhat="$1"; shift
131             skip[$skipwhat]=1
132             ;;
133         --only)
134             only="$1"; shift
135             ;;
136         --skip-install)
137             skip_install=1
138             ;;
139         --leave-temp)
140             leave_temp[VENVDIR]=1
141             leave_temp[GOPATH]=1
142             leave_temp[GEMHOME]=1
143             ;;
144         *_test=*)
145             suite="${arg%%_test=*}"
146             args="${arg#*=}"
147             testargs["$suite"]="$args"
148             ;;
149         *=*)
150             eval export $(echo $arg | cut -d= -f1)=\"$(echo $arg | cut -d= -f2-)\"
151             ;;
152         *)
153             echo >&2 "$0: Unrecognized option: '$arg'. Try: $0 --help"
154             exit 1
155             ;;
156     esac
157 done
158
159 # Sanity check
160 echo "WORKSPACE=$WORKSPACE"
161 [[ -n "$WORKSPACE" ]] || fatal "WORKSPACE not set"
162
163 if [[ -z "$CONFIGSRC" ]] && [[ -d "$HOME/arvados-api-server" ]]; then
164     # Jenkins expects us to use this by default.
165     CONFIGSRC="$HOME/arvados-api-server"
166 fi
167
168 # Clean up .pyc files that may exist in the workspace
169 cd "$WORKSPACE"
170 find -name '*.pyc' -delete
171
172 # Set up temporary install dirs (unless existing dirs were supplied)
173 for tmpdir in VENVDIR GOPATH GEMHOME
174 do
175     if [[ -n "${!tmpdir}" ]]; then
176         leave_temp[$tmpdir]=1
177     else
178         eval $tmpdir=$(mktemp -d)
179     fi
180 done
181 PATH="$GEMHOME/.gem/ruby/2.1.0/bin:$PATH"
182 export GOPATH
183 mkdir -p "$GOPATH/src/git.curoverse.com"
184 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
185     || fatal "symlink failed"
186
187 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
188 . "$VENVDIR/bin/activate"
189
190 checkexit() {
191     if [[ "$?" != "0" ]]; then
192         title "!!!!!! $1 FAILED !!!!!!"
193         failures+=("$1 (`timer`)")
194     else
195         successes+=("$1 (`timer`)")
196     fi
197 }
198
199 timer_reset() {
200     t0=$SECONDS
201 }
202
203 timer() {
204     echo -n "$(($SECONDS - $t0))s"
205 }
206
207 do_test() {
208     if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
209     then
210         title "Running $1 tests"
211         timer_reset
212         if [[ "$2" == "go" ]]
213         then
214             go test "git.curoverse.com/arvados.git/$1"
215         elif [[ "$2" == "pip" ]]
216         then
217            # Other test suites can depend on tests_require
218            # dependencies of this package. For example, keepproxy runs
219            # run_test_server.py, which depends on the yaml package,
220            # which is in sdk/python's tests_require but not
221            # install_requires, and therefore does not get installed by
222            # setuptools until we run "setup.py test" *and* install the
223            # .egg files that setup.py downloads.
224            cd "$WORKSPACE/$1" \
225                 && HOME="$GEMHOME" python setup.py test ${testargs[$1]} \
226                 && easy_install *.egg
227         else
228             "test_$1"
229         fi
230         checkexit "$1 tests"
231         title "End of $1 tests (`timer`)"
232     else
233         title "Skipping $1 tests"
234     fi
235 }
236
237 do_install() {
238     if [[ -z "$skip_install" ]]
239     then
240         title "Running $1 install"
241         timer_reset
242         if [[ "$2" == "go" ]]
243         then
244             go get -t "git.curoverse.com/arvados.git/$1"
245         elif [[ "$2" == "pip" ]]
246         then
247             cd "$WORKSPACE/$1" \
248                 && python setup.py sdist rotate --keep=1 --match .tar.gz \
249                 && pip install --upgrade dist/*.tar.gz
250         else
251             "install_$1"
252         fi
253         checkexit "$1 install"
254         title "End of $1 install (`timer`)"
255     else
256         title "Skipping $1 install"
257     fi
258 }
259
260 title () {
261     txt="********** $1 **********"
262     printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
263 }
264
265 install_docs() {
266     cd "$WORKSPACE/doc"
267     HOME="$GEMHOME" bundle install --no-deployment
268     rm -rf .site
269     # Make sure python-epydoc is installed or the next line won't do much good!
270     ARVADOS_API_HOST=qr1hi.arvadosapi.com
271     PYTHONPATH=$WORKSPACE/sdk/python/ HOME="$GEMHOME" bundle exec rake generate baseurl=file://$WORKSPACE/doc/.site/ arvados_workbench_host=workbench.$ARVADOS_API_HOST arvados_api_host=$ARVADOS_API_HOST
272     unset ARVADOS_API_HOST
273 }
274 do_install docs
275
276 install_ruby_sdk() {
277     cd "$WORKSPACE/sdk/ruby" \
278         && HOME="$GEMHOME" bundle install --no-deployment \
279         && gem build arvados.gemspec \
280         && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
281 }
282 do_install ruby_sdk
283
284 install_cli() {
285     cd "$WORKSPACE/sdk/cli" \
286         && gem build arvados-cli.gemspec \
287         && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
288 }
289 do_install cli
290
291 # Install the Python SDK early. Various other test suites (like
292 # keepproxy) bring up run_test_server.py, which imports the arvados
293 # module. We can't actually *test* the Python SDK yet though, because
294 # its own test suite brings up some of those other programs (like
295 # keepproxy).
296 declare -a pythonstuff
297 pythonstuff=(
298     sdk/python
299     services/fuse
300     services/nodemanager
301     )
302 for p in "${pythonstuff[@]}"
303 do
304     do_install "$p" pip
305 done
306
307 install_apiserver() {
308     cd "$WORKSPACE/services/api"
309     export RAILS_ENV=test
310     HOME="$GEMHOME" bundle install --no-deployment
311
312     rm -f config/environments/test.rb
313     cp config/environments/test.rb.example config/environments/test.rb
314
315     if [ -n "$CONFIGSRC" ]
316     then
317         for f in database.yml application.yml
318         do
319             cp "$CONFIGSRC/$f" config/ || fatal "$f"
320         done
321     fi
322
323     # Fill in a random secret_token and blob_signing_key for testing
324     SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
325     BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
326
327     sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
328     sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
329
330     # Set up empty git repo (for git tests)
331     GITDIR=$(mktemp -d)
332     sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
333
334     rm -rf $GITDIR
335     mkdir -p $GITDIR/test
336     cd $GITDIR/test \
337         && git init \
338         && git config user.email "jenkins@ci.curoverse.com" \
339         && git config user.name "Jenkins, CI" \
340         && touch tmp \
341         && git add tmp \
342         && git commit -m 'initial commit'
343
344     # Clear out any lingering postgresql connections to arvados_test, so that we can drop it
345     # This assumes the current user is a postgresql superuser
346     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
347
348     cd "$WORKSPACE/services/api" \
349         && HOME="$GEMHOME" bundle exec rake db:drop \
350         && HOME="$GEMHOME" bundle exec rake db:create \
351         && HOME="$GEMHOME" bundle exec rake db:setup
352 }
353 do_install apiserver
354
355 declare -a gostuff
356 gostuff=(
357     services/crunchstat
358     services/keepstore
359     services/keepproxy
360     sdk/go/arvadosclient
361     sdk/go/keepclient
362     sdk/go/streamer
363     )
364 for g in "${gostuff[@]}"
365 do
366     do_install "$g" go
367 done
368
369 test_doclinkchecker() {
370     cd "$WORKSPACE/doc"
371     HOME="$GEMHOME" bundle exec rake linkchecker baseurl=file://$WORKSPACE/doc/.site/
372 }
373 do_test doclinkchecker
374
375 test_ruby_sdk() {
376     cd "$WORKSPACE/sdk/ruby" \
377         && HOME="$GEMHOME" bundle install --no-deployment \
378         && HOME="$GEMHOME" bundle exec rake test ${testargs[sdk/ruby]}
379 }
380 do_test ruby_sdk
381
382 test_cli() {
383     title "Starting SDK CLI tests"
384     cd "$WORKSPACE/sdk/cli" \
385         && HOME="$GEMHOME" bundle install --no-deployment \
386         && mkdir -p /tmp/keep \
387         && KEEP_LOCAL_STORE=/tmp/keep HOME="$GEMHOME" bundle exec rake test ${testargs[sdk/cli]}
388 }
389 do_test cli
390
391 test_apiserver() {
392     cd "$WORKSPACE/services/api"
393     HOME="$GEMHOME" bundle exec rake test ${testargs[apiserver]}
394 }
395 do_test apiserver
396
397 # We must test sdk/python before testing services/keepproxy, because
398 # keepproxy depends on sdk/python's test dependencies.
399 for p in "${pythonstuff[@]}"
400 do
401     do_test "$p" pip
402 done
403
404 for g in "${gostuff[@]}"
405 do
406     do_test "$g" go
407 done
408
409 test_workbench() {
410     cd "$WORKSPACE/apps/workbench" \
411         && HOME="$GEMHOME" bundle install --no-deployment \
412         && HOME="$GEMHOME" bundle exec rake test ${testargs[workbench]}
413 }
414 do_test workbench
415
416 report_outcomes
417 clear_temp
418
419 exit ${#failures}