skiplist_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. package skiplist
  2. import (
  3. "fmt"
  4. "math"
  5. "math/rand"
  6. "testing"
  7. "time"
  8. //"github.com/pkg/profile"
  9. )
  10. const (
  11. maxN = 1000000
  12. )
  13. type Element int
  14. func (e Element) ExtractKey() float64 {
  15. return float64(e)
  16. }
  17. func (e Element) String() string {
  18. return fmt.Sprintf("%03d", e)
  19. }
  20. type FloatElement float64
  21. func (e FloatElement) ExtractKey() float64 {
  22. return float64(e)
  23. }
  24. func (e FloatElement) String() string {
  25. return fmt.Sprintf("%.3f", e)
  26. }
  27. type ComplexElement struct {
  28. E int
  29. S string
  30. }
  31. func (e ComplexElement) ExtractKey() float64 {
  32. return float64(e.E)
  33. }
  34. func (e ComplexElement) String() string {
  35. return fmt.Sprintf("%03d", e.E)
  36. }
  37. // timeTrack will print out the number of nanoseconds since the start time divided by n
  38. // Useful for printing out how long each iteration took in a benchmark
  39. func timeTrack(start time.Time, n int, name string) {
  40. loopNS := time.Since(start).Nanoseconds() / int64(n)
  41. fmt.Printf("%s: %d\n", name, loopNS)
  42. }
  43. func TestInsertAndFind(t *testing.T) {
  44. var list SkipList
  45. var listPointer *SkipList
  46. listPointer.Insert(Element(0))
  47. if _, ok := listPointer.Find(Element(0)); ok {
  48. t.Fail()
  49. }
  50. list = New()
  51. if _, ok := list.Find(Element(0)); ok {
  52. t.Fail()
  53. }
  54. if !list.IsEmpty() {
  55. t.Fail()
  56. }
  57. // Test at the beginning of the list.
  58. for i := 0; i < maxN; i++ {
  59. list.Insert(Element(maxN - i))
  60. }
  61. for i := 0; i < maxN; i++ {
  62. if _, ok := list.Find(Element(maxN - i)); !ok {
  63. t.Fail()
  64. }
  65. }
  66. list = New()
  67. // Test at the end of the list.
  68. for i := 0; i < maxN; i++ {
  69. list.Insert(Element(i))
  70. }
  71. for i := 0; i < maxN; i++ {
  72. if _, ok := list.Find(Element(i)); !ok {
  73. t.Fail()
  74. }
  75. }
  76. list = New()
  77. // Test at random positions in the list.
  78. rList := rand.Perm(maxN)
  79. for _, e := range rList {
  80. list.Insert(Element(e))
  81. }
  82. for _, e := range rList {
  83. if _, ok := list.Find(Element(e)); !ok {
  84. t.Fail()
  85. }
  86. }
  87. }
  88. func TestDelete(t *testing.T) {
  89. var list SkipList
  90. // Delete on empty list
  91. list.Delete(Element(0))
  92. list = New()
  93. list.Delete(Element(0))
  94. if !list.IsEmpty() {
  95. t.Fail()
  96. }
  97. // Delete elements at the beginning of the list.
  98. for i := 0; i < maxN; i++ {
  99. list.Insert(Element(i))
  100. }
  101. for i := 0; i < maxN; i++ {
  102. list.Delete(Element(i))
  103. }
  104. if !list.IsEmpty() {
  105. t.Fail()
  106. }
  107. list = New()
  108. // Delete elements at the end of the list.
  109. for i := 0; i < maxN; i++ {
  110. list.Insert(Element(i))
  111. }
  112. for i := 0; i < maxN; i++ {
  113. list.Delete(Element(maxN - i - 1))
  114. }
  115. if !list.IsEmpty() {
  116. t.Fail()
  117. }
  118. list = New()
  119. // Delete elements at random positions in the list.
  120. rList := rand.Perm(maxN)
  121. for _, e := range rList {
  122. list.Insert(Element(e))
  123. }
  124. for _, e := range rList {
  125. list.Delete(Element(e))
  126. }
  127. if !list.IsEmpty() {
  128. t.Fail()
  129. }
  130. }
  131. func TestFindGreaterOrEqual(t *testing.T) {
  132. eps := 0.00000001
  133. maxNumber := 1000.0
  134. var list SkipList
  135. var listPointer *SkipList
  136. // Test on empty list.
  137. if _, ok := listPointer.FindGreaterOrEqual(FloatElement(0)); ok {
  138. t.Fail()
  139. }
  140. list = NewEps(eps)
  141. for i := 0; i < maxN; i++ {
  142. list.Insert(FloatElement(rand.Float64() * maxNumber))
  143. }
  144. first := float64(list.GetSmallestNode().GetValue().(FloatElement))
  145. // Find the very first element. This is a special case in the implementation that needs testing!
  146. if v, ok := list.FindGreaterOrEqual(FloatElement(first - 2.0*eps)); ok {
  147. // We found an element different to the first one!
  148. if math.Abs(float64(v.GetValue().(FloatElement))-first) > eps {
  149. t.Fail()
  150. }
  151. } else {
  152. // No element found.
  153. t.Fail()
  154. }
  155. for i := 0; i < maxN; i++ {
  156. f := rand.Float64() * maxNumber
  157. if v, ok := list.FindGreaterOrEqual(FloatElement(f)); ok {
  158. // if f is v should be bigger than the element before
  159. lastV := float64(list.Prev(v).GetValue().(FloatElement))
  160. thisV := float64(v.GetValue().(FloatElement))
  161. isFirst := math.Abs(first-thisV) <= eps
  162. if !isFirst && lastV >= f {
  163. fmt.Printf("PrevV: %.8f\n f: %.8f\n\n", lastV, f)
  164. t.Fail()
  165. }
  166. // v should be bigger or equal to f
  167. // If we compare directly, we get an equal key with a difference on the 10th decimal point, which fails.
  168. if f-thisV > eps {
  169. fmt.Printf("f: %.8f\nv: %.8f\n\n", f, thisV)
  170. t.Fail()
  171. }
  172. } else {
  173. lastV := float64(list.GetLargestNode().GetValue().(FloatElement))
  174. // It is OK, to fail, as long as f is bigger than the last element.
  175. if f <= lastV {
  176. fmt.Printf("lastV: %.8f\n f: %.8f\n\n", lastV, f)
  177. t.Fail()
  178. }
  179. }
  180. }
  181. }
  182. func TestPrev(t *testing.T) {
  183. list := New()
  184. for i := 0; i < maxN; i++ {
  185. list.Insert(Element(i))
  186. }
  187. smallest := list.GetSmallestNode()
  188. largest := list.GetLargestNode()
  189. lastNode := largest
  190. node := lastNode
  191. for node != smallest {
  192. node = list.Prev(node)
  193. // Must always be incrementing here!
  194. if node.value.(Element) >= lastNode.value.(Element) {
  195. t.Fail()
  196. }
  197. // Next.Prev must always point to itself!
  198. if list.Prev(list.Next(node)) != node {
  199. t.Fail()
  200. }
  201. lastNode = node
  202. }
  203. if list.Prev(smallest) != largest {
  204. t.Fail()
  205. }
  206. }
  207. func TestNext(t *testing.T) {
  208. list := New()
  209. for i := 0; i < maxN; i++ {
  210. list.Insert(Element(i))
  211. }
  212. smallest := list.GetSmallestNode()
  213. largest := list.GetLargestNode()
  214. lastNode := smallest
  215. node := lastNode
  216. for node != largest {
  217. node = list.Next(node)
  218. // Must always be incrementing here!
  219. if node.value.(Element) <= lastNode.value.(Element) {
  220. t.Fail()
  221. }
  222. // Next.Prev must always point to itself!
  223. if list.Next(list.Prev(node)) != node {
  224. t.Fail()
  225. }
  226. lastNode = node
  227. }
  228. if list.Next(largest) != smallest {
  229. t.Fail()
  230. }
  231. }
  232. func TestChangeValue(t *testing.T) {
  233. list := New()
  234. for i := 0; i < maxN; i++ {
  235. list.Insert(ComplexElement{i, "value"})
  236. }
  237. for i := 0; i < maxN; i++ {
  238. // The key only looks at the int so the string doesn't matter here!
  239. f1, ok := list.Find(ComplexElement{i, ""})
  240. if !ok {
  241. t.Fail()
  242. }
  243. ok = list.ChangeValue(f1, ComplexElement{i, "different value"})
  244. if !ok {
  245. t.Fail()
  246. }
  247. f2, ok := list.Find(ComplexElement{i, ""})
  248. if !ok {
  249. t.Fail()
  250. }
  251. if f2.GetValue().(ComplexElement).S != "different value" {
  252. t.Fail()
  253. }
  254. if ok = list.ChangeValue(f2, ComplexElement{i + 5, "different key"}); ok {
  255. t.Fail()
  256. }
  257. }
  258. }
  259. func TestGetNodeCount(t *testing.T) {
  260. list := New()
  261. for i := 0; i < maxN; i++ {
  262. list.Insert(Element(i))
  263. }
  264. if list.GetNodeCount() != maxN {
  265. t.Fail()
  266. }
  267. }
  268. func TestString(t *testing.T) {
  269. list := NewSeed(1531889620180049576)
  270. for i := 0; i < 20; i++ {
  271. list.Insert(Element(i))
  272. }
  273. testString := ` --> [000] -> [002] -> [009] -> [010]
  274. 000: [---|001]
  275. 001: [000|002]
  276. 002: [001|003] -> [004]
  277. 003: [002|004]
  278. 004: [003|005] -> [005]
  279. 005: [004|006] -> [009]
  280. 006: [005|007]
  281. 007: [006|008]
  282. 008: [007|009]
  283. 009: [008|010] -> [010] -> [010]
  284. 010: [009|011] -> [012] -> [---] -> [---]
  285. 011: [010|012]
  286. 012: [011|013] -> [013]
  287. 013: [012|014] -> [---]
  288. 014: [013|015]
  289. 015: [014|016]
  290. 016: [015|017]
  291. 017: [016|018]
  292. 018: [017|019]
  293. 019: [018|---]
  294. --> [019] -> [013] -> [010] -> [010]
  295. `
  296. if list.String() != testString {
  297. t.Fail()
  298. }
  299. }
  300. func TestInfiniteLoop(t *testing.T) {
  301. list := New()
  302. list.Insert(Element(1))
  303. if _, ok := list.Find(Element(2)); ok {
  304. t.Fail()
  305. }
  306. if _, ok := list.FindGreaterOrEqual(Element(2)); ok {
  307. t.Fail()
  308. }
  309. }