github.com/matrixorigin/matrixone@v0.7.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(newTestBackendFactory(), WithClientMaxBackendPerHost(1)) 130 assert.NoError(t, err) 131 c := rc.(*client) 132 defer func() { 133 assert.NoError(t, c.Close()) 134 }() 135 136 assert.True(t, c.maybeCreateLocked("b1")) 137 } 138 139 func TestMaybeCreateLockedWithNotFullBackendsAndHasAnyBusy(t *testing.T) { 140 rc, err := NewClient(newTestBackendFactory(), WithClientMaxBackendPerHost(3)) 141 assert.NoError(t, err) 142 c := rc.(*client) 143 defer func() { 144 assert.NoError(t, c.Close()) 145 }() 146 c.mu.backends["b1"] = []Backend{ 147 &testBackend{busy: false}, 148 &testBackend{busy: true}, 149 } 150 assert.True(t, c.maybeCreateLocked("b1")) 151 } 152 153 func TestMaybeCreateLockedWithNotFullBackendsAndNoBusy(t *testing.T) { 154 rc, err := NewClient(newTestBackendFactory(), WithClientMaxBackendPerHost(3)) 155 assert.NoError(t, err) 156 c := rc.(*client) 157 defer func() { 158 assert.NoError(t, c.Close()) 159 }() 160 c.mu.backends["b1"] = []Backend{ 161 &testBackend{busy: false}, 162 } 163 assert.False(t, c.maybeCreateLocked("b1")) 164 } 165 166 func TestMaybeCreateLockedWithFullBackends(t *testing.T) { 167 rc, err := NewClient(newTestBackendFactory(), WithClientMaxBackendPerHost(1)) 168 assert.NoError(t, err) 169 c := rc.(*client) 170 defer func() { 171 assert.NoError(t, c.Close()) 172 }() 173 c.mu.backends["b1"] = []Backend{ 174 &testBackend{busy: false}, 175 } 176 assert.False(t, c.maybeCreateLocked("b1")) 177 } 178 179 func TestInitBackendsAndMaxBackendsPerHostNotMatch(t *testing.T) { 180 rc, err := NewClient(newTestBackendFactory(), 181 WithClientCreateTaskChanSize(2), 182 WithClientInitBackends([]string{"b1", "b2"}, []int{3, 1})) 183 assert.NoError(t, err) 184 c := rc.(*client) 185 defer func() { 186 assert.NoError(t, c.Close()) 187 }() 188 189 assert.Equal(t, 3, c.options.maxBackendsPerHost) 190 } 191 192 func TestGetBackendWithCreateBackend(t *testing.T) { 193 rc, err := NewClient(newTestBackendFactory(), 194 WithClientCreateTaskChanSize(1)) 195 assert.NoError(t, err) 196 c := rc.(*client) 197 defer func() { 198 assert.NoError(t, c.Close()) 199 }() 200 201 b, err := c.getBackend("b1", false) 202 assert.NoError(t, err) 203 assert.NotNil(t, b) 204 assert.Equal(t, 1, len(c.mu.backends["b1"])) 205 } 206 207 func TestCloseIdleBackends(t *testing.T) { 208 rc, err := NewClient(newTestBackendFactory(), 209 WithClientMaxBackendPerHost(2), 210 WithClientMaxBackendMaxIdleDuration(time.Millisecond*100), 211 WithClientCreateTaskChanSize(1)) 212 assert.NoError(t, err) 213 c := rc.(*client) 214 defer func() { 215 assert.NoError(t, c.Close()) 216 }() 217 218 b, err := c.getBackend("b1", false) 219 assert.NoError(t, err) 220 assert.NotNil(t, b) 221 b.(*testBackend).busy = true 222 223 _, err = c.getBackend("b1", false) 224 assert.NoError(t, err) 225 for { 226 c.mu.Lock() 227 v := len(c.mu.backends["b1"]) 228 c.mu.Unlock() 229 if v == 2 { 230 break 231 } 232 } 233 234 b, err = c.getBackend("b1", false) 235 assert.NoError(t, err) 236 assert.NotNil(t, b) 237 238 b2, err := c.getBackend("b1", false) 239 assert.NoError(t, err) 240 assert.NotNil(t, b2) 241 assert.NotEqual(t, b, b2) 242 243 go func() { 244 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 245 defer cancel() 246 st, err := b2.NewStream(false) 247 assert.NoError(t, err) 248 for { 249 assert.NoError(t, st.Send(ctx, newTestMessage(1))) 250 } 251 }() 252 253 for { 254 c.mu.Lock() 255 v := len(c.mu.backends["b1"]) 256 c.mu.Unlock() 257 if v == 1 { 258 tb := b.(*testBackend) 259 tb.RLock() 260 closed := tb.closed 261 tb.RUnlock() 262 if closed { 263 tb2 := b2.(*testBackend) 264 tb2.RLock() 265 assert.False(t, tb2.closed) 266 tb2.RUnlock() 267 268 c.mu.Lock() 269 assert.Equal(t, 1, len(c.mu.backends["b1"])) 270 c.mu.Unlock() 271 return 272 } 273 } 274 } 275 } 276 277 func TestLockedbackendCannotClosedWithGCIdleTask(t *testing.T) { 278 rc, err := NewClient(newTestBackendFactory(), 279 WithClientMaxBackendPerHost(2), 280 WithClientMaxBackendMaxIdleDuration(time.Millisecond*100), 281 WithClientCreateTaskChanSize(1)) 282 assert.NoError(t, err) 283 c := rc.(*client) 284 defer func() { 285 assert.NoError(t, c.Close()) 286 }() 287 288 b, err := c.getBackend("b1", true) 289 assert.NoError(t, err) 290 assert.NotNil(t, b) 291 assert.True(t, b.Locked()) 292 b.(*testBackend).RWMutex.Lock() 293 b.(*testBackend).activeTime = time.Time{} 294 b.(*testBackend).RWMutex.Unlock() 295 296 time.Sleep(time.Second * 1) 297 c.mu.Lock() 298 assert.Equal(t, 1, len(c.mu.backends["b1"])) 299 c.mu.Unlock() 300 } 301 302 func TestGetBackendsWithAllInactiveAndWillCreateNew(t *testing.T) { 303 rc, err := NewClient(newTestBackendFactory(), 304 WithClientMaxBackendPerHost(1), 305 WithClientCreateTaskChanSize(1)) 306 assert.NoError(t, err) 307 c := rc.(*client) 308 defer func() { 309 assert.NoError(t, c.Close()) 310 }() 311 312 b, err := c.getBackend("b1", false) 313 assert.NoError(t, err) 314 assert.NotNil(t, b) 315 316 b.(*testBackend).activeTime = time.Time{} 317 b, _ = c.getBackend("b1", false) 318 assert.Nil(t, b) 319 320 for { 321 b, err := c.getBackend("b1", false) 322 if err == nil { 323 assert.NotNil(t, b) 324 return 325 } 326 } 327 }