slice_test.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. type closer struct {
  11. }
  12. func (c *closer) Close() error {
  13. return nil
  14. }
  15. type connection struct {
  16. c io.Closer
  17. pool Pool
  18. }
  19. func (c *connection) HandleQuick() {
  20. // time.Sleep(1 * time.Millisecond)
  21. }
  22. func (c *connection) HandleNormal() {
  23. time.Sleep(20 * time.Millisecond)
  24. }
  25. func (c *connection) HandleSlow() {
  26. time.Sleep(500 * time.Millisecond)
  27. }
  28. func (c *connection) Close() {
  29. c.pool.Put(context.Background(), c.c, false)
  30. }
  31. func TestSliceGetPut(t *testing.T) {
  32. // new pool
  33. config := &Config{
  34. Active: 1,
  35. Idle: 1,
  36. IdleTimeout: xtime.Duration(90 * time.Second),
  37. WaitTimeout: xtime.Duration(10 * time.Millisecond),
  38. Wait: false,
  39. }
  40. pool := NewSlice(config)
  41. pool.New = func(ctx context.Context) (io.Closer, error) {
  42. return &closer{}, nil
  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.Close()
  50. }
  51. func TestSlicePut(t *testing.T) {
  52. var id = 0
  53. type connID struct {
  54. io.Closer
  55. id int
  56. }
  57. config := &Config{
  58. Active: 1,
  59. Idle: 1,
  60. IdleTimeout: xtime.Duration(1 * time.Second),
  61. // WaitTimeout: xtime.Duration(10 * time.Millisecond),
  62. Wait: false,
  63. }
  64. pool := NewSlice(config)
  65. pool.New = func(ctx context.Context) (io.Closer, error) {
  66. id = id + 1
  67. return &connID{id: id, Closer: &closer{}}, nil
  68. }
  69. // test Put(ctx, conn, true)
  70. conn, err := pool.Get(context.TODO())
  71. assert.Nil(t, err)
  72. conn1 := conn.(*connID)
  73. // Put(ctx, conn, true) drop the connection.
  74. pool.Put(context.TODO(), conn, true)
  75. conn, err = pool.Get(context.TODO())
  76. assert.Nil(t, err)
  77. conn2 := conn.(*connID)
  78. assert.NotEqual(t, conn1.id, conn2.id)
  79. }
  80. func TestSliceIdleTimeout(t *testing.T) {
  81. var id = 0
  82. type connID struct {
  83. io.Closer
  84. id int
  85. }
  86. config := &Config{
  87. Active: 1,
  88. Idle: 1,
  89. // conn timeout
  90. IdleTimeout: xtime.Duration(1 * time.Millisecond),
  91. }
  92. pool := NewSlice(config)
  93. pool.New = func(ctx context.Context) (io.Closer, error) {
  94. id = id + 1
  95. return &connID{id: id, Closer: &closer{}}, nil
  96. }
  97. // test Put(ctx, conn, true)
  98. conn, err := pool.Get(context.TODO())
  99. assert.Nil(t, err)
  100. conn1 := conn.(*connID)
  101. // Put(ctx, conn, true) drop the connection.
  102. pool.Put(context.TODO(), conn, false)
  103. time.Sleep(5 * time.Millisecond)
  104. // idletimeout and get new conn
  105. conn, err = pool.Get(context.TODO())
  106. assert.Nil(t, err)
  107. conn2 := conn.(*connID)
  108. assert.NotEqual(t, conn1.id, conn2.id)
  109. }
  110. func TestSliceContextTimeout(t *testing.T) {
  111. // new pool
  112. config := &Config{
  113. Active: 1,
  114. Idle: 1,
  115. IdleTimeout: xtime.Duration(90 * time.Second),
  116. WaitTimeout: xtime.Duration(10 * time.Millisecond),
  117. Wait: false,
  118. }
  119. pool := NewSlice(config)
  120. pool.New = func(ctx context.Context) (io.Closer, error) {
  121. return &closer{}, nil
  122. }
  123. // test context timeout
  124. ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond)
  125. defer cancel()
  126. conn, err := pool.Get(ctx)
  127. assert.Nil(t, err)
  128. _, err = pool.Get(ctx)
  129. // context timeout error
  130. assert.NotNil(t, err)
  131. pool.Put(context.TODO(), conn, false)
  132. _, err = pool.Get(ctx)
  133. assert.Nil(t, err)
  134. }
  135. func TestSlicePoolExhausted(t *testing.T) {
  136. // test pool exhausted
  137. config := &Config{
  138. Active: 1,
  139. Idle: 1,
  140. IdleTimeout: xtime.Duration(90 * time.Second),
  141. // WaitTimeout: xtime.Duration(10 * time.Millisecond),
  142. Wait: false,
  143. }
  144. pool := NewSlice(config)
  145. pool.New = func(ctx context.Context) (io.Closer, error) {
  146. return &closer{}, nil
  147. }
  148. ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond)
  149. defer cancel()
  150. conn, err := pool.Get(context.TODO())
  151. assert.Nil(t, err)
  152. _, err = pool.Get(ctx)
  153. // config active == 1, so no avaliable conns make connection exhausted.
  154. assert.NotNil(t, err)
  155. pool.Put(context.TODO(), conn, false)
  156. _, err = pool.Get(ctx)
  157. assert.Nil(t, err)
  158. }
  159. func TestSliceStaleClean(t *testing.T) {
  160. var id = 0
  161. type connID struct {
  162. io.Closer
  163. id int
  164. }
  165. config := &Config{
  166. Active: 1,
  167. Idle: 1,
  168. IdleTimeout: xtime.Duration(1 * time.Second),
  169. // WaitTimeout: xtime.Duration(10 * time.Millisecond),
  170. Wait: false,
  171. }
  172. pool := NewList(config)
  173. pool.New = func(ctx context.Context) (io.Closer, error) {
  174. id = id + 1
  175. return &connID{id: id, Closer: &closer{}}, nil
  176. }
  177. conn, err := pool.Get(context.TODO())
  178. assert.Nil(t, err)
  179. conn1 := conn.(*connID)
  180. pool.Put(context.TODO(), conn, false)
  181. conn, err = pool.Get(context.TODO())
  182. assert.Nil(t, err)
  183. conn2 := conn.(*connID)
  184. assert.Equal(t, conn1.id, conn2.id)
  185. pool.Put(context.TODO(), conn, false)
  186. // sleep more than idleTimeout
  187. time.Sleep(2 * time.Second)
  188. conn, err = pool.Get(context.TODO())
  189. assert.Nil(t, err)
  190. conn3 := conn.(*connID)
  191. assert.NotEqual(t, conn1.id, conn3.id)
  192. }
  193. func BenchmarkSlice1(b *testing.B) {
  194. config := &Config{
  195. Active: 30,
  196. Idle: 30,
  197. IdleTimeout: xtime.Duration(90 * time.Second),
  198. WaitTimeout: xtime.Duration(10 * time.Millisecond),
  199. Wait: false,
  200. }
  201. pool := NewSlice(config)
  202. pool.New = func(ctx context.Context) (io.Closer, error) {
  203. return &closer{}, nil
  204. }
  205. b.ResetTimer()
  206. b.RunParallel(func(pb *testing.PB) {
  207. for pb.Next() {
  208. conn, err := pool.Get(context.TODO())
  209. if err != nil {
  210. b.Error(err)
  211. continue
  212. }
  213. c1 := connection{pool: pool, c: conn}
  214. c1.HandleQuick()
  215. c1.Close()
  216. }
  217. })
  218. }
  219. func BenchmarkSlice2(b *testing.B) {
  220. config := &Config{
  221. Active: 30,
  222. Idle: 30,
  223. IdleTimeout: xtime.Duration(90 * time.Second),
  224. WaitTimeout: xtime.Duration(10 * time.Millisecond),
  225. Wait: false,
  226. }
  227. pool := NewSlice(config)
  228. pool.New = func(ctx context.Context) (io.Closer, error) {
  229. return &closer{}, nil
  230. }
  231. b.ResetTimer()
  232. b.RunParallel(func(pb *testing.PB) {
  233. for pb.Next() {
  234. conn, err := pool.Get(context.TODO())
  235. if err != nil {
  236. b.Error(err)
  237. continue
  238. }
  239. c1 := connection{pool: pool, c: conn}
  240. c1.HandleNormal()
  241. c1.Close()
  242. }
  243. })
  244. }
  245. func BenchmarkSlice3(b *testing.B) {
  246. config := &Config{
  247. Active: 30,
  248. Idle: 30,
  249. IdleTimeout: xtime.Duration(90 * time.Second),
  250. WaitTimeout: xtime.Duration(10 * time.Millisecond),
  251. Wait: false,
  252. }
  253. pool := NewSlice(config)
  254. pool.New = func(ctx context.Context) (io.Closer, error) {
  255. return &closer{}, nil
  256. }
  257. b.ResetTimer()
  258. b.RunParallel(func(pb *testing.PB) {
  259. for pb.Next() {
  260. conn, err := pool.Get(context.TODO())
  261. if err != nil {
  262. b.Error(err)
  263. continue
  264. }
  265. c1 := connection{pool: pool, c: conn}
  266. c1.HandleSlow()
  267. c1.Close()
  268. }
  269. })
  270. }
  271. func BenchmarkSlice4(b *testing.B) {
  272. config := &Config{
  273. Active: 30,
  274. Idle: 30,
  275. IdleTimeout: xtime.Duration(90 * time.Second),
  276. // WaitTimeout: xtime.Duration(10 * time.Millisecond),
  277. Wait: false,
  278. }
  279. pool := NewSlice(config)
  280. pool.New = func(ctx context.Context) (io.Closer, error) {
  281. return &closer{}, nil
  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.Close()
  294. }
  295. })
  296. }
  297. func BenchmarkSlice5(b *testing.B) {
  298. config := &Config{
  299. Active: 30,
  300. Idle: 30,
  301. IdleTimeout: xtime.Duration(90 * time.Second),
  302. // WaitTimeout: xtime.Duration(10 * time.Millisecond),
  303. Wait: true,
  304. }
  305. pool := NewSlice(config)
  306. pool.New = func(ctx context.Context) (io.Closer, error) {
  307. return &closer{}, nil
  308. }
  309. b.ResetTimer()
  310. b.RunParallel(func(pb *testing.PB) {
  311. for pb.Next() {
  312. conn, err := pool.Get(context.TODO())
  313. if err != nil {
  314. b.Error(err)
  315. continue
  316. }
  317. c1 := connection{pool: pool, c: conn}
  318. c1.HandleSlow()
  319. c1.Close()
  320. }
  321. })
  322. }