Merge branch '3848-build-packages-pyversion'
[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_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 $(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 # Set up temporary install dirs (unless existing dirs were supplied)
169 for tmpdir in VENVDIR GOPATH GEMHOME
170 do
171     if [[ -n "${!tmpdir}" ]]; then
172         leave_temp[$tmpdir]=1
173     else
174         eval $tmpdir=$(mktemp -d)
175     fi
176 done
177 PATH="$GEMHOME/.gem/ruby/2.1.0/bin:$PATH"
178 export GOPATH
179 mkdir -p "$GOPATH/src/git.curoverse.com"
180 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
181     || fatal "symlink failed"
182
183 virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
184 . "$VENVDIR/bin/activate"
185
186 checkexit() {
187     if [[ "$?" != "0" ]]; then
188         title "!!!!!! $1 FAILED !!!!!!"
189         failures+=("$1 (`timer`)")
190     else
191         successes+=("$1 (`timer`)")
192     fi
193 }
194
195 timer_reset() {
196     t0=$SECONDS
197 }
198
199 timer() {
200     echo -n "$(($SECONDS - $t0))s"
201 }
202
203 do_test() {
204     if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
205     then
206         title "Running $1 tests"
207         timer_reset
208         if [[ "$2" == "go" ]]
209         then
210             go test "git.curoverse.com/arvados.git/$1"
211         else
212             "test_$1"
213         fi
214         checkexit "$1 tests"
215         title "End of $1 tests (`timer`)"
216     else
217         title "Skipping $1 tests"
218     fi
219 }
220
221 do_install() {
222     if [[ -z "$skip_install" ]]
223     then
224         title "Running $1 install"
225         timer_reset
226         if [[ "$2" == "go" ]]
227         then
228             go get -t "git.curoverse.com/arvados.git/$1"
229         else
230             "install_$1"
231         fi
232         checkexit "$1 install"
233         title "End of $1 install (`timer`)"
234     else
235         title "Skipping $1 install"
236     fi
237 }
238
239 title () {
240     txt="********** $1 **********"
241     printf "\n%*s%s\n\n" $((($COLUMNS-${#txt})/2)) "" "$txt"
242 }
243
244 install_docs() {
245     cd "$WORKSPACE/doc"
246     HOME="$GEMHOME" bundle install --no-deployment
247     rm -rf .site
248     # Make sure python-epydoc is installed or the next line won't do much good!
249     ARVADOS_API_HOST=qr1hi.arvadosapi.com
250     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
251     unset ARVADOS_API_HOST
252 }
253 do_install docs
254
255 install_ruby_sdk() {
256     cd "$WORKSPACE/sdk/ruby" \
257         && HOME="$GEMHOME" bundle install --no-deployment \
258         && gem build arvados.gemspec \
259         && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
260 }
261 do_install ruby_sdk
262
263 install_cli() {
264     cd "$WORKSPACE/sdk/cli" \
265         && gem build arvados-cli.gemspec \
266         && HOME="$GEMHOME" gem install --user-install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
267 }
268 do_install cli
269
270 install_python_sdk() {
271     # Install the Python SDK early. Various other test suites (like
272     # keepproxy) bring up run_test_server.py, which imports the arvados
273     # module. We can't actually *test* the Python SDK yet though, because
274     # its own test suite brings up some of those other programs (like
275     # keepproxy).
276
277     cd "$WORKSPACE/sdk/python" \
278         && python setup.py sdist rotate --keep=1 --match .tar.gz \
279         && pip install dist/arvados-python-client-0.1.*.tar.gz
280 }
281 do_install python_sdk
282
283 install_fuse() {
284     cd "$WORKSPACE/services/fuse" \
285         && python setup.py sdist rotate --keep=1 --match .tar.gz \
286         && pip install dist/arvados_fuse-0.1.*.tar.gz
287 }
288 do_install fuse
289
290 install_apiserver() {
291     cd "$WORKSPACE/services/api"
292     export RAILS_ENV=test
293     HOME="$GEMHOME" bundle install --no-deployment
294
295     rm -f config/environments/test.rb
296     cp config/environments/test.rb.example config/environments/test.rb
297
298     if [ -n "$CONFIGSRC" ]
299     then
300         for f in database.yml application.yml
301         do
302             cp "$CONFIGSRC/$f" config/ || fatal "$f"
303         done
304     fi
305
306     # Fill in a random secret_token and blob_signing_key for testing
307     SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
308     BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
309
310     sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
311     sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
312
313     # Set up empty git repo (for git tests)
314     GITDIR=$(mktemp -d)
315     sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
316
317     rm -rf $GITDIR
318     mkdir -p $GITDIR/test
319     cd $GITDIR/test \
320         && git init \
321         && git config user.email "jenkins@ci.curoverse.com" \
322         && git config user.name "Jenkins, CI" \
323         && touch tmp \
324         && git add tmp \
325         && git commit -m 'initial commit'
326
327     # Clear out any lingering postgresql connections to arvados_test, so that we can drop it
328     # This assumes the current user is a postgresql superuser
329     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
330
331     cd "$WORKSPACE/services/api" \
332         && HOME="$GEMHOME" bundle exec rake db:drop \
333         && HOME="$GEMHOME" bundle exec rake db:create \
334         && HOME="$GEMHOME" bundle exec rake db:setup
335 }
336 do_install apiserver
337
338 declare -a gostuff
339 gostuff=(
340     services/keepstore
341     services/keepproxy
342     sdk/go/arvadosclient
343     sdk/go/keepclient
344     sdk/go/streamer
345     )
346 for g in "${gostuff[@]}"
347 do
348     do_install "$g" go
349 done
350
351 test_doclinkchecker() {
352     cd "$WORKSPACE/doc"
353     HOME="$GEMHOME" bundle exec rake linkchecker baseurl=file://$WORKSPACE/doc/.site/
354 }
355 do_test doclinkchecker
356
357 test_ruby_sdk() {
358     cd "$WORKSPACE/sdk/ruby" \
359         && HOME="$GEMHOME" bundle install --no-deployment \
360         && HOME="$GEMHOME" bundle exec rake test
361 }
362 do_test ruby_sdk
363
364 test_cli() {
365     title "Starting SDK CLI tests"
366     cd "$WORKSPACE/sdk/cli" \
367         && HOME="$GEMHOME" bundle install --no-deployment \
368         && mkdir -p /tmp/keep \
369         && KEEP_LOCAL_STORE=/tmp/keep HOME="$GEMHOME" bundle exec rake test $cli_test
370 }
371 do_test cli
372
373 test_apiserver() {
374     cd "$WORKSPACE/services/api"
375     HOME="$GEMHOME" bundle exec rake test $apiserver_test
376 }
377 do_test apiserver
378
379 test_python_sdk() {
380     # Python SDK. We test this before testing keepproxy: keepproxy runs
381     # run_test_server.py, which depends on the yaml package, which is in
382     # tests_require but not install_requires, and therefore does not get
383     # installed by setuptools until we run "setup.py test" *and* install
384     # the .egg files that setup.py downloads.
385
386     cd "$WORKSPACE/sdk/python" \
387         && python setup.py test $python_sdk_test
388     r=$?
389     easy_install *.egg
390     return $r
391 }
392 do_test python_sdk
393
394 test_fuse() {
395     # Install test dependencies here too, in case run_test_server needs them.
396     cd "$WORKSPACE/services/fuse" \
397         && python setup.py test $fuse_test
398     r=$?
399     easy_install *.egg
400     return $r
401 }
402 do_test fuse
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 $workbench_test
413 }
414 do_test workbench
415
416 report_outcomes
417 clear_temp
418
419 exit ${#failures}