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