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