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