7 "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
8 "git.curoverse.com/arvados.git/sdk/go/arvadostest"
9 "git.curoverse.com/arvados.git/sdk/go/streamer"
21 // Gocheck boilerplate
22 func Test(t *testing.T) {
26 // Gocheck boilerplate
27 var _ = Suite(&ServerRequiredSuite{})
28 var _ = Suite(&StandaloneSuite{})
30 var no_server = flag.Bool("no-server", false, "Skip 'ServerRequireSuite'")
32 // Tests that require the Keep server running
33 type ServerRequiredSuite struct{}
36 type StandaloneSuite struct{}
38 func pythonDir() string {
40 return fmt.Sprintf("%s/../../python/tests", cwd)
43 func (s *ServerRequiredSuite) SetUpSuite(c *C) {
45 c.Skip("Skipping tests that require server")
48 arvadostest.StartAPI()
49 arvadostest.StartKeep(2, false)
52 func (s *ServerRequiredSuite) TearDownSuite(c *C) {
56 arvadostest.StopKeep(2)
60 func (s *ServerRequiredSuite) TestMakeKeepClient(c *C) {
61 arv, err := arvadosclient.MakeArvadosClient()
62 c.Assert(err, Equals, nil)
64 kc, err := MakeKeepClient(&arv)
66 c.Assert(err, Equals, nil)
67 c.Check(len(kc.LocalRoots()), Equals, 2)
68 for _, root := range kc.LocalRoots() {
69 c.Check(root, Matches, "http://localhost:\\d+")
73 func (s *ServerRequiredSuite) TestDefaultReplications(c *C) {
74 arv, err := arvadosclient.MakeArvadosClient()
75 c.Assert(err, Equals, nil)
77 kc, err := MakeKeepClient(&arv)
78 c.Assert(kc.Want_replicas, Equals, 2)
80 arv.DiscoveryDoc["defaultCollectionReplication"] = 3.0
81 kc, err = MakeKeepClient(&arv)
82 c.Assert(kc.Want_replicas, Equals, 3)
84 arv.DiscoveryDoc["defaultCollectionReplication"] = 1.0
85 kc, err = MakeKeepClient(&arv)
86 c.Assert(kc.Want_replicas, Equals, 1)
89 type StubPutHandler struct {
97 func (sph StubPutHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
98 sph.c.Check(req.URL.Path, Equals, "/"+sph.expectPath)
99 sph.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", sph.expectApiToken))
100 body, err := ioutil.ReadAll(req.Body)
101 sph.c.Check(err, Equals, nil)
102 sph.c.Check(body, DeepEquals, []byte(sph.expectBody))
103 resp.WriteHeader(200)
104 sph.handled <- fmt.Sprintf("http://%s", req.Host)
107 func RunFakeKeepServer(st http.Handler) (ks KeepServer) {
109 ks.listener, err = net.ListenTCP("tcp", &net.TCPAddr{Port: 0})
111 panic(fmt.Sprintf("Could not listen on any port"))
113 ks.url = fmt.Sprintf("http://%s", ks.listener.Addr().String())
114 go http.Serve(ks.listener, st)
118 func UploadToStubHelper(c *C, st http.Handler, f func(*KeepClient, string,
119 io.ReadCloser, io.WriteCloser, chan uploadStatus)) {
121 ks := RunFakeKeepServer(st)
122 defer ks.listener.Close()
124 arv, _ := arvadosclient.MakeArvadosClient()
125 arv.ApiToken = "abc123"
127 kc, _ := MakeKeepClient(&arv)
129 reader, writer := io.Pipe()
130 upload_status := make(chan uploadStatus)
132 f(kc, ks.url, reader, writer, upload_status)
135 func (s *StandaloneSuite) TestUploadToStubKeepServer(c *C) {
136 log.Printf("TestUploadToStubKeepServer")
138 st := StubPutHandler{
140 "acbd18db4cc2f85cedef654fccc4a4d8",
145 UploadToStubHelper(c, st,
146 func(kc *KeepClient, url string, reader io.ReadCloser,
147 writer io.WriteCloser, upload_status chan uploadStatus) {
149 go kc.uploadToKeepServer(url, st.expectPath, reader, upload_status, int64(len("foo")), "TestUploadToStubKeepServer")
151 writer.Write([]byte("foo"))
155 status := <-upload_status
156 c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
159 log.Printf("TestUploadToStubKeepServer done")
162 func (s *StandaloneSuite) TestUploadToStubKeepServerBufferReader(c *C) {
163 log.Printf("TestUploadToStubKeepServerBufferReader")
165 st := StubPutHandler{
167 "acbd18db4cc2f85cedef654fccc4a4d8",
172 UploadToStubHelper(c, st,
173 func(kc *KeepClient, url string, reader io.ReadCloser,
174 writer io.WriteCloser, upload_status chan uploadStatus) {
176 tr := streamer.AsyncStreamFromReader(512, reader)
179 br1 := tr.MakeStreamReader()
181 go kc.uploadToKeepServer(url, st.expectPath, br1, upload_status, 3, "TestUploadToStubKeepServerBufferReader")
183 writer.Write([]byte("foo"))
188 status := <-upload_status
189 c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
192 log.Printf("TestUploadToStubKeepServerBufferReader done")
195 type FailHandler struct {
199 func (fh FailHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
200 resp.WriteHeader(500)
201 fh.handled <- fmt.Sprintf("http://%s", req.Host)
204 type FailThenSucceedHandler struct {
207 successhandler StubGetHandler
210 func (fh *FailThenSucceedHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
212 resp.WriteHeader(500)
214 fh.handled <- fmt.Sprintf("http://%s", req.Host)
216 fh.successhandler.ServeHTTP(resp, req)
220 type Error404Handler struct {
224 func (fh Error404Handler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
225 resp.WriteHeader(404)
226 fh.handled <- fmt.Sprintf("http://%s", req.Host)
229 func (s *StandaloneSuite) TestFailedUploadToStubKeepServer(c *C) {
230 log.Printf("TestFailedUploadToStubKeepServer")
235 hash := "acbd18db4cc2f85cedef654fccc4a4d8"
237 UploadToStubHelper(c, st,
238 func(kc *KeepClient, url string, reader io.ReadCloser,
239 writer io.WriteCloser, upload_status chan uploadStatus) {
241 go kc.uploadToKeepServer(url, hash, reader, upload_status, 3, "TestFailedUploadToStubKeepServer")
243 writer.Write([]byte("foo"))
248 status := <-upload_status
249 c.Check(status.url, Equals, fmt.Sprintf("%s/%s", url, hash))
250 c.Check(status.statusCode, Equals, 500)
252 log.Printf("TestFailedUploadToStubKeepServer done")
255 type KeepServer struct {
256 listener net.Listener
260 func RunSomeFakeKeepServers(st http.Handler, n int) (ks []KeepServer) {
261 ks = make([]KeepServer, n)
263 for i := 0; i < n; i += 1 {
264 ks[i] = RunFakeKeepServer(st)
270 func (s *StandaloneSuite) TestPutB(c *C) {
271 log.Printf("TestPutB")
273 hash := Md5String("foo")
275 st := StubPutHandler{
280 make(chan string, 5)}
282 arv, _ := arvadosclient.MakeArvadosClient()
283 kc, _ := MakeKeepClient(&arv)
286 arv.ApiToken = "abc123"
287 localRoots := make(map[string]string)
288 writableLocalRoots := make(map[string]string)
290 ks := RunSomeFakeKeepServers(st, 5)
292 for i, k := range ks {
293 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
294 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
295 defer k.listener.Close()
298 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
300 kc.PutB([]byte("foo"))
302 shuff := NewRootSorter(
303 kc.LocalRoots(), Md5String("foo")).GetSortedRoots()
307 c.Check((s1 == shuff[0] && s2 == shuff[1]) ||
308 (s1 == shuff[1] && s2 == shuff[0]),
312 log.Printf("TestPutB done")
315 func (s *StandaloneSuite) TestPutHR(c *C) {
316 log.Printf("TestPutHR")
318 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
320 st := StubPutHandler{
325 make(chan string, 5)}
327 arv, _ := arvadosclient.MakeArvadosClient()
328 kc, _ := MakeKeepClient(&arv)
331 arv.ApiToken = "abc123"
332 localRoots := make(map[string]string)
333 writableLocalRoots := make(map[string]string)
335 ks := RunSomeFakeKeepServers(st, 5)
337 for i, k := range ks {
338 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
339 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
340 defer k.listener.Close()
343 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
345 reader, writer := io.Pipe()
348 writer.Write([]byte("foo"))
352 kc.PutHR(hash, reader, 3)
354 shuff := NewRootSorter(kc.LocalRoots(), hash).GetSortedRoots()
360 c.Check((s1 == shuff[0] && s2 == shuff[1]) ||
361 (s1 == shuff[1] && s2 == shuff[0]),
365 log.Printf("TestPutHR done")
368 func (s *StandaloneSuite) TestPutWithFail(c *C) {
369 log.Printf("TestPutWithFail")
371 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
373 st := StubPutHandler{
378 make(chan string, 4)}
381 make(chan string, 1)}
383 arv, err := arvadosclient.MakeArvadosClient()
384 kc, _ := MakeKeepClient(&arv)
387 arv.ApiToken = "abc123"
388 localRoots := make(map[string]string)
389 writableLocalRoots := make(map[string]string)
391 ks1 := RunSomeFakeKeepServers(st, 4)
392 ks2 := RunSomeFakeKeepServers(fh, 1)
394 for i, k := range ks1 {
395 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
396 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
397 defer k.listener.Close()
399 for i, k := range ks2 {
400 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
401 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
402 defer k.listener.Close()
405 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
407 shuff := NewRootSorter(
408 kc.LocalRoots(), Md5String("foo")).GetSortedRoots()
410 phash, replicas, err := kc.PutB([]byte("foo"))
414 c.Check(err, Equals, nil)
415 c.Check(phash, Equals, "")
416 c.Check(replicas, Equals, 2)
421 c.Check((s1 == shuff[1] && s2 == shuff[2]) ||
422 (s1 == shuff[2] && s2 == shuff[1]),
427 func (s *StandaloneSuite) TestPutWithTooManyFail(c *C) {
428 log.Printf("TestPutWithTooManyFail")
430 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
432 st := StubPutHandler{
437 make(chan string, 1)}
440 make(chan string, 4)}
442 arv, err := arvadosclient.MakeArvadosClient()
443 kc, _ := MakeKeepClient(&arv)
446 arv.ApiToken = "abc123"
447 localRoots := make(map[string]string)
448 writableLocalRoots := make(map[string]string)
450 ks1 := RunSomeFakeKeepServers(st, 1)
451 ks2 := RunSomeFakeKeepServers(fh, 4)
453 for i, k := range ks1 {
454 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
455 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
456 defer k.listener.Close()
458 for i, k := range ks2 {
459 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
460 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
461 defer k.listener.Close()
464 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
466 _, replicas, err := kc.PutB([]byte("foo"))
468 c.Check(err, Equals, InsufficientReplicasError)
469 c.Check(replicas, Equals, 1)
470 c.Check(<-st.handled, Equals, ks1[0].url)
472 log.Printf("TestPutWithTooManyFail done")
475 type StubGetHandler struct {
478 expectApiToken string
483 func (sgh StubGetHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
484 sgh.c.Check(req.URL.Path, Equals, "/"+sgh.expectPath)
485 sgh.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", sgh.expectApiToken))
486 resp.WriteHeader(sgh.httpStatus)
487 resp.Header().Set("Content-Length", fmt.Sprintf("%d", len(sgh.body)))
491 func (s *StandaloneSuite) TestGet(c *C) {
492 log.Printf("TestGet")
494 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
496 st := StubGetHandler{
503 ks := RunFakeKeepServer(st)
504 defer ks.listener.Close()
506 arv, err := arvadosclient.MakeArvadosClient()
507 kc, _ := MakeKeepClient(&arv)
508 arv.ApiToken = "abc123"
509 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
511 r, n, url2, err := kc.Get(hash)
513 c.Check(err, Equals, nil)
514 c.Check(n, Equals, int64(3))
515 c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks.url, hash))
517 content, err2 := ioutil.ReadAll(r)
518 c.Check(err2, Equals, nil)
519 c.Check(content, DeepEquals, []byte("foo"))
521 log.Printf("TestGet done")
524 func (s *StandaloneSuite) TestGet404(c *C) {
525 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
527 st := Error404Handler{make(chan string, 1)}
529 ks := RunFakeKeepServer(st)
530 defer ks.listener.Close()
532 arv, err := arvadosclient.MakeArvadosClient()
533 kc, _ := MakeKeepClient(&arv)
534 arv.ApiToken = "abc123"
535 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
537 r, n, url2, err := kc.Get(hash)
538 c.Check(err, Equals, BlockNotFound)
539 c.Check(n, Equals, int64(0))
540 c.Check(url2, Equals, "")
541 c.Check(r, Equals, nil)
544 func (s *StandaloneSuite) TestGetFail(c *C) {
545 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
547 st := FailHandler{make(chan string, 1)}
549 ks := RunFakeKeepServer(st)
550 defer ks.listener.Close()
552 arv, err := arvadosclient.MakeArvadosClient()
553 kc, _ := MakeKeepClient(&arv)
554 arv.ApiToken = "abc123"
555 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
557 r, n, url2, err := kc.Get(hash)
558 errNotFound, _ := err.(ErrNotFound)
559 c.Check(errNotFound, NotNil)
560 c.Check(strings.Contains(err.Error(), "use of closed network connection"), Equals, true)
561 c.Check(n, Equals, int64(0))
562 c.Check(url2, Equals, "")
563 c.Check(r, Equals, nil)
566 func (s *StandaloneSuite) TestGetFailRetry(c *C) {
567 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
569 st := &FailThenSucceedHandler{make(chan string, 1), 0,
577 ks := RunFakeKeepServer(st)
578 defer ks.listener.Close()
580 arv, err := arvadosclient.MakeArvadosClient()
581 kc, _ := MakeKeepClient(&arv)
582 arv.ApiToken = "abc123"
583 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
585 r, n, url2, err := kc.Get(hash)
587 c.Check(err, Equals, nil)
588 c.Check(n, Equals, int64(3))
589 c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks.url, hash))
591 content, err2 := ioutil.ReadAll(r)
592 c.Check(err2, Equals, nil)
593 c.Check(content, DeepEquals, []byte("foo"))
596 func (s *StandaloneSuite) TestGetNetError(c *C) {
597 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
599 arv, err := arvadosclient.MakeArvadosClient()
600 kc, _ := MakeKeepClient(&arv)
601 arv.ApiToken = "abc123"
602 kc.SetServiceRoots(map[string]string{"x": "http://localhost:62222"}, nil, nil)
604 r, n, url2, err := kc.Get(hash)
605 errNotFound, _ := err.(ErrNotFound)
606 c.Check(errNotFound, NotNil)
607 c.Check(strings.Contains(err.Error(), "connection refused"), Equals, true)
608 c.Check(n, Equals, int64(0))
609 c.Check(url2, Equals, "")
610 c.Check(r, Equals, nil)
613 func (s *StandaloneSuite) TestGetWithServiceHint(c *C) {
614 uuid := "zzzzz-bi6l4-123451234512345"
615 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
617 // This one shouldn't be used:
618 ks0 := RunFakeKeepServer(StubGetHandler{
624 defer ks0.listener.Close()
625 // This one should be used:
626 ks := RunFakeKeepServer(StubGetHandler{
632 defer ks.listener.Close()
634 arv, err := arvadosclient.MakeArvadosClient()
635 kc, _ := MakeKeepClient(&arv)
636 arv.ApiToken = "abc123"
638 map[string]string{"x": ks0.url},
640 map[string]string{uuid: ks.url})
642 r, n, uri, err := kc.Get(hash + "+K@" + uuid)
644 c.Check(err, Equals, nil)
645 c.Check(n, Equals, int64(3))
646 c.Check(uri, Equals, fmt.Sprintf("%s/%s", ks.url, hash+"+K@"+uuid))
648 content, err := ioutil.ReadAll(r)
649 c.Check(err, Equals, nil)
650 c.Check(content, DeepEquals, []byte("foo"))
653 // Use a service hint to fetch from a local disk service, overriding
654 // rendezvous probe order.
655 func (s *StandaloneSuite) TestGetWithLocalServiceHint(c *C) {
656 uuid := "zzzzz-bi6l4-zzzzzzzzzzzzzzz"
657 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
659 // This one shouldn't be used, although it appears first in
660 // rendezvous probe order:
661 ks0 := RunFakeKeepServer(StubGetHandler{
667 defer ks0.listener.Close()
668 // This one should be used:
669 ks := RunFakeKeepServer(StubGetHandler{
675 defer ks.listener.Close()
677 arv, err := arvadosclient.MakeArvadosClient()
678 kc, _ := MakeKeepClient(&arv)
679 arv.ApiToken = "abc123"
682 "zzzzz-bi6l4-yyyyyyyyyyyyyyy": ks0.url,
683 "zzzzz-bi6l4-xxxxxxxxxxxxxxx": ks0.url,
684 "zzzzz-bi6l4-wwwwwwwwwwwwwww": ks0.url,
688 "zzzzz-bi6l4-yyyyyyyyyyyyyyy": ks0.url,
689 "zzzzz-bi6l4-xxxxxxxxxxxxxxx": ks0.url,
690 "zzzzz-bi6l4-wwwwwwwwwwwwwww": ks0.url,
694 r, n, uri, err := kc.Get(hash + "+K@" + uuid)
696 c.Check(err, Equals, nil)
697 c.Check(n, Equals, int64(3))
698 c.Check(uri, Equals, fmt.Sprintf("%s/%s", ks.url, hash+"+K@"+uuid))
700 content, err := ioutil.ReadAll(r)
701 c.Check(err, Equals, nil)
702 c.Check(content, DeepEquals, []byte("foo"))
705 func (s *StandaloneSuite) TestGetWithServiceHintFailoverToLocals(c *C) {
706 uuid := "zzzzz-bi6l4-123451234512345"
707 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
709 ksLocal := RunFakeKeepServer(StubGetHandler{
715 defer ksLocal.listener.Close()
716 ksGateway := RunFakeKeepServer(StubGetHandler{
720 http.StatusInternalServerError,
722 defer ksGateway.listener.Close()
724 arv, err := arvadosclient.MakeArvadosClient()
725 kc, _ := MakeKeepClient(&arv)
726 arv.ApiToken = "abc123"
728 map[string]string{"zzzzz-bi6l4-keepdisk0000000": ksLocal.url},
730 map[string]string{uuid: ksGateway.url})
732 r, n, uri, err := kc.Get(hash + "+K@" + uuid)
733 c.Assert(err, Equals, nil)
735 c.Check(n, Equals, int64(3))
736 c.Check(uri, Equals, fmt.Sprintf("%s/%s", ksLocal.url, hash+"+K@"+uuid))
738 content, err := ioutil.ReadAll(r)
739 c.Check(err, Equals, nil)
740 c.Check(content, DeepEquals, []byte("foo"))
743 type BarHandler struct {
747 func (this BarHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
748 resp.Write([]byte("bar"))
749 this.handled <- fmt.Sprintf("http://%s", req.Host)
752 func (s *StandaloneSuite) TestChecksum(c *C) {
753 foohash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
754 barhash := fmt.Sprintf("%x", md5.Sum([]byte("bar")))
756 st := BarHandler{make(chan string, 1)}
758 ks := RunFakeKeepServer(st)
759 defer ks.listener.Close()
761 arv, err := arvadosclient.MakeArvadosClient()
762 kc, _ := MakeKeepClient(&arv)
763 arv.ApiToken = "abc123"
764 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
766 r, n, _, err := kc.Get(barhash)
767 _, err = ioutil.ReadAll(r)
768 c.Check(n, Equals, int64(3))
769 c.Check(err, Equals, nil)
773 r, n, _, err = kc.Get(foohash)
774 _, err = ioutil.ReadAll(r)
775 c.Check(n, Equals, int64(3))
776 c.Check(err, Equals, BadChecksum)
781 func (s *StandaloneSuite) TestGetWithFailures(c *C) {
782 content := []byte("waz")
783 hash := fmt.Sprintf("%x", md5.Sum(content))
785 fh := Error404Handler{
786 make(chan string, 4)}
788 st := StubGetHandler{
795 arv, err := arvadosclient.MakeArvadosClient()
796 kc, _ := MakeKeepClient(&arv)
797 arv.ApiToken = "abc123"
798 localRoots := make(map[string]string)
799 writableLocalRoots := make(map[string]string)
801 ks1 := RunSomeFakeKeepServers(st, 1)
802 ks2 := RunSomeFakeKeepServers(fh, 4)
804 for i, k := range ks1 {
805 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
806 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
807 defer k.listener.Close()
809 for i, k := range ks2 {
810 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
811 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
812 defer k.listener.Close()
815 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
817 // This test works only if one of the failing services is
818 // attempted before the succeeding service. Otherwise,
819 // <-fh.handled below will just hang! (Probe order depends on
820 // the choice of block content "waz" and the UUIDs of the fake
821 // servers, so we just tried different strings until we found
822 // an example that passes this Assert.)
823 c.Assert(NewRootSorter(localRoots, hash).GetSortedRoots()[0], Not(Equals), ks1[0].url)
825 r, n, url2, err := kc.Get(hash)
828 c.Check(err, Equals, nil)
829 c.Check(n, Equals, int64(3))
830 c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks1[0].url, hash))
832 read_content, err2 := ioutil.ReadAll(r)
833 c.Check(err2, Equals, nil)
834 c.Check(read_content, DeepEquals, content)
837 func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
838 content := []byte("TestPutGetHead")
840 arv, err := arvadosclient.MakeArvadosClient()
841 kc, err := MakeKeepClient(&arv)
842 c.Assert(err, Equals, nil)
844 hash := fmt.Sprintf("%x", md5.Sum(content))
847 n, _, err := kc.Ask(hash)
848 c.Check(err, Equals, BlockNotFound)
849 c.Check(n, Equals, int64(0))
852 hash2, replicas, err := kc.PutB(content)
853 c.Check(hash2, Matches, fmt.Sprintf(`%s\+%d\b.*`, hash, len(content)))
854 c.Check(replicas, Equals, 2)
855 c.Check(err, Equals, nil)
858 r, n, url2, err := kc.Get(hash)
859 c.Check(err, Equals, nil)
860 c.Check(n, Equals, int64(len(content)))
861 c.Check(url2, Matches, fmt.Sprintf("http://localhost:\\d+/%s", hash))
863 read_content, err2 := ioutil.ReadAll(r)
864 c.Check(err2, Equals, nil)
865 c.Check(read_content, DeepEquals, content)
868 n, url2, err := kc.Ask(hash)
869 c.Check(err, Equals, nil)
870 c.Check(n, Equals, int64(len(content)))
871 c.Check(url2, Matches, fmt.Sprintf("http://localhost:\\d+/%s", hash))
875 type StubProxyHandler struct {
879 func (this StubProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
880 resp.Header().Set("X-Keep-Replicas-Stored", "2")
881 this.handled <- fmt.Sprintf("http://%s", req.Host)
884 func (s *StandaloneSuite) TestPutProxy(c *C) {
885 log.Printf("TestPutProxy")
887 st := StubProxyHandler{make(chan string, 1)}
889 arv, err := arvadosclient.MakeArvadosClient()
890 kc, _ := MakeKeepClient(&arv)
893 kc.Using_proxy = true
894 arv.ApiToken = "abc123"
895 localRoots := make(map[string]string)
896 writableLocalRoots := make(map[string]string)
898 ks1 := RunSomeFakeKeepServers(st, 1)
900 for i, k := range ks1 {
901 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
902 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
903 defer k.listener.Close()
906 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
908 _, replicas, err := kc.PutB([]byte("foo"))
911 c.Check(err, Equals, nil)
912 c.Check(replicas, Equals, 2)
914 log.Printf("TestPutProxy done")
917 func (s *StandaloneSuite) TestPutProxyInsufficientReplicas(c *C) {
918 log.Printf("TestPutProxy")
920 st := StubProxyHandler{make(chan string, 1)}
922 arv, err := arvadosclient.MakeArvadosClient()
923 kc, _ := MakeKeepClient(&arv)
926 kc.Using_proxy = true
927 arv.ApiToken = "abc123"
928 localRoots := make(map[string]string)
929 writableLocalRoots := make(map[string]string)
931 ks1 := RunSomeFakeKeepServers(st, 1)
933 for i, k := range ks1 {
934 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
935 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
936 defer k.listener.Close()
938 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
940 _, replicas, err := kc.PutB([]byte("foo"))
943 c.Check(err, Equals, InsufficientReplicasError)
944 c.Check(replicas, Equals, 2)
946 log.Printf("TestPutProxy done")
949 func (s *StandaloneSuite) TestMakeLocator(c *C) {
950 l, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31ce+3+Aabcde@12345678")
951 c.Check(err, Equals, nil)
952 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
953 c.Check(l.Size, Equals, 3)
954 c.Check(l.Hints, DeepEquals, []string{"3", "Aabcde@12345678"})
957 func (s *StandaloneSuite) TestMakeLocatorNoHints(c *C) {
958 l, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31ce")
959 c.Check(err, Equals, nil)
960 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
961 c.Check(l.Size, Equals, -1)
962 c.Check(l.Hints, DeepEquals, []string{})
965 func (s *StandaloneSuite) TestMakeLocatorNoSizeHint(c *C) {
966 l, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31ce+Aabcde@12345678")
967 c.Check(err, Equals, nil)
968 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
969 c.Check(l.Size, Equals, -1)
970 c.Check(l.Hints, DeepEquals, []string{"Aabcde@12345678"})
973 func (s *StandaloneSuite) TestMakeLocatorPreservesUnrecognizedHints(c *C) {
974 str := "91f372a266fe2bf2823cb8ec7fda31ce+3+Unknown+Kzzzzz+Afoobar"
975 l, err := MakeLocator(str)
976 c.Check(err, Equals, nil)
977 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
978 c.Check(l.Size, Equals, 3)
979 c.Check(l.Hints, DeepEquals, []string{"3", "Unknown", "Kzzzzz", "Afoobar"})
980 c.Check(l.String(), Equals, str)
983 func (s *StandaloneSuite) TestMakeLocatorInvalidInput(c *C) {
984 _, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31c")
985 c.Check(err, Equals, InvalidLocatorError)
988 func (s *StandaloneSuite) TestPutBWant2ReplicasWithOnlyOneWritableLocalRoot(c *C) {
989 hash := Md5String("foo")
991 st := StubPutHandler{
996 make(chan string, 5)}
998 arv, _ := arvadosclient.MakeArvadosClient()
999 kc, _ := MakeKeepClient(&arv)
1001 kc.Want_replicas = 2
1002 arv.ApiToken = "abc123"
1003 localRoots := make(map[string]string)
1004 writableLocalRoots := make(map[string]string)
1006 ks := RunSomeFakeKeepServers(st, 5)
1008 for i, k := range ks {
1009 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
1011 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
1013 defer k.listener.Close()
1016 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
1018 _, replicas, err := kc.PutB([]byte("foo"))
1020 c.Check(err, Equals, InsufficientReplicasError)
1021 c.Check(replicas, Equals, 1)
1023 c.Check(<-st.handled, Equals, localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", 0)])
1026 func (s *StandaloneSuite) TestPutBWithNoWritableLocalRoots(c *C) {
1027 hash := Md5String("foo")
1029 st := StubPutHandler{
1034 make(chan string, 5)}
1036 arv, _ := arvadosclient.MakeArvadosClient()
1037 kc, _ := MakeKeepClient(&arv)
1039 kc.Want_replicas = 2
1040 arv.ApiToken = "abc123"
1041 localRoots := make(map[string]string)
1042 writableLocalRoots := make(map[string]string)
1044 ks := RunSomeFakeKeepServers(st, 5)
1046 for i, k := range ks {
1047 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
1048 defer k.listener.Close()
1051 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
1053 _, replicas, err := kc.PutB([]byte("foo"))
1055 c.Check(err, Equals, InsufficientReplicasError)
1056 c.Check(replicas, Equals, 0)
1059 type StubGetIndexHandler struct {
1062 expectAPIToken string
1067 func (h StubGetIndexHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
1068 h.c.Check(req.URL.Path, Equals, h.expectPath)
1069 h.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", h.expectAPIToken))
1070 resp.WriteHeader(h.httpStatus)
1071 resp.Header().Set("Content-Length", fmt.Sprintf("%d", len(h.body)))
1075 func (s *StandaloneSuite) TestGetIndexWithNoPrefix(c *C) {
1076 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1078 st := StubGetIndexHandler{
1083 []byte(hash + "+3 1443559274\n\n")}
1085 ks := RunFakeKeepServer(st)
1086 defer ks.listener.Close()
1088 arv, err := arvadosclient.MakeArvadosClient()
1089 kc, _ := MakeKeepClient(&arv)
1090 arv.ApiToken = "abc123"
1091 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
1093 r, err := kc.GetIndex("x", "")
1094 c.Check(err, Equals, nil)
1096 content, err2 := ioutil.ReadAll(r)
1097 c.Check(err2, Equals, nil)
1098 c.Check(content, DeepEquals, st.body[0:len(st.body)-1])
1101 func (s *StandaloneSuite) TestGetIndexWithPrefix(c *C) {
1102 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1104 st := StubGetIndexHandler{
1106 "/index/" + hash[0:3],
1109 []byte(hash + "+3 1443559274\n\n")}
1111 ks := RunFakeKeepServer(st)
1112 defer ks.listener.Close()
1114 arv, err := arvadosclient.MakeArvadosClient()
1115 kc, _ := MakeKeepClient(&arv)
1116 arv.ApiToken = "abc123"
1117 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
1119 r, err := kc.GetIndex("x", hash[0:3])
1120 c.Check(err, Equals, nil)
1122 content, err2 := ioutil.ReadAll(r)
1123 c.Check(err2, Equals, nil)
1124 c.Check(content, DeepEquals, st.body[0:len(st.body)-1])
1127 func (s *StandaloneSuite) TestGetIndexIncomplete(c *C) {
1128 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1130 st := StubGetIndexHandler{
1132 "/index/" + hash[0:3],
1137 ks := RunFakeKeepServer(st)
1138 defer ks.listener.Close()
1140 arv, err := arvadosclient.MakeArvadosClient()
1141 kc, _ := MakeKeepClient(&arv)
1142 arv.ApiToken = "abc123"
1143 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
1145 _, err = kc.GetIndex("x", hash[0:3])
1146 c.Check(err, Equals, ErrIncompleteIndex)
1149 func (s *StandaloneSuite) TestGetIndexWithNoSuchServer(c *C) {
1150 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1152 st := StubGetIndexHandler{
1154 "/index/" + hash[0:3],
1159 ks := RunFakeKeepServer(st)
1160 defer ks.listener.Close()
1162 arv, err := arvadosclient.MakeArvadosClient()
1163 kc, _ := MakeKeepClient(&arv)
1164 arv.ApiToken = "abc123"
1165 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
1167 _, err = kc.GetIndex("y", hash[0:3])
1168 c.Check(err, Equals, ErrNoSuchKeepServer)
1171 func (s *StandaloneSuite) TestGetIndexWithNoSuchPrefix(c *C) {
1172 st := StubGetIndexHandler{
1179 ks := RunFakeKeepServer(st)
1180 defer ks.listener.Close()
1182 arv, err := arvadosclient.MakeArvadosClient()
1183 kc, _ := MakeKeepClient(&arv)
1184 arv.ApiToken = "abc123"
1185 kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
1187 r, err := kc.GetIndex("x", "abcd")
1188 c.Check(err, Equals, nil)
1190 content, err2 := ioutil.ReadAll(r)
1191 c.Check(err2, Equals, nil)
1192 c.Check(content, DeepEquals, st.body[0:len(st.body)-1])