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.

218 lines
4.0 KiB

  1. package clist
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "runtime"
  6. "sync/atomic"
  7. "testing"
  8. "time"
  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. func _TestGCFifo(t *testing.T) {
  48. const numElements = 1000000
  49. l := New()
  50. gcCount := new(uint64)
  51. // SetFinalizer doesn't work well with circular structures,
  52. // so we construct a trivial non-circular structure to
  53. // track.
  54. type value struct {
  55. Int int
  56. }
  57. done := make(chan struct{})
  58. for i := 0; i < numElements; i++ {
  59. v := new(value)
  60. v.Int = i
  61. l.PushBack(v)
  62. runtime.SetFinalizer(v, func(v *value) {
  63. atomic.AddUint64(gcCount, 1)
  64. })
  65. }
  66. for el := l.Front(); el != nil; {
  67. l.Remove(el)
  68. //oldEl := el
  69. el = el.Next()
  70. //oldEl.DetachPrev()
  71. //oldEl.DetachNext()
  72. }
  73. runtime.GC()
  74. time.Sleep(time.Second * 3)
  75. runtime.GC()
  76. time.Sleep(time.Second * 3)
  77. _ = done
  78. if *gcCount != numElements {
  79. t.Errorf("Expected gcCount to be %v, got %v", numElements,
  80. *gcCount)
  81. }
  82. }
  83. /*
  84. This test is quite hacky because it relies on SetFinalizer
  85. which isn't guaranteed to run at all.
  86. */
  87. func _TestGCRandom(t *testing.T) {
  88. const numElements = 1000000
  89. l := New()
  90. gcCount := 0
  91. // SetFinalizer doesn't work well with circular structures,
  92. // so we construct a trivial non-circular structure to
  93. // track.
  94. type value struct {
  95. Int int
  96. }
  97. for i := 0; i < numElements; i++ {
  98. v := new(value)
  99. v.Int = i
  100. l.PushBack(v)
  101. runtime.SetFinalizer(v, func(v *value) {
  102. gcCount += 1
  103. })
  104. }
  105. els := make([]*CElement, 0, numElements)
  106. for el := l.Front(); el != nil; el = el.Next() {
  107. els = append(els, el)
  108. }
  109. for _, i := range rand.Perm(numElements) {
  110. el := els[i]
  111. l.Remove(el)
  112. el = el.Next()
  113. }
  114. runtime.GC()
  115. time.Sleep(time.Second * 3)
  116. if gcCount != numElements {
  117. t.Errorf("Expected gcCount to be %v, got %v", numElements,
  118. gcCount)
  119. }
  120. }
  121. func TestScanRightDeleteRandom(t *testing.T) {
  122. const numElements = 10000
  123. const numTimes = 100000
  124. const numScanners = 10
  125. l := New()
  126. stop := make(chan struct{})
  127. els := make([]*CElement, numElements, numElements)
  128. for i := 0; i < numElements; i++ {
  129. el := l.PushBack(i)
  130. els[i] = el
  131. }
  132. // Launch scanner routines that will rapidly iterate over elements.
  133. for i := 0; i < numScanners; i++ {
  134. go func(scannerID int) {
  135. var el *CElement
  136. restartCounter := 0
  137. counter := 0
  138. FOR_LOOP:
  139. for {
  140. select {
  141. case <-stop:
  142. fmt.Println("stopped")
  143. break FOR_LOOP
  144. default:
  145. }
  146. if el == nil {
  147. el = l.FrontWait()
  148. restartCounter += 1
  149. }
  150. el = el.Next()
  151. counter += 1
  152. }
  153. fmt.Printf("Scanner %v restartCounter: %v counter: %v\n", scannerID, restartCounter, counter)
  154. }(i)
  155. }
  156. // Remove an element, push back an element.
  157. for i := 0; i < numTimes; i++ {
  158. // Pick an element to remove
  159. rmElIdx := rand.Intn(len(els))
  160. rmEl := els[rmElIdx]
  161. // Remove it
  162. l.Remove(rmEl)
  163. //fmt.Print(".")
  164. // Insert a new element
  165. newEl := l.PushBack(-1*i - 1)
  166. els[rmElIdx] = newEl
  167. if i%100000 == 0 {
  168. fmt.Printf("Pushed %vK elements so far...\n", i/1000)
  169. }
  170. }
  171. // Stop scanners
  172. close(stop)
  173. time.Sleep(time.Second * 1)
  174. // And remove all the elements.
  175. for el := l.Front(); el != nil; el = el.Next() {
  176. l.Remove(el)
  177. }
  178. if l.Len() != 0 {
  179. t.Fatal("Failed to remove all elements from CList")
  180. }
  181. }