14807: Add lib/service test.
authorTom Clegg <tclegg@veritasgenetics.com>
Fri, 22 Mar 2019 20:20:29 +0000 (16:20 -0400)
committerTom Clegg <tclegg@veritasgenetics.com>
Fri, 22 Mar 2019 20:20:29 +0000 (16:20 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

build/run-tests.sh
lib/service/cmd.go
lib/service/cmd_test.go [new file with mode: 0644]

index a6858f315f873cf384e0ba3110ae430bf3a49bf1..f2c7a3e867fa18e40e97f540dd2618de4f4959ec 100755 (executable)
@@ -85,6 +85,7 @@ lib/dispatchcloud/container
 lib/dispatchcloud/scheduler
 lib/dispatchcloud/ssh_executor
 lib/dispatchcloud/worker
+lib/service
 services/api
 services/arv-git-httpd
 services/crunchstat
@@ -953,6 +954,7 @@ gostuff=(
     lib/dispatchcloud/scheduler
     lib/dispatchcloud/ssh_executor
     lib/dispatchcloud/worker
+    lib/service
     sdk/go/arvados
     sdk/go/arvadosclient
     sdk/go/auth
index e23791b30a214d659390b3fe987ca247dde569e4..2d3fb90259da90d3d42eab2747e5b2efa6967d91 100644 (file)
@@ -31,6 +31,7 @@ type NewHandlerFunc func(_ context.Context, _ *arvados.Cluster, _ *arvados.NodeP
 type command struct {
        newHandler NewHandlerFunc
        svcName    arvados.ServiceName
+       ctx        context.Context // enables tests to shutdown service; no public API yet
 }
 
 // Command returns a cmd.Handler that loads site config, calls
@@ -43,6 +44,7 @@ func Command(svcName arvados.ServiceName, newHandler NewHandlerFunc) cmd.Handler
        return &command{
                newHandler: newHandler,
                svcName:    svcName,
+               ctx:        context.Background(),
        }
 }
 
@@ -77,7 +79,7 @@ func (c *command) RunCommand(prog string, args []string, stdin io.Reader, stdout
        log = ctxlog.New(stderr, cluster.Logging.Format, cluster.Logging.Level).WithFields(logrus.Fields{
                "PID": os.Getpid(),
        })
-       ctx := ctxlog.Context(context.Background(), log)
+       ctx := ctxlog.Context(c.ctx, log)
 
        profileName := *nodeProfile
        if profileName == "" {
@@ -123,6 +125,10 @@ func (c *command) RunCommand(prog string, args []string, stdin io.Reader, stdout
        if _, err := daemon.SdNotify(false, "READY=1"); err != nil {
                log.WithError(err).Errorf("error notifying init daemon")
        }
+       go func() {
+               <-ctx.Done()
+               srv.Close()
+       }()
        err = srv.Wait()
        if err != nil {
                return 1
diff --git a/lib/service/cmd_test.go b/lib/service/cmd_test.go
new file mode 100644 (file)
index 0000000..62960dc
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+// package service provides a cmd.Handler that brings up a system service.
+package service
+
+import (
+       "bytes"
+       "context"
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "os"
+       "testing"
+
+       "git.curoverse.com/arvados.git/sdk/go/arvados"
+       "git.curoverse.com/arvados.git/sdk/go/ctxlog"
+       check "gopkg.in/check.v1"
+)
+
+func Test(t *testing.T) {
+       check.TestingT(t)
+}
+
+var _ = check.Suite(&Suite{})
+
+type Suite struct{}
+
+func (*Suite) TestCommand(c *check.C) {
+       cf, err := ioutil.TempFile("", "cmd_test.")
+       c.Assert(err, check.IsNil)
+       defer os.Remove(cf.Name())
+       defer cf.Close()
+       fmt.Fprintf(cf, "Clusters:\n zzzzz:\n  SystemRootToken: abcde\n  NodeProfiles: {\"*\": {\"arvados-controller\": {Listen: \":1234\"}}}")
+
+       healthCheck := make(chan bool, 1)
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       cmd := Command(arvados.ServiceNameController, func(ctx context.Context, _ *arvados.Cluster, _ *arvados.NodeProfile, token string) Handler {
+               c.Check(ctx.Value("foo"), check.Equals, "bar")
+               c.Check(token, check.Equals, "abcde")
+               return &testHandler{ctx: ctx, healthCheck: healthCheck}
+       })
+       cmd.(*command).ctx = context.WithValue(ctx, "foo", "bar")
+
+       done := make(chan bool)
+       var stdin, stdout, stderr bytes.Buffer
+
+       go func() {
+               cmd.RunCommand("arvados-controller", []string{"-config", cf.Name()}, &stdin, &stdout, &stderr)
+               close(done)
+       }()
+       select {
+       case <-healthCheck:
+       case <-done:
+               c.Error("command exited without health check")
+       }
+       cancel()
+       c.Check(stdout.String(), check.Equals, "")
+       c.Check(stderr.String(), check.Matches, `(?ms).*"msg":"CheckHealth called".*`)
+}
+
+type testHandler struct {
+       ctx         context.Context
+       healthCheck chan bool
+}
+
+func (th *testHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}
+func (th *testHandler) CheckHealth() error {
+       ctxlog.FromContext(th.ctx).Info("CheckHealth called")
+       select {
+       case th.healthCheck <- true:
+       default:
+       }
+       return nil
+}