Merge branch '7311-temp-base' closes #7311
[arvados-dev.git] / jenkins / run-tests.sh
index fe33948bf369ec93bd376617fbfa2fa975722bdd..639cd14588a90098bb579043292cf64ea17fc9ce 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+. `dirname "$(readlink -f "$0")"`/libcloud-pin
+
 read -rd "\000" helpmessage <<EOF
 $(basename $0): Install and test Arvados components.
 
@@ -12,9 +14,11 @@ Options:
 
 --skip FOO     Do not test the FOO component.
 --only FOO     Do not test anything except the FOO component.
+--temp DIR     Install components and dependencies under DIR instead of
+               making a new temporary directory. Implies --leave-temp.
 --leave-temp   Do not remove GOPATH, virtualenv, and other temp dirs at exit.
-               Instead, show which directories were used this time so they
-               can be reused in subsequent invocations.
+               Instead, show the path to give as --temp to reuse them in
+               subsequent invocations.
 --skip-install Do not run any install steps. Just run tests.
                You should provide GOPATH, GEMHOME, and VENVDIR options
                from a previous invocation if you use this option.
@@ -60,9 +64,11 @@ services/dockercleaner
 services/fuse
 services/keepproxy
 services/keepstore
+services/login-sync
 services/nodemanager
 services/arv-git-httpd
 sdk/cli
+sdk/pam
 sdk/python
 sdk/ruby
 sdk/go/arvadosclient
@@ -83,29 +89,22 @@ VENVDIR=
 VENV3DIR=
 PYTHONPATH=
 GEMHOME=
+PERLINSTALLBASE=
 
 COLUMNS=80
 
-leave_temp=
 skip_install=
+temp=
+temp_preserve=
 
-declare -A leave_temp
 clear_temp() {
-    leaving=""
-    for var in VENVDIR VENV3DIR GOPATH GITDIR GEMHOME
-    do
-        if [[ -z "${leave_temp[$var]}" ]]
-        then
-            if [[ -n "${!var}" ]]
-            then
-                rm -rf "${!var}"
-            fi
-        else
-            leaving+=" $var=\"${!var}\""
-        fi
-    done
-    if [[ -n "$leaving" ]]; then
-        echo "Leaving behind temp dirs: $leaving"
+    if [[ -z "$temp" ]]; then
+        # we didn't even get as far as making a temp dir
+        :
+    elif [[ -z "$temp_preserve" ]]; then
+        rm -rf "$temp"
+    else
+        echo "Leaving behind temp dirs in $temp"
     fi
 }
 
@@ -166,6 +165,17 @@ sanity_checks() {
     echo -n 'nginx: '
     PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" nginx -v \
         || fatal "No nginx. Try: apt-get install nginx"
+    echo -n 'perl: '
+    perl -v | grep version \
+        || fatal "No perl. Try: apt-get install perl"
+    for mod in ExtUtils::MakeMaker JSON LWP Net::SSL; do
+        echo -n "perl $mod: "
+        perl -e "use $mod; print \"\$$mod::VERSION\\n\"" \
+            || fatal "No $mod. Try: apt-get install perl-modules libcrypt-ssleay-perl libjson-perl"
+    done
+    echo -n 'gitolite: '
+    which gitolite \
+        || fatal "No gitolite. Try: apt-get install gitolite3"
 }
 
 rotate_logfile() {
@@ -206,11 +216,12 @@ do
             skip_install=1
             only_install="$1"; shift
             ;;
+        --temp)
+            temp="$1"; shift
+            temp_preserve=1
+            ;;
         --leave-temp)
-            leave_temp[VENVDIR]=1
-            leave_temp[VENV3DIR]=1
-            leave_temp[GOPATH]=1
-            leave_temp[GEMHOME]=1
+            temp_preserve=1
             ;;
         --retry)
             retry=1
@@ -282,14 +293,18 @@ fi
 cd "$WORKSPACE"
 find -name '*.pyc' -delete
 
+if [[ -z "$temp" ]]; then
+    temp="$(mktemp -d)"
+fi
+
 # Set up temporary install dirs (unless existing dirs were supplied)
-for tmpdir in VENVDIR VENV3DIR GOPATH GEMHOME
+for tmpdir in VENVDIR VENV3DIR GOPATH GEMHOME PERLINSTALLBASE
 do
-    if [[ -n "${!tmpdir}" ]]; then
-        leave_temp[$tmpdir]=1
-        mkdir -p "${!tmpdir}"
-    else
-        eval "$tmpdir"='$(mktemp -d)'
+    if [[ -z "${!tmpdir}" ]]; then
+        eval "$tmpdir"="$temp/$tmpdir"
+    fi
+    if ! [[ -d "${!tmpdir}" ]]; then
+        mkdir "${!tmpdir}" || fatal "can't create ${!tmpdir} (does $temp exist?)"
     fi
 done
 
@@ -359,18 +374,33 @@ with_test_gemset() {
     if [[ "$using_rvm" == true ]]; then
         "$@"
     else
-        GEM_HOME="$tmpdir_gem_home" "$@"
+        GEM_HOME="$tmpdir_gem_home" GEM_PATH="$tmpdir_gem_home" "$@"
+    fi
+}
+
+gem_uninstall_if_exists() {
+    if gem list "$1\$" | egrep '^\w'; then
+        gem uninstall --force --all --executables "$1"
     fi
 }
 
+export PERLINSTALLBASE
+export PERLLIB="$PERLINSTALLBASE/lib/perl5:${PERLLIB:+$PERLLIB}"
+
 export GOPATH
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
     || fatal "symlink failed"
 
-virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
+if ! [[ -e "$VENVDIR/bin/activate" ]] || ! [[ -e "$VENVDIR/bin/pip" ]]; then
+    virtualenv --setuptools "$VENVDIR" || fatal "virtualenv $VENVDIR failed"
+fi
 . "$VENVDIR/bin/activate"
 
+if (pip install setuptools | grep setuptools-0) || [ "$($VENVDIR/bin/easy_install --version | cut -d\  -f2 | cut -d. -f1)" -lt 18 ]; then
+    pip install --upgrade setuptools pip
+fi
+
 # Note: this must be the last time we change PATH, otherwise rvm will
 # whine a lot.
 setup_ruby_environment
@@ -387,6 +417,12 @@ pip freeze 2>/dev/null | egrep ^PyYAML= \
     || pip install PyYAML >/dev/null \
     || fatal "pip install PyYAML failed"
 
+# Preinstall forked version of libcloud, because nodemanager "pip install"
+# won't pick it up by default.
+pip freeze 2>/dev/null | egrep ^apache-libcloud==$LIBCLOUD_PIN \
+    || pip install --pre --ignore-installed https://github.com/curoverse/libcloud/archive/apache-libcloud-$LIBCLOUD_PIN.zip >/dev/null \
+    || fatal "pip install apache-libcloud failed"
+
 # If Python 3 is available, set up its virtualenv in $VENV3DIR.
 # Otherwise, skip dependent tests.
 PYTHON3=$(which python3)
@@ -433,22 +469,28 @@ do_test() {
 }
 
 do_test_once() {
+    unset result
     if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$1" ]] )
     then
         title "Running $1 tests"
         timer_reset
         if [[ "$2" == "go" ]]
         then
+            covername="coverage-$(echo "$1" | sed -e 's/\//_/g')"
+            coverflags=("-covermode=count" "-coverprofile=$WORKSPACE/tmp/.$covername.tmp")
             if [[ -n "${testargs[$1]}" ]]
             then
                 # "go test -check.vv giturl" doesn't work, but this
                 # does:
-                cd "$WORKSPACE/$1" && go test ${testargs[$1]}
+                cd "$WORKSPACE/$1" && go test ${coverflags[@]} ${testargs[$1]}
             else
                 # The above form gets verbose even when testargs is
                 # empty, so use this form in such cases:
-                go test "git.curoverse.com/arvados.git/$1"
+                go test ${coverflags[@]} "git.curoverse.com/arvados.git/$1"
             fi
+            result="$?"
+            go tool cover -html="$WORKSPACE/tmp/.$covername.tmp" -o "$WORKSPACE/tmp/$covername.html"
+            rm "$WORKSPACE/tmp/.$covername.tmp"
         elif [[ "$2" == "pip" ]]
         then
             # $3 can name a path directory for us to use, including trailing
@@ -461,7 +503,7 @@ do_test_once() {
         else
             "test_$1"
         fi
-        result="$?"
+        result=${result:-$?}
         checkexit $result "$1 tests"
         title "End of $1 tests (`timer`)"
         return $result
@@ -487,10 +529,10 @@ do_install() {
             # the source dist package to avoid a pip bug.
             # see https://arvados.org/issues/5766 for details.
 
-            # Also need to install twice, because if it belives the package is
+            # Also need to install twice, because if it believes the package is
             # already installed, pip it won't install it.  So the first "pip
             # install" ensures that the dependencies are met, the second "pip
-            # install" ensures that we've actually install the local package
+            # install" ensures that we've actually installed the local package
             # we just built.
             cd "$WORKSPACE/$1" \
                 && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
@@ -534,24 +576,38 @@ install_doc() {
 }
 do_install doc
 
-install_ruby_sdk() {
-    with_test_gemset gem uninstall --force --all --executables arvados \
-        && cd "$WORKSPACE/sdk/ruby" \
+install_gem() {
+    gemname=$1
+    srcpath=$2
+    with_test_gemset gem_uninstall_if_exists "$gemname" \
+        && cd "$WORKSPACE/$srcpath" \
         && bundle_install_trylocal \
-        && gem build arvados.gemspec \
-        && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-*.gem|head -n1`
+        && gem build "$gemname.gemspec" \
+        && with_test_gemset gem install --no-ri --no-rdoc $(ls -t "$gemname"-*.gem|head -n1)
+}
+
+install_ruby_sdk() {
+    install_gem arvados sdk/ruby
 }
 do_install sdk/ruby ruby_sdk
 
+install_perl_sdk() {
+    cd "$WORKSPACE/sdk/perl" \
+        && perl Makefile.PL INSTALL_BASE="$PERLINSTALLBASE" \
+        && make install INSTALLDIRS=perl
+}
+do_install sdk/perl perl_sdk
+
 install_cli() {
-    with_test_gemset gem uninstall --force --all --executables arvados-cli \
-        && cd "$WORKSPACE/sdk/cli" \
-        && bundle_install_trylocal \
-        && gem build arvados-cli.gemspec \
-        && with_test_gemset gem install --no-ri --no-rdoc `ls -t arvados-cli-*.gem|head -n1`
+    install_gem arvados-cli sdk/cli
 }
 do_install sdk/cli cli
 
+install_login-sync() {
+    install_gem arvados-login-sync services/login-sync
+}
+do_install services/login-sync login-sync
+
 # Install the Python SDK early. Various other test suites (like
 # keepproxy) bring up run_test_server.py, which imports the arvados
 # module. We can't actually *test* the Python SDK yet though, because
@@ -559,6 +615,7 @@ do_install sdk/cli cli
 # keepproxy).
 declare -a pythonstuff
 pythonstuff=(
+    sdk/pam
     sdk/python
     services/fuse
     services/nodemanager
@@ -627,6 +684,8 @@ gostuff=(
     services/crunchstat
     services/keepstore
     services/keepproxy
+    services/datamanager/summary
+    services/datamanager/collection
     sdk/go/arvadosclient
     sdk/go/keepclient
     sdk/go/streamer
@@ -685,6 +744,12 @@ test_cli() {
 }
 do_test sdk/cli cli
 
+test_login-sync() {
+    cd "$WORKSPACE/services/login-sync" \
+        && bundle exec rake test TESTOPTS=-v ${testargs[services/login-sync]}
+}
+do_test services/login-sync login-sync
+
 for p in "${pythonstuff[@]}"
 do
     do_test "$p" pip