Export vars provided on command line, e.g., ARVADOS_DEBUG=1. No issue #
[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 python_sdk_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 cli_test=
63 workbench_test=
64 apiserver_test=
65 python_sdk_test=
66 ruby_sdk_test=
67 fuse_test=
68 leave_temp=
69 skip_install=
70
71 if [[ -f /etc/profile.d/rvm.sh ]]
72 then
73     source /etc/profile.d/rvm.sh
74 fi
75
76 declare -A leave_temp
77 clear_temp() {
78     leaving=""
79     for var in VENVDIR GOPATH GITDIR GEMHOME
80     do
81         if [[ -z "${leave_temp[$var]}" ]]
82         then
83             if [[ -n "${!var}" ]]
84             then
85                 rm -rf "${!var}"
86             fi
87         else
88             leaving+=" $var=\"${!var}\""
89         fi
90     done
91     if [[ -n "$leaving" ]]; then
92         echo "Leaving behind temp dirs: $leaving"
93     fi
94 }
95
96 fatal() {
97     clear_temp
98     echo >&2 "Fatal: $* in ${FUNCNAME[1]} at ${BASH_SOURCE[1]} line ${BASH_LINENO[0]}"
99     exit 1
100 }
101
102 report_outcomes() {
103     for x in "${successes[@]}"
104     do
105         echo "Pass: $x"
106     done
107
108     if [[ ${#failures[@]} == 0 ]]
109     then
110         echo "All test suites passed."
111     else
112         echo "Failures (${#failures[@]}):"
113         for x in "${failures[@]}"
114         do
115             echo "Fail: $x"
116         done
117     fi
118 }
119 declare -a failures
120 declare -A skip
121
122 # Always skip CLI tests. They don't know how to use run_test_server.py.
123 skip[cli]=1
124
125 while [[ -n "$1" ]]
126 do
127     arg="$1"; shift
128     case "$arg" in
129         --help)
130             echo >&2 "$helpmessage"
131             echo >&2
132             exit 1
133             ;;
134         --skip)
135             skipwhat="$1"; shift
136             skip[$skipwhat]=1
137             ;;
138         --only)
139             only="$1"; shift
140             ;;
141         --skip-install)
142             skip_install=1
143             ;;
144         --leave-temp)
145             leave_temp[VENVDIR]=1
146             leave_temp[GOPATH]=1
147             leave_temp[GEMHOME]=1
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         else
216             "test_$1"
217         fi
218         checkexit "$1 tests"
219         title "End of $1 tests (`timer`)"
220     else
221         title "Skipping $1 tests"
222     fi
223 }
224
225 do_install() {
226     if [[ -z "$skip_install" ]]
227     then
228         title "Running $1 install"
229         timer_reset
230         if [[ "$2" == "go" ]]
231         then
232             go get -t "git.curoverse.com/arvados.git/$1"
233         else
234             "install_$1"
235         fi
236         checkexit "$1 install"
237         title "End of $1 install (`timer`)"
238     else
239         title "Skipping $1 install"
240     fi
241 }
242
243 title () {
244     txt="********** $1 **********"
245     printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
246 }
247
248 install_docs() {
249     cd "$WORKSPACE/doc"
250     HOME="$GEMHOME" bundle install --no-deployment
251     rm -rf .site
252     # Make sure python-epydoc is installed or the next line won't do much good!
253     ARVADOS_API_HOST=qr1hi.arvadosapi.com
254     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
255     unset ARVADOS_API_HOST
256 }
257 do_install docs
258
259 install_ruby_sdk() {
260     cd "$WORKSPACE/sdk/ruby" \
261         && HOME="$GEMHOME" bundle install --no-deployment \
262         && gem build arvados.gemspec \
263         && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
264 }
265 do_install ruby_sdk
266
267 install_cli() {
268     cd "$WORKSPACE/sdk/cli" \
269         && gem build arvados-cli.gemspec \
270         && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
271 }
272 do_install cli
273
274 install_python_sdk() {
275     # Install the Python SDK early. Various other test suites (like
276     # keepproxy) bring up run_test_server.py, which imports the arvados
277     # module. We can't actually *test* the Python SDK yet though, because
278     # its own test suite brings up some of those other programs (like
279     # keepproxy).
280
281     cd "$WORKSPACE/sdk/python" \
282         && python setup.py sdist rotate --keep=1 --match .tar.gz \
283         && pip install dist/arvados-python-client-0.1.*.tar.gz
284 }
285 do_install python_sdk
286
287 install_fuse() {
288     cd "$WORKSPACE/services/fuse" \
289         && python setup.py sdist rotate --keep=1 --match .tar.gz \
290         && pip install dist/arvados_fuse-0.1.*.tar.gz
291 }
292 do_install fuse
293
294 install_apiserver() {
295     cd "$WORKSPACE/services/api"
296     export RAILS_ENV=test
297     HOME="$GEMHOME" bundle install --no-deployment
298
299     rm -f config/environments/test.rb
300     cp config/environments/test.rb.example config/environments/test.rb
301
302     if [ -n "$CONFIGSRC" ]
303     then
304         for f in database.yml application.yml
305         do
306             cp "$CONFIGSRC/$f" config/ || fatal "$f"
307         done
308     fi
309
310     # Fill in a random secret_token and blob_signing_key for testing
311     SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
312     BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
313
314     sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
315     sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
316
317     # Set up empty git repo (for git tests)
318     GITDIR=$(mktemp -d)
319     sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
320
321     rm -rf $GITDIR
322     mkdir -p $GITDIR/test
323     cd $GITDIR/test \
324         && git init \
325         && git config user.email "jenkins@ci.curoverse.com" \
326         && git config user.name "Jenkins, CI" \
327         && touch tmp \
328         && git add tmp \
329         && git commit -m 'initial commit'
330
331     # Clear out any lingering postgresql connections to arvados_test, so that we can drop it
332     # This assumes the current user is a postgresql superuser
333     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
334
335     cd "$WORKSPACE/services/api" \
336         && HOME="$GEMHOME" bundle exec rake db:drop \
337         && HOME="$GEMHOME" bundle exec rake db:create \
338         && HOME="$GEMHOME" bundle exec rake db:setup
339 }
340 do_install apiserver
341
342 declare -a gostuff
343 gostuff=(
344     services/crunchstat
345     services/keepstore
346     services/keepproxy
347     sdk/go/arvadosclient
348     sdk/go/keepclient
349     sdk/go/streamer
350     )
351 for g in "${gostuff[@]}"
352 do
353     do_install "$g" go
354 done
355
356 test_doclinkchecker() {
357     cd "$WORKSPACE/doc"
358     HOME="$GEMHOME" bundle exec rake linkchecker baseurl=file://$WORKSPACE/doc/.site/
359 }
360 do_test doclinkchecker
361
362 test_ruby_sdk() {
363     cd "$WORKSPACE/sdk/ruby" \
364         && HOME="$GEMHOME" bundle install --no-deployment \
365         && HOME="$GEMHOME" bundle exec rake test
366 }
367 do_test ruby_sdk
368
369 test_cli() {
370     title "Starting SDK CLI tests"
371     cd "$WORKSPACE/sdk/cli" \
372         && HOME="$GEMHOME" bundle install --no-deployment \
373         && mkdir -p /tmp/keep \
374         && KEEP_LOCAL_STORE=/tmp/keep HOME="$GEMHOME" bundle exec rake test $cli_test
375 }
376 do_test cli
377
378 test_apiserver() {
379     cd "$WORKSPACE/services/api"
380     HOME="$GEMHOME" bundle exec rake test $apiserver_test
381 }
382 do_test apiserver
383
384 test_python_sdk() {
385     # Python SDK. We test this before testing keepproxy: keepproxy runs
386     # run_test_server.py, which depends on the yaml package, which is in
387     # tests_require but not install_requires, and therefore does not get
388     # installed by setuptools until we run "setup.py test" *and* install
389     # the .egg files that setup.py downloads.
390
391     cd "$WORKSPACE/sdk/python" \
392         && python setup.py test $python_sdk_test
393     r=$?
394     easy_install *.egg
395     return $r
396 }
397 do_test python_sdk
398
399 test_fuse() {
400     # Install test dependencies here too, in case run_test_server needs them.
401     cd "$WORKSPACE/services/fuse" \
402         && python setup.py test $fuse_test
403     r=$?
404     easy_install *.egg
405     return $r
406 }
407 do_test fuse
408
409 test_nodemanager() {
410     cd "$WORKSPACE/services/nodemanager" && python setup.py test
411 }
412 do_test nodemanager
413
414 for g in "${gostuff[@]}"
415 do
416     do_test "$g" go
417 done
418
419 test_workbench() {
420     cd "$WORKSPACE/apps/workbench" \
421         && HOME="$GEMHOME" bundle install --no-deployment \
422         && HOME="$GEMHOME" bundle exec rake test $workbench_test
423 }
424 do_test workbench
425
426 report_outcomes
427 clear_temp
428
429 exit ${#failures}