github.com/songzhibin97/gkit@v1.2.13/container/pool/list_test.go (about) 1 package pool 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 type shutdown struct{} 12 13 func (c *shutdown) Shutdown() error { 14 return nil 15 } 16 17 type connection struct { 18 c IShutdown 19 pool Pool 20 } 21 22 func (c *connection) HandleQuick() { 23 // time.Sleep(1 * time.Millisecond) 24 } 25 26 func (c *connection) HandleNormal() { 27 time.Sleep(20 * time.Millisecond) 28 } 29 30 func (c *connection) HandleSlow() { 31 time.Sleep(500 * time.Millisecond) 32 } 33 34 func (c *connection) Shutdown() error { 35 return c.pool.Put(context.Background(), c.c, false) 36 } 37 38 func TestListGetPut(t *testing.T) { 39 pool := NewList(SetActive(1), SetIdle(1), SetIdleTimeout(90*time.Second), SetWait(false, 10*time.Millisecond)) 40 pool.New(func(ctx context.Context) (IShutdown, error) { 41 return &shutdown{}, nil 42 }) 43 44 // test Get Put 45 conn, err := pool.Get(context.TODO()) 46 assert.Nil(t, err) 47 c1 := connection{pool: pool, c: conn} 48 c1.HandleNormal() 49 _ = c1.Shutdown() 50 } 51 52 func TestListPut(t *testing.T) { 53 id := 0 54 type connID struct { 55 IShutdown 56 id int 57 } 58 pool := NewList(SetActive(1), SetIdle(1), SetIdleTimeout(1*time.Second)) 59 pool.New(func(ctx context.Context) (IShutdown, error) { 60 id = id + 1 61 return &connID{ 62 IShutdown: &shutdown{}, 63 id: id, 64 }, nil 65 }) 66 67 // test Put(ctx, conn, true) 68 conn, err := pool.Get(context.TODO()) 69 assert.Nil(t, err) 70 conn1 := conn.(*connID) 71 // Put(ctx, conn, true) drop the connection. 72 _ = pool.Put(context.TODO(), conn, true) 73 conn, err = pool.Get(context.TODO()) 74 75 assert.Nil(t, err) 76 conn2 := conn.(*connID) 77 assert.NotEqual(t, conn1.id, conn2.id) 78 } 79 80 func TestListIdleTimeout(t *testing.T) { 81 id := 0 82 type connID struct { 83 IShutdown 84 id int 85 } 86 pool := NewList(SetActive(1), SetIdle(1), SetIdleTimeout(1*time.Millisecond)) 87 pool.New(func(ctx context.Context) (IShutdown, error) { 88 id = id + 1 89 return &connID{id: id, IShutdown: &shutdown{}}, nil 90 }) 91 // test Put(ctx, conn, true) 92 conn, err := pool.Get(context.TODO()) 93 94 assert.Nil(t, err) 95 conn1 := conn.(*connID) 96 // Put(ctx, conn, true) drop the connection. 97 _ = pool.Put(context.TODO(), conn, false) 98 time.Sleep(5 * time.Millisecond) 99 // idletimeout and get new conn 100 conn, err = pool.Get(context.TODO()) 101 102 assert.Nil(t, err) 103 conn2 := conn.(*connID) 104 105 assert.NotEqual(t, conn1.id, conn2.id) 106 } 107 108 func TestListContextTimeout(t *testing.T) { 109 // new pool 110 pool := NewList(SetActive(1), SetIdle(1), SetIdleTimeout(90*time.Second), SetWait(false, 10*time.Millisecond)) 111 pool.New(func(ctx context.Context) (IShutdown, error) { 112 return &shutdown{}, nil 113 }) 114 // test context timeout 115 ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond) 116 defer cancel() 117 conn, err := pool.Get(ctx) 118 119 assert.Nil(t, err) 120 _, err = pool.Get(ctx) 121 // context timeout error 122 assert.NotNil(t, err) 123 _ = pool.Put(context.TODO(), conn, false) 124 _, err = pool.Get(ctx) 125 assert.Nil(t, err) 126 } 127 128 func TestListPoolExhausted(t *testing.T) { 129 // test pool exhausted 130 131 pool := NewList(SetActive(1), SetIdle(1), SetIdleTimeout(90*time.Second)) 132 pool.New(func(ctx context.Context) (IShutdown, error) { 133 return &shutdown{}, nil 134 }) 135 136 ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond) 137 defer cancel() 138 conn, err := pool.Get(context.TODO()) 139 assert.Nil(t, err) 140 _, err = pool.Get(ctx) 141 // config active == 1, so no available conns make connection exhausted. 142 assert.NotNil(t, err) 143 _ = pool.Put(context.TODO(), conn, false) 144 _, err = pool.Get(ctx) 145 assert.Nil(t, err) 146 } 147 148 func TestListStaleClean(t *testing.T) { 149 id := 0 150 type connID struct { 151 IShutdown 152 id int 153 } 154 pool := NewList(SetActive(1), SetIdle(1), SetIdleTimeout(1*time.Second)) 155 pool.New(func(ctx context.Context) (IShutdown, error) { 156 id = id + 1 157 return &connID{id: id, IShutdown: &shutdown{}}, nil 158 }) 159 conn, err := pool.Get(context.TODO()) 160 assert.Nil(t, err) 161 conn1 := conn.(*connID) 162 _ = pool.Put(context.TODO(), conn, false) 163 conn, err = pool.Get(context.TODO()) 164 assert.Nil(t, err) 165 conn2 := conn.(*connID) 166 assert.Equal(t, conn1.id, conn2.id) 167 _ = pool.Put(context.TODO(), conn, false) 168 // sleep more than idleTimeout 169 time.Sleep(2 * time.Second) 170 conn, err = pool.Get(context.TODO()) 171 assert.Nil(t, err) 172 conn3 := conn.(*connID) 173 assert.NotEqual(t, conn1.id, conn3.id) 174 } 175 176 func BenchmarkList(b *testing.B) { 177 pool := NewList(SetActive(30), SetIdle(30), SetIdleTimeout(90*time.Second), SetWait(false, 10*time.Millisecond)) 178 pool.New(func(ctx context.Context) (IShutdown, error) { 179 return &shutdown{}, nil 180 }) 181 for i := 0; i < b.N; i++ { 182 conn, err := pool.Get(context.TODO()) 183 if err != nil { 184 b.Error(err) 185 continue 186 } 187 c1 := connection{pool: pool, c: conn} 188 c1.HandleQuick() 189 _ = pool.Put(context.TODO(), conn, false) 190 } 191 } 192 193 func BenchmarkList1(b *testing.B) { 194 pool := NewList(SetActive(30), SetIdle(30), SetIdleTimeout(90*time.Second), SetWait(false, 10*time.Millisecond)) 195 pool.New(func(ctx context.Context) (IShutdown, error) { 196 return &shutdown{}, nil 197 }) 198 199 b.ResetTimer() 200 b.RunParallel(func(pb *testing.PB) { 201 for pb.Next() { 202 conn, err := pool.Get(context.TODO()) 203 if err != nil { 204 b.Error(err) 205 continue 206 } 207 c1 := connection{pool: pool, c: conn} 208 c1.HandleQuick() 209 _ = c1.Shutdown() 210 } 211 }) 212 } 213 214 func BenchmarkList2(b *testing.B) { 215 pool := NewList(SetActive(30), SetIdle(30), SetIdleTimeout(90*time.Second), SetWait(false, 10*time.Millisecond)) 216 pool.New(func(ctx context.Context) (IShutdown, error) { 217 return &shutdown{}, nil 218 }) 219 220 b.ResetTimer() 221 b.RunParallel(func(pb *testing.PB) { 222 for pb.Next() { 223 conn, err := pool.Get(context.TODO()) 224 if err != nil { 225 b.Error(err) 226 continue 227 } 228 c1 := connection{pool: pool, c: conn} 229 c1.HandleNormal() 230 _ = c1.Shutdown() 231 } 232 }) 233 } 234 235 func BenchmarkPool3(b *testing.B) { 236 pool := NewList(SetActive(30), SetIdle(30), SetIdleTimeout(90*time.Second), SetWait(false, 10*time.Millisecond)) 237 pool.New(func(ctx context.Context) (IShutdown, error) { 238 return &shutdown{}, nil 239 }) 240 241 b.ResetTimer() 242 b.RunParallel(func(pb *testing.PB) { 243 for pb.Next() { 244 conn, err := pool.Get(context.TODO()) 245 if err != nil { 246 b.Error(err) 247 continue 248 } 249 c1 := connection{pool: pool, c: conn} 250 c1.HandleSlow() 251 _ = c1.Shutdown() 252 } 253 }) 254 } 255 256 func BenchmarkList4(b *testing.B) { 257 pool := NewList(SetActive(30), SetIdle(30), SetIdleTimeout(90*time.Second)) 258 pool.New(func(ctx context.Context) (IShutdown, error) { 259 return &shutdown{}, nil 260 }) 261 262 b.ResetTimer() 263 b.RunParallel(func(pb *testing.PB) { 264 for pb.Next() { 265 conn, err := pool.Get(context.TODO()) 266 if err != nil { 267 b.Error(err) 268 continue 269 } 270 c1 := connection{pool: pool, c: conn} 271 c1.HandleSlow() 272 _ = c1.Shutdown() 273 } 274 }) 275 } 276 277 func BenchmarkList5(b *testing.B) { 278 pool := NewList(SetActive(30), SetIdle(30), SetIdleTimeout(90*time.Second)) 279 pool.New(func(ctx context.Context) (IShutdown, error) { 280 return &shutdown{}, nil 281 }) 282 283 b.ResetTimer() 284 b.RunParallel(func(pb *testing.PB) { 285 for pb.Next() { 286 conn, err := pool.Get(context.TODO()) 287 if err != nil { 288 b.Error(err) 289 continue 290 } 291 c1 := connection{pool: pool, c: conn} 292 c1.HandleSlow() 293 _ = c1.Shutdown() 294 } 295 }) 296 }