@marcel91200 / caddy Mirror · read-only / commits / b4f4fcd4
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

Migrate some selection policy tests over to v2

Matthew Holt committed Sep 9, 2019 at 21:44 UTC b4f4fcd437c2f9816f9511217bde703679808679
4 files changed +272 -360
modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go
+1 -1
@@ -55,7 +55,7 @@ type Transport struct {
55 // PATH_INFO for the CGI script to use.
56 SplitPath string `json:"split_path,omitempty"`
57
58 - // Environment Variables
58 + // Environment variables (TODO: make a map of string to value...?)
59 EnvVars [][2]string `json:"env,omitempty"`
60
61 // The duration used to set a deadline when connecting to an upstream.
modules/caddyhttp/reverseproxy/hosts.go
+11 -9
@@ -34,19 +34,21 @@ type Host interface {
34 // Unhealthy returns true if the backend is unhealthy.
35 Unhealthy() bool
36
37 - // CountRequest counts the given number of requests
38 - // as currently in process with the host. The count
39 - // should not go below 0.
37 + // CountRequest atomically counts the given number of
38 + // requests as currently in process with the host. The
39 + // count should not go below 0.
40 CountRequest(int) error
41
42 - // CountFail counts the given number of failures
43 - // with the host. The count should not go below 0.
42 + // CountFail atomically counts the given number of
43 + // failures with the host. The count should not go
44 + // below 0.
45 CountFail(int) error
46
46 - // SetHealthy marks the host as either healthy (true)
47 - // or unhealthy (false). If the given status is the
48 - // same, this should be a no-op. It returns true if
49 - // the given status was different, false otherwise.
47 + // SetHealthy atomically marks the host as either
48 + // healthy (true) or unhealthy (false). If the given
49 + // status is the same, this should be a no-op and
50 + // return false. It returns true if the status was
51 + // changed; i.e. if it is now different from before.
52 SetHealthy(bool) (bool, error)
53 }
54
modules/caddyhttp/reverseproxy/selectionpolicies.go
+3 -3
@@ -82,7 +82,7 @@ type RandomChoiceSelection struct {
82 // CaddyModule returns the Caddy module information.
83 func (RandomChoiceSelection) CaddyModule() caddy.ModuleInfo {
84 return caddy.ModuleInfo{
85 - Name: "http.handlers.reverse_proxy.selection_policies.random_choice",
85 + Name: "http.handlers.reverse_proxy.selection_policies.random_choose",
86 New: func() caddy.Module { return new(RandomChoiceSelection) },
87 }
88 }
@@ -147,14 +147,14 @@ func (LeastConnSelection) CaddyModule() caddy.ModuleInfo {
147 func (LeastConnSelection) Select(pool UpstreamPool, _ *http.Request) *Upstream {
148 var bestHost *Upstream
149 var count int
150 - var leastReqs int
150 + leastReqs := -1
151
152 for _, host := range pool {
153 if !host.Available() {
154 continue
155 }
156 numReqs := host.NumRequests()
157 - if numReqs < leastReqs {
157 + if leastReqs == -1 || numReqs < leastReqs {
158 leastReqs = numReqs
159 count = 0
160 }
modules/caddyhttp/reverseproxy/selectionpolicies_test.go
+257 -347
@@ -14,350 +14,260 @@
14
15 package reverseproxy
16
17 -// TODO: finish migrating these
18 -
19 -// import (
20 -// "net/http"
21 -// "net/http/httptest"
22 -// "os"
23 -// "testing"
24 -// )
25 -
26 -// var workableServer *httptest.Server
27 -
28 -// func TestMain(m *testing.M) {
29 -// workableServer = httptest.NewServer(http.HandlerFunc(
30 -// func(w http.ResponseWriter, r *http.Request) {
31 -// // do nothing
32 -// }))
33 -// r := m.Run()
34 -// workableServer.Close()
35 -// os.Exit(r)
36 -// }
37 -
38 -// type customPolicy struct{}
39 -
40 -// func (customPolicy) Select(pool HostPool, _ *http.Request) Host {
41 -// return pool[0]
42 -// }
43 -
44 -// func testPool() HostPool {
45 -// pool := []*UpstreamHost{
46 -// {
47 -// Name: workableServer.URL, // this should resolve (healthcheck test)
48 -// },
49 -// {
50 -// Name: "http://localhost:99998", // this shouldn't
51 -// },
52 -// {
53 -// Name: "http://C",
54 -// },
55 -// }
56 -// return HostPool(pool)
57 -// }
58 -
59 -// func TestRoundRobinPolicy(t *testing.T) {
60 -// pool := testPool()
61 -// rrPolicy := &RoundRobin{}
62 -// request, _ := http.NewRequest("GET", "/", nil)
63 -
64 -// h := rrPolicy.Select(pool, request)
65 -// // First selected host is 1, because counter starts at 0
66 -// // and increments before host is selected
67 -// if h != pool[1] {
68 -// t.Error("Expected first round robin host to be second host in the pool.")
69 -// }
70 -// h = rrPolicy.Select(pool, request)
71 -// if h != pool[2] {
72 -// t.Error("Expected second round robin host to be third host in the pool.")
73 -// }
74 -// h = rrPolicy.Select(pool, request)
75 -// if h != pool[0] {
76 -// t.Error("Expected third round robin host to be first host in the pool.")
77 -// }
78 -// // mark host as down
79 -// pool[1].Unhealthy = 1
80 -// h = rrPolicy.Select(pool, request)
81 -// if h != pool[2] {
82 -// t.Error("Expected to skip down host.")
83 -// }
84 -// // mark host as up
85 -// pool[1].Unhealthy = 0
86 -
87 -// h = rrPolicy.Select(pool, request)
88 -// if h == pool[2] {
89 -// t.Error("Expected to balance evenly among healthy hosts")
90 -// }
91 -// // mark host as full
92 -// pool[1].Conns = 1
93 -// pool[1].MaxConns = 1
94 -// h = rrPolicy.Select(pool, request)
95 -// if h != pool[2] {
96 -// t.Error("Expected to skip full host.")
97 -// }
98 -// }
99 -
100 -// func TestLeastConnPolicy(t *testing.T) {
101 -// pool := testPool()
102 -// lcPolicy := &LeastConn{}
103 -// request, _ := http.NewRequest("GET", "/", nil)
104 -
105 -// pool[0].Conns = 10
106 -// pool[1].Conns = 10
107 -// h := lcPolicy.Select(pool, request)
108 -// if h != pool[2] {
109 -// t.Error("Expected least connection host to be third host.")
110 -// }
111 -// pool[2].Conns = 100
112 -// h = lcPolicy.Select(pool, request)
113 -// if h != pool[0] && h != pool[1] {
114 -// t.Error("Expected least connection host to be first or second host.")
115 -// }
116 -// }
117 -
118 -// func TestCustomPolicy(t *testing.T) {
119 -// pool := testPool()
120 -// customPolicy := &customPolicy{}
121 -// request, _ := http.NewRequest("GET", "/", nil)
122 -
123 -// h := customPolicy.Select(pool, request)
124 -// if h != pool[0] {
125 -// t.Error("Expected custom policy host to be the first host.")
126 -// }
127 -// }
128 -
129 -// func TestIPHashPolicy(t *testing.T) {
130 -// pool := testPool()
131 -// ipHash := &IPHash{}
132 -// request, _ := http.NewRequest("GET", "/", nil)
133 -// // We should be able to predict where every request is routed.
134 -// request.RemoteAddr = "172.0.0.1:80"
135 -// h := ipHash.Select(pool, request)
136 -// if h != pool[1] {
137 -// t.Error("Expected ip hash policy host to be the second host.")
138 -// }
139 -// request.RemoteAddr = "172.0.0.2:80"
140 -// h = ipHash.Select(pool, request)
141 -// if h != pool[1] {
142 -// t.Error("Expected ip hash policy host to be the second host.")
143 -// }
144 -// request.RemoteAddr = "172.0.0.3:80"
145 -// h = ipHash.Select(pool, request)
146 -// if h != pool[2] {
147 -// t.Error("Expected ip hash policy host to be the third host.")
148 -// }
149 -// request.RemoteAddr = "172.0.0.4:80"
150 -// h = ipHash.Select(pool, request)
151 -// if h != pool[1] {
152 -// t.Error("Expected ip hash policy host to be the second host.")
153 -// }
154 -
155 -// // we should get the same results without a port
156 -// request.RemoteAddr = "172.0.0.1"
157 -// h = ipHash.Select(pool, request)
158 -// if h != pool[1] {
159 -// t.Error("Expected ip hash policy host to be the second host.")
160 -// }
161 -// request.RemoteAddr = "172.0.0.2"
162 -// h = ipHash.Select(pool, request)
163 -// if h != pool[1] {
164 -// t.Error("Expected ip hash policy host to be the second host.")
165 -// }
166 -// request.RemoteAddr = "172.0.0.3"
167 -// h = ipHash.Select(pool, request)
168 -// if h != pool[2] {
169 -// t.Error("Expected ip hash policy host to be the third host.")
170 -// }
171 -// request.RemoteAddr = "172.0.0.4"
172 -// h = ipHash.Select(pool, request)
173 -// if h != pool[1] {
174 -// t.Error("Expected ip hash policy host to be the second host.")
175 -// }
176 -
177 -// // we should get a healthy host if the original host is unhealthy and a
178 -// // healthy host is available
179 -// request.RemoteAddr = "172.0.0.1"
180 -// pool[1].Unhealthy = 1
181 -// h = ipHash.Select(pool, request)
182 -// if h != pool[2] {
183 -// t.Error("Expected ip hash policy host to be the third host.")
184 -// }
185 -
186 -// request.RemoteAddr = "172.0.0.2"
187 -// h = ipHash.Select(pool, request)
188 -// if h != pool[2] {
189 -// t.Error("Expected ip hash policy host to be the third host.")
190 -// }
191 -// pool[1].Unhealthy = 0
192 -
193 -// request.RemoteAddr = "172.0.0.3"
194 -// pool[2].Unhealthy = 1
195 -// h = ipHash.Select(pool, request)
196 -// if h != pool[0] {
197 -// t.Error("Expected ip hash policy host to be the first host.")
198 -// }
199 -// request.RemoteAddr = "172.0.0.4"
200 -// h = ipHash.Select(pool, request)
201 -// if h != pool[1] {
202 -// t.Error("Expected ip hash policy host to be the second host.")
203 -// }
204 -
205 -// // We should be able to resize the host pool and still be able to predict
206 -// // where a request will be routed with the same IP's used above
207 -// pool = []*UpstreamHost{
208 -// {
209 -// Name: workableServer.URL, // this should resolve (healthcheck test)
210 -// },
211 -// {
212 -// Name: "http://localhost:99998", // this shouldn't
213 -// },
214 -// }
215 -// pool = HostPool(pool)
216 -// request.RemoteAddr = "172.0.0.1:80"
217 -// h = ipHash.Select(pool, request)
218 -// if h != pool[0] {
219 -// t.Error("Expected ip hash policy host to be the first host.")
220 -// }
221 -// request.RemoteAddr = "172.0.0.2:80"
222 -// h = ipHash.Select(pool, request)
223 -// if h != pool[1] {
224 -// t.Error("Expected ip hash policy host to be the second host.")
225 -// }
226 -// request.RemoteAddr = "172.0.0.3:80"
227 -// h = ipHash.Select(pool, request)
228 -// if h != pool[0] {
229 -// t.Error("Expected ip hash policy host to be the first host.")
230 -// }
231 -// request.RemoteAddr = "172.0.0.4:80"
232 -// h = ipHash.Select(pool, request)
233 -// if h != pool[1] {
234 -// t.Error("Expected ip hash policy host to be the second host.")
235 -// }
236 -
237 -// // We should get nil when there are no healthy hosts
238 -// pool[0].Unhealthy = 1
239 -// pool[1].Unhealthy = 1
240 -// h = ipHash.Select(pool, request)
241 -// if h != nil {
242 -// t.Error("Expected ip hash policy host to be nil.")
243 -// }
244 -// }
245 -
246 -// func TestFirstPolicy(t *testing.T) {
247 -// pool := testPool()
248 -// firstPolicy := &First{}
249 -// req := httptest.NewRequest(http.MethodGet, "/", nil)
250 -
251 -// h := firstPolicy.Select(pool, req)
252 -// if h != pool[0] {
253 -// t.Error("Expected first policy host to be the first host.")
254 -// }
255 -
256 -// pool[0].Unhealthy = 1
257 -// h = firstPolicy.Select(pool, req)
258 -// if h != pool[1] {
259 -// t.Error("Expected first policy host to be the second host.")
260 -// }
261 -// }
262 -
263 -// func TestUriPolicy(t *testing.T) {
264 -// pool := testPool()
265 -// uriPolicy := &URIHash{}
266 -
267 -// request := httptest.NewRequest(http.MethodGet, "/test", nil)
268 -// h := uriPolicy.Select(pool, request)
269 -// if h != pool[0] {
270 -// t.Error("Expected uri policy host to be the first host.")
271 -// }
272 -
273 -// pool[0].Unhealthy = 1
274 -// h = uriPolicy.Select(pool, request)
275 -// if h != pool[1] {
276 -// t.Error("Expected uri policy host to be the first host.")
277 -// }
278 -
279 -// request = httptest.NewRequest(http.MethodGet, "/test_2", nil)
280 -// h = uriPolicy.Select(pool, request)
281 -// if h != pool[1] {
282 -// t.Error("Expected uri policy host to be the second host.")
283 -// }
284 -
285 -// // We should be able to resize the host pool and still be able to predict
286 -// // where a request will be routed with the same URI's used above
287 -// pool = []*UpstreamHost{
288 -// {
289 -// Name: workableServer.URL, // this should resolve (healthcheck test)
290 -// },
291 -// {
292 -// Name: "http://localhost:99998", // this shouldn't
293 -// },
294 -// }
295 -
296 -// request = httptest.NewRequest(http.MethodGet, "/test", nil)
297 -// h = uriPolicy.Select(pool, request)
298 -// if h != pool[0] {
299 -// t.Error("Expected uri policy host to be the first host.")
300 -// }
301 -
302 -// pool[0].Unhealthy = 1
303 -// h = uriPolicy.Select(pool, request)
304 -// if h != pool[1] {
305 -// t.Error("Expected uri policy host to be the first host.")
306 -// }
307 -
308 -// request = httptest.NewRequest(http.MethodGet, "/test_2", nil)
309 -// h = uriPolicy.Select(pool, request)
310 -// if h != pool[1] {
311 -// t.Error("Expected uri policy host to be the second host.")
312 -// }
313 -
314 -// pool[0].Unhealthy = 1
315 -// pool[1].Unhealthy = 1
316 -// h = uriPolicy.Select(pool, request)
317 -// if h != nil {
318 -// t.Error("Expected uri policy policy host to be nil.")
319 -// }
320 -// }
321 -
322 -// func TestHeaderPolicy(t *testing.T) {
323 -// pool := testPool()
324 -// tests := []struct {
325 -// Name string
326 -// Policy *Header
327 -// RequestHeaderName string
328 -// RequestHeaderValue string
329 -// NilHost bool
330 -// HostIndex int
331 -// }{
332 -// {"empty config", &Header{""}, "", "", true, 0},
333 -// {"empty config+header+value", &Header{""}, "Affinity", "somevalue", true, 0},
334 -// {"empty config+header", &Header{""}, "Affinity", "", true, 0},
335 -
336 -// {"no header(fallback to roundrobin)", &Header{"Affinity"}, "", "", false, 1},
337 -// {"no header(fallback to roundrobin)", &Header{"Affinity"}, "", "", false, 2},
338 -// {"no header(fallback to roundrobin)", &Header{"Affinity"}, "", "", false, 0},
339 -
340 -// {"hash route to host", &Header{"Affinity"}, "Affinity", "somevalue", false, 1},
341 -// {"hash route to host", &Header{"Affinity"}, "Affinity", "somevalue2", false, 0},
342 -// {"hash route to host", &Header{"Affinity"}, "Affinity", "somevalue3", false, 2},
343 -// {"hash route with empty value", &Header{"Affinity"}, "Affinity", "", false, 1},
344 -// }
345 -
346 -// for idx, test := range tests {
347 -// request, _ := http.NewRequest("GET", "/", nil)
348 -// if test.RequestHeaderName != "" {
349 -// request.Header.Add(test.RequestHeaderName, test.RequestHeaderValue)
350 -// }
351 -
352 -// host := test.Policy.Select(pool, request)
353 -// if test.NilHost && host != nil {
354 -// t.Errorf("%d: Expected host to be nil", idx)
355 -// }
356 -// if !test.NilHost && host == nil {
357 -// t.Errorf("%d: Did not expect host to be nil", idx)
358 -// }
359 -// if !test.NilHost && host != pool[test.HostIndex] {
360 -// t.Errorf("%d: Expected Header policy to be host %d", idx, test.HostIndex)
361 -// }
362 -// }
363 -// }
17 +import (
18 + "net/http"
19 + "net/http/httptest"
20 + "testing"
21 +)
22 +
23 +func testPool() UpstreamPool {
24 + return UpstreamPool{
25 + {Host: new(upstreamHost)},
26 + {Host: new(upstreamHost)},
27 + {Host: new(upstreamHost)},
28 + }
29 +}
30 +
31 +func TestRoundRobinPolicy(t *testing.T) {
32 + pool := testPool()
33 + rrPolicy := new(RoundRobinSelection)
34 + req, _ := http.NewRequest("GET", "/", nil)
35 +
36 + h := rrPolicy.Select(pool, req)
37 + // First selected host is 1, because counter starts at 0
38 + // and increments before host is selected
39 + if h != pool[1] {
40 + t.Error("Expected first round robin host to be second host in the pool.")
41 + }
42 + h = rrPolicy.Select(pool, req)
43 + if h != pool[2] {
44 + t.Error("Expected second round robin host to be third host in the pool.")
45 + }
46 + h = rrPolicy.Select(pool, req)
47 + if h != pool[0] {
48 + t.Error("Expected third round robin host to be first host in the pool.")
49 + }
50 + // mark host as down
51 + pool[1].SetHealthy(false)
52 + h = rrPolicy.Select(pool, req)
53 + if h != pool[2] {
54 + t.Error("Expected to skip down host.")
55 + }
56 + // mark host as up
57 + pool[1].SetHealthy(true)
58 +
59 + h = rrPolicy.Select(pool, req)
60 + if h == pool[2] {
61 + t.Error("Expected to balance evenly among healthy hosts")
62 + }
63 + // mark host as full
64 + pool[1].CountRequest(1)
65 + pool[1].MaxRequests = 1
66 + h = rrPolicy.Select(pool, req)
67 + if h != pool[2] {
68 + t.Error("Expected to skip full host.")
69 + }
70 +}
71 +
72 +func TestLeastConnPolicy(t *testing.T) {
73 + pool := testPool()
74 + lcPolicy := new(LeastConnSelection)
75 + req, _ := http.NewRequest("GET", "/", nil)
76 +
77 + pool[0].CountRequest(10)
78 + pool[1].CountRequest(10)
79 + h := lcPolicy.Select(pool, req)
80 + if h != pool[2] {
81 + t.Error("Expected least connection host to be third host.")
82 + }
83 + pool[2].CountRequest(100)
84 + h = lcPolicy.Select(pool, req)
85 + if h != pool[0] && h != pool[1] {
86 + t.Error("Expected least connection host to be first or second host.")
87 + }
88 +}
89 +
90 +func TestIPHashPolicy(t *testing.T) {
91 + pool := testPool()
92 + ipHash := new(IPHashSelection)
93 + req, _ := http.NewRequest("GET", "/", nil)
94 +
95 + // We should be able to predict where every request is routed.
96 + req.RemoteAddr = "172.0.0.1:80"
97 + h := ipHash.Select(pool, req)
98 + if h != pool[1] {
99 + t.Error("Expected ip hash policy host to be the second host.")
100 + }
101 + req.RemoteAddr = "172.0.0.2:80"
102 + h = ipHash.Select(pool, req)
103 + if h != pool[1] {
104 + t.Error("Expected ip hash policy host to be the second host.")
105 + }
106 + req.RemoteAddr = "172.0.0.3:80"
107 + h = ipHash.Select(pool, req)
108 + if h != pool[2] {
109 + t.Error("Expected ip hash policy host to be the third host.")
110 + }
111 + req.RemoteAddr = "172.0.0.4:80"
112 + h = ipHash.Select(pool, req)
113 + if h != pool[1] {
114 + t.Error("Expected ip hash policy host to be the second host.")
115 + }
116 +
117 + // we should get the same results without a port
118 + req.RemoteAddr = "172.0.0.1"
119 + h = ipHash.Select(pool, req)
120 + if h != pool[1] {
121 + t.Error("Expected ip hash policy host to be the second host.")
122 + }
123 + req.RemoteAddr = "172.0.0.2"
124 + h = ipHash.Select(pool, req)
125 + if h != pool[1] {
126 + t.Error("Expected ip hash policy host to be the second host.")
127 + }
128 + req.RemoteAddr = "172.0.0.3"
129 + h = ipHash.Select(pool, req)
130 + if h != pool[2] {
131 + t.Error("Expected ip hash policy host to be the third host.")
132 + }
133 + req.RemoteAddr = "172.0.0.4"
134 + h = ipHash.Select(pool, req)
135 + if h != pool[1] {
136 + t.Error("Expected ip hash policy host to be the second host.")
137 + }
138 +
139 + // we should get a healthy host if the original host is unhealthy and a
140 + // healthy host is available
141 + req.RemoteAddr = "172.0.0.1"
142 + pool[1].SetHealthy(false)
143 + h = ipHash.Select(pool, req)
144 + if h != pool[2] {
145 + t.Error("Expected ip hash policy host to be the third host.")
146 + }
147 +
148 + req.RemoteAddr = "172.0.0.2"
149 + h = ipHash.Select(pool, req)
150 + if h != pool[2] {
151 + t.Error("Expected ip hash policy host to be the third host.")
152 + }
153 + pool[1].SetHealthy(true)
154 +
155 + req.RemoteAddr = "172.0.0.3"
156 + pool[2].SetHealthy(false)
157 + h = ipHash.Select(pool, req)
158 + if h != pool[0] {
159 + t.Error("Expected ip hash policy host to be the first host.")
160 + }
161 + req.RemoteAddr = "172.0.0.4"
162 + h = ipHash.Select(pool, req)
163 + if h != pool[1] {
164 + t.Error("Expected ip hash policy host to be the second host.")
165 + }
166 +
167 + // We should be able to resize the host pool and still be able to predict
168 + // where a req will be routed with the same IP's used above
169 + pool = UpstreamPool{
170 + {Host: new(upstreamHost)},
171 + {Host: new(upstreamHost)},
172 + }
173 + req.RemoteAddr = "172.0.0.1:80"
174 + h = ipHash.Select(pool, req)
175 + if h != pool[0] {
176 + t.Error("Expected ip hash policy host to be the first host.")
177 + }
178 + req.RemoteAddr = "172.0.0.2:80"
179 + h = ipHash.Select(pool, req)
180 + if h != pool[1] {
181 + t.Error("Expected ip hash policy host to be the second host.")
182 + }
183 + req.RemoteAddr = "172.0.0.3:80"
184 + h = ipHash.Select(pool, req)
185 + if h != pool[0] {
186 + t.Error("Expected ip hash policy host to be the first host.")
187 + }
188 + req.RemoteAddr = "172.0.0.4:80"
189 + h = ipHash.Select(pool, req)
190 + if h != pool[1] {
191 + t.Error("Expected ip hash policy host to be the second host.")
192 + }
193 +
194 + // We should get nil when there are no healthy hosts
195 + pool[0].SetHealthy(false)
196 + pool[1].SetHealthy(false)
197 + h = ipHash.Select(pool, req)
198 + if h != nil {
199 + t.Error("Expected ip hash policy host to be nil.")
200 + }
201 +}
202 +
203 +func TestFirstPolicy(t *testing.T) {
204 + pool := testPool()
205 + firstPolicy := new(FirstSelection)
206 + req := httptest.NewRequest(http.MethodGet, "/", nil)
207 +
208 + h := firstPolicy.Select(pool, req)
209 + if h != pool[0] {
210 + t.Error("Expected first policy host to be the first host.")
211 + }
212 +
213 + pool[0].SetHealthy(false)
214 + h = firstPolicy.Select(pool, req)
215 + if h != pool[1] {
216 + t.Error("Expected first policy host to be the second host.")
217 + }
218 +}
219 +
220 +func TestURIHashPolicy(t *testing.T) {
221 + pool := testPool()
222 + uriPolicy := new(URIHashSelection)
223 +
224 + request := httptest.NewRequest(http.MethodGet, "/test", nil)
225 + h := uriPolicy.Select(pool, request)
226 + if h != pool[0] {
227 + t.Error("Expected uri policy host to be the first host.")
228 + }
229 +
230 + pool[0].SetHealthy(false)
231 + h = uriPolicy.Select(pool, request)
232 + if h != pool[1] {
233 + t.Error("Expected uri policy host to be the first host.")
234 + }
235 +
236 + request = httptest.NewRequest(http.MethodGet, "/test_2", nil)
237 + h = uriPolicy.Select(pool, request)
238 + if h != pool[1] {
239 + t.Error("Expected uri policy host to be the second host.")
240 + }
241 +
242 + // We should be able to resize the host pool and still be able to predict
243 + // where a request will be routed with the same URI's used above
244 + pool = UpstreamPool{
245 + {Host: new(upstreamHost)},
246 + {Host: new(upstreamHost)},
247 + }
248 +
249 + request = httptest.NewRequest(http.MethodGet, "/test", nil)
250 + h = uriPolicy.Select(pool, request)
251 + if h != pool[0] {
252 + t.Error("Expected uri policy host to be the first host.")
253 + }
254 +
255 + pool[0].SetHealthy(false)
256 + h = uriPolicy.Select(pool, request)
257 + if h != pool[1] {
258 + t.Error("Expected uri policy host to be the first host.")
259 + }
260 +
261 + request = httptest.NewRequest(http.MethodGet, "/test_2", nil)
262 + h = uriPolicy.Select(pool, request)
263 + if h != pool[1] {
264 + t.Error("Expected uri policy host to be the second host.")
265 + }
266 +
267 + pool[0].SetHealthy(false)
268 + pool[1].SetHealthy(false)
269 + h = uriPolicy.Select(pool, request)
270 + if h != nil {
271 + t.Error("Expected uri policy policy host to be nil.")
272 + }
273 +}