github.com/matrixorigin/matrixone@v1.2.0/pkg/common/morpc/client_test.go (about) 1 // Copyright 2021 - 2022 Matrix Origin 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 morpc 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/assert" 23 ) 24 25 func TestCreateBackendLocked(t *testing.T) { 26 rc, err := NewClient("", newTestBackendFactory(), WithClientMaxBackendPerHost(1)) 27 assert.NoError(t, err) 28 c := rc.(*client) 29 defer func() { 30 assert.NoError(t, c.Close()) 31 }() 32 33 b, err := c.createBackendLocked("b1") 34 assert.NoError(t, err) 35 assert.Equal(t, 1, len(c.mu.backends["b1"])) 36 assert.NotNil(t, b) 37 38 b, err = c.createBackendLocked("b1") 39 assert.Error(t, err) 40 assert.Nil(t, b) 41 assert.Equal(t, 1, len(c.mu.backends["b1"])) 42 } 43 44 func TestGetBackendLockedWithClosed(t *testing.T) { 45 rc, err := NewClient("", newTestBackendFactory(), WithClientMaxBackendPerHost(1)) 46 assert.NoError(t, err) 47 c := rc.(*client) 48 assert.NoError(t, c.Close()) 49 50 b, err := c.getBackendLocked("b1", false) 51 assert.Error(t, err) 52 assert.Nil(t, b) 53 } 54 55 func TestGetBackendLockedWithEmptyBackends(t *testing.T) { 56 rc, err := NewClient("", newTestBackendFactory(), WithClientMaxBackendPerHost(1 /*disable create*/)) 57 assert.NoError(t, err) 58 c := rc.(*client) 59 defer func() { 60 assert.NoError(t, c.Close()) 61 }() 62 63 b, err := c.getBackendLocked("b1", false) 64 assert.NoError(t, err) 65 assert.Nil(t, b) 66 } 67 68 func TestGetBackend(t *testing.T) { 69 rc, err := NewClient("", newTestBackendFactory(), WithClientMaxBackendPerHost(1)) 70 assert.NoError(t, err) 71 c := rc.(*client) 72 defer func() { 73 assert.NoError(t, c.Close()) 74 }() 75 76 n := 2 77 for i := 0; i < n; i++ { 78 c.mu.backends["b1"] = append(c.mu.backends["b1"], &testBackend{id: i, busy: false, activeTime: time.Now()}) 79 } 80 c.mu.ops["b1"] = &op{} 81 82 for i := 0; i < n; i++ { 83 b, err := c.getBackend("b1", false) 84 assert.NoError(t, err) 85 assert.Equal(t, c.mu.backends["b1"][(i+1)%n], b) 86 } 87 } 88 89 func TestCannotGetLocedBackend(t *testing.T) { 90 rc, err := NewClient("", newTestBackendFactory(), WithClientMaxBackendPerHost(1)) 91 assert.NoError(t, err) 92 c := rc.(*client) 93 defer func() { 94 assert.NoError(t, c.Close()) 95 }() 96 97 n := 10 98 for i := 0; i < n; i++ { 99 c.mu.backends["b1"] = append(c.mu.backends["b1"], &testBackend{id: i, locked: i == 0, busy: false, activeTime: time.Now()}) 100 } 101 c.mu.ops["b1"] = &op{} 102 103 for i := 0; i < n; i++ { 104 b, err := c.getBackend("b1", false) 105 assert.NoError(t, err) 106 assert.False(t, b.Locked()) 107 } 108 } 109 110 func TestCanGetBackendIfALLLockedAndNotReachMaxPerHost(t *testing.T) { 111 rc, err := NewClient("", newTestBackendFactory(), WithClientMaxBackendPerHost(3)) 112 assert.NoError(t, err) 113 c := rc.(*client) 114 defer func() { 115 assert.NoError(t, c.Close()) 116 }() 117 118 c.mu.backends["b1"] = append(c.mu.backends["b1"], 119 &testBackend{id: 1, locked: true, busy: false, activeTime: time.Now()}, 120 &testBackend{id: 2, locked: true, busy: false, activeTime: time.Now()}) 121 c.mu.ops["b1"] = &op{} 122 123 b, err := c.getBackend("b1", false) 124 assert.NoError(t, err) 125 assert.False(t, b.Locked()) 126 } 127 128 func TestMaybeCreateLockedWithEmptyBackends(t *testing.T) { 129 rc, err := NewClient("", 130 newTestBackendFactory(), 131 WithClientMaxBackendPerHost(1), 132 WithClientEnableAutoCreateBackend()) 133 assert.NoError(t, err) 134 c := rc.(*client) 135 defer func() { 136 assert.NoError(t, c.Close()) 137 }() 138 139 assert.True(t, c.maybeCreateLocked("b1")) 140 } 141 142 func TestMaybeCreateLockedWithNotFullBackendsAndHasAnyBusy(t *testing.T) { 143 rc, err := NewClient("", 144 newTestBackendFactory(), 145 WithClientMaxBackendPerHost(3), 146 WithClientEnableAutoCreateBackend()) 147 assert.NoError(t, err) 148 c := rc.(*client) 149 defer func() { 150 assert.NoError(t, c.Close()) 151 }() 152 c.mu.backends["b1"] = []Backend{ 153 &testBackend{busy: false}, 154 &testBackend{busy: true}, 155 } 156 assert.True(t, c.maybeCreateLocked("b1")) 157 } 158 159 func TestMaybeCreateLockedWithNotFullBackendsAndNoBusy(t *testing.T) { 160 rc, err := NewClient("", newTestBackendFactory(), WithClientMaxBackendPerHost(3)) 161 assert.NoError(t, err) 162 c := rc.(*client) 163 defer func() { 164 assert.NoError(t, c.Close()) 165 }() 166 c.mu.backends["b1"] = []Backend{ 167 &testBackend{busy: false}, 168 } 169 assert.False(t, c.maybeCreateLocked("b1")) 170 } 171 172 func TestMaybeCreateLockedWithFullBackends(t *testing.T) { 173 rc, err := NewClient("", 174 newTestBackendFactory(), 175 WithClientMaxBackendPerHost(1), 176 WithClientEnableAutoCreateBackend()) 177 assert.NoError(t, err) 178 c := rc.(*client) 179 defer func() { 180 assert.NoError(t, c.Close()) 181 }() 182 c.mu.backends["b1"] = []Backend{ 183 &testBackend{busy: false}, 184 } 185 assert.False(t, c.maybeCreateLocked("b1")) 186 } 187 188 func TestInitBackendsAndMaxBackendsPerHostNotMatch(t *testing.T) { 189 rc, err := NewClient( 190 "", 191 newTestBackendFactory(), 192 WithClientCreateTaskChanSize(2), 193 WithClientInitBackends([]string{"b1", "b2"}, []int{3, 1})) 194 assert.NoError(t, err) 195 c := rc.(*client) 196 defer func() { 197 assert.NoError(t, c.Close()) 198 }() 199 200 assert.Equal(t, 3, c.options.maxBackendsPerHost) 201 } 202 203 func TestGetBackendWithCreateBackend(t *testing.T) { 204 rc, err := NewClient( 205 "", 206 newTestBackendFactory(), 207 WithClientCreateTaskChanSize(1)) 208 assert.NoError(t, err) 209 c := rc.(*client) 210 defer func() { 211 assert.NoError(t, c.Close()) 212 }() 213 214 b, err := c.getBackend("b1", false) 215 assert.NoError(t, err) 216 assert.NotNil(t, b) 217 assert.Equal(t, 1, len(c.mu.backends["b1"])) 218 } 219 220 func TestCloseIdleBackends(t *testing.T) { 221 rc, err := NewClient( 222 "", 223 newTestBackendFactory(), 224 WithClientMaxBackendPerHost(2), 225 WithClientMaxBackendMaxIdleDuration(time.Millisecond*100), 226 WithClientCreateTaskChanSize(1), 227 WithClientEnableAutoCreateBackend()) 228 assert.NoError(t, err) 229 c := rc.(*client) 230 defer func() { 231 assert.NoError(t, c.Close()) 232 }() 233 234 b, err := c.getBackend("b1", false) 235 assert.NoError(t, err) 236 assert.NotNil(t, b) 237 b.(*testBackend).busy = true 238 239 _, err = c.getBackend("b1", false) 240 assert.NoError(t, err) 241 for { 242 c.mu.Lock() 243 v := len(c.mu.backends["b1"]) 244 c.mu.Unlock() 245 if v == 2 { 246 break 247 } 248 time.Sleep(time.Millisecond * 10) 249 } 250 251 b, err = c.getBackend("b1", false) 252 assert.NoError(t, err) 253 assert.NotNil(t, b) 254 255 b2, err := c.getBackend("b1", false) 256 assert.NoError(t, err) 257 assert.NotNil(t, b2) 258 assert.NotEqual(t, b, b2) 259 260 go func() { 261 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 262 defer cancel() 263 st, err := b2.NewStream(false) 264 assert.NoError(t, err) 265 for { 266 assert.NoError(t, st.Send(ctx, newTestMessage(1))) 267 time.Sleep(time.Millisecond * 10) 268 } 269 }() 270 271 for { 272 c.mu.Lock() 273 v := len(c.mu.backends["b1"]) 274 c.mu.Unlock() 275 if v == 1 { 276 tb := b.(*testBackend) 277 tb.RLock() 278 closed := tb.closed 279 tb.RUnlock() 280 if closed { 281 tb2 := b2.(*testBackend) 282 tb2.RLock() 283 assert.False(t, tb2.closed) 284 tb2.RUnlock() 285 286 c.mu.Lock() 287 assert.Equal(t, 1, len(c.mu.backends["b1"])) 288 c.mu.Unlock() 289 return 290 } 291 } 292 time.Sleep(time.Millisecond * 10) 293 } 294 } 295 296 func TestLockedBackendCannotClosedWithGCIdleTask(t *testing.T) { 297 rc, err := NewClient( 298 "", 299 newTestBackendFactory(), 300 WithClientMaxBackendPerHost(2), 301 WithClientMaxBackendMaxIdleDuration(time.Millisecond*100), 302 WithClientCreateTaskChanSize(1)) 303 assert.NoError(t, err) 304 c := rc.(*client) 305 defer func() { 306 assert.NoError(t, c.Close()) 307 }() 308 309 b, err := c.getBackend("b1", true) 310 assert.NoError(t, err) 311 assert.NotNil(t, b) 312 assert.True(t, b.Locked()) 313 b.(*testBackend).RWMutex.Lock() 314 b.(*testBackend).activeTime = time.Time{} 315 b.(*testBackend).RWMutex.Unlock() 316 317 time.Sleep(time.Second * 1) 318 c.mu.Lock() 319 assert.Equal(t, 1, len(c.mu.backends["b1"])) 320 c.mu.Unlock() 321 } 322 323 func TestGetBackendsWithAllInactiveAndWillCreateNew(t *testing.T) { 324 rc, err := NewClient( 325 "", 326 newTestBackendFactory(), 327 WithClientMaxBackendPerHost(1), 328 WithClientCreateTaskChanSize(1)) 329 assert.NoError(t, err) 330 c := rc.(*client) 331 defer func() { 332 assert.NoError(t, c.Close()) 333 }() 334 335 b, err := c.getBackend("b1", false) 336 assert.NoError(t, err) 337 assert.NotNil(t, b) 338 339 b.(*testBackend).activeTime = time.Time{} 340 b, _ = c.getBackend("b1", false) 341 assert.Nil(t, b) 342 343 for { 344 b, err := c.getBackend("b1", false) 345 if err == nil { 346 assert.NotNil(t, b) 347 return 348 } 349 } 350 }