4 "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
5 "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 if err := exec.Command("python", "run_test_server.py", "start").Run(); err != nil {
48 panic("'python run_test_server.py start' returned error")
50 if err := exec.Command("python", "run_test_server.py", "start_keep").Run(); err != nil {
51 panic("'python run_test_server.py start_keep' returned error")
56 func (s *ServerRequiredSuite) TearDownSuite(c *C) {
58 exec.Command("python", "run_test_server.py", "stop_keep").Run()
59 exec.Command("python", "run_test_server.py", "stop").Run()
62 func (s *ServerRequiredSuite) TestMakeKeepClient(c *C) {
63 os.Setenv("ARVADOS_API_HOST", "localhost:3001")
64 os.Setenv("ARVADOS_API_TOKEN", "4axaw8zxe0qm22wa6urpp5nskcne8z88cvbupv653y1njyi05h")
65 os.Setenv("ARVADOS_API_HOST_INSECURE", "true")
67 arv, err := arvadosclient.MakeArvadosClient()
68 c.Assert(err, Equals, nil)
70 kc, err := MakeKeepClient(&arv)
72 c.Assert(err, Equals, nil)
73 c.Check(len(kc.ServiceRoots()), Equals, 2)
74 c.Check(kc.ServiceRoots()[0], Equals, "http://localhost:25107")
75 c.Check(kc.ServiceRoots()[1], Equals, "http://localhost:25108")
78 func (s *StandaloneSuite) TestShuffleServiceRoots(c *C) {
80 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"})
82 // "foo" acbd18db4cc2f85cedef654fccc4a4d8
83 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"}
84 c.Check(kc.shuffledServiceRoots("acbd18db4cc2f85cedef654fccc4a4d8"), DeepEquals, foo_shuffle)
86 // "bar" 37b51d194a7513e45b56f6524f2d51f2
87 bar_shuffle := []string{"http://localhost:25108", "http://localhost:25112", "http://localhost:25119", "http://localhost:25107", "http://localhost:25110", "http://localhost:25116", "http://localhost:25122", "http://localhost:25120", "http://localhost:25121", "http://localhost:25117", "http://localhost:25111", "http://localhost:25123", "http://localhost:25118", "http://localhost:25113", "http://localhost:25114", "http://localhost:25115", "http://localhost:25109"}
88 c.Check(kc.shuffledServiceRoots("37b51d194a7513e45b56f6524f2d51f2"), DeepEquals, bar_shuffle)
91 type StubPutHandler struct {
99 func (this StubPutHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
100 this.c.Check(req.URL.Path, Equals, "/"+this.expectPath)
101 this.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", this.expectApiToken))
102 body, err := ioutil.ReadAll(req.Body)
103 this.c.Check(err, Equals, nil)
104 this.c.Check(body, DeepEquals, []byte(this.expectBody))
105 resp.WriteHeader(200)
106 this.handled <- fmt.Sprintf("http://%s", req.Host)
109 func RunBogusKeepServer(st http.Handler, port int) (listener net.Listener, url string) {
111 listener, err = net.ListenTCP("tcp", &net.TCPAddr{Port: port})
113 panic(fmt.Sprintf("Could not listen on tcp port %v", port))
116 url = fmt.Sprintf("http://localhost:%d", port)
118 go http.Serve(listener, st)
122 func UploadToStubHelper(c *C, st http.Handler, f func(KeepClient, string,
123 io.ReadCloser, io.WriteCloser, chan uploadStatus)) {
125 listener, url := RunBogusKeepServer(st, 2990)
126 defer listener.Close()
128 arv, _ := arvadosclient.MakeArvadosClient()
129 arv.ApiToken = "abc123"
131 kc, _ := MakeKeepClient(&arv)
133 reader, writer := io.Pipe()
134 upload_status := make(chan uploadStatus)
136 f(kc, url, reader, writer, upload_status)
139 func (s *StandaloneSuite) TestUploadToStubKeepServer(c *C) {
140 log.Printf("TestUploadToStubKeepServer")
142 st := StubPutHandler{
144 "acbd18db4cc2f85cedef654fccc4a4d8",
149 UploadToStubHelper(c, st,
150 func(kc KeepClient, url string, reader io.ReadCloser,
151 writer io.WriteCloser, upload_status chan uploadStatus) {
153 go kc.uploadToKeepServer(url, st.expectPath, reader, upload_status, int64(len("foo")))
155 writer.Write([]byte("foo"))
159 status := <-upload_status
160 c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
163 log.Printf("TestUploadToStubKeepServer done")
166 func (s *StandaloneSuite) TestUploadToStubKeepServerBufferReader(c *C) {
167 log.Printf("TestUploadToStubKeepServerBufferReader")
169 st := StubPutHandler{
171 "acbd18db4cc2f85cedef654fccc4a4d8",
176 UploadToStubHelper(c, st,
177 func(kc KeepClient, url string, reader io.ReadCloser,
178 writer io.WriteCloser, upload_status chan uploadStatus) {
180 tr := streamer.AsyncStreamFromReader(512, reader)
183 br1 := tr.MakeStreamReader()
185 go kc.uploadToKeepServer(url, st.expectPath, br1, upload_status, 3)
187 writer.Write([]byte("foo"))
192 status := <-upload_status
193 c.Check(status, DeepEquals, uploadStatus{nil, fmt.Sprintf("%s/%s", url, st.expectPath), 200, 1, ""})
196 log.Printf("TestUploadToStubKeepServerBufferReader done")
199 type FailHandler struct {
203 func (this FailHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
204 resp.WriteHeader(500)
205 this.handled <- fmt.Sprintf("http://%s", req.Host)
208 func (s *StandaloneSuite) TestFailedUploadToStubKeepServer(c *C) {
209 log.Printf("TestFailedUploadToStubKeepServer")
214 hash := "acbd18db4cc2f85cedef654fccc4a4d8"
216 UploadToStubHelper(c, st,
217 func(kc KeepClient, url string, reader io.ReadCloser,
218 writer io.WriteCloser, upload_status chan uploadStatus) {
220 go kc.uploadToKeepServer(url, hash, reader, upload_status, 3)
222 writer.Write([]byte("foo"))
227 status := <-upload_status
228 c.Check(status.url, Equals, fmt.Sprintf("%s/%s", url, hash))
229 c.Check(status.statusCode, Equals, 500)
231 log.Printf("TestFailedUploadToStubKeepServer done")
234 type KeepServer struct {
235 listener net.Listener
239 func RunSomeFakeKeepServers(st http.Handler, n int, port int) (ks []KeepServer) {
240 ks = make([]KeepServer, n)
242 for i := 0; i < n; i += 1 {
243 boguslistener, bogusurl := RunBogusKeepServer(st, port+i)
244 ks[i] = KeepServer{boguslistener, bogusurl}
250 func (s *StandaloneSuite) TestPutB(c *C) {
251 log.Printf("TestPutB")
253 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
255 st := StubPutHandler{
260 make(chan string, 2)}
262 arv, _ := arvadosclient.MakeArvadosClient()
263 kc, _ := MakeKeepClient(&arv)
266 arv.ApiToken = "abc123"
267 service_roots := make([]string, 5)
269 ks := RunSomeFakeKeepServers(st, 5, 2990)
271 for i := 0; i < len(ks); i += 1 {
272 service_roots[i] = ks[i].url
273 defer ks[i].listener.Close()
276 kc.SetServiceRoots(service_roots)
278 kc.PutB([]byte("foo"))
280 shuff := kc.shuffledServiceRoots(fmt.Sprintf("%x", md5.Sum([]byte("foo"))))
284 c.Check((s1 == shuff[0] && s2 == shuff[1]) ||
285 (s1 == shuff[1] && s2 == shuff[0]),
289 log.Printf("TestPutB done")
292 func (s *StandaloneSuite) TestPutHR(c *C) {
293 log.Printf("TestPutHR")
295 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
297 st := StubPutHandler{
302 make(chan string, 2)}
304 arv, _ := arvadosclient.MakeArvadosClient()
305 kc, _ := MakeKeepClient(&arv)
308 arv.ApiToken = "abc123"
309 service_roots := make([]string, 5)
311 ks := RunSomeFakeKeepServers(st, 5, 2990)
313 for i := 0; i < len(ks); i += 1 {
314 service_roots[i] = ks[i].url
315 defer ks[i].listener.Close()
318 kc.SetServiceRoots(service_roots)
320 reader, writer := io.Pipe()
323 writer.Write([]byte("foo"))
327 kc.PutHR(hash, reader, 3)
329 shuff := kc.shuffledServiceRoots(hash)
335 c.Check((s1 == shuff[0] && s2 == shuff[1]) ||
336 (s1 == shuff[1] && s2 == shuff[0]),
340 log.Printf("TestPutHR done")
343 func (s *StandaloneSuite) TestPutWithFail(c *C) {
344 log.Printf("TestPutWithFail")
346 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
348 st := StubPutHandler{
353 make(chan string, 2)}
356 make(chan string, 1)}
358 arv, err := arvadosclient.MakeArvadosClient()
359 kc, _ := MakeKeepClient(&arv)
362 arv.ApiToken = "abc123"
363 service_roots := make([]string, 5)
365 ks1 := RunSomeFakeKeepServers(st, 4, 2990)
366 ks2 := RunSomeFakeKeepServers(fh, 1, 2995)
368 for i, k := range ks1 {
369 service_roots[i] = k.url
370 defer k.listener.Close()
372 for i, k := range ks2 {
373 service_roots[len(ks1)+i] = k.url
374 defer k.listener.Close()
377 kc.SetServiceRoots(service_roots)
379 shuff := kc.shuffledServiceRoots(fmt.Sprintf("%x", md5.Sum([]byte("foo"))))
381 phash, replicas, err := kc.PutB([]byte("foo"))
385 c.Check(err, Equals, nil)
386 c.Check(phash, Equals, "")
387 c.Check(replicas, Equals, 2)
388 c.Check(<-st.handled, Equals, shuff[1])
389 c.Check(<-st.handled, Equals, shuff[2])
392 func (s *StandaloneSuite) TestPutWithTooManyFail(c *C) {
393 log.Printf("TestPutWithTooManyFail")
395 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
397 st := StubPutHandler{
402 make(chan string, 1)}
405 make(chan string, 4)}
407 arv, err := arvadosclient.MakeArvadosClient()
408 kc, _ := MakeKeepClient(&arv)
411 arv.ApiToken = "abc123"
412 service_roots := make([]string, 5)
414 ks1 := RunSomeFakeKeepServers(st, 1, 2990)
415 ks2 := RunSomeFakeKeepServers(fh, 4, 2991)
417 for i, k := range ks1 {
418 service_roots[i] = k.url
419 defer k.listener.Close()
421 for i, k := range ks2 {
422 service_roots[len(ks1)+i] = k.url
423 defer k.listener.Close()
426 kc.SetServiceRoots(service_roots)
428 shuff := kc.shuffledServiceRoots(fmt.Sprintf("%x", md5.Sum([]byte("foo"))))
430 _, replicas, err := kc.PutB([]byte("foo"))
432 c.Check(err, Equals, InsufficientReplicasError)
433 c.Check(replicas, Equals, 1)
434 c.Check(<-st.handled, Equals, shuff[1])
436 log.Printf("TestPutWithTooManyFail done")
439 type StubGetHandler struct {
442 expectApiToken string
446 func (this StubGetHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
447 this.c.Check(req.URL.Path, Equals, "/"+this.expectPath)
448 this.c.Check(req.Header.Get("Authorization"), Equals, fmt.Sprintf("OAuth2 %s", this.expectApiToken))
449 resp.Header().Set("Content-Length", fmt.Sprintf("%d", len(this.returnBody)))
450 resp.Write(this.returnBody)
453 func (s *StandaloneSuite) TestGet(c *C) {
454 log.Printf("TestGet")
456 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
458 st := StubGetHandler{
464 listener, url := RunBogusKeepServer(st, 2990)
465 defer listener.Close()
467 arv, err := arvadosclient.MakeArvadosClient()
468 kc, _ := MakeKeepClient(&arv)
469 arv.ApiToken = "abc123"
470 kc.SetServiceRoots([]string{url})
472 r, n, url2, err := kc.Get(hash)
474 c.Check(err, Equals, nil)
475 c.Check(n, Equals, int64(3))
476 c.Check(url2, Equals, fmt.Sprintf("%s/%s", url, hash))
478 content, err2 := ioutil.ReadAll(r)
479 c.Check(err2, Equals, nil)
480 c.Check(content, DeepEquals, []byte("foo"))
482 log.Printf("TestGet done")
485 func (s *StandaloneSuite) TestGetFail(c *C) {
486 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
488 st := FailHandler{make(chan string, 1)}
490 listener, url := RunBogusKeepServer(st, 2990)
491 defer listener.Close()
493 arv, err := arvadosclient.MakeArvadosClient()
494 kc, _ := MakeKeepClient(&arv)
495 arv.ApiToken = "abc123"
496 kc.SetServiceRoots([]string{url})
498 r, n, url2, err := kc.Get(hash)
499 c.Check(err, Equals, BlockNotFound)
500 c.Check(n, Equals, int64(0))
501 c.Check(url2, Equals, "")
502 c.Check(r, Equals, nil)
505 type BarHandler struct {
509 func (this BarHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
510 resp.Write([]byte("bar"))
511 this.handled <- fmt.Sprintf("http://%s", req.Host)
514 func (s *StandaloneSuite) TestChecksum(c *C) {
515 foohash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
516 barhash := fmt.Sprintf("%x", md5.Sum([]byte("bar")))
518 st := BarHandler{make(chan string, 1)}
520 listener, url := RunBogusKeepServer(st, 2990)
521 defer listener.Close()
523 arv, err := arvadosclient.MakeArvadosClient()
524 kc, _ := MakeKeepClient(&arv)
525 arv.ApiToken = "abc123"
526 kc.SetServiceRoots([]string{url})
528 r, n, _, err := kc.Get(barhash)
529 _, err = ioutil.ReadAll(r)
530 c.Check(n, Equals, int64(3))
531 c.Check(err, Equals, nil)
535 r, n, _, err = kc.Get(foohash)
536 _, err = ioutil.ReadAll(r)
537 c.Check(n, Equals, int64(3))
538 c.Check(err, Equals, BadChecksum)
543 func (s *StandaloneSuite) TestGetWithFailures(c *C) {
545 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
548 make(chan string, 1)}
550 st := StubGetHandler{
556 arv, err := arvadosclient.MakeArvadosClient()
557 kc, _ := MakeKeepClient(&arv)
558 arv.ApiToken = "abc123"
559 service_roots := make([]string, 5)
561 ks1 := RunSomeFakeKeepServers(st, 1, 2990)
562 ks2 := RunSomeFakeKeepServers(fh, 4, 2991)
564 for i, k := range ks1 {
565 service_roots[i] = k.url
566 defer k.listener.Close()
568 for i, k := range ks2 {
569 service_roots[len(ks1)+i] = k.url
570 defer k.listener.Close()
573 kc.SetServiceRoots(service_roots)
575 r, n, url2, err := kc.Get(hash)
577 c.Check(err, Equals, nil)
578 c.Check(n, Equals, int64(3))
579 c.Check(url2, Equals, fmt.Sprintf("%s/%s", ks1[0].url, hash))
581 content, err2 := ioutil.ReadAll(r)
582 c.Check(err2, Equals, nil)
583 c.Check(content, DeepEquals, []byte("foo"))
586 func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
587 os.Setenv("ARVADOS_API_HOST", "localhost:3001")
588 os.Setenv("ARVADOS_API_TOKEN", "4axaw8zxe0qm22wa6urpp5nskcne8z88cvbupv653y1njyi05h")
589 os.Setenv("ARVADOS_API_HOST_INSECURE", "true")
591 arv, err := arvadosclient.MakeArvadosClient()
592 kc, err := MakeKeepClient(&arv)
593 c.Assert(err, Equals, nil)
595 hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
598 n, _, err := kc.Ask(hash)
599 c.Check(err, Equals, BlockNotFound)
600 c.Check(n, Equals, int64(0))
603 hash2, replicas, err := kc.PutB([]byte("foo"))
604 c.Check(hash2, Equals, fmt.Sprintf("%s+%v", hash, 3))
605 c.Check(replicas, Equals, 2)
606 c.Check(err, Equals, nil)
609 r, n, url2, err := kc.Get(hash)
610 c.Check(err, Equals, nil)
611 c.Check(n, Equals, int64(3))
612 c.Check(url2, Equals, fmt.Sprintf("http://localhost:25108/%s", hash))
614 content, err2 := ioutil.ReadAll(r)
615 c.Check(err2, Equals, nil)
616 c.Check(content, DeepEquals, []byte("foo"))
619 n, url2, err := kc.Ask(hash)
620 c.Check(err, Equals, nil)
621 c.Check(n, Equals, int64(3))
622 c.Check(url2, Equals, fmt.Sprintf("http://localhost:25108/%s", hash))
626 type StubProxyHandler struct {
630 func (this StubProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
631 resp.Header().Set("X-Keep-Replicas-Stored", "2")
632 this.handled <- fmt.Sprintf("http://%s", req.Host)
635 func (s *StandaloneSuite) TestPutProxy(c *C) {
636 log.Printf("TestPutProxy")
638 st := StubProxyHandler{make(chan string, 1)}
640 arv, err := arvadosclient.MakeArvadosClient()
641 kc, _ := MakeKeepClient(&arv)
644 kc.Using_proxy = true
645 arv.ApiToken = "abc123"
646 service_roots := make([]string, 1)
648 ks1 := RunSomeFakeKeepServers(st, 1, 2990)
650 for i, k := range ks1 {
651 service_roots[i] = k.url
652 defer k.listener.Close()
655 kc.SetServiceRoots(service_roots)
657 _, replicas, err := kc.PutB([]byte("foo"))
660 c.Check(err, Equals, nil)
661 c.Check(replicas, Equals, 2)
663 log.Printf("TestPutProxy done")
666 func (s *StandaloneSuite) TestPutProxyInsufficientReplicas(c *C) {
667 log.Printf("TestPutProxy")
669 st := StubProxyHandler{make(chan string, 1)}
671 arv, err := arvadosclient.MakeArvadosClient()
672 kc, _ := MakeKeepClient(&arv)
675 kc.Using_proxy = true
676 arv.ApiToken = "abc123"
677 service_roots := make([]string, 1)
679 ks1 := RunSomeFakeKeepServers(st, 1, 2990)
681 for i, k := range ks1 {
682 service_roots[i] = k.url
683 defer k.listener.Close()
685 kc.SetServiceRoots(service_roots)
687 _, replicas, err := kc.PutB([]byte("foo"))
690 c.Check(err, Equals, InsufficientReplicasError)
691 c.Check(replicas, Equals, 2)
693 log.Printf("TestPutProxy done")
696 func (s *StandaloneSuite) TestMakeLocator(c *C) {
697 l := MakeLocator("91f372a266fe2bf2823cb8ec7fda31ce+3+Aabcde@12345678")
699 c.Check(l.Hash, Equals, "91f372a266fe2bf2823cb8ec7fda31ce")
700 c.Check(l.Size, Equals, 3)
701 c.Check(l.Signature, Equals, "abcde")
702 c.Check(l.Timestamp, Equals, "12345678")