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
+}