| 
									
										
										
										
											2019-09-02 22:01:02 -06:00
										 |  |  | // Copyright 2015 Matthew Holt and The Caddy Authors | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | // You may obtain a copy of the License at | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and | 
					
						
							|  |  |  | // limitations under the License. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package reverseproxy | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"net/http/httptest" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testPool() UpstreamPool { | 
					
						
							|  |  |  | 	return UpstreamPool{ | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRoundRobinPolicy(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	rrPolicy := new(RoundRobinSelection) | 
					
						
							|  |  |  | 	req, _ := http.NewRequest("GET", "/", nil) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h := rrPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	// First selected host is 1, because counter starts at 0 | 
					
						
							|  |  |  | 	// and increments before host is selected | 
					
						
							|  |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected first round robin host to be second host in the pool.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = rrPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected second round robin host to be third host in the pool.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = rrPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected third round robin host to be first host in the pool.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// mark host as down | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[1].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = rrPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected to skip down host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// mark host as up | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[1].setHealthy(true) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = rrPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h == pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected to balance evenly among healthy hosts") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// mark host as full | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[1].countRequest(1) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	pool[1].MaxRequests = 1 | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = rrPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected to skip full host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestLeastConnPolicy(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	lcPolicy := new(LeastConnSelection) | 
					
						
							|  |  |  | 	req, _ := http.NewRequest("GET", "/", nil) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].countRequest(10) | 
					
						
							|  |  |  | 	pool[1].countRequest(10) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h := lcPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected least connection host to be third host.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[2].countRequest(100) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = lcPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] && h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected least connection host to be first or second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestIPHashPolicy(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	ipHash := new(IPHashSelection) | 
					
						
							|  |  |  | 	req, _ := http.NewRequest("GET", "/", nil) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We should be able to predict where every request is routed. | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.1:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h := ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.2:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.3:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the third host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.4:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// we should get the same results without a port | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.1" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.2" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.3" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the third host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.4" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// we should get a healthy host if the original host is unhealthy and a | 
					
						
							|  |  |  | 	// healthy host is available | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.1" | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[1].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the third host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.2" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[2] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the third host.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[1].setHealthy(true) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.3" | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[2].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.4" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We should be able to resize the host pool and still be able to predict | 
					
						
							|  |  |  | 	// where a req will be routed with the same IP's used above | 
					
						
							|  |  |  | 	pool = UpstreamPool{ | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.1:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.2:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.3:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req.RemoteAddr = "172.0.0.4:80" | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We should get nil when there are no healthy hosts | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(false) | 
					
						
							|  |  |  | 	pool[1].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != nil { | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to be nil.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-29 18:52:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Reproduce #4135 | 
					
						
							|  |  |  | 	pool = UpstreamPool{ | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pool[0].setHealthy(false) | 
					
						
							|  |  |  | 	pool[1].setHealthy(false) | 
					
						
							|  |  |  | 	pool[2].setHealthy(false) | 
					
						
							|  |  |  | 	pool[3].setHealthy(false) | 
					
						
							|  |  |  | 	pool[4].setHealthy(false) | 
					
						
							|  |  |  | 	pool[5].setHealthy(false) | 
					
						
							|  |  |  | 	pool[6].setHealthy(false) | 
					
						
							|  |  |  | 	pool[7].setHealthy(false) | 
					
						
							|  |  |  | 	pool[8].setHealthy(true) | 
					
						
							| 
									
										
										
										
											2021-04-29 18:52:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// We should get a result back when there is one healthy host left. | 
					
						
							|  |  |  | 	h = ipHash.Select(pool, req, nil) | 
					
						
							|  |  |  | 	if h == nil { | 
					
						
							|  |  |  | 		// If it is nil, it means we missed a host even though one is available | 
					
						
							|  |  |  | 		t.Error("Expected ip hash policy host to not be nil, but it is nil.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFirstPolicy(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	firstPolicy := new(FirstSelection) | 
					
						
							|  |  |  | 	req := httptest.NewRequest(http.MethodGet, "/", nil) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h := firstPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected first policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = firstPolicy.Select(pool, req, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected first policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestURIHashPolicy(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	uriPolicy := new(URIHashSelection) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	request := httptest.NewRequest(http.MethodGet, "/test", nil) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h := uriPolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected uri policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = uriPolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected uri policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	request = httptest.NewRequest(http.MethodGet, "/test_2", nil) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = uriPolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected uri policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We should be able to resize the host pool and still be able to predict | 
					
						
							|  |  |  | 	// where a request will be routed with the same URI's used above | 
					
						
							|  |  |  | 	pool = UpstreamPool{ | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 		{Host: new(Host)}, | 
					
						
							|  |  |  | 		{Host: new(Host)}, | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	request = httptest.NewRequest(http.MethodGet, "/test", nil) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = uriPolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected uri policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = uriPolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected uri policy host to be the first host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	request = httptest.NewRequest(http.MethodGet, "/test_2", nil) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = uriPolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != pool[1] { | 
					
						
							|  |  |  | 		t.Error("Expected uri policy host to be the second host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(false) | 
					
						
							|  |  |  | 	pool[1].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = uriPolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2019-09-09 21:44:58 -06:00
										 |  |  | 	if h != nil { | 
					
						
							|  |  |  | 		t.Error("Expected uri policy policy host to be nil.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-16 20:47:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestLeastRequests(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	pool[0].Dial = "localhost:8080" | 
					
						
							|  |  |  | 	pool[1].Dial = "localhost:8081" | 
					
						
							|  |  |  | 	pool[2].Dial = "localhost:8082" | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(true) | 
					
						
							|  |  |  | 	pool[1].setHealthy(true) | 
					
						
							|  |  |  | 	pool[2].setHealthy(true) | 
					
						
							|  |  |  | 	pool[0].countRequest(10) | 
					
						
							|  |  |  | 	pool[1].countRequest(20) | 
					
						
							|  |  |  | 	pool[2].countRequest(30) | 
					
						
							| 
									
										
										
										
											2020-11-16 20:47:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	result := leastRequests(pool) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if result == nil { | 
					
						
							|  |  |  | 		t.Error("Least request should not return nil") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if result != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Least request should return pool[0]") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRandomChoicePolicy(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	pool[0].Dial = "localhost:8080" | 
					
						
							|  |  |  | 	pool[1].Dial = "localhost:8081" | 
					
						
							|  |  |  | 	pool[2].Dial = "localhost:8082" | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(false) | 
					
						
							|  |  |  | 	pool[1].setHealthy(true) | 
					
						
							|  |  |  | 	pool[2].setHealthy(true) | 
					
						
							|  |  |  | 	pool[0].countRequest(10) | 
					
						
							|  |  |  | 	pool[1].countRequest(20) | 
					
						
							|  |  |  | 	pool[2].countRequest(30) | 
					
						
							| 
									
										
										
										
											2020-11-16 20:47:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	request := httptest.NewRequest(http.MethodGet, "/test", nil) | 
					
						
							|  |  |  | 	randomChoicePolicy := new(RandomChoiceSelection) | 
					
						
							|  |  |  | 	randomChoicePolicy.Choose = 2 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h := randomChoicePolicy.Select(pool, request, nil) | 
					
						
							| 
									
										
										
										
											2020-11-16 20:47:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if h == nil { | 
					
						
							|  |  |  | 		t.Error("RandomChoicePolicy should not return nil") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if h == pool[0] { | 
					
						
							|  |  |  | 		t.Error("RandomChoicePolicy should not choose pool[0]") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestCookieHashPolicy(t *testing.T) { | 
					
						
							|  |  |  | 	pool := testPool() | 
					
						
							|  |  |  | 	pool[0].Dial = "localhost:8080" | 
					
						
							|  |  |  | 	pool[1].Dial = "localhost:8081" | 
					
						
							|  |  |  | 	pool[2].Dial = "localhost:8082" | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(true) | 
					
						
							|  |  |  | 	pool[1].setHealthy(false) | 
					
						
							|  |  |  | 	pool[2].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	request := httptest.NewRequest(http.MethodGet, "/test", nil) | 
					
						
							|  |  |  | 	w := httptest.NewRecorder() | 
					
						
							|  |  |  | 	cookieHashPolicy := new(CookieHashSelection) | 
					
						
							|  |  |  | 	h := cookieHashPolicy.Select(pool, request, w) | 
					
						
							| 
									
										
										
										
											2020-12-14 15:30:55 -07:00
										 |  |  | 	cookieServer1 := w.Result().Cookies()[0] | 
					
						
							|  |  |  | 	if cookieServer1 == nil { | 
					
						
							| 
									
										
										
										
											2021-05-05 14:52:18 -06:00
										 |  |  | 		t.Fatal("cookieHashPolicy should set a cookie") | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-12-14 15:30:55 -07:00
										 |  |  | 	if cookieServer1.Name != "lb" { | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 		t.Error("cookieHashPolicy should set a cookie with name lb") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected cookieHashPolicy host to be the first only available host.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[1].setHealthy(true) | 
					
						
							|  |  |  | 	pool[2].setHealthy(true) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	request = httptest.NewRequest(http.MethodGet, "/test", nil) | 
					
						
							|  |  |  | 	w = httptest.NewRecorder() | 
					
						
							| 
									
										
										
										
											2020-12-14 15:30:55 -07:00
										 |  |  | 	request.AddCookie(cookieServer1) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = cookieHashPolicy.Select(pool, request, w) | 
					
						
							|  |  |  | 	if h != pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected cookieHashPolicy host to stick to the first host (matching cookie).") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	s := w.Result().Cookies() | 
					
						
							|  |  |  | 	if len(s) != 0 { | 
					
						
							|  |  |  | 		t.Error("Expected cookieHashPolicy to not set a new cookie.") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-06 17:43:39 -07:00
										 |  |  | 	pool[0].setHealthy(false) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	request = httptest.NewRequest(http.MethodGet, "/test", nil) | 
					
						
							|  |  |  | 	w = httptest.NewRecorder() | 
					
						
							| 
									
										
										
										
											2020-12-14 15:30:55 -07:00
										 |  |  | 	request.AddCookie(cookieServer1) | 
					
						
							| 
									
										
										
										
											2020-11-20 20:39:26 +01:00
										 |  |  | 	h = cookieHashPolicy.Select(pool, request, w) | 
					
						
							|  |  |  | 	if h == pool[0] { | 
					
						
							|  |  |  | 		t.Error("Expected cookieHashPolicy to select a new host.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if w.Result().Cookies() == nil { | 
					
						
							|  |  |  | 		t.Error("Expected cookieHashPolicy to set a new cookie.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |