Merge branch '15044-test-fixes'
authorTom Clegg <tclegg@veritasgenetics.com>
Tue, 2 Apr 2019 17:28:10 +0000 (13:28 -0400)
committerTom Clegg <tclegg@veritasgenetics.com>
Tue, 2 Apr 2019 17:28:10 +0000 (13:28 -0400)
closes #15044

Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

15 files changed:
build/run-tests.sh
sdk/python/tests/nginx.conf
sdk/python/tests/run_test_server.py
sdk/python/tests/test_arv_put.py
services/api/config/database.yml.example
services/arv-git-httpd/gitolite_test.go
services/arv-git-httpd/integration_test.go
services/crunch-run/crunchrun.go
services/keep-web/server_test.go
services/keepproxy/keepproxy.go
services/login-sync/Gemfile
services/login-sync/arvados-login-sync.gemspec
services/login-sync/bin/arvados-login-sync
services/login-sync/test/stubs.rb
services/login-sync/test/test_add_user.rb

index dc46594538e8f27b4bc0024bf5b208bc25f368e1..d72a39110266387bca3831dca254a2aa5856e290 100755 (executable)
@@ -148,6 +148,7 @@ PYTHONPATH=
 GEMHOME=
 PERLINSTALLBASE=
 R_LIBS=
+export LANG=en_US.UTF-8
 
 short=
 only_install=
@@ -189,6 +190,9 @@ sanity_checks() {
     ( [[ -n "$WORKSPACE" ]] && [[ -d "$WORKSPACE/services" ]] ) \
         || fatal "WORKSPACE environment variable not set to a source directory (see: $0 --help)"
     echo Checking dependencies:
+    echo "locale: ${LANG}"
+    [[ "$(locale charmap)" = "UTF-8" ]] \
+        || fatal "Locale '${LANG}' is broken/missing. Try: echo ${LANG} | sudo tee -a /etc/locale.gen && sudo locale-gen"
     echo -n 'virtualenv: '
     virtualenv --version \
         || fatal "No virtualenv. Try: apt-get install virtualenv (on ubuntu: python-virtualenv)"
@@ -364,6 +368,27 @@ if [[ $NEED_SDK_R == false ]]; then
        echo "R SDK not needed, it will not be installed."
 fi
 
+checkpidfile() {
+    svc="$1"
+    pid="$(cat "$WORKSPACE/tmp/${svc}.pid")"
+    if [[ -z "$pid" ]] || ! kill -0 "$pid"; then
+        tail $WORKSPACE/tmp/${1}*.log
+        echo "${svc} pid ${pid} not running"
+        return 1
+    fi
+    echo "${svc} pid ${pid} ok"
+}
+
+checkdiscoverydoc() {
+    dd="https://${1}/discovery/v1/apis/arvados/v1/rest"
+    if ! (set -o pipefail; curl -fsk "$dd" | jq . >/dev/null); then
+        echo >&2 "ERROR: could not retrieve discovery doc from RailsAPI at $dd"
+        tail -v $WORKSPACE/services/api/log/test.log
+        return 1
+    fi
+    echo "${dd} ok"
+}
+
 start_services() {
     if [[ -n "$ARVADOS_TEST_API_HOST" ]]; then
         return 0
@@ -383,15 +408,29 @@ start_services() {
         && eval $(python sdk/python/tests/run_test_server.py start --auth admin || echo "fail=1; false") \
         && export ARVADOS_TEST_API_HOST="$ARVADOS_API_HOST" \
         && export ARVADOS_TEST_API_INSTALLED="$$" \
+        && checkpidfile api \
+        && checkdiscoverydoc $ARVADOS_API_HOST \
         && python sdk/python/tests/run_test_server.py start_controller \
+        && checkpidfile controller \
         && python sdk/python/tests/run_test_server.py start_keep_proxy \
+        && checkpidfile keepproxy \
         && python sdk/python/tests/run_test_server.py start_keep-web \
+        && checkpidfile keep-web \
         && python sdk/python/tests/run_test_server.py start_arv-git-httpd \
+        && checkpidfile arv-git-httpd \
         && python sdk/python/tests/run_test_server.py start_ws \
+        && checkpidfile ws \
         && eval $(python sdk/python/tests/run_test_server.py start_nginx || echo "fail=1; false") \
+        && checkdiscoverydoc $ARVADOS_API_HOST \
+        && checkpidfile nginx \
+        && export ARVADOS_TEST_PROXY_SERVICES=1 \
         && (env | egrep ^ARVADOS) \
         || fail=1
     deactivate
+    if [[ $fail = 0 ]] && ! kill -0 "$(cat "$WORKSPACE/tmp/nginx.pid")"; then
+        echo >&2 "ERROR: nginx seems to have died already"
+        fail=1
+    fi
     if [[ $fail != 0 ]]; then
         unset ARVADOS_TEST_API_HOST
     fi
@@ -402,7 +441,7 @@ stop_services() {
     if [[ -n "$all_services_stopped" ]]; then
         return
     fi
-    unset ARVADOS_TEST_API_HOST
+    unset ARVADOS_TEST_API_HOST ARVADOS_TEST_PROXY_SERVICES
     . "$VENVDIR/bin/activate" || return
     cd "$WORKSPACE" \
         && python sdk/python/tests/run_test_server.py stop_nginx \
@@ -695,7 +734,7 @@ do_test() {
         services/api)
             stop_services
             ;;
-        doc | lib/cli | lib/cloud/azure | lib/cloud/ec2 | lib/cmd | lib/dispatchcloud/ssh_executor | lib/dispatchcloud/worker)
+        gofmt | doc | lib/cli | lib/cloud/azure | lib/cloud/ec2 | lib/cmd | lib/dispatchcloud/ssh_executor | lib/dispatchcloud/worker)
             # don't care whether services are running
             ;;
         *)
@@ -728,7 +767,6 @@ do_test_once() {
         # compilation errors.
         go get -ldflags "-X main.version=${ARVADOS_VERSION:-$(git log -n1 --format=%H)-dev}" -t "git.curoverse.com/arvados.git/$1" && \
             cd "$GOPATH/src/git.curoverse.com/arvados.git/$1" && \
-            [[ -z "$(gofmt -e -d . | tee /dev/stderr)" ]] && \
             if [[ -n "${testargs[$1]}" ]]
         then
             # "go test -check.vv giturl" doesn't work, but this
@@ -745,6 +783,7 @@ do_test_once() {
             go tool cover -html="$WORKSPACE/tmp/.$covername.tmp" -o "$WORKSPACE/tmp/$covername.html"
             rm "$WORKSPACE/tmp/.$covername.tmp"
         fi
+        [[ $result = 0 ]] && gofmt -e -d *.go
     elif [[ "$2" == "pip" ]]
     then
         tries=0
@@ -895,7 +934,7 @@ install_services/api() {
     # database, so that we can drop it. This assumes the current user
     # is a postgresql superuser.
     cd "$WORKSPACE/services/api" \
-        && test_database=$(python -c "import yaml; print yaml.load(file('config/database.yml'))['test']['database']") \
+        && test_database=$(python -c "import yaml; print yaml.safe_load(file('config/database.yml'))['test']['database']") \
         && psql "$test_database" -c "SELECT pg_terminate_backend (pg_stat_activity.pid::int) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$test_database';" 2>/dev/null
 
     mkdir -p "$WORKSPACE/services/api/tmp/pids"
@@ -1002,6 +1041,12 @@ test_doc() {
     )
 }
 
+test_gofmt() {
+    cd "$WORKSPACE" || return 1
+    dirs=$(ls -d */ | egrep -v 'vendor|tmp')
+    [[ -z "$(gofmt -e -d $dirs | tee -a /dev/stderr)" ]]
+}
+
 test_services/api() {
     rm -f "$WORKSPACE/services/api/git-commit.version"
     cd "$WORKSPACE/services/api" \
@@ -1038,17 +1083,17 @@ test_services/nodemanager_integration() {
 
 test_apps/workbench_units() {
     cd "$WORKSPACE/apps/workbench" \
-        && env RAILS_ENV=test ${short:+RAILS_TEST_SHORT=1} bundle exec rake test:units TESTOPTS=-v ${testargs[apps/workbench]}
+        && env RAILS_ENV=test ${short:+RAILS_TEST_SHORT=1} bundle exec rake test:units TESTOPTS=-v ${testargs[apps/workbench]} ${testargs[apps/workbench_units]}
 }
 
 test_apps/workbench_functionals() {
     cd "$WORKSPACE/apps/workbench" \
-        && env RAILS_ENV=test ${short:+RAILS_TEST_SHORT=1} bundle exec rake test:functionals TESTOPTS=-v ${testargs[apps/workbench]}
+        && env RAILS_ENV=test ${short:+RAILS_TEST_SHORT=1} bundle exec rake test:functionals TESTOPTS=-v ${testargs[apps/workbench]} ${testargs[apps/workbench_functionals]}
 }
 
 test_apps/workbench_integration() {
     cd "$WORKSPACE/apps/workbench" \
-        && env RAILS_ENV=test ${short:+RAILS_TEST_SHORT=1} bundle exec rake test:integration TESTOPTS=-v ${testargs[apps/workbench]}
+        && env RAILS_ENV=test ${short:+RAILS_TEST_SHORT=1} bundle exec rake test:integration TESTOPTS=-v ${testargs[apps/workbench]} ${testargs[apps/workbench_integration]}
 }
 
 test_apps/workbench_benchmark() {
@@ -1117,6 +1162,7 @@ test_all() {
         exit_cleanly
     fi
 
+    do_test gofmt
     do_test doc
     do_test sdk/ruby
     do_test sdk/R
@@ -1204,32 +1250,32 @@ else
         read verb target opts <<<"${nextcmd}"
         target="${target%/}"
         target="${target/\/:/:}"
-        if [[ -z "${target}" ]]; then
-            verb=help
-        fi
         case "${verb}" in
-            "" | "help")
-                help_interactive
-                ;;
             "exit" | "quit")
                 exit_cleanly
                 ;;
             "reset")
                 stop_services
                 ;;
-            *)
-                testargs["$target"]="${opts}"
+            "test" | "install")
                 case "$target" in
+                    "")
+                        help_interactive
+                        ;;
                     all | deps)
                         ${verb}_${target}
                         ;;
                     *)
+                        testargs["$target"]="${opts}"
                         tt="${testfuncargs[${target}]}"
                         tt="${tt:-$target}"
                         do_$verb $tt
                         ;;
                 esac
                 ;;
+            "" | "help" | *)
+                help_interactive
+                ;;
         esac
         if [[ ${#successes[@]} -gt 0 || ${#failures[@]} -gt 0 ]]; then
             report_outcomes
index 130d8c964df2fdbc9931394049feb1bcf717dafd..1ef3b00c665e89c61aaa7853c7b0b455c944259a 100644 (file)
@@ -12,6 +12,10 @@ http {
     '"$http_referer" "$http_user_agent"';
   access_log "{{ACCESSLOG}}" customlog;
   client_body_temp_path "{{TMPDIR}}";
+  proxy_temp_path "{{TMPDIR}}";
+  fastcgi_temp_path "{{TMPDIR}}";
+  uwsgi_temp_path "{{TMPDIR}}";
+  scgi_temp_path "{{TMPDIR}}";
   upstream arv-git-http {
     server localhost:{{GITPORT}};
   }
index 7b1f6059aeef07b8ff2a2d03a6d4980f9d5a835f..6687ca491a769140aa8c803a5fd2b1a6ce3b1850 100644 (file)
@@ -582,6 +582,7 @@ def stop_keep(num_servers=2):
 
 def run_keep_proxy():
     if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+        os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(_getport('keepproxy'))
         return
     stop_keep_proxy()
 
@@ -738,7 +739,7 @@ def _getport(program):
 def _dbconfig(key):
     global _cached_db_config
     if not _cached_db_config:
-        _cached_db_config = yaml.load(open(os.path.join(
+        _cached_db_config = yaml.safe_load(open(os.path.join(
             SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
     return _cached_db_config['test'][key]
 
@@ -750,7 +751,7 @@ def _apiconfig(key):
         fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
         if not required and not os.path.exists(fullpath):
             return {}
-        return yaml.load(fullpath)
+        return yaml.safe_load(fullpath)
     cdefault = _load('application.default.yml')
     csite = _load('application.yml', required=False)
     _cached_config = {}
@@ -769,7 +770,7 @@ def fixture(fix):
           yaml_file = yaml_file[0:trim_index]
         except ValueError:
           pass
-        return yaml.load(yaml_file)
+        return yaml.safe_load(yaml_file)
 
 def auth_token(token_name):
     return fixture("api_client_authorizations")[token_name]["api_token"]
index 01a52a5e6681ec07daaf16eb0c0c18a9b7ba2ada..540e06c6c6a0d571e7a269e5eae7c9e8a1989419 100644 (file)
@@ -859,7 +859,7 @@ class ArvPutIntegrationTest(run_test_server.TestCaseWithServers,
             if not mandatory and not os.path.exists(path):
                 continue
             with open(path) as f:
-                rails_config = yaml.load(f.read())
+                rails_config = yaml.safe_load(f.read())
                 for config_section in ['test', 'common']:
                     try:
                         key = rails_config[config_section]["blob_signing_key"]
index 80876888cf53eb512085dd88641b3388cfe0c814..2ec90050ae74ee88158d19d8a68581f17e3a9bd9 100644 (file)
@@ -15,6 +15,7 @@ test:
   adapter: postgresql
   template: template0
   encoding: utf8
+  collation: en_US.utf8
   database: arvados_test
   username: arvados
   password: xxxxxxxx
@@ -28,7 +29,4 @@ production:
   username: arvados
   password: xxxxxxxx
   host: localhost
-  # For the websockets server, prefer a larger database connection pool size since it
-  # multithreaded and can serve a large number of long-lived clients.  See also
-  # websocket_max_connections configuration option.
   pool: 50
index 0656cbf89ad34661d08bb467c96b2be152a7908f..88cd221cbf8aaed87e4f91a6289e8dd02458cd90 100644 (file)
@@ -52,7 +52,7 @@ func (s *GitoliteSuite) SetUpTest(c *check.C) {
                        APIHost:  arvadostest.APIHost(),
                        Insecure: true,
                },
-               Listen:       ":0",
+               Listen:       "localhost:0",
                GitCommand:   "/usr/share/gitolite3/gitolite-shell",
                GitoliteHome: s.gitoliteHome,
                RepoRoot:     s.tmpRepoRoot,
index 10c69eedd3bf2e2c81cb51ea7c92961d108f1204..53b636dc0e577e75bf5577e66a54059628be8774 100644 (file)
@@ -77,7 +77,7 @@ func (s *IntegrationSuite) SetUpTest(c *check.C) {
                                APIHost:  arvadostest.APIHost(),
                                Insecure: true,
                        },
-                       Listen:          ":0",
+                       Listen:          "localhost:0",
                        GitCommand:      "/usr/bin/git",
                        RepoRoot:        s.tmpRepoRoot,
                        ManagementToken: arvadostest.ManagementToken,
index 3925b0b7b1f810c9c451c7e756693ba5875bc252..84b578a3e21ee6a1b9b70f1adf48709154452bb9 100644 (file)
@@ -987,7 +987,7 @@ func (runner *ContainerRunner) AttachStreams() (err error) {
                go func() {
                        _, err := io.Copy(response.Conn, stdinRdr)
                        if err != nil {
-                               runner.CrunchLog.Print("While writing stdin collection to docker container %q", err)
+                               runner.CrunchLog.Printf("While writing stdin collection to docker container %q", err)
                                runner.stop(nil)
                        }
                        stdinRdr.Close()
@@ -997,7 +997,7 @@ func (runner *ContainerRunner) AttachStreams() (err error) {
                go func() {
                        _, err := io.Copy(response.Conn, bytes.NewReader(stdinJson))
                        if err != nil {
-                               runner.CrunchLog.Print("While writing stdin json to docker container %q", err)
+                               runner.CrunchLog.Printf("While writing stdin json to docker container %q", err)
                                runner.stop(nil)
                        }
                        response.CloseWrite()
index 8b689efbdc1f1d731bc2a9dfb106c12e3c214cef..a9830bc1de4715d2cfdaa39049106bcf95cce779 100644 (file)
@@ -266,9 +266,10 @@ func (s *IntegrationSuite) runCurl(c *check.C, token, host, uri string, args ...
        c.Log(fmt.Sprintf("curlArgs == %#v", curlArgs))
        cmd := exec.Command("curl", curlArgs...)
        stdout, err := cmd.StdoutPipe()
-       c.Assert(err, check.Equals, nil)
-       cmd.Stderr = cmd.Stdout
-       go cmd.Start()
+       c.Assert(err, check.IsNil)
+       cmd.Stderr = os.Stderr
+       err = cmd.Start()
+       c.Assert(err, check.IsNil)
        buf := make([]byte, 2<<27)
        n, err := io.ReadFull(stdout, buf)
        // Discard (but measure size of) anything past 128 MiB.
@@ -276,9 +277,9 @@ func (s *IntegrationSuite) runCurl(c *check.C, token, host, uri string, args ...
        if err == io.ErrUnexpectedEOF {
                buf = buf[:n]
        } else {
-               c.Assert(err, check.Equals, nil)
+               c.Assert(err, check.IsNil)
                discarded, err = io.Copy(ioutil.Discard, stdout)
-               c.Assert(err, check.Equals, nil)
+               c.Assert(err, check.IsNil)
        }
        err = cmd.Wait()
        // Without "-f", curl exits 0 as long as it gets a valid HTTP
index 0cb93ffb3182803aa3a4ea3094cf68f15ff1ef8a..c6fd99b9d8ed2f70b264b342ed041d5062eeb0a8 100644 (file)
@@ -152,7 +152,7 @@ func main() {
                }
                err = f.Sync()
                if err != nil {
-                       log.Fatal("sync(%s): %s", cfg.PIDFile, err)
+                       log.Fatalf("sync(%s): %s", cfg.PIDFile, err)
                }
        }
 
index 42d990fa6675a8e6e9c7d8484448254898c7dbfc..420b1528618c10ec4f3b2f2b986060e25dfd2116 100644 (file)
@@ -6,6 +6,6 @@ source 'https://rubygems.org'
 gemspec
 group :test, :performance do
   gem 'minitest', '>= 5.0.0'
-  gem 'mocha', require: false
+  gem 'mocha', '>= 1.5.0', require: false
   gem 'rake'
 end
index b64aab2dc6cb0e189341ab93d175e27d38a659ce..f998a8f35211c89ae81dd89def87d5aef9d46412 100644 (file)
@@ -2,7 +2,7 @@
 #
 # SPDX-License-Identifier: AGPL-3.0
 
-if not File.exists?('/usr/bin/git') then
+if not File.exist?('/usr/bin/git') then
   STDERR.puts "\nGit binary not found, aborting. Please install git and run gem build from a checked out copy of the git repository.\n\n"
   exit
 end
index eb680043e4b50bf3f44bbd28a97bd551a39c12de..e00495c04db7db621ba0bf377cbe62072b82feba 100755 (executable)
@@ -108,7 +108,7 @@ begin
                 "-G", groups.join(","),
                 l[:username],
                 out: devnull)
-        STDERR.puts "Account creation failed for #{l[:username]}: $?"
+        STDERR.puts "Account creation failed for #{l[:username]}: #{$?}"
         next
       end
       begin
@@ -121,13 +121,13 @@ begin
 
     @homedir = pwnam[l[:username]].dir
     userdotssh = File.join(@homedir, ".ssh")
-    Dir.mkdir(userdotssh) if !File.exists?(userdotssh)
+    Dir.mkdir(userdotssh) if !File.exist?(userdotssh)
 
     newkeys = "###\n###\n" + keys[l[:username]].join("\n") + "\n###\n###\n"
 
     keysfile = File.join(userdotssh, "authorized_keys")
 
-    if File.exists?(keysfile)
+    if File.exist?(keysfile)
       oldkeys = IO::read(keysfile)
     else
       oldkeys = ""
index d7fab3c0db8fe202ad979f7ed469db1632ebc685..cf69da6efcc6e94d0b877cf84d738dd0b7386fc5 100644 (file)
@@ -3,19 +3,10 @@
 # SPDX-License-Identifier: AGPL-3.0
 
 require 'etc'
-require 'mocha/mini_test'
+require 'mocha/minitest'
 require 'ostruct'
 
 module Stubs
-  # These Etc mocks help only when we run arvados-login-sync in-process.
-
-  def setup
-    super
-    ENV['ARVADOS_VIRTUAL_MACHINE_UUID'] = 'testvm2.shell'
-    Etc.stubs(:to_enum).with(:passwd).returns stubpasswd.map { |x| OpenStruct.new x }
-    Etc.stubs(:to_enum).with(:group).returns stubgroup.map { |x| OpenStruct.new x }
-  end
-
   def stubpasswd
     [{name: 'root', uid: 0}]
   end
@@ -24,10 +15,16 @@ module Stubs
     [{name: 'root', gid: 0}]
   end
 
-  # These child-ENV tricks help only when we run arvados-login-sync as a subprocess.
 
   def setup
     super
+
+    # These Etc mocks help only when we run arvados-login-sync in-process.
+    ENV['ARVADOS_VIRTUAL_MACHINE_UUID'] = 'testvm2.shell'
+    Etc.stubs(:to_enum).with(:passwd).returns stubpasswd.map { |x| OpenStruct.new x }
+    Etc.stubs(:to_enum).with(:group).returns stubgroup.map { |x| OpenStruct.new x }
+
+    # These child-ENV tricks help only when we run arvados-login-sync as a subprocess.
     @env_was = Hash[ENV]
     @tmpdir = Dir.mktmpdir
   end
index 17942c2cffa784993b4338dc64711e56f5e17028..e90c16d64fae900df698c1db9d0cd6814022604b 100644 (file)
@@ -10,17 +10,14 @@ class TestAddUser < Minitest::Test
   include Stubs
 
   def test_useradd_error
+    valid_groups = %w(docker admin fuse).select { |g| Etc.getgrnam(g) rescue false }
     # binstub_new_user/useradd will exit non-zero because its args
     # won't match any line in this empty file:
     File.open(@tmpdir+'/succeed', 'w') do |f| end
     invoke_sync binstubs: ['new_user']
     spied = File.read(@tmpdir+'/spy')
     assert_match %r{useradd -m -c active -s /bin/bash -G (fuse)? active}, spied
-    # BUG(TC): This assertion succeeds only if docker and fuse groups
-    # exist on the host, but is insensitive to the admin group (groups
-    # are quietly ignored by login-sync if they don't exist on the
-    # current host).
-    assert_match %r{useradd -m -c adminroot -s /bin/bash -G (docker)?(,admin)?(,fuse)? adminroot}, spied
+    assert_match %r{useradd -m -c adminroot -s /bin/bash -G #{valid_groups.join(',')} adminroot}, spied
   end
 
   def test_useradd_success