1885: Made ServiceRoots atomically updatable, so that KeepProxy can poll for
[arvados.git] / sdk / go / src / arvados.org / keepclient / keepclient_test.go
index 1d3bbeee308761be39b189ecfac044f6d009ff97..395603d5ad3b5c3f92363763c2be719fd723d494 100644 (file)
@@ -13,7 +13,6 @@ import (
        "net/http"
        "os"
        "os/exec"
-       "sort"
        "strings"
        "testing"
 )
@@ -75,13 +74,14 @@ func (s *ServerRequiredSuite) TestMakeKeepClient(c *C) {
        c.Check(kc.Client.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify, Equals, true)
 
        c.Assert(err, Equals, nil)
-       c.Check(len(kc.Service_roots), Equals, 2)
-       c.Check(kc.Service_roots[0], Equals, "http://localhost:25107")
-       c.Check(kc.Service_roots[1], Equals, "http://localhost:25108")
+       c.Check(len(kc.ServiceRoots()), Equals, 2)
+       c.Check(kc.ServiceRoots()[0], Equals, "http://localhost:25107")
+       c.Check(kc.ServiceRoots()[1], Equals, "http://localhost:25108")
 }
 
 func (s *StandaloneSuite) TestShuffleServiceRoots(c *C) {
-       kc := KeepClient{Service_roots: []string{"http://localhost:25107", "http://localhost:25108", "http://localhost:25109", "http://localhost:25110", "http://localhost:25111", "http://localhost:25112", "http://localhost:25113", "http://localhost:25114", "http://localhost:25115", "http://localhost:25116", "http://localhost:25117", "http://localhost:25118", "http://localhost:25119", "http://localhost:25120", "http://localhost:25121", "http://localhost:25122", "http://localhost:25123"}}
+       kc := KeepClient{}
+       kc.SetServiceRoots([]string{"http://localhost:25107", "http://localhost:25108", "http://localhost:25109", "http://localhost:25110", "http://localhost:25111", "http://localhost:25112", "http://localhost:25113", "http://localhost:25114", "http://localhost:25115", "http://localhost:25116", "http://localhost:25117", "http://localhost:25118", "http://localhost:25119", "http://localhost:25120", "http://localhost:25121", "http://localhost:25122", "http://localhost:25123"})
 
        // "foo" acbd18db4cc2f85cedef654fccc4a4d8
        foo_shuffle := []string{"http://localhost:25116", "http://localhost:25120", "http://localhost:25119", "http://localhost:25122", "http://localhost:25108", "http://localhost:25114", "http://localhost:25112", "http://localhost:25107", "http://localhost:25118", "http://localhost:25111", "http://localhost:25113", "http://localhost:25121", "http://localhost:25110", "http://localhost:25117", "http://localhost:25109", "http://localhost:25115", "http://localhost:25123"}
@@ -111,17 +111,15 @@ func (this StubPutHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request
 }
 
 func RunBogusKeepServer(st http.Handler, port int) (listener net.Listener, url string) {
-       server := http.Server{Handler: st}
-
        var err error
        listener, err = net.ListenTCP("tcp", &net.TCPAddr{Port: port})
        if err != nil {
                panic(fmt.Sprintf("Could not listen on tcp port %v", port))
        }
 
-       url = fmt.Sprintf("http://localhost:%d", listener.Addr().(*net.TCPAddr).Port)
+       url = fmt.Sprintf("http://localhost:%d", port)
 
-       go server.Serve(listener)
+       go http.Serve(listener, st)
        return listener, url
 }
 
@@ -161,7 +159,7 @@ func (s *StandaloneSuite) TestUploadToStubKeepServer(c *C) {
 
                        <-st.handled
                        status := <-upload_status
-                       c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200})
+                       c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1})
                })
 
        log.Printf("TestUploadToStubKeepServer done")
@@ -194,7 +192,7 @@ func (s *StandaloneSuite) TestUploadToStubKeepServerBufferReader(c *C) {
                        <-st.handled
 
                        status := <-upload_status
-                       c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200})
+                       c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1})
                })
 
        log.Printf("TestUploadToStubKeepServerBufferReader done")
@@ -229,8 +227,8 @@ func (s *StandaloneSuite) TestFailedUploadToStubKeepServer(c *C) {
                        <-st.handled
 
                        status := <-upload_status
-                       c.Check(status.Url, Equals, fmt.Sprintf("%s/%s", url, hash))
-                       c.Check(status.StatusCode, Equals, 500)
+                       c.Check(status.url, Equals, fmt.Sprintf("%s/%s", url, hash))
+                       c.Check(status.statusCode, Equals, 500)
                })
        log.Printf("TestFailedUploadToStubKeepServer done")
 }
@@ -267,16 +265,16 @@ func (s *StandaloneSuite) TestPutB(c *C) {
 
        kc.Want_replicas = 2
        kc.ApiToken = "abc123"
-       kc.Service_roots = make([]string, 5)
+       service_roots := make([]string, 5)
 
        ks := RunSomeFakeKeepServers(st, 5, 2990)
 
        for i := 0; i < len(ks); i += 1 {
-               kc.Service_roots[i] = ks[i].url
+               service_roots[i] = ks[i].url
                defer ks[i].listener.Close()
        }
 
-       sort.Strings(kc.Service_roots)
+       kc.SetServiceRoots(service_roots)
 
        kc.PutB([]byte("foo"))
 
@@ -308,16 +306,16 @@ func (s *StandaloneSuite) TestPutHR(c *C) {
 
        kc.Want_replicas = 2
        kc.ApiToken = "abc123"
-       kc.Service_roots = make([]string, 5)
+       service_roots := make([]string, 5)
 
        ks := RunSomeFakeKeepServers(st, 5, 2990)
 
        for i := 0; i < len(ks); i += 1 {
-               kc.Service_roots[i] = ks[i].url
+               service_roots[i] = ks[i].url
                defer ks[i].listener.Close()
        }
 
-       sort.Strings(kc.Service_roots)
+       kc.SetServiceRoots(service_roots)
 
        reader, writer := io.Pipe()
 
@@ -361,21 +359,21 @@ func (s *StandaloneSuite) TestPutWithFail(c *C) {
 
        kc.Want_replicas = 2
        kc.ApiToken = "abc123"
-       kc.Service_roots = make([]string, 5)
+       service_roots := make([]string, 5)
 
        ks1 := RunSomeFakeKeepServers(st, 4, 2990)
        ks2 := RunSomeFakeKeepServers(fh, 1, 2995)
 
        for i, k := range ks1 {
-               kc.Service_roots[i] = k.url
+               service_roots[i] = k.url
                defer k.listener.Close()
        }
        for i, k := range ks2 {
-               kc.Service_roots[len(ks1)+i] = k.url
+               service_roots[len(ks1)+i] = k.url
                defer k.listener.Close()
        }
 
-       sort.Strings(kc.Service_roots)
+       kc.SetServiceRoots(service_roots)
 
        shuff := kc.shuffledServiceRoots(fmt.Sprintf("%x", md5.Sum([]byte("foo"))))
 
@@ -409,21 +407,21 @@ func (s *StandaloneSuite) TestPutWithTooManyFail(c *C) {
 
        kc.Want_replicas = 2
        kc.ApiToken = "abc123"
-       kc.Service_roots = make([]string, 5)
+       service_roots := make([]string, 5)
 
        ks1 := RunSomeFakeKeepServers(st, 1, 2990)
        ks2 := RunSomeFakeKeepServers(fh, 4, 2991)
 
        for i, k := range ks1 {
-               kc.Service_roots[i] = k.url
+               service_roots[i] = k.url
                defer k.listener.Close()
        }
        for i, k := range ks2 {
-               kc.Service_roots[len(ks1)+i] = k.url
+               service_roots[len(ks1)+i] = k.url
                defer k.listener.Close()
        }
 
-       sort.Strings(kc.Service_roots)
+       kc.SetServiceRoots(service_roots)
 
        shuff := kc.shuffledServiceRoots(fmt.Sprintf("%x", md5.Sum([]byte("foo"))))
 
@@ -466,7 +464,7 @@ func (s *StandaloneSuite) TestGet(c *C) {
 
        kc, _ := MakeKeepClient()
        kc.ApiToken = "abc123"
-       kc.Service_roots = []string{url}
+       kc.SetServiceRoots([]string{url})
 
        r, n, url2, err := kc.Get(hash)
        defer r.Close()
@@ -491,7 +489,7 @@ func (s *StandaloneSuite) TestGetFail(c *C) {
 
        kc, _ := MakeKeepClient()
        kc.ApiToken = "abc123"
-       kc.Service_roots = []string{url}
+       kc.SetServiceRoots([]string{url})
 
        r, n, url2, err := kc.Get(hash)
        c.Check(err, Equals, BlockNotFound)
@@ -520,7 +518,7 @@ func (s *StandaloneSuite) TestChecksum(c *C) {
 
        kc, _ := MakeKeepClient()
        kc.ApiToken = "abc123"
-       kc.Service_roots = []string{url}
+       kc.SetServiceRoots([]string{url})
 
        r, n, _, err := kc.Get(barhash)
        _, err = ioutil.ReadAll(r)
@@ -552,21 +550,21 @@ func (s *StandaloneSuite) TestGetWithFailures(c *C) {
 
        kc, _ := MakeKeepClient()
        kc.ApiToken = "abc123"
-       kc.Service_roots = make([]string, 5)
+       service_roots := make([]string, 5)
 
        ks1 := RunSomeFakeKeepServers(st, 1, 2990)
        ks2 := RunSomeFakeKeepServers(fh, 4, 2991)
 
        for i, k := range ks1 {
-               kc.Service_roots[i] = k.url
+               service_roots[i] = k.url
                defer k.listener.Close()
        }
        for i, k := range ks2 {
-               kc.Service_roots[len(ks1)+i] = k.url
+               service_roots[len(ks1)+i] = k.url
                defer k.listener.Close()
        }
 
-       sort.Strings(kc.Service_roots)
+       kc.SetServiceRoots(service_roots)
 
        r, n, url2, err := kc.Get(hash)
        <-fh.handled
@@ -587,11 +585,19 @@ func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
        kc, err := MakeKeepClient()
        c.Assert(err, Equals, nil)
 
-       hash, replicas, err := kc.PutB([]byte("foo"))
-       c.Check(hash, Equals, fmt.Sprintf("%x", md5.Sum([]byte("foo"))))
-       c.Check(replicas, Equals, 2)
-       c.Check(err, Equals, nil)
+       hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
 
+       {
+               n, _, err := kc.Ask(hash)
+               c.Check(err, Equals, BlockNotFound)
+               c.Check(n, Equals, int64(0))
+       }
+       {
+               hash2, replicas, err := kc.PutB([]byte("foo"))
+               c.Check(hash2, Equals, hash)
+               c.Check(replicas, Equals, 2)
+               c.Check(err, Equals, nil)
+       }
        {
                r, n, url2, err := kc.Get(hash)
                c.Check(err, Equals, nil)
@@ -602,7 +608,6 @@ func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
                c.Check(err2, Equals, nil)
                c.Check(content, DeepEquals, []byte("foo"))
        }
-
        {
                n, url2, err := kc.Ask(hash)
                c.Check(err, Equals, nil)
@@ -610,3 +615,71 @@ func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
                c.Check(url2, Equals, fmt.Sprintf("http://localhost:25108/%s", hash))
        }
 }
+
+type StubProxyHandler struct {
+       handled chan string
+}
+
+func (this StubProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
+       resp.Header().Set("X-Keep-Replicas-Stored", "2")
+       this.handled <- fmt.Sprintf("http://%s", req.Host)
+}
+
+func (s *StandaloneSuite) TestPutProxy(c *C) {
+       log.Printf("TestPutProxy")
+
+       st := StubProxyHandler{make(chan string, 1)}
+
+       kc, _ := MakeKeepClient()
+
+       kc.Want_replicas = 2
+       kc.Using_proxy = true
+       kc.ApiToken = "abc123"
+       service_roots := make([]string, 1)
+
+       ks1 := RunSomeFakeKeepServers(st, 1, 2990)
+
+       for i, k := range ks1 {
+               service_roots[i] = k.url
+               defer k.listener.Close()
+       }
+
+       kc.SetServiceRoots(service_roots)
+
+       _, replicas, err := kc.PutB([]byte("foo"))
+       <-st.handled
+
+       c.Check(err, Equals, nil)
+       c.Check(replicas, Equals, 2)
+
+       log.Printf("TestPutProxy done")
+}
+
+func (s *StandaloneSuite) TestPutProxyInsufficientReplicas(c *C) {
+       log.Printf("TestPutProxy")
+
+       st := StubProxyHandler{make(chan string, 1)}
+
+       kc, _ := MakeKeepClient()
+
+       kc.Want_replicas = 3
+       kc.Using_proxy = true
+       kc.ApiToken = "abc123"
+       service_roots := make([]string, 1)
+
+       ks1 := RunSomeFakeKeepServers(st, 1, 2990)
+
+       for i, k := range ks1 {
+               service_roots[i] = k.url
+               defer k.listener.Close()
+       }
+       kc.SetServiceRoots(service_roots)
+
+       _, replicas, err := kc.PutB([]byte("foo"))
+       <-st.handled
+
+       c.Check(err, Equals, InsufficientReplicasError)
+       c.Check(replicas, Equals, 2)
+
+       log.Printf("TestPutProxy done")
+}