Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

queue_channel_test.go 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package queue
  4. import (
  5. "sync"
  6. "testing"
  7. "time"
  8. "code.gitea.io/gitea/modules/log"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestChannelQueue(t *testing.T) {
  12. handleChan := make(chan *testData)
  13. handle := func(data ...Data) []Data {
  14. for _, datum := range data {
  15. testDatum := datum.(*testData)
  16. handleChan <- testDatum
  17. }
  18. return nil
  19. }
  20. nilFn := func(_ func()) {}
  21. queue, err := NewChannelQueue(handle,
  22. ChannelQueueConfiguration{
  23. WorkerPoolConfiguration: WorkerPoolConfiguration{
  24. QueueLength: 0,
  25. MaxWorkers: 10,
  26. BlockTimeout: 1 * time.Second,
  27. BoostTimeout: 5 * time.Minute,
  28. BoostWorkers: 5,
  29. Name: "TestChannelQueue",
  30. },
  31. Workers: 0,
  32. }, &testData{})
  33. assert.NoError(t, err)
  34. assert.Equal(t, 5, queue.(*ChannelQueue).WorkerPool.boostWorkers)
  35. go queue.Run(nilFn, nilFn)
  36. test1 := testData{"A", 1}
  37. go queue.Push(&test1)
  38. result1 := <-handleChan
  39. assert.Equal(t, test1.TestString, result1.TestString)
  40. assert.Equal(t, test1.TestInt, result1.TestInt)
  41. err = queue.Push(test1)
  42. assert.Error(t, err)
  43. }
  44. func TestChannelQueue_Batch(t *testing.T) {
  45. handleChan := make(chan *testData)
  46. handle := func(data ...Data) []Data {
  47. assert.True(t, len(data) == 2)
  48. for _, datum := range data {
  49. testDatum := datum.(*testData)
  50. handleChan <- testDatum
  51. }
  52. return nil
  53. }
  54. nilFn := func(_ func()) {}
  55. queue, err := NewChannelQueue(handle,
  56. ChannelQueueConfiguration{
  57. WorkerPoolConfiguration: WorkerPoolConfiguration{
  58. QueueLength: 20,
  59. BatchLength: 2,
  60. BlockTimeout: 0,
  61. BoostTimeout: 0,
  62. BoostWorkers: 0,
  63. MaxWorkers: 10,
  64. },
  65. Workers: 1,
  66. }, &testData{})
  67. assert.NoError(t, err)
  68. go queue.Run(nilFn, nilFn)
  69. test1 := testData{"A", 1}
  70. test2 := testData{"B", 2}
  71. queue.Push(&test1)
  72. go queue.Push(&test2)
  73. result1 := <-handleChan
  74. assert.Equal(t, test1.TestString, result1.TestString)
  75. assert.Equal(t, test1.TestInt, result1.TestInt)
  76. result2 := <-handleChan
  77. assert.Equal(t, test2.TestString, result2.TestString)
  78. assert.Equal(t, test2.TestInt, result2.TestInt)
  79. err = queue.Push(test1)
  80. assert.Error(t, err)
  81. }
  82. func TestChannelQueue_Pause(t *testing.T) {
  83. lock := sync.Mutex{}
  84. var queue Queue
  85. var err error
  86. pushBack := false
  87. handleChan := make(chan *testData)
  88. handle := func(data ...Data) []Data {
  89. lock.Lock()
  90. if pushBack {
  91. if pausable, ok := queue.(Pausable); ok {
  92. pausable.Pause()
  93. }
  94. lock.Unlock()
  95. return data
  96. }
  97. lock.Unlock()
  98. for _, datum := range data {
  99. testDatum := datum.(*testData)
  100. handleChan <- testDatum
  101. }
  102. return nil
  103. }
  104. queueShutdown := []func(){}
  105. queueTerminate := []func(){}
  106. terminated := make(chan struct{})
  107. queue, err = NewChannelQueue(handle,
  108. ChannelQueueConfiguration{
  109. WorkerPoolConfiguration: WorkerPoolConfiguration{
  110. QueueLength: 20,
  111. BatchLength: 1,
  112. BlockTimeout: 0,
  113. BoostTimeout: 0,
  114. BoostWorkers: 0,
  115. MaxWorkers: 10,
  116. },
  117. Workers: 1,
  118. }, &testData{})
  119. assert.NoError(t, err)
  120. go func() {
  121. queue.Run(func(shutdown func()) {
  122. lock.Lock()
  123. defer lock.Unlock()
  124. queueShutdown = append(queueShutdown, shutdown)
  125. }, func(terminate func()) {
  126. lock.Lock()
  127. defer lock.Unlock()
  128. queueTerminate = append(queueTerminate, terminate)
  129. })
  130. close(terminated)
  131. }()
  132. // Shutdown and Terminate in defer
  133. defer func() {
  134. lock.Lock()
  135. callbacks := make([]func(), len(queueShutdown))
  136. copy(callbacks, queueShutdown)
  137. lock.Unlock()
  138. for _, callback := range callbacks {
  139. callback()
  140. }
  141. lock.Lock()
  142. log.Info("Finally terminating")
  143. callbacks = make([]func(), len(queueTerminate))
  144. copy(callbacks, queueTerminate)
  145. lock.Unlock()
  146. for _, callback := range callbacks {
  147. callback()
  148. }
  149. }()
  150. test1 := testData{"A", 1}
  151. test2 := testData{"B", 2}
  152. queue.Push(&test1)
  153. pausable, ok := queue.(Pausable)
  154. if !assert.True(t, ok) {
  155. return
  156. }
  157. result1 := <-handleChan
  158. assert.Equal(t, test1.TestString, result1.TestString)
  159. assert.Equal(t, test1.TestInt, result1.TestInt)
  160. pausable.Pause()
  161. paused, _ := pausable.IsPausedIsResumed()
  162. select {
  163. case <-paused:
  164. case <-time.After(100 * time.Millisecond):
  165. assert.Fail(t, "Queue is not paused")
  166. return
  167. }
  168. queue.Push(&test2)
  169. var result2 *testData
  170. select {
  171. case result2 = <-handleChan:
  172. assert.Fail(t, "handler chan should be empty")
  173. case <-time.After(100 * time.Millisecond):
  174. }
  175. assert.Nil(t, result2)
  176. pausable.Resume()
  177. _, resumed := pausable.IsPausedIsResumed()
  178. select {
  179. case <-resumed:
  180. case <-time.After(100 * time.Millisecond):
  181. assert.Fail(t, "Queue should be resumed")
  182. }
  183. select {
  184. case result2 = <-handleChan:
  185. case <-time.After(500 * time.Millisecond):
  186. assert.Fail(t, "handler chan should contain test2")
  187. }
  188. assert.Equal(t, test2.TestString, result2.TestString)
  189. assert.Equal(t, test2.TestInt, result2.TestInt)
  190. lock.Lock()
  191. pushBack = true
  192. lock.Unlock()
  193. _, resumed = pausable.IsPausedIsResumed()
  194. select {
  195. case <-resumed:
  196. case <-time.After(100 * time.Millisecond):
  197. assert.Fail(t, "Queue is not resumed")
  198. return
  199. }
  200. queue.Push(&test1)
  201. paused, _ = pausable.IsPausedIsResumed()
  202. select {
  203. case <-paused:
  204. case <-handleChan:
  205. assert.Fail(t, "handler chan should not contain test1")
  206. return
  207. case <-time.After(100 * time.Millisecond):
  208. assert.Fail(t, "queue should be paused")
  209. return
  210. }
  211. lock.Lock()
  212. pushBack = false
  213. lock.Unlock()
  214. paused, _ = pausable.IsPausedIsResumed()
  215. select {
  216. case <-paused:
  217. case <-time.After(100 * time.Millisecond):
  218. assert.Fail(t, "Queue is not paused")
  219. return
  220. }
  221. pausable.Resume()
  222. _, resumed = pausable.IsPausedIsResumed()
  223. select {
  224. case <-resumed:
  225. case <-time.After(100 * time.Millisecond):
  226. assert.Fail(t, "Queue should be resumed")
  227. }
  228. select {
  229. case result1 = <-handleChan:
  230. case <-time.After(500 * time.Millisecond):
  231. assert.Fail(t, "handler chan should contain test1")
  232. }
  233. assert.Equal(t, test1.TestString, result1.TestString)
  234. assert.Equal(t, test1.TestInt, result1.TestInt)
  235. lock.Lock()
  236. callbacks := make([]func(), len(queueShutdown))
  237. copy(callbacks, queueShutdown)
  238. queueShutdown = queueShutdown[:0]
  239. lock.Unlock()
  240. // Now shutdown the queue
  241. for _, callback := range callbacks {
  242. callback()
  243. }
  244. // terminate the queue
  245. lock.Lock()
  246. callbacks = make([]func(), len(queueTerminate))
  247. copy(callbacks, queueTerminate)
  248. queueShutdown = queueTerminate[:0]
  249. lock.Unlock()
  250. for _, callback := range callbacks {
  251. callback()
  252. }
  253. select {
  254. case <-terminated:
  255. case <-time.After(10 * time.Second):
  256. assert.Fail(t, "Queue should have terminated")
  257. return
  258. }
  259. }