Merge branch 'master' into 13804-no-shutdown-wanted-nodes
[arvados.git] / lib / controller / handler_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package controller
6
7 import (
8         "encoding/json"
9         "net/http"
10         "net/http/httptest"
11         "net/url"
12         "os"
13         "strings"
14         "testing"
15         "time"
16
17         "git.curoverse.com/arvados.git/sdk/go/arvados"
18         "git.curoverse.com/arvados.git/sdk/go/arvadostest"
19         "git.curoverse.com/arvados.git/sdk/go/httpserver"
20         check "gopkg.in/check.v1"
21 )
22
23 // Gocheck boilerplate
24 func Test(t *testing.T) {
25         check.TestingT(t)
26 }
27
28 var _ = check.Suite(&HandlerSuite{})
29
30 type HandlerSuite struct {
31         cluster *arvados.Cluster
32         handler http.Handler
33 }
34
35 func (s *HandlerSuite) SetUpTest(c *check.C) {
36         s.cluster = &arvados.Cluster{
37                 ClusterID: "zzzzz",
38                 NodeProfiles: map[string]arvados.NodeProfile{
39                         "*": {
40                                 Controller: arvados.SystemServiceInstance{Listen: ":"},
41                                 RailsAPI:   arvados.SystemServiceInstance{Listen: os.Getenv("ARVADOS_TEST_API_HOST"), TLS: true},
42                         },
43                 },
44         }
45         node := s.cluster.NodeProfiles["*"]
46         s.handler = newHandler(s.cluster, &node)
47 }
48
49 func (s *HandlerSuite) TestProxyDiscoveryDoc(c *check.C) {
50         req := httptest.NewRequest("GET", "/discovery/v1/apis/arvados/v1/rest", nil)
51         resp := httptest.NewRecorder()
52         s.handler.ServeHTTP(resp, req)
53         c.Check(resp.Code, check.Equals, http.StatusOK)
54         var dd arvados.DiscoveryDocument
55         err := json.Unmarshal(resp.Body.Bytes(), &dd)
56         c.Check(err, check.IsNil)
57         c.Check(dd.BlobSignatureTTL, check.Not(check.Equals), int64(0))
58         c.Check(dd.BlobSignatureTTL > 0, check.Equals, true)
59         c.Check(len(dd.Resources), check.Not(check.Equals), 0)
60         c.Check(len(dd.Schemas), check.Not(check.Equals), 0)
61 }
62
63 func (s *HandlerSuite) TestRequestTimeout(c *check.C) {
64         s.cluster.HTTPRequestTimeout = arvados.Duration(time.Nanosecond)
65         req := httptest.NewRequest("GET", "/discovery/v1/apis/arvados/v1/rest", nil)
66         resp := httptest.NewRecorder()
67         s.handler.ServeHTTP(resp, req)
68         c.Check(resp.Code, check.Equals, http.StatusInternalServerError)
69         var jresp httpserver.ErrorResponse
70         err := json.Unmarshal(resp.Body.Bytes(), &jresp)
71         c.Check(err, check.IsNil)
72         c.Assert(len(jresp.Errors), check.Equals, 1)
73         c.Check(jresp.Errors[0], check.Matches, `.*context deadline exceeded`)
74 }
75
76 func (s *HandlerSuite) TestProxyWithoutToken(c *check.C) {
77         req := httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
78         resp := httptest.NewRecorder()
79         s.handler.ServeHTTP(resp, req)
80         c.Check(resp.Code, check.Equals, http.StatusUnauthorized)
81         jresp := map[string]interface{}{}
82         err := json.Unmarshal(resp.Body.Bytes(), &jresp)
83         c.Check(err, check.IsNil)
84         c.Check(jresp["errors"], check.FitsTypeOf, []interface{}{})
85 }
86
87 func (s *HandlerSuite) TestProxyWithToken(c *check.C) {
88         req := httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
89         req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
90         resp := httptest.NewRecorder()
91         s.handler.ServeHTTP(resp, req)
92         c.Check(resp.Code, check.Equals, http.StatusOK)
93         var u arvados.User
94         err := json.Unmarshal(resp.Body.Bytes(), &u)
95         c.Check(err, check.IsNil)
96         c.Check(u.UUID, check.Equals, arvadostest.ActiveUserUUID)
97 }
98
99 func (s *HandlerSuite) TestProxyWithTokenInRequestBody(c *check.C) {
100         req := httptest.NewRequest("POST", "/arvados/v1/users/current", strings.NewReader(url.Values{
101                 "_method":   {"GET"},
102                 "api_token": {arvadostest.ActiveToken},
103         }.Encode()))
104         resp := httptest.NewRecorder()
105         s.handler.ServeHTTP(resp, req)
106         c.Check(resp.Code, check.Equals, http.StatusOK)
107         var u arvados.User
108         err := json.Unmarshal(resp.Body.Bytes(), &u)
109         c.Check(err, check.IsNil)
110         c.Check(u.UUID, check.Equals, arvadostest.ActiveUserUUID)
111 }
112
113 func (s *HandlerSuite) TestProxyNotFound(c *check.C) {
114         req := httptest.NewRequest("GET", "/arvados/v1/xyzzy", nil)
115         resp := httptest.NewRecorder()
116         s.handler.ServeHTTP(resp, req)
117         c.Check(resp.Code, check.Equals, http.StatusNotFound)
118         jresp := map[string]interface{}{}
119         err := json.Unmarshal(resp.Body.Bytes(), &jresp)
120         c.Check(err, check.IsNil)
121         c.Check(jresp["errors"], check.FitsTypeOf, []interface{}{})
122 }
123
124 func (s *HandlerSuite) TestProxyRedirect(c *check.C) {
125         req := httptest.NewRequest("GET", "https://example.org:1234/login?return_to=foo", nil)
126         resp := httptest.NewRecorder()
127         s.handler.ServeHTTP(resp, req)
128         c.Check(resp.Code, check.Equals, http.StatusFound)
129         c.Check(resp.Header().Get("Location"), check.Matches, `https://example\.org:1234/auth/joshid\?return_to=foo&?`)
130 }