github.com/pawelgaczynski/gain@v0.4.0-alpha.0.20230821120126-41f1e60a18da/load_balancer_test.go (about) 1 // Copyright (c) 2023 Paweł Gaczyński 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package gain 16 17 import ( 18 "net" 19 "testing" 20 21 "github.com/pawelgaczynski/gain/pkg/errors" 22 . "github.com/stretchr/testify/require" 23 ) 24 25 const numberOfTestWorkers = 4 26 27 type testWorker struct { 28 conns int 29 } 30 31 func (w *testWorker) activeConnections() int { 32 return w.conns 33 } 34 35 func (w *testWorker) setIndex(_ int) { 36 } 37 38 func (w *testWorker) index() int { 39 return 0 40 } 41 42 func (w *testWorker) loop(_ int) error { 43 w.conns++ 44 45 return nil 46 } 47 48 func (w *testWorker) shutdown() { 49 } 50 51 func (w *testWorker) setSocketAddr(_ int, _ net.Addr) { 52 } 53 54 func (w *testWorker) addConnToQueue(_ int) error { 55 return nil 56 } 57 58 func (w *testWorker) ringFd() int { 59 return 0 60 } 61 62 func (w *testWorker) started() bool { 63 return true 64 } 65 66 func (w *testWorker) close() { 67 } 68 69 func createTestWorkers() []*testWorker { 70 workers := make([]*testWorker, 0) 71 for i := 0; i < numberOfTestWorkers; i++ { 72 workers = append(workers, &testWorker{}) 73 } 74 75 return workers 76 } 77 78 func TestRoundRobinLoadBalander(t *testing.T) { 79 lb := newRoundRobinLoadBalancer() 80 81 workers := createTestWorkers() 82 for _, worker := range workers { 83 lb.register(worker) 84 } 85 worker := lb.next(nil) 86 err := worker.loop(0) 87 Nil(t, err) 88 Same(t, worker, workers[0]) 89 worker = lb.next(nil) 90 err = worker.loop(0) 91 Nil(t, err) 92 Same(t, worker, workers[1]) 93 worker = lb.next(nil) 94 err = worker.loop(0) 95 Nil(t, err) 96 Same(t, worker, workers[2]) 97 worker = lb.next(nil) 98 err = worker.loop(0) 99 Nil(t, err) 100 Same(t, worker, workers[3]) 101 worker = lb.next(nil) 102 err = worker.loop(0) 103 Nil(t, err) 104 Same(t, worker, workers[0]) 105 worker = lb.next(nil) 106 err = worker.loop(0) 107 Nil(t, err) 108 Same(t, worker, workers[1]) 109 worker = lb.next(nil) 110 err = worker.loop(0) 111 Nil(t, err) 112 Same(t, worker, workers[2]) 113 worker = lb.next(nil) 114 err = worker.loop(0) 115 Nil(t, err) 116 Same(t, worker, workers[3]) 117 } 118 119 func TestLeastConnectionsLoadBalander(t *testing.T) { 120 loadBl := newLeastConnectionsLoadBalancer() 121 122 workers := createTestWorkers() 123 for _, worker := range workers { 124 loadBl.register(worker) 125 } 126 workers[0].conns = 1 127 workers[1].conns = 0 128 workers[2].conns = 2 129 workers[3].conns = 1 130 worker := loadBl.next(nil) 131 err := worker.loop(0) 132 Nil(t, err) 133 Same(t, worker, workers[1]) 134 worker = loadBl.next(nil) 135 err = worker.loop(0) 136 Nil(t, err) 137 Same(t, worker, workers[0]) 138 worker = loadBl.next(nil) 139 err = worker.loop(0) 140 Nil(t, err) 141 Same(t, worker, workers[1]) 142 worker = loadBl.next(nil) 143 err = worker.loop(0) 144 Nil(t, err) 145 Same(t, worker, workers[3]) 146 worker = loadBl.next(nil) 147 err = worker.loop(0) 148 Nil(t, err) 149 Same(t, worker, workers[0]) 150 worker = loadBl.next(nil) 151 err = worker.loop(0) 152 Nil(t, err) 153 Same(t, worker, workers[1]) 154 worker = loadBl.next(nil) 155 err = worker.loop(0) 156 Nil(t, err) 157 Same(t, worker, workers[2]) 158 worker = loadBl.next(nil) 159 err = worker.loop(0) 160 Nil(t, err) 161 Same(t, worker, workers[3]) 162 } 163 164 func TestSourceIPHashLoadBalancer(t *testing.T) { 165 loadBl := newSourceIPHashLoadBalancer() 166 167 workers := createTestWorkers() 168 for _, worker := range workers { 169 loadBl.register(worker) 170 } 171 workers[0].conns = 1 172 workers[1].conns = 0 173 workers[2].conns = 2 174 workers[3].conns = 1 175 addr, err := net.ResolveTCPAddr("tcp", "10.3.2.1:1234") 176 Nil(t, err) 177 worker := loadBl.next(addr) 178 err = worker.loop(0) 179 Nil(t, err) 180 Same(t, worker, workers[2]) 181 addr, err = net.ResolveTCPAddr("tcp", "10.123.5.1:51234") 182 Nil(t, err) 183 worker = loadBl.next(addr) 184 err = worker.loop(0) 185 Nil(t, err) 186 Same(t, worker, workers[0]) 187 addr, err = net.ResolveTCPAddr("tcp", "10.123.5.31:52354") 188 Nil(t, err) 189 worker = loadBl.next(addr) 190 err = worker.loop(0) 191 Nil(t, err) 192 Same(t, worker, workers[2]) 193 addr, err = net.ResolveTCPAddr("tcp", "192.123.19.1:1234") 194 Nil(t, err) 195 worker = loadBl.next(addr) 196 err = worker.loop(0) 197 Nil(t, err) 198 Same(t, worker, workers[1]) 199 addr, err = net.ResolveTCPAddr("tcp", "10.123.5.31:52354") 200 Nil(t, err) 201 worker = loadBl.next(addr) 202 err = worker.loop(0) 203 Nil(t, err) 204 Same(t, worker, workers[2]) 205 addr, err = net.ResolveTCPAddr("tcp", "192.123.19.1:1234") 206 Nil(t, err) 207 worker = loadBl.next(addr) 208 err = worker.loop(0) 209 Nil(t, err) 210 Same(t, worker, workers[1]) 211 addr, err = net.ResolveTCPAddr("tcp", "10.123.5.1:51234") 212 Nil(t, err) 213 worker = loadBl.next(addr) 214 err = worker.loop(0) 215 Nil(t, err) 216 Same(t, worker, workers[0]) 217 addr, err = net.ResolveTCPAddr("tcp", "10.123.5.31:52354") 218 Nil(t, err) 219 worker = loadBl.next(addr) 220 err = worker.loop(0) 221 Nil(t, err) 222 Same(t, worker, workers[2]) 223 } 224 225 func TestCreateLoadBalancer(t *testing.T) { 226 lb, err := createLoadBalancer(RoundRobin) 227 NoError(t, err) 228 IsType(t, &roundRobinLoadBalancer{}, lb) 229 230 lb, err = createLoadBalancer(LeastConnections) 231 NoError(t, err) 232 IsType(t, &leastConnectionsLoadBalancer{}, lb) 233 234 lb, err = createLoadBalancer(SourceIPHash) 235 NoError(t, err) 236 IsType(t, &sourceIPHashLoadBalancer{}, lb) 237 238 lb, err = createLoadBalancer(10) 239 ErrorIs(t, errors.ErrNotSupported, err) 240 Nil(t, lb) 241 }