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