github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/api/api_test.go (about) 1 package api 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "net/http/httptest" 7 "os" 8 "testing" 9 "time" 10 11 "github.com/hashicorp/nomad/testutil" 12 ) 13 14 type configCallback func(c *Config) 15 16 // seen is used to track which tests we have already marked as parallel 17 var seen map[*testing.T]struct{} 18 19 func init() { 20 seen = make(map[*testing.T]struct{}) 21 } 22 23 func makeClient(t *testing.T, cb1 configCallback, 24 cb2 testutil.ServerConfigCallback) (*Client, *testutil.TestServer) { 25 // Always run these tests in parallel. Check if we have already 26 // marked the current test, as more than 1 call causes panics. 27 if _, ok := seen[t]; !ok { 28 seen[t] = struct{}{} 29 t.Parallel() 30 } 31 32 // Make client config 33 conf := DefaultConfig() 34 if cb1 != nil { 35 cb1(conf) 36 } 37 38 // Create server 39 server := testutil.NewTestServer(t, cb2) 40 conf.Address = "http://" + server.HTTPAddr 41 42 // Create client 43 client, err := NewClient(conf) 44 if err != nil { 45 t.Fatalf("err: %v", err) 46 } 47 48 return client, server 49 } 50 51 func TestRequestTime(t *testing.T) { 52 t.Parallel() 53 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 54 time.Sleep(100 * time.Millisecond) 55 d, err := json.Marshal(struct{ Done bool }{true}) 56 if err != nil { 57 http.Error(w, err.Error(), http.StatusInternalServerError) 58 return 59 } 60 w.Write(d) 61 })) 62 defer srv.Close() 63 64 conf := DefaultConfig() 65 conf.Address = srv.URL 66 67 client, err := NewClient(conf) 68 if err != nil { 69 t.Fatalf("err: %v", err) 70 } 71 72 var out interface{} 73 74 qm, err := client.query("/", &out, nil) 75 if err != nil { 76 t.Fatalf("query err: %v", err) 77 } 78 if qm.RequestTime == 0 { 79 t.Errorf("bad request time: %d", qm.RequestTime) 80 } 81 82 wm, err := client.write("/", struct{ S string }{"input"}, &out, nil) 83 if err != nil { 84 t.Fatalf("write err: %v", err) 85 } 86 if wm.RequestTime == 0 { 87 t.Errorf("bad request time: %d", wm.RequestTime) 88 } 89 90 wm, err = client.delete("/", &out, nil) 91 if err != nil { 92 t.Fatalf("delete err: %v", err) 93 } 94 if wm.RequestTime == 0 { 95 t.Errorf("bad request time: %d", wm.RequestTime) 96 } 97 } 98 99 func TestDefaultConfig_env(t *testing.T) { 100 t.Parallel() 101 url := "http://1.2.3.4:5678" 102 103 os.Setenv("NOMAD_ADDR", url) 104 defer os.Setenv("NOMAD_ADDR", "") 105 106 config := DefaultConfig() 107 108 if config.Address != url { 109 t.Errorf("expected %q to be %q", config.Address, url) 110 } 111 } 112 113 func TestSetQueryOptions(t *testing.T) { 114 c, s := makeClient(t, nil, nil) 115 defer s.Stop() 116 117 r := c.newRequest("GET", "/v1/jobs") 118 q := &QueryOptions{ 119 Region: "foo", 120 AllowStale: true, 121 WaitIndex: 1000, 122 WaitTime: 100 * time.Second, 123 } 124 r.setQueryOptions(q) 125 126 if r.params.Get("region") != "foo" { 127 t.Fatalf("bad: %v", r.params) 128 } 129 if _, ok := r.params["stale"]; !ok { 130 t.Fatalf("bad: %v", r.params) 131 } 132 if r.params.Get("index") != "1000" { 133 t.Fatalf("bad: %v", r.params) 134 } 135 if r.params.Get("wait") != "100000ms" { 136 t.Fatalf("bad: %v", r.params) 137 } 138 } 139 140 func TestSetWriteOptions(t *testing.T) { 141 c, s := makeClient(t, nil, nil) 142 defer s.Stop() 143 144 r := c.newRequest("GET", "/v1/jobs") 145 q := &WriteOptions{ 146 Region: "foo", 147 } 148 r.setWriteOptions(q) 149 150 if r.params.Get("region") != "foo" { 151 t.Fatalf("bad: %v", r.params) 152 } 153 } 154 155 func TestRequestToHTTP(t *testing.T) { 156 c, s := makeClient(t, nil, nil) 157 defer s.Stop() 158 159 r := c.newRequest("DELETE", "/v1/jobs/foo") 160 q := &QueryOptions{ 161 Region: "foo", 162 } 163 r.setQueryOptions(q) 164 req, err := r.toHTTP() 165 if err != nil { 166 t.Fatalf("err: %v", err) 167 } 168 169 if req.Method != "DELETE" { 170 t.Fatalf("bad: %v", req) 171 } 172 if req.URL.RequestURI() != "/v1/jobs/foo?region=foo" { 173 t.Fatalf("bad: %v", req) 174 } 175 } 176 177 func TestParseQueryMeta(t *testing.T) { 178 t.Parallel() 179 resp := &http.Response{ 180 Header: make(map[string][]string), 181 } 182 resp.Header.Set("X-Nomad-Index", "12345") 183 resp.Header.Set("X-Nomad-LastContact", "80") 184 resp.Header.Set("X-Nomad-KnownLeader", "true") 185 186 qm := &QueryMeta{} 187 if err := parseQueryMeta(resp, qm); err != nil { 188 t.Fatalf("err: %v", err) 189 } 190 191 if qm.LastIndex != 12345 { 192 t.Fatalf("Bad: %v", qm) 193 } 194 if qm.LastContact != 80*time.Millisecond { 195 t.Fatalf("Bad: %v", qm) 196 } 197 if !qm.KnownLeader { 198 t.Fatalf("Bad: %v", qm) 199 } 200 } 201 202 func TestParseWriteMeta(t *testing.T) { 203 t.Parallel() 204 resp := &http.Response{ 205 Header: make(map[string][]string), 206 } 207 resp.Header.Set("X-Nomad-Index", "12345") 208 209 wm := &WriteMeta{} 210 if err := parseWriteMeta(resp, wm); err != nil { 211 t.Fatalf("err: %v", err) 212 } 213 214 if wm.LastIndex != 12345 { 215 t.Fatalf("Bad: %v", wm) 216 } 217 } 218 219 func TestQueryString(t *testing.T) { 220 c, s := makeClient(t, nil, nil) 221 defer s.Stop() 222 223 r := c.newRequest("PUT", "/v1/abc?foo=bar&baz=zip") 224 q := &WriteOptions{Region: "foo"} 225 r.setWriteOptions(q) 226 227 req, err := r.toHTTP() 228 if err != nil { 229 t.Fatalf("err: %s", err) 230 } 231 232 if uri := req.URL.RequestURI(); uri != "/v1/abc?baz=zip&foo=bar®ion=foo" { 233 t.Fatalf("bad uri: %q", uri) 234 } 235 }