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