1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
25 "git.arvados.org/arvados.git/lib/config"
26 "git.arvados.org/arvados.git/sdk/go/arvados"
27 "git.arvados.org/arvados.git/sdk/go/arvadosclient"
28 "git.arvados.org/arvados.git/sdk/go/arvadostest"
29 "git.arvados.org/arvados.git/sdk/go/ctxlog"
30 "git.arvados.org/arvados.git/sdk/go/httpserver"
31 "git.arvados.org/arvados.git/sdk/go/keepclient"
32 "github.com/prometheus/client_golang/prometheus"
33 check "gopkg.in/check.v1"
36 var testAPIHost = os.Getenv("ARVADOS_API_HOST")
38 var _ = check.Suite(&IntegrationSuite{})
40 // IntegrationSuite tests need an API server and a keep-web server
41 type IntegrationSuite struct {
42 testServer *httptest.Server
47 func (s *IntegrationSuite) TestNoToken(c *check.C) {
48 for _, token := range []string{
52 hdr, body, _ := s.runCurl(c, token, s.handler.Cluster.Services.WebDAVDownload.ExternalURL.Host, "/c="+arvadostest.FooCollection+"/foo")
53 c.Check(hdr, check.Matches, `(?s)HTTP/1.1 401 Unauthorized\r\n.*`)
54 c.Check(strings.TrimSpace(body), check.Equals, unauthorizedMessage)
57 hdr, body, _ = s.runCurl(c, token, s.handler.Cluster.Services.WebDAVDownload.ExternalURL.Host, "/collections/download/"+arvadostest.FooCollection+"/"+token+"/foo")
58 c.Check(hdr, check.Matches, `(?s)HTTP/1.1 404 Not Found\r\n.*`)
59 c.Check(strings.TrimSpace(body), check.Equals, notFoundMessage)
62 hdr, body, _ = s.runCurl(c, token, s.handler.Cluster.Services.WebDAVDownload.ExternalURL.Host, "/bad-route")
63 c.Check(hdr, check.Matches, `(?s)HTTP/1.1 404 Not Found\r\n.*`)
64 c.Check(strings.TrimSpace(body), check.Equals, notFoundMessage)
68 // TODO: Move most cases to functional tests -- at least use Go's own
69 // http client instead of forking curl. Just leave enough of an
70 // integration test to assure that the documented way of invoking curl
71 // really works against the server.
72 func (s *IntegrationSuite) Test404(c *check.C) {
73 for _, uri := range []string{
74 // Routing errors (always 404 regardless of what's stored in Keep)
79 // Non-existent file/directory
80 "/c=" + arvadostest.FooCollection + "/theperthcountyconspiracy",
81 "/c=" + arvadostest.FooCollection + "/theperthcountyconspiracy/",
82 "/collections/download/" + arvadostest.FooCollection + "/" + arvadostest.ActiveToken + "/theperthcountyconspiracy",
83 "/collections/download/" + arvadostest.FooCollection + "/" + arvadostest.ActiveToken + "/theperthcountyconspiracy/",
84 // Non-existent collection
85 "/c=" + arvadostest.NonexistentCollection,
86 "/c=" + arvadostest.NonexistentCollection + "/",
87 "/c=" + arvadostest.NonexistentCollection + "/theperthcountyconspiracy",
88 "/collections/download/" + arvadostest.NonexistentCollection + "/" + arvadostest.ActiveToken + "/theperthcountyconspiracy",
90 hdr, body, _ := s.runCurl(c, arvadostest.ActiveToken, s.handler.Cluster.Services.WebDAVDownload.ExternalURL.Host, uri)
91 c.Check(hdr, check.Matches, "(?s)HTTP/1.1 404 Not Found\r\n.*")
93 c.Check(strings.TrimSpace(body), check.Equals, notFoundMessage)
98 func (s *IntegrationSuite) Test1GBFile(c *check.C) {
100 c.Skip("skipping 1GB integration test in short mode")
102 s.test100BlockFile(c, 10000000)
105 func (s *IntegrationSuite) Test100BlockFile(c *check.C) {
108 s.test100BlockFile(c, 30000)
111 s.test100BlockFile(c, 3000000)
115 func (s *IntegrationSuite) test100BlockFile(c *check.C, blocksize int) {
116 testdata := make([]byte, blocksize)
117 for i := 0; i < blocksize; i++ {
118 testdata[i] = byte(' ')
120 arv, err := arvadosclient.MakeArvadosClient()
121 c.Assert(err, check.Equals, nil)
122 arv.ApiToken = arvadostest.ActiveToken
123 kc, err := keepclient.MakeKeepClient(arv)
124 c.Assert(err, check.Equals, nil)
125 loc, _, err := kc.PutB(testdata[:])
126 c.Assert(err, check.Equals, nil)
128 for i := 0; i < 100; i++ {
129 mtext = mtext + " " + loc
131 mtext = mtext + fmt.Sprintf(" 0:%d00:testdata.bin\n", blocksize)
132 coll := map[string]interface{}{}
133 err = arv.Create("collections",
134 map[string]interface{}{
135 "collection": map[string]interface{}{
136 "name": fmt.Sprintf("testdata blocksize=%d", blocksize),
137 "manifest_text": mtext,
140 c.Assert(err, check.Equals, nil)
141 uuid := coll["uuid"].(string)
143 hdr, body, size := s.runCurl(c, arv.ApiToken, uuid+".collections.example.com", "/testdata.bin")
144 c.Check(hdr, check.Matches, `(?s)HTTP/1.1 200 OK\r\n.*`)
145 c.Check(hdr, check.Matches, `(?si).*Content-length: `+fmt.Sprintf("%d00", blocksize)+`\r\n.*`)
146 c.Check([]byte(body)[:1234], check.DeepEquals, testdata[:1234])
147 c.Check(size, check.Equals, int64(blocksize)*100)
150 type curlCase struct {
157 func (s *IntegrationSuite) Test200(c *check.C) {
158 s.handler.Cluster.Users.AnonymousUserToken = arvadostest.AnonymousToken
159 for _, spec := range []curlCase{
162 auth: arvadostest.ActiveToken,
163 host: arvadostest.FooCollection + "--collections.example.com",
165 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
168 auth: arvadostest.ActiveToken,
169 host: arvadostest.FooCollection + ".collections.example.com",
171 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
174 host: strings.Replace(arvadostest.FooCollectionPDH, "+", "-", 1) + ".collections.example.com",
175 path: "/t=" + arvadostest.ActiveToken + "/foo",
176 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
179 path: "/c=" + arvadostest.FooCollectionPDH + "/t=" + arvadostest.ActiveToken + "/foo",
180 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
183 path: "/c=" + strings.Replace(arvadostest.FooCollectionPDH, "+", "-", 1) + "/t=" + arvadostest.ActiveToken + "/_/foo",
184 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
187 path: "/collections/download/" + arvadostest.FooCollection + "/" + arvadostest.ActiveToken + "/foo",
188 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
191 auth: "tokensobogus",
192 path: "/collections/download/" + arvadostest.FooCollection + "/" + arvadostest.ActiveToken + "/foo",
193 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
196 auth: arvadostest.ActiveToken,
197 path: "/collections/download/" + arvadostest.FooCollection + "/" + arvadostest.ActiveToken + "/foo",
198 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
201 auth: arvadostest.AnonymousToken,
202 path: "/collections/download/" + arvadostest.FooCollection + "/" + arvadostest.ActiveToken + "/foo",
203 dataMD5: "acbd18db4cc2f85cedef654fccc4a4d8",
206 // Anonymously accessible data
208 path: "/c=" + arvadostest.HelloWorldCollection + "/Hello%20world.txt",
209 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
212 host: arvadostest.HelloWorldCollection + ".collections.example.com",
213 path: "/Hello%20world.txt",
214 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
217 host: arvadostest.HelloWorldCollection + ".collections.example.com",
218 path: "/_/Hello%20world.txt",
219 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
222 path: "/collections/" + arvadostest.HelloWorldCollection + "/Hello%20world.txt",
223 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
226 auth: arvadostest.ActiveToken,
227 path: "/collections/" + arvadostest.HelloWorldCollection + "/Hello%20world.txt",
228 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
231 auth: arvadostest.SpectatorToken,
232 path: "/collections/" + arvadostest.HelloWorldCollection + "/Hello%20world.txt",
233 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
236 auth: arvadostest.SpectatorToken,
237 host: arvadostest.HelloWorldCollection + "--collections.example.com",
238 path: "/Hello%20world.txt",
239 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
242 auth: arvadostest.SpectatorToken,
243 path: "/collections/download/" + arvadostest.HelloWorldCollection + "/" + arvadostest.SpectatorToken + "/Hello%20world.txt",
244 dataMD5: "f0ef7081e1539ac00ef5b761b4fb01b3",
249 host = "collections.example.com"
251 hdr, body, _ := s.runCurl(c, spec.auth, host, spec.path)
252 c.Check(hdr, check.Matches, `(?s)HTTP/1.1 200 OK\r\n.*`)
253 if strings.HasSuffix(spec.path, ".txt") {
254 c.Check(hdr, check.Matches, `(?s).*\r\nContent-Type: text/plain.*`)
255 // TODO: Check some types that aren't
256 // automatically detected by Go's http server
257 // by sniffing the content.
259 c.Check(fmt.Sprintf("%x", md5.Sum([]byte(body))), check.Equals, spec.dataMD5)
263 // Return header block and body.
264 func (s *IntegrationSuite) runCurl(c *check.C, auth, hostport, uri string, args ...string) (hdr, bodyPart string, bodySize int64) {
265 curlArgs := []string{"--silent", "--show-error", "--include"}
266 testHost, testPort, _ := net.SplitHostPort(s.testServer.URL[7:])
267 host, port, _ := net.SplitHostPort(hostport)
271 curlArgs = append(curlArgs, "--connect-to", host+":"+port+":"+testHost+":"+testPort)
272 if strings.Contains(auth, " ") {
273 // caller supplied entire Authorization header value
274 curlArgs = append(curlArgs, "-H", "Authorization: "+auth)
275 } else if auth != "" {
276 // caller supplied Arvados token
277 curlArgs = append(curlArgs, "-H", "Authorization: Bearer "+auth)
279 curlArgs = append(curlArgs, args...)
280 curlArgs = append(curlArgs, "http://"+hostport+uri)
281 c.Log(fmt.Sprintf("curlArgs == %#v", curlArgs))
282 cmd := exec.Command("curl", curlArgs...)
283 stdout, err := cmd.StdoutPipe()
284 c.Assert(err, check.IsNil)
285 cmd.Stderr = os.Stderr
287 c.Assert(err, check.IsNil)
288 buf := make([]byte, 2<<27)
289 n, err := io.ReadFull(stdout, buf)
290 // Discard (but measure size of) anything past 128 MiB.
292 if err == io.ErrUnexpectedEOF {
295 c.Assert(err, check.IsNil)
296 discarded, err = io.Copy(ioutil.Discard, stdout)
297 c.Assert(err, check.IsNil)
300 // Without "-f", curl exits 0 as long as it gets a valid HTTP
301 // response from the server, even if the response status
302 // indicates that the request failed. In our test suite, we
303 // always expect a valid HTTP response, and we parse the
304 // headers ourselves. If curl exits non-zero, our testing
305 // environment is broken.
306 c.Assert(err, check.Equals, nil)
307 hdrsAndBody := strings.SplitN(string(buf), "\r\n\r\n", 2)
308 c.Assert(len(hdrsAndBody), check.Equals, 2)
310 bodyPart = hdrsAndBody[1]
311 bodySize = int64(len(bodyPart)) + discarded
315 // Run a full-featured server, including the metrics/health routes
316 // that are added by service.Command.
317 func (s *IntegrationSuite) runServer(c *check.C) (cluster arvados.Cluster, srvaddr string, logbuf *bytes.Buffer) {
318 logbuf = &bytes.Buffer{}
319 cluster = *s.handler.Cluster
320 cluster.Services.WebDAV.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Scheme: "http", Host: "0.0.0.0:0"}: {}}
321 cluster.Services.WebDAVDownload.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Scheme: "http", Host: "0.0.0.0:0"}: {}}
323 var configjson bytes.Buffer
324 json.NewEncoder(&configjson).Encode(arvados.Config{Clusters: map[string]arvados.Cluster{"zzzzz": cluster}})
325 go Command.RunCommand("keep-web", []string{"-config=-"}, &configjson, os.Stderr, io.MultiWriter(os.Stderr, logbuf))
326 for deadline := time.Now().Add(time.Second); deadline.After(time.Now()); time.Sleep(time.Second / 100) {
327 if m := regexp.MustCompile(`"Listen":"(.*?)"`).FindStringSubmatch(logbuf.String()); m != nil {
328 srvaddr = "http://" + m[1]
338 // Ensure uploads can take longer than API.RequestTimeout.
340 // Currently, this works only by accident: service.Command cancels the
341 // request context as usual (there is no exemption), but
342 // webdav.Handler doesn't notice if the request context is cancelled
343 // while waiting to send or receive file data.
344 func (s *IntegrationSuite) TestRequestTimeoutExemption(c *check.C) {
345 s.handler.Cluster.API.RequestTimeout = arvados.Duration(time.Second / 2)
346 _, srvaddr, _ := s.runServer(c)
348 var coll arvados.Collection
349 arv, err := arvadosclient.MakeArvadosClient()
350 c.Assert(err, check.IsNil)
351 arv.ApiToken = arvadostest.ActiveTokenV2
352 err = arv.Create("collections", map[string]interface{}{"ensure_unique_name": true}, &coll)
353 c.Assert(err, check.IsNil)
357 time.Sleep(time.Second)
358 pw.Write(make([]byte, 10000000))
361 req, _ := http.NewRequest("PUT", srvaddr+"/testfile", pr)
362 req.Host = coll.UUID + ".example"
363 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveTokenV2)
364 resp, err := http.DefaultClient.Do(req)
365 c.Assert(err, check.IsNil)
366 c.Check(resp.StatusCode, check.Equals, http.StatusCreated)
368 req, _ = http.NewRequest("GET", srvaddr+"/testfile", nil)
369 req.Host = coll.UUID + ".example"
370 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveTokenV2)
371 resp, err = http.DefaultClient.Do(req)
372 c.Assert(err, check.IsNil)
373 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
374 time.Sleep(time.Second)
375 body, err := ioutil.ReadAll(resp.Body)
376 c.Check(err, check.IsNil)
377 c.Check(len(body), check.Equals, 10000000)
380 func (s *IntegrationSuite) TestHealthCheckPing(c *check.C) {
381 cluster, srvaddr, _ := s.runServer(c)
382 req, _ := http.NewRequest("GET", srvaddr+"/_health/ping", nil)
383 req.Header.Set("Authorization", "Bearer "+cluster.ManagementToken)
384 resp, err := http.DefaultClient.Do(req)
385 c.Assert(err, check.IsNil)
386 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
387 body, _ := ioutil.ReadAll(resp.Body)
388 c.Check(string(body), check.Matches, `{"health":"OK"}\n`)
391 func (s *IntegrationSuite) TestMetrics(c *check.C) {
392 cluster, srvaddr, _ := s.runServer(c)
394 req, _ := http.NewRequest("GET", srvaddr+"/notfound", nil)
395 req.Host = cluster.Services.WebDAVDownload.ExternalURL.Host
396 _, err := http.DefaultClient.Do(req)
397 c.Assert(err, check.IsNil)
398 req, _ = http.NewRequest("GET", srvaddr+"/by_id/", nil)
399 req.Host = cluster.Services.WebDAVDownload.ExternalURL.Host
400 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
401 resp, err := http.DefaultClient.Do(req)
402 c.Assert(err, check.IsNil)
403 c.Assert(resp.StatusCode, check.Equals, http.StatusOK)
404 for i := 0; i < 2; i++ {
405 req, _ = http.NewRequest("GET", srvaddr+"/foo", nil)
406 req.Host = arvadostest.FooCollection + ".example.com"
407 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
408 resp, err = http.DefaultClient.Do(req)
409 c.Assert(err, check.IsNil)
410 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
411 buf, _ := ioutil.ReadAll(resp.Body)
412 c.Check(buf, check.DeepEquals, []byte("foo"))
416 var coll arvados.Collection
417 arv, err := arvadosclient.MakeArvadosClient()
418 c.Assert(err, check.IsNil)
419 arv.ApiToken = arvadostest.ActiveTokenV2
420 err = arv.Create("collections", map[string]interface{}{"ensure_unique_name": true}, &coll)
421 c.Assert(err, check.IsNil)
422 defer arv.Delete("collections", coll.UUID, nil, nil)
423 for i := 0; i < 2; i++ {
424 size := 1 << (i * 12)
425 req, _ = http.NewRequest("PUT", srvaddr+"/zero-"+fmt.Sprintf("%d", size), bytes.NewReader(make([]byte, size)))
426 req.Host = coll.UUID + ".example.com"
427 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
428 resp, err = http.DefaultClient.Do(req)
429 c.Assert(err, check.IsNil)
430 c.Check(resp.StatusCode, check.Equals, http.StatusCreated)
434 time.Sleep(metricsUpdateInterval * 2)
436 req, _ = http.NewRequest("GET", srvaddr+"/metrics.json", nil)
437 req.Host = cluster.Services.WebDAVDownload.ExternalURL.Host
438 resp, err = http.DefaultClient.Do(req)
439 c.Assert(err, check.IsNil)
440 c.Check(resp.StatusCode, check.Equals, http.StatusUnauthorized)
442 req, _ = http.NewRequest("GET", srvaddr+"/metrics.json", nil)
443 req.Host = cluster.Services.WebDAVDownload.ExternalURL.Host
444 req.Header.Set("Authorization", "Bearer badtoken")
445 resp, err = http.DefaultClient.Do(req)
446 c.Assert(err, check.IsNil)
447 c.Check(resp.StatusCode, check.Equals, http.StatusForbidden)
449 req, _ = http.NewRequest("GET", srvaddr+"/metrics.json", nil)
450 req.Host = cluster.Services.WebDAVDownload.ExternalURL.Host
451 req.Header.Set("Authorization", "Bearer "+arvadostest.ManagementToken)
452 resp, err = http.DefaultClient.Do(req)
453 c.Assert(err, check.IsNil)
454 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
455 type summary struct {
459 type counter struct {
479 json.NewDecoder(resp.Body).Decode(&ents)
480 summaries := map[string]summary{}
481 gauges := map[string]gauge{}
482 counters := map[string]counter{}
483 for _, e := range ents {
484 for _, m := range e.Metric {
485 labels := map[string]string{}
486 for _, lbl := range m.Label {
487 labels[lbl.Name] = lbl.Value
489 summaries[e.Name+"/"+labels["method"]+"/"+labels["code"]] = m.Summary
490 counters[e.Name+"/"+labels["method"]+"/"+labels["code"]] = m.Counter
491 gauges[e.Name+"/"+labels["method"]+"/"+labels["code"]] = m.Gauge
494 c.Check(summaries["request_duration_seconds/get/200"].SampleSum, check.Not(check.Equals), 0)
495 c.Check(summaries["request_duration_seconds/get/200"].SampleCount, check.Equals, "3")
496 c.Check(summaries["request_duration_seconds/get/404"].SampleCount, check.Equals, "1")
497 c.Check(summaries["time_to_status_seconds/get/404"].SampleCount, check.Equals, "1")
498 c.Check(gauges["arvados_keepweb_sessions_cached_session_bytes//"].Value, check.Equals, float64(992))
500 // If the Host header indicates a collection, /metrics.json
501 // refers to a file in the collection -- the metrics handler
502 // must not intercept that route. Ditto health check paths.
503 for _, path := range []string{"/metrics.json", "/_health/ping"} {
504 c.Logf("path: %q", path)
505 req, _ = http.NewRequest("GET", srvaddr+path, nil)
506 req.Host = strings.Replace(arvadostest.FooCollectionPDH, "+", "-", -1) + ".example.com"
507 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
508 resp, err = http.DefaultClient.Do(req)
509 c.Assert(err, check.IsNil)
510 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
513 req, _ = http.NewRequest("GET", srvaddr+"/metrics", nil)
514 req.Host = cluster.Services.WebDAVDownload.ExternalURL.Host
515 req.Header.Set("Authorization", "Bearer "+arvadostest.ManagementToken)
516 resp, err = http.DefaultClient.Do(req)
517 c.Assert(err, check.IsNil)
518 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
519 allmetrics, err := ioutil.ReadAll(resp.Body)
520 c.Check(err, check.IsNil)
522 c.Check(string(allmetrics), check.Matches, `(?ms).*\narvados_keepweb_download_apparent_backend_speed_bucket{size_range="0",le="\+Inf"} 4\n.*`)
523 c.Check(string(allmetrics), check.Matches, `(?ms).*\narvados_keepweb_download_speed_bucket{size_range="0",le="\+Inf"} 4\n.*`)
524 c.Check(string(allmetrics), check.Matches, `(?ms).*\narvados_keepweb_upload_speed_bucket{size_range="0",le="\+Inf"} 2\n.*`)
525 c.Check(string(allmetrics), check.Matches, `(?ms).*\narvados_keepweb_upload_sync_delay_seconds_bucket{size_range="0",le="10"} 2\n.*`)
527 c.Logf("%s", allmetrics)
530 func (s *IntegrationSuite) SetUpSuite(c *check.C) {
531 arvadostest.ResetDB(c)
532 arvadostest.StartKeep(2, true)
534 arv, err := arvadosclient.MakeArvadosClient()
535 c.Assert(err, check.Equals, nil)
536 arv.ApiToken = arvadostest.ActiveToken
537 kc, err := keepclient.MakeKeepClient(arv)
538 c.Assert(err, check.Equals, nil)
539 kc.PutB([]byte("Hello world\n"))
540 kc.PutB([]byte("foo"))
541 kc.PutB([]byte("foobar"))
542 kc.PutB([]byte("waz"))
545 func (s *IntegrationSuite) TearDownSuite(c *check.C) {
546 arvadostest.StopKeep(2)
549 func (s *IntegrationSuite) SetUpTest(c *check.C) {
550 arvadostest.ResetEnv()
551 logger := ctxlog.TestLogger(c)
552 ldr := config.NewLoader(&bytes.Buffer{}, logger)
553 cfg, err := ldr.Load()
554 c.Assert(err, check.IsNil)
555 cluster, err := cfg.GetCluster("")
556 c.Assert(err, check.IsNil)
558 s.ctx = ctxlog.Context(context.Background(), logger)
559 s.handler = newHandlerOrErrorHandler(s.ctx, cluster, cluster.SystemRootToken, prometheus.NewRegistry()).(*handler)
560 s.testServer = httptest.NewUnstartedServer(
561 httpserver.AddRequestIDs(
562 httpserver.LogRequests(
564 s.testServer.Config.BaseContext = func(net.Listener) context.Context { return s.ctx }
567 cluster.Services.WebDAV.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Host: s.testServer.URL[7:]}: {}}
568 cluster.Services.WebDAVDownload.InternalURLs = map[arvados.URL]arvados.ServiceInstance{{Host: s.testServer.URL[7:]}: {}}
571 func (s *IntegrationSuite) TearDownTest(c *check.C) {
572 if s.testServer != nil {
575 if s.handler != nil {
580 // Gocheck boilerplate
581 func Test(t *testing.T) {