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"
20 // Gocheck boilerplate
21 func Test(t *testing.T) {
25 // Gocheck boilerplate
26 var _ = Suite(&ServerRequiredSuite{})
27 var _ = Suite(&StandaloneSuite{})
29 var no_server = flag.Bool("no-server", false, "Skip 'ServerRequireSuite'")
31 // Tests that require the Keep server running
32 type ServerRequiredSuite struct{}
35 type StandaloneSuite struct{}
37 func pythonDir() string {
39 return fmt.Sprintf("%s/../../python/tests", cwd)
42 func (s *ServerRequiredSuite) SetUpSuite(c *C) {
44 c.Skip("Skipping tests that require server")
47 arvadostest.StartAPI()
48 arvadostest.StartKeep()
51 func (s *ServerRequiredSuite) TearDownSuite(c *C) {
55 arvadostest.StopKeep()
59 func (s *ServerRequiredSuite) TestMakeKeepClient(c *C) {
60 arv, err := arvadosclient.MakeArvadosClient()
61 c.Assert(err, Equals, nil)
63 kc, err := MakeKeepClient(&arv)
65 c.Assert(err, Equals, nil)
66 c.Check(len(kc.LocalRoots()), Equals, 2)
67 for _, root := range kc.LocalRoots() {
68 c.Check(root, Matches, "http://localhost:\\d+")
72 func (s *ServerRequiredSuite) TestDefaultReplications(c *C) {
73 arv, err := arvadosclient.MakeArvadosClient()
74 c.Assert(err, Equals, nil)
76 kc, err := MakeKeepClient(&arv)
77 c.Assert(kc.Want_replicas, Equals, 2)
79 arv.DiscoveryDoc["defaultCollectionReplication"] = 3.0
80 kc, err = MakeKeepClient(&arv)
81 c.Assert(kc.Want_replicas, Equals, 3)
83 arv.DiscoveryDoc["defaultCollectionReplication"] = 1.0
84 kc, err = MakeKeepClient(&arv)
85 c.Assert(kc.Want_replicas, Equals, 1)
88 type StubPutHandler struct {
96 func (sph StubPutHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
97 sph.c.Check(req.URL.Path, Equals, "/"+sph.expectPath)
98 sph.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", sph.expectApiToken))
99 body, err := ioutil.ReadAll(req.Body)
100 sph.c.Check(err, Equals, nil)
101 sph.c.Check(body, DeepEquals, []byte(sph.expectBody))
102 resp.WriteHeader(200)
103 sph.handled <- fmt.Sprintf("http://%s", req.Host)
106 func RunFakeKeepServer(st http.Handler) (ks KeepServer) {
108 ks.listener, err = net.ListenTCP("tcp", &net.TCPAddr{Port: 0})
110 panic(fmt.Sprintf("Could not listen on any port"))
112 ks.url = fmt.Sprintf("http://%s", ks.listener.Addr().String())
113 go http.Serve(ks.listener, st)
117 func UploadToStubHelper(c *C, st http.Handler, f func(*KeepClient, string,
118 io.ReadCloser, io.WriteCloser, chan uploadStatus)) {
120 ks := RunFakeKeepServer(st)
121 defer ks.listener.Close()
123 arv, _ := arvadosclient.MakeArvadosClient()
124 arv.ApiToken = "abc123"
126 kc, _ := MakeKeepClient(&arv)
128 reader, writer := io.Pipe()
129 upload_status := make(chan uploadStatus)
131 f(kc, ks.url, reader, writer, upload_status)
134 func (s *StandaloneSuite) TestUploadToStubKeepServer(c *C) {
135 log.Printf("TestUploadToStubKeepServer")
137 st := StubPutHandler{
139 "acbd18db4cc2f85cedef654fccc4a4d8",
144 UploadToStubHelper(c, st,
145 func(kc *KeepClient, url string, reader io.ReadCloser,
146 writer io.WriteCloser, upload_status chan uploadStatus) {
148 go kc.uploadToKeepServer(url, st.expectPath, reader, upload_status, int64(len("foo")), "TestUploadToStubKeepServer")
150 writer.Write([]byte("foo"))
154 status := <-upload_status
155 c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
158 log.Printf("TestUploadToStubKeepServer done")
161 func (s *StandaloneSuite) TestUploadToStubKeepServerBufferReader(c *C) {
162 log.Printf("TestUploadToStubKeepServerBufferReader")
164 st := StubPutHandler{
166 "acbd18db4cc2f85cedef654fccc4a4d8",
171 UploadToStubHelper(c, st,
172 func(kc *KeepClient, url string, reader io.ReadCloser,
173 writer io.WriteCloser, upload_status chan uploadStatus) {
175 tr := streamer.AsyncStreamFromReader(512, reader)
178 br1 := tr.MakeStreamReader()
180 go kc.uploadToKeepServer(url, st.expectPath, br1, upload_status, 3, "TestUploadToStubKeepServerBufferReader")
182 writer.Write([]byte("foo"))
187 status := <-upload_status
188 c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
191 log.Printf("TestUploadToStubKeepServerBufferReader done")
194 type FailHandler struct {
198 func (fh FailHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
199 resp.WriteHeader(500)
200 fh.handled <- fmt.Sprintf("http://%s", req.Host)
203 type FailThenSucceedHandler struct {
206 successhandler StubGetHandler
209 func (fh *FailThenSucceedHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
211 resp.WriteHeader(500)
213 fh.handled <- fmt.Sprintf("http://%s", req.Host)
215 fh.successhandler.ServeHTTP(resp, req)
219 type Error404Handler struct {
223 func (fh Error404Handler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
224 resp.WriteHeader(404)
225 fh.handled <- fmt.Sprintf("http://%s", req.Host)
228 func (s *StandaloneSuite) TestFailedUploadToStubKeepServer(c *C) {
229 log.Printf("TestFailedUploadToStubKeepServer")
234 hash := "acbd18db4cc2f85cedef654fccc4a4d8"
236 UploadToStubHelper(c, st,
237 func(kc *KeepClient, url string, reader io.ReadCloser,
238 writer io.WriteCloser, upload_status chan uploadStatus) {
240 go kc.uploadToKeepServer(url, hash, reader, upload_status, 3, "TestFailedUploadToStubKeepServer")
242 writer.Write([]byte("foo"))
247 status := <-upload_status
248 c.Check(status.url, Equals, fmt.Sprintf("%s/%s", url, hash))
249 c.Check(status.statusCode, Equals, 500)
251 log.Printf("TestFailedUploadToStubKeepServer done")
254 type KeepServer struct {
255 listener net.Listener
259 func RunSomeFakeKeepServers(st http.Handler, n int) (ks []KeepServer) {
260 ks = make([]KeepServer, n)
262 for i := 0; i < n; i += 1 {
263 ks[i] = RunFakeKeepServer(st)
269 func (s *StandaloneSuite) TestPutB(c *C) {
270 log.Printf("TestPutB")
272 hash := Md5String("foo")
274 st := StubPutHandler{
279 make(chan string, 5)}
281 arv, _ := arvadosclient.MakeArvadosClient()
282 kc, _ := MakeKeepClient(&arv)
285 arv.ApiToken = "abc123"
286 localRoots := make(map[string]string)
287 writableLocalRoots := make(map[string]string)
289 ks := RunSomeFakeKeepServers(st, 5)
291 for i, k := range ks {
292 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
293 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
294 defer k.listener.Close()
297 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
299 kc.PutB([]byte("foo"))
301 shuff := NewRootSorter(
302 kc.LocalRoots(), Md5String("foo")).GetSortedRoots()
306 c.Check((s1 == shuff[0] && s2 == shuff[1]) ||
307 (s1 == shuff[1] && s2 == shuff[0]),
311 log.Printf("TestPutB done")
314 func (s *StandaloneSuite) TestPutHR(c *C) {
315 log.Printf("TestPutHR")
317 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
319 st := StubPutHandler{
324 make(chan string, 5)}
326 arv, _ := arvadosclient.MakeArvadosClient()
327 kc, _ := MakeKeepClient(&arv)
330 arv.ApiToken = "abc123"
331 localRoots := make(map[string]string)
332 writableLocalRoots := make(map[string]string)
334 ks := RunSomeFakeKeepServers(st, 5)
336 for i, k := range ks {
337 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
338 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
339 defer k.listener.Close()
342 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
344 reader, writer := io.Pipe()
347 writer.Write([]byte("foo"))
351 kc.PutHR(hash, reader, 3)
353 shuff := NewRootSorter(kc.LocalRoots(), hash).GetSortedRoots()
359 c.Check((s1 == shuff[0] && s2 == shuff[1]) ||
360 (s1 == shuff[1] && s2 == shuff[0]),
364 log.Printf("TestPutHR done")
367 func (s *StandaloneSuite) TestPutWithFail(c *C) {
368 log.Printf("TestPutWithFail")
370 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
372 st := StubPutHandler{
377 make(chan string, 4)}
380 make(chan string, 1)}
382 arv, err := arvadosclient.MakeArvadosClient()
383 kc, _ := MakeKeepClient(&arv)
386 arv.ApiToken = "abc123"
387 localRoots := make(map[string]string)
388 writableLocalRoots := make(map[string]string)
390 ks1 := RunSomeFakeKeepServers(st, 4)
391 ks2 := RunSomeFakeKeepServers(fh, 1)
393 for i, k := range ks1 {
394 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
395 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
396 defer k.listener.Close()
398 for i, k := range ks2 {
399 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
400 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
401 defer k.listener.Close()
404 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
406 shuff := NewRootSorter(
407 kc.LocalRoots(), Md5String("foo")).GetSortedRoots()
409 phash, replicas, err := kc.PutB([]byte("foo"))
413 c.Check(err, Equals, nil)
414 c.Check(phash, Equals, "")
415 c.Check(replicas, Equals, 2)
420 c.Check((s1 == shuff[1] && s2 == shuff[2]) ||
421 (s1 == shuff[2] && s2 == shuff[1]),
426 func (s *StandaloneSuite) TestPutWithTooManyFail(c *C) {
427 log.Printf("TestPutWithTooManyFail")
429 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
431 st := StubPutHandler{
436 make(chan string, 1)}
439 make(chan string, 4)}
441 arv, err := arvadosclient.MakeArvadosClient()
442 kc, _ := MakeKeepClient(&arv)
445 arv.ApiToken = "abc123"
446 localRoots := make(map[string]string)
447 writableLocalRoots := make(map[string]string)
449 ks1 := RunSomeFakeKeepServers(st, 1)
450 ks2 := RunSomeFakeKeepServers(fh, 4)
452 for i, k := range ks1 {
453 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
454 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
455 defer k.listener.Close()
457 for i, k := range ks2 {
458 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
459 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
460 defer k.listener.Close()
463 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
465 _, replicas, err := kc.PutB([]byte("foo"))
467 c.Check(err, Equals, InsufficientReplicasError)
468 c.Check(replicas, Equals, 1)
469 c.Check(<-st.handled, Equals, ks1[0].url)
471 log.Printf("TestPutWithTooManyFail done")
474 type StubGetHandler struct {
477 expectApiToken string
482 func (sgh StubGetHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
483 sgh.c.Check(req.URL.Path, Equals, "/"+sgh.expectPath)
484 sgh.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", sgh.expectApiToken))
485 resp.WriteHeader(sgh.httpStatus)
486 resp.Header().Set("Content-Length", fmt.Sprintf("%d", len(sgh.body)))
490 func (s *StandaloneSuite) TestGet(c *C) {
491 log.Printf("TestGet")
493 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
495 st := StubGetHandler{
502 ks := RunFakeKeepServer(st)
503 defer ks.listener.Close()
505 arv, err := arvadosclient.MakeArvadosClient()
506 kc, _ := MakeKeepClient(&arv)
507 arv.ApiToken = "abc123"
508 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
510 r, n, url2, err := kc.Get(hash)
512 c.Check(err, Equals, nil)
513 c.Check(n, Equals, int64(3))
514 c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks.url, hash))
516 content, err2 := ioutil.ReadAll(r)
517 c.Check(err2, Equals, nil)
518 c.Check(content, DeepEquals, []byte("foo"))
520 log.Printf("TestGet done")
523 func (s *StandaloneSuite) TestGet404(c *C) {
524 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
526 st := Error404Handler{make(chan string, 1)}
528 ks := RunFakeKeepServer(st)
529 defer ks.listener.Close()
531 arv, err := arvadosclient.MakeArvadosClient()
532 kc, _ := MakeKeepClient(&arv)
533 arv.ApiToken = "abc123"
534 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
536 r, n, url2, err := kc.Get(hash)
537 c.Check(err, Equals, BlockNotFound)
538 c.Check(n, Equals, int64(0))
539 c.Check(url2, Equals, "")
540 c.Check(r, Equals, nil)
543 func (s *StandaloneSuite) TestGetFail(c *C) {
544 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
546 st := FailHandler{make(chan string, 1)}
548 ks := RunFakeKeepServer(st)
549 defer ks.listener.Close()
551 arv, err := arvadosclient.MakeArvadosClient()
552 kc, _ := MakeKeepClient(&arv)
553 arv.ApiToken = "abc123"
554 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
556 r, n, url2, err := kc.Get(hash)
557 c.Check(err, Equals, BlockNotFound)
558 c.Check(n, Equals, int64(0))
559 c.Check(url2, Equals, "")
560 c.Check(r, Equals, nil)
563 func (s *StandaloneSuite) TestGetFailRetry(c *C) {
564 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
566 st := &FailThenSucceedHandler{make(chan string, 1), 0,
574 ks := RunFakeKeepServer(st)
575 defer ks.listener.Close()
577 arv, err := arvadosclient.MakeArvadosClient()
578 kc, _ := MakeKeepClient(&arv)
579 arv.ApiToken = "abc123"
580 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
582 r, n, url2, err := kc.Get(hash)
584 c.Check(err, Equals, nil)
585 c.Check(n, Equals, int64(3))
586 c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks.url, hash))
588 content, err2 := ioutil.ReadAll(r)
589 c.Check(err2, Equals, nil)
590 c.Check(content, DeepEquals, []byte("foo"))
593 func (s *StandaloneSuite) TestGetNetError(c *C) {
594 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
596 arv, err := arvadosclient.MakeArvadosClient()
597 kc, _ := MakeKeepClient(&arv)
598 arv.ApiToken = "abc123"
599 kc.SetServiceRoots(map[string]string{"x": "http://localhost:62222"}, map[string]string{"http://localhost:62222": ""}, nil)
601 r, n, url2, err := kc.Get(hash)
602 c.Check(err, Equals, BlockNotFound)
603 c.Check(n, Equals, int64(0))
604 c.Check(url2, Equals, "")
605 c.Check(r, Equals, nil)
608 func (s *StandaloneSuite) TestGetWithServiceHint(c *C) {
609 uuid := "zzzzz-bi6l4-123451234512345"
610 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
612 // This one shouldn't be used:
613 ks0 := RunFakeKeepServer(StubGetHandler{
619 defer ks0.listener.Close()
620 // This one should be used:
621 ks := RunFakeKeepServer(StubGetHandler{
627 defer ks.listener.Close()
629 arv, err := arvadosclient.MakeArvadosClient()
630 kc, _ := MakeKeepClient(&arv)
631 arv.ApiToken = "abc123"
633 map[string]string{"x": ks0.url},
634 map[string]string{"x": ks0.url},
635 map[string]string{uuid: ks.url})
637 r, n, uri, err := kc.Get(hash + "+K@" + uuid)
639 c.Check(err, Equals, nil)
640 c.Check(n, Equals, int64(3))
641 c.Check(uri, Equals, fmt.Sprintf("%s/%s", ks.url, hash+"+K@"+uuid))
643 content, err := ioutil.ReadAll(r)
644 c.Check(err, Equals, nil)
645 c.Check(content, DeepEquals, []byte("foo"))
648 // Use a service hint to fetch from a local disk service, overriding
649 // rendezvous probe order.
650 func (s *StandaloneSuite) TestGetWithLocalServiceHint(c *C) {
651 uuid := "zzzzz-bi6l4-zzzzzzzzzzzzzzz"
652 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
654 // This one shouldn't be used, although it appears first in
655 // rendezvous probe order:
656 ks0 := RunFakeKeepServer(StubGetHandler{
662 defer ks0.listener.Close()
663 // This one should be used:
664 ks := RunFakeKeepServer(StubGetHandler{
670 defer ks.listener.Close()
672 arv, err := arvadosclient.MakeArvadosClient()
673 kc, _ := MakeKeepClient(&arv)
674 arv.ApiToken = "abc123"
677 "zzzzz-bi6l4-yyyyyyyyyyyyyyy": ks0.url,
678 "zzzzz-bi6l4-xxxxxxxxxxxxxxx": ks0.url,
679 "zzzzz-bi6l4-wwwwwwwwwwwwwww": ks0.url,
682 "zzzzz-bi6l4-yyyyyyyyyyyyyyy": ks0.url,
683 "zzzzz-bi6l4-xxxxxxxxxxxxxxx": ks0.url,
684 "zzzzz-bi6l4-wwwwwwwwwwwwwww": ks0.url,
687 "zzzzz-bi6l4-yyyyyyyyyyyyyyy": ks0.url,
688 "zzzzz-bi6l4-xxxxxxxxxxxxxxx": ks0.url,
689 "zzzzz-bi6l4-wwwwwwwwwwwwwww": ks0.url,
693 r, n, uri, err := kc.Get(hash + "+K@" + uuid)
695 c.Check(err, Equals, nil)
696 c.Check(n, Equals, int64(3))
697 c.Check(uri, Equals, fmt.Sprintf("%s/%s", ks.url, hash+"+K@"+uuid))
699 content, err := ioutil.ReadAll(r)
700 c.Check(err, Equals, nil)
701 c.Check(content, DeepEquals, []byte("foo"))
704 func (s *StandaloneSuite) TestGetWithServiceHintFailoverToLocals(c *C) {
705 uuid := "zzzzz-bi6l4-123451234512345"
706 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
708 ksLocal := RunFakeKeepServer(StubGetHandler{
714 defer ksLocal.listener.Close()
715 ksGateway := RunFakeKeepServer(StubGetHandler{
719 http.StatusInternalServerError,
721 defer ksGateway.listener.Close()
723 arv, err := arvadosclient.MakeArvadosClient()
724 kc, _ := MakeKeepClient(&arv)
725 arv.ApiToken = "abc123"
727 map[string]string{"zzzzz-bi6l4-keepdisk0000000": ksLocal.url},
728 map[string]string{"zzzzz-bi6l4-keepdisk0000000": ksLocal.url},
729 map[string]string{uuid: ksGateway.url})
731 r, n, uri, err := kc.Get(hash + "+K@" + uuid)
732 c.Assert(err, Equals, nil)
734 c.Check(n, Equals, int64(3))
735 c.Check(uri, Equals, fmt.Sprintf("%s/%s", ksLocal.url, hash+"+K@"+uuid))
737 content, err := ioutil.ReadAll(r)
738 c.Check(err, Equals, nil)
739 c.Check(content, DeepEquals, []byte("foo"))
742 type BarHandler struct {
746 func (this BarHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
747 resp.Write([]byte("bar"))
748 this.handled <- fmt.Sprintf("http://%s", req.Host)
751 func (s *StandaloneSuite) TestChecksum(c *C) {
752 foohash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
753 barhash := fmt.Sprintf("%x", md5.Sum([]byte("bar")))
755 st := BarHandler{make(chan string, 1)}
757 ks := RunFakeKeepServer(st)
758 defer ks.listener.Close()
760 arv, err := arvadosclient.MakeArvadosClient()
761 kc, _ := MakeKeepClient(&arv)
762 arv.ApiToken = "abc123"
763 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
765 r, n, _, err := kc.Get(barhash)
766 _, err = ioutil.ReadAll(r)
767 c.Check(n, Equals, int64(3))
768 c.Check(err, Equals, nil)
772 r, n, _, err = kc.Get(foohash)
773 _, err = ioutil.ReadAll(r)
774 c.Check(n, Equals, int64(3))
775 c.Check(err, Equals, BadChecksum)
780 func (s *StandaloneSuite) TestGetWithFailures(c *C) {
781 content := []byte("waz")
782 hash := fmt.Sprintf("%x", md5.Sum(content))
784 fh := Error404Handler{
785 make(chan string, 4)}
787 st := StubGetHandler{
794 arv, err := arvadosclient.MakeArvadosClient()
795 kc, _ := MakeKeepClient(&arv)
796 arv.ApiToken = "abc123"
797 localRoots := make(map[string]string)
798 writableLocalRoots := make(map[string]string)
800 ks1 := RunSomeFakeKeepServers(st, 1)
801 ks2 := RunSomeFakeKeepServers(fh, 4)
803 for i, k := range ks1 {
804 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
805 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
806 defer k.listener.Close()
808 for i, k := range ks2 {
809 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
810 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i+len(ks1))] = k.url
811 defer k.listener.Close()
814 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
816 // This test works only if one of the failing services is
817 // attempted before the succeeding service. Otherwise,
818 // <-fh.handled below will just hang! (Probe order depends on
819 // the choice of block content "waz" and the UUIDs of the fake
820 // servers, so we just tried different strings until we found
821 // an example that passes this Assert.)
822 c.Assert(NewRootSorter(localRoots, hash).GetSortedRoots()[0], Not(Equals), ks1[0].url)
824 r, n, url2, err := kc.Get(hash)
827 c.Check(err, Equals, nil)
828 c.Check(n, Equals, int64(3))
829 c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks1[0].url, hash))
831 read_content, err2 := ioutil.ReadAll(r)
832 c.Check(err2, Equals, nil)
833 c.Check(read_content, DeepEquals, content)
836 func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
837 content := []byte("TestPutGetHead")
839 arv, err := arvadosclient.MakeArvadosClient()
840 kc, err := MakeKeepClient(&arv)
841 c.Assert(err, Equals, nil)
843 hash := fmt.Sprintf("%x", md5.Sum(content))
846 n, _, err := kc.Ask(hash)
847 c.Check(err, Equals, BlockNotFound)
848 c.Check(n, Equals, int64(0))
851 hash2, replicas, err := kc.PutB(content)
852 c.Check(hash2, Matches, fmt.Sprintf(`%s\+%d\b.*`, hash, len(content)))
853 c.Check(replicas, Equals, 2)
854 c.Check(err, Equals, nil)
857 r, n, url2, err := kc.Get(hash)
858 c.Check(err, Equals, nil)
859 c.Check(n, Equals, int64(len(content)))
860 c.Check(url2, Matches, fmt.Sprintf("http://localhost:\\d+/%s", hash))
862 read_content, err2 := ioutil.ReadAll(r)
863 c.Check(err2, Equals, nil)
864 c.Check(read_content, DeepEquals, content)
867 n, url2, err := kc.Ask(hash)
868 c.Check(err, Equals, nil)
869 c.Check(n, Equals, int64(len(content)))
870 c.Check(url2, Matches, fmt.Sprintf("http://localhost:\\d+/%s", hash))
874 type StubProxyHandler struct {
878 func (this StubProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
879 resp.Header().Set("X-Keep-Replicas-Stored", "2")
880 this.handled <- fmt.Sprintf("http://%s", req.Host)
883 func (s *StandaloneSuite) TestPutProxy(c *C) {
884 log.Printf("TestPutProxy")
886 st := StubProxyHandler{make(chan string, 1)}
888 arv, err := arvadosclient.MakeArvadosClient()
889 kc, _ := MakeKeepClient(&arv)
892 kc.Using_proxy = true
893 arv.ApiToken = "abc123"
894 localRoots := make(map[string]string)
895 writableLocalRoots := make(map[string]string)
897 ks1 := RunSomeFakeKeepServers(st, 1)
899 for i, k := range ks1 {
900 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
901 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
902 defer k.listener.Close()
905 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
907 _, replicas, err := kc.PutB([]byte("foo"))
910 c.Check(err, Equals, nil)
911 c.Check(replicas, Equals, 2)
913 log.Printf("TestPutProxy done")
916 func (s *StandaloneSuite) TestPutProxyInsufficientReplicas(c *C) {
917 log.Printf("TestPutProxy")
919 st := StubProxyHandler{make(chan string, 1)}
921 arv, err := arvadosclient.MakeArvadosClient()
922 kc, _ := MakeKeepClient(&arv)
925 kc.Using_proxy = true
926 arv.ApiToken = "abc123"
927 localRoots := make(map[string]string)
928 writableLocalRoots := make(map[string]string)
930 ks1 := RunSomeFakeKeepServers(st, 1)
932 for i, k := range ks1 {
933 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
934 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
935 defer k.listener.Close()
937 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
939 _, replicas, err := kc.PutB([]byte("foo"))
942 c.Check(err, Equals, InsufficientReplicasError)
943 c.Check(replicas, Equals, 2)
945 log.Printf("TestPutProxy done")
948 func (s *StandaloneSuite) TestMakeLocator(c *C) {
949 l, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31ce+3+Aabcde@12345678")
950 c.Check(err, Equals, nil)
951 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
952 c.Check(l.Size, Equals, 3)
953 c.Check(l.Hints, DeepEquals, []string{"3", "Aabcde@12345678"})
956 func (s *StandaloneSuite) TestMakeLocatorNoHints(c *C) {
957 l, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31ce")
958 c.Check(err, Equals, nil)
959 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
960 c.Check(l.Size, Equals, -1)
961 c.Check(l.Hints, DeepEquals, []string{})
964 func (s *StandaloneSuite) TestMakeLocatorNoSizeHint(c *C) {
965 l, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31ce+Aabcde@12345678")
966 c.Check(err, Equals, nil)
967 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
968 c.Check(l.Size, Equals, -1)
969 c.Check(l.Hints, DeepEquals, []string{"Aabcde@12345678"})
972 func (s *StandaloneSuite) TestMakeLocatorPreservesUnrecognizedHints(c *C) {
973 str := "91f372a266fe2bf2823cb8ec7fda31ce+3+Unknown+Kzzzzz+Afoobar"
974 l, err := MakeLocator(str)
975 c.Check(err, Equals, nil)
976 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
977 c.Check(l.Size, Equals, 3)
978 c.Check(l.Hints, DeepEquals, []string{"3", "Unknown", "Kzzzzz", "Afoobar"})
979 c.Check(l.String(), Equals, str)
982 func (s *StandaloneSuite) TestMakeLocatorInvalidInput(c *C) {
983 _, err := MakeLocator("91f372a266fe2bf2823cb8ec7fda31c")
984 c.Check(err, Equals, InvalidLocatorError)
987 func (s *StandaloneSuite) TestPutBWant2ReplicasWithOnlyOneWritableLocalRoot(c *C) {
988 hash := Md5String("foo")
990 st := StubPutHandler{
995 make(chan string, 5)}
997 arv, _ := arvadosclient.MakeArvadosClient()
998 kc, _ := MakeKeepClient(&arv)
1000 kc.Want_replicas = 2
1001 arv.ApiToken = "abc123"
1002 localRoots := make(map[string]string)
1003 writableLocalRoots := make(map[string]string)
1005 ks := RunSomeFakeKeepServers(st, 5)
1007 for i, k := range ks {
1008 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
1010 writableLocalRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
1012 defer k.listener.Close()
1015 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
1017 _, replicas, err := kc.PutB([]byte("foo"))
1019 c.Check(err, Equals, InsufficientReplicasError)
1020 c.Check(replicas, Equals, 1)
1022 c.Check(<-st.handled, Equals, localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", 0)])
1025 func (s *StandaloneSuite) TestPutBWithNoWritableLocalRoots(c *C) {
1026 hash := Md5String("foo")
1028 st := StubPutHandler{
1033 make(chan string, 5)}
1035 arv, _ := arvadosclient.MakeArvadosClient()
1036 kc, _ := MakeKeepClient(&arv)
1038 kc.Want_replicas = 2
1039 arv.ApiToken = "abc123"
1040 localRoots := make(map[string]string)
1041 writableLocalRoots := make(map[string]string)
1043 ks := RunSomeFakeKeepServers(st, 5)
1045 for i, k := range ks {
1046 localRoots[fmt.Sprintf("zzzzz-bi6l4-fakefakefake%03d", i)] = k.url
1047 defer k.listener.Close()
1050 kc.SetServiceRoots(localRoots, writableLocalRoots, nil)
1052 _, replicas, err := kc.PutB([]byte("foo"))
1054 c.Check(err, Equals, InsufficientReplicasError)
1055 c.Check(replicas, Equals, 0)
1058 type StubGetIndexHandler struct {
1061 expectAPIToken string
1066 func (h StubGetIndexHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
1067 h.c.Check(req.URL.Path, Equals, h.expectPath)
1068 h.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", h.expectAPIToken))
1069 resp.WriteHeader(h.httpStatus)
1070 resp.Header().Set("Content-Length", fmt.Sprintf("%d", len(h.body)))
1074 func (s *StandaloneSuite) TestGetIndexWithNoPrefix(c *C) {
1075 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1077 st := StubGetIndexHandler{
1082 []byte(hash + "+3 1443559274\n\n")}
1084 ks := RunFakeKeepServer(st)
1085 defer ks.listener.Close()
1087 arv, err := arvadosclient.MakeArvadosClient()
1088 kc, _ := MakeKeepClient(&arv)
1089 arv.ApiToken = "abc123"
1090 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
1092 r, err := kc.GetIndex("x", "")
1093 c.Check(err, Equals, nil)
1095 content, err2 := ioutil.ReadAll(r)
1096 c.Check(err2, Equals, nil)
1097 c.Check(content, DeepEquals, st.body[0:len(st.body)-1])
1100 func (s *StandaloneSuite) TestGetIndexWithPrefix(c *C) {
1101 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1103 st := StubGetIndexHandler{
1105 "/index/" + hash[0:3],
1108 []byte(hash + "+3 1443559274\n\n")}
1110 ks := RunFakeKeepServer(st)
1111 defer ks.listener.Close()
1113 arv, err := arvadosclient.MakeArvadosClient()
1114 kc, _ := MakeKeepClient(&arv)
1115 arv.ApiToken = "abc123"
1116 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
1118 r, err := kc.GetIndex("x", hash[0:3])
1119 c.Check(err, Equals, nil)
1121 content, err2 := ioutil.ReadAll(r)
1122 c.Check(err2, Equals, nil)
1123 c.Check(content, DeepEquals, st.body[0:len(st.body)-1])
1126 func (s *StandaloneSuite) TestGetIndexIncomplete(c *C) {
1127 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1129 st := StubGetIndexHandler{
1131 "/index/" + hash[0:3],
1136 ks := RunFakeKeepServer(st)
1137 defer ks.listener.Close()
1139 arv, err := arvadosclient.MakeArvadosClient()
1140 kc, _ := MakeKeepClient(&arv)
1141 arv.ApiToken = "abc123"
1142 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
1144 _, err = kc.GetIndex("x", hash[0:3])
1145 c.Check(err, Equals, ErrIncompleteIndex)
1148 func (s *StandaloneSuite) TestGetIndexWithNoSuchServer(c *C) {
1149 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
1151 st := StubGetIndexHandler{
1153 "/index/" + hash[0:3],
1158 ks := RunFakeKeepServer(st)
1159 defer ks.listener.Close()
1161 arv, err := arvadosclient.MakeArvadosClient()
1162 kc, _ := MakeKeepClient(&arv)
1163 arv.ApiToken = "abc123"
1164 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
1166 _, err = kc.GetIndex("y", hash[0:3])
1167 c.Check(err, Equals, ErrNoSuchKeepServer)
1170 func (s *StandaloneSuite) TestGetIndexWithNoSuchPrefix(c *C) {
1171 st := StubGetIndexHandler{
1178 ks := RunFakeKeepServer(st)
1179 defer ks.listener.Close()
1181 arv, err := arvadosclient.MakeArvadosClient()
1182 kc, _ := MakeKeepClient(&arv)
1183 arv.ApiToken = "abc123"
1184 kc.SetServiceRoots(map[string]string{"x": ks.url}, map[string]string{ks.url: ""}, nil)
1186 r, err := kc.GetIndex("x", "abcd")
1187 c.Check(err, Equals, nil)
1189 content, err2 := ioutil.ReadAll(r)
1190 c.Check(err2, Equals, nil)
1191 c.Check(content, DeepEquals, st.body[0:len(st.body)-1])