closes #9514
[arvados.git] / sdk / go / arvados / client_test.go
1 package arvados
2
3 import (
4         "bytes"
5         "fmt"
6         "io/ioutil"
7         "net/http"
8         "net/url"
9         "sync"
10         "testing"
11 )
12
13 type stubTransport struct {
14         Responses map[string]string
15         Requests  []http.Request
16         sync.Mutex
17 }
18
19 func (stub *stubTransport) RoundTrip(req *http.Request) (*http.Response, error) {
20         stub.Lock()
21         stub.Requests = append(stub.Requests, *req)
22         stub.Unlock()
23
24         resp := &http.Response{
25                 Status:     "200 OK",
26                 StatusCode: 200,
27                 Proto:      "HTTP/1.1",
28                 ProtoMajor: 1,
29                 ProtoMinor: 1,
30                 Request:    req,
31         }
32         str := stub.Responses[req.URL.Path]
33         if str == "" {
34                 resp.Status = "404 Not Found"
35                 resp.StatusCode = 404
36                 str = "{}"
37         }
38         buf := bytes.NewBufferString(str)
39         resp.Body = ioutil.NopCloser(buf)
40         resp.ContentLength = int64(buf.Len())
41         return resp, nil
42 }
43
44 type errorTransport struct{}
45
46 func (stub *errorTransport) RoundTrip(req *http.Request) (*http.Response, error) {
47         return nil, fmt.Errorf("something awful happened")
48 }
49
50 func TestCurrentUser(t *testing.T) {
51         t.Parallel()
52         stub := &stubTransport{
53                 Responses: map[string]string{
54                         "/arvados/v1/users/current": `{"uuid":"zzzzz-abcde-012340123401234"}`,
55                 },
56         }
57         c := &Client{
58                 Client: &http.Client{
59                         Transport: stub,
60                 },
61                 APIHost:   "zzzzz.arvadosapi.com",
62                 AuthToken: "xyzzy",
63         }
64         u, err := c.CurrentUser()
65         if err != nil {
66                 t.Fatal(err)
67         }
68         if x := "zzzzz-abcde-012340123401234"; u.UUID != x {
69                 t.Errorf("got uuid %q, expected %q", u.UUID, x)
70         }
71         if len(stub.Requests) < 1 {
72                 t.Fatal("empty stub.Requests")
73         }
74         hdr := stub.Requests[len(stub.Requests)-1].Header
75         if hdr.Get("Authorization") != "OAuth2 xyzzy" {
76                 t.Errorf("got headers %+q, expected Authorization header", hdr)
77         }
78
79         c.Client.Transport = &errorTransport{}
80         u, err = c.CurrentUser()
81         if err == nil {
82                 t.Errorf("got nil error, expected something awful")
83         }
84 }
85
86 func TestAnythingToValues(t *testing.T) {
87         type testCase struct {
88                 in interface{}
89                 // ok==nil means anythingToValues should return an
90                 // error, otherwise it's a func that returns true if
91                 // out is correct
92                 ok func(out url.Values) bool
93         }
94         for _, tc := range []testCase{
95                 {
96                         in: map[string]interface{}{"foo": "bar"},
97                         ok: func(out url.Values) bool {
98                                 return out.Get("foo") == "bar"
99                         },
100                 },
101                 {
102                         in: map[string]interface{}{"foo": 2147483647},
103                         ok: func(out url.Values) bool {
104                                 return out.Get("foo") == "2147483647"
105                         },
106                 },
107                 {
108                         in: map[string]interface{}{"foo": 1.234},
109                         ok: func(out url.Values) bool {
110                                 return out.Get("foo") == "1.234"
111                         },
112                 },
113                 {
114                         in: map[string]interface{}{"foo": "1.234"},
115                         ok: func(out url.Values) bool {
116                                 return out.Get("foo") == "1.234"
117                         },
118                 },
119                 {
120                         in: map[string]interface{}{"foo": map[string]interface{}{"bar": 1.234}},
121                         ok: func(out url.Values) bool {
122                                 return out.Get("foo") == `{"bar":1.234}`
123                         },
124                 },
125                 {
126                         in: url.Values{"foo": {"bar"}},
127                         ok: func(out url.Values) bool {
128                                 return out.Get("foo") == "bar"
129                         },
130                 },
131                 {
132                         in: 1234,
133                         ok: nil,
134                 },
135                 {
136                         in: []string{"foo"},
137                         ok: nil,
138                 },
139         } {
140                 t.Logf("%#v", tc.in)
141                 out, err := anythingToValues(tc.in)
142                 switch {
143                 case tc.ok == nil:
144                         if err == nil {
145                                 t.Errorf("got %#v, expected error", out)
146                         }
147                 case err != nil:
148                         t.Errorf("got err %#v, expected nil", err)
149                 case !tc.ok(out):
150                         t.Errorf("got %#v but tc.ok() says that is wrong", out)
151                 }
152         }
153 }