list_test.go 7.2 KB

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