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