You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
5.4 KiB

  1. package clist
  2. import (
  3. "fmt"
  4. "runtime"
  5. "sync/atomic"
  6. "testing"
  7. "time"
  8. cmn "github.com/tendermint/tendermint/libs/common"
  9. )
  10. func TestSmall(t *testing.T) {
  11. l := New()
  12. el1 := l.PushBack(1)
  13. el2 := l.PushBack(2)
  14. el3 := l.PushBack(3)
  15. if l.Len() != 3 {
  16. t.Error("Expected len 3, got ", l.Len())
  17. }
  18. //fmt.Printf("%p %v\n", el1, el1)
  19. //fmt.Printf("%p %v\n", el2, el2)
  20. //fmt.Printf("%p %v\n", el3, el3)
  21. r1 := l.Remove(el1)
  22. //fmt.Printf("%p %v\n", el1, el1)
  23. //fmt.Printf("%p %v\n", el2, el2)
  24. //fmt.Printf("%p %v\n", el3, el3)
  25. r2 := l.Remove(el2)
  26. //fmt.Printf("%p %v\n", el1, el1)
  27. //fmt.Printf("%p %v\n", el2, el2)
  28. //fmt.Printf("%p %v\n", el3, el3)
  29. r3 := l.Remove(el3)
  30. if r1 != 1 {
  31. t.Error("Expected 1, got ", r1)
  32. }
  33. if r2 != 2 {
  34. t.Error("Expected 2, got ", r2)
  35. }
  36. if r3 != 3 {
  37. t.Error("Expected 3, got ", r3)
  38. }
  39. if l.Len() != 0 {
  40. t.Error("Expected len 0, got ", l.Len())
  41. }
  42. }
  43. /*
  44. This test is quite hacky because it relies on SetFinalizer
  45. which isn't guaranteed to run at all.
  46. */
  47. // nolint: megacheck
  48. func _TestGCFifo(t *testing.T) {
  49. const numElements = 1000000
  50. l := New()
  51. gcCount := new(uint64)
  52. // SetFinalizer doesn't work well with circular structures,
  53. // so we construct a trivial non-circular structure to
  54. // track.
  55. type value struct {
  56. Int int
  57. }
  58. done := make(chan struct{})
  59. for i := 0; i < numElements; i++ {
  60. v := new(value)
  61. v.Int = i
  62. l.PushBack(v)
  63. runtime.SetFinalizer(v, func(v *value) {
  64. atomic.AddUint64(gcCount, 1)
  65. })
  66. }
  67. for el := l.Front(); el != nil; {
  68. l.Remove(el)
  69. //oldEl := el
  70. el = el.Next()
  71. //oldEl.DetachPrev()
  72. //oldEl.DetachNext()
  73. }
  74. runtime.GC()
  75. time.Sleep(time.Second * 3)
  76. runtime.GC()
  77. time.Sleep(time.Second * 3)
  78. _ = done
  79. if *gcCount != numElements {
  80. t.Errorf("Expected gcCount to be %v, got %v", numElements,
  81. *gcCount)
  82. }
  83. }
  84. /*
  85. This test is quite hacky because it relies on SetFinalizer
  86. which isn't guaranteed to run at all.
  87. */
  88. // nolint: megacheck
  89. func _TestGCRandom(t *testing.T) {
  90. const numElements = 1000000
  91. l := New()
  92. gcCount := 0
  93. // SetFinalizer doesn't work well with circular structures,
  94. // so we construct a trivial non-circular structure to
  95. // track.
  96. type value struct {
  97. Int int
  98. }
  99. for i := 0; i < numElements; i++ {
  100. v := new(value)
  101. v.Int = i
  102. l.PushBack(v)
  103. runtime.SetFinalizer(v, func(v *value) {
  104. gcCount++
  105. })
  106. }
  107. els := make([]*CElement, 0, numElements)
  108. for el := l.Front(); el != nil; el = el.Next() {
  109. els = append(els, el)
  110. }
  111. for _, i := range cmn.RandPerm(numElements) {
  112. el := els[i]
  113. l.Remove(el)
  114. _ = el.Next()
  115. }
  116. runtime.GC()
  117. time.Sleep(time.Second * 3)
  118. if gcCount != numElements {
  119. t.Errorf("Expected gcCount to be %v, got %v", numElements,
  120. gcCount)
  121. }
  122. }
  123. func TestScanRightDeleteRandom(t *testing.T) {
  124. const numElements = 10000
  125. const numTimes = 1000
  126. const numScanners = 10
  127. l := New()
  128. stop := make(chan struct{})
  129. els := make([]*CElement, numElements)
  130. for i := 0; i < numElements; i++ {
  131. el := l.PushBack(i)
  132. els[i] = el
  133. }
  134. // Launch scanner routines that will rapidly iterate over elements.
  135. for i := 0; i < numScanners; i++ {
  136. go func(scannerID int) {
  137. var el *CElement
  138. restartCounter := 0
  139. counter := 0
  140. FOR_LOOP:
  141. for {
  142. select {
  143. case <-stop:
  144. fmt.Println("stopped")
  145. break FOR_LOOP
  146. default:
  147. }
  148. if el == nil {
  149. el = l.FrontWait()
  150. restartCounter++
  151. }
  152. el = el.Next()
  153. counter++
  154. }
  155. fmt.Printf("Scanner %v restartCounter: %v counter: %v\n", scannerID, restartCounter, counter)
  156. }(i)
  157. }
  158. // Remove an element, push back an element.
  159. for i := 0; i < numTimes; i++ {
  160. // Pick an element to remove
  161. rmElIdx := cmn.RandIntn(len(els))
  162. rmEl := els[rmElIdx]
  163. // Remove it
  164. l.Remove(rmEl)
  165. //fmt.Print(".")
  166. // Insert a new element
  167. newEl := l.PushBack(-1*i - 1)
  168. els[rmElIdx] = newEl
  169. if i%100000 == 0 {
  170. fmt.Printf("Pushed %vK elements so far...\n", i/1000)
  171. }
  172. }
  173. // Stop scanners
  174. close(stop)
  175. time.Sleep(time.Second * 1)
  176. // And remove all the elements.
  177. for el := l.Front(); el != nil; el = el.Next() {
  178. l.Remove(el)
  179. }
  180. if l.Len() != 0 {
  181. t.Fatal("Failed to remove all elements from CList")
  182. }
  183. }
  184. func TestWaitChan(t *testing.T) {
  185. l := New()
  186. ch := l.WaitChan()
  187. // 1) add one element to an empty list
  188. go l.PushBack(1)
  189. <-ch
  190. // 2) and remove it
  191. el := l.Front()
  192. v := l.Remove(el)
  193. if v != 1 {
  194. t.Fatal("where is 1 coming from?")
  195. }
  196. // 3) test iterating forward and waiting for Next (NextWaitChan and Next)
  197. el = l.PushBack(0)
  198. done := make(chan struct{})
  199. pushed := 0
  200. go func() {
  201. for i := 1; i < 100; i++ {
  202. l.PushBack(i)
  203. pushed++
  204. time.Sleep(time.Duration(cmn.RandIntn(100)) * time.Millisecond)
  205. }
  206. close(done)
  207. }()
  208. next := el
  209. seen := 0
  210. FOR_LOOP:
  211. for {
  212. select {
  213. case <-next.NextWaitChan():
  214. next = next.Next()
  215. seen++
  216. if next == nil {
  217. continue
  218. }
  219. case <-done:
  220. break FOR_LOOP
  221. case <-time.After(10 * time.Second):
  222. t.Fatal("max execution time")
  223. }
  224. }
  225. if pushed != seen {
  226. t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen)
  227. }
  228. // 4) test iterating backwards (PrevWaitChan and Prev)
  229. prev := next
  230. seen = 0
  231. FOR_LOOP2:
  232. for {
  233. select {
  234. case <-prev.PrevWaitChan():
  235. prev = prev.Prev()
  236. seen++
  237. if prev == nil {
  238. t.Fatal("expected PrevWaitChan to block forever on nil when reached first elem")
  239. }
  240. case <-time.After(5 * time.Second):
  241. break FOR_LOOP2
  242. }
  243. }
  244. if pushed != seen {
  245. t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen)
  246. }
  247. }