skiplist_test.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  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() int64 {
  15. return int64(e)
  16. }
  17. func (e Element) String() string {
  18. return fmt.Sprintf("%03d", e)
  19. }
  20. type FloatElement float64
  21. func (e FloatElement) ExtractKey() int64 {
  22. return int64(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() int64 {
  32. return int64(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. t.Run("nil list", func(t *testing.T) {
  45. var listPointer *SkipList
  46. listPointer.Insert(Element(0))
  47. if _, ok := listPointer.Find(Element(0)); ok {
  48. t.Error("should not find element in nil list")
  49. }
  50. })
  51. t.Run("empty list", func(t *testing.T) {
  52. list := New()
  53. if _, ok := list.Find(Element(0)); ok {
  54. t.Error("should not find element in empty list")
  55. }
  56. if !list.IsEmpty() {
  57. t.Error("list should be empty")
  58. }
  59. })
  60. t.Run("sequential insert at beginning", func(t *testing.T) {
  61. list := New()
  62. for i := 0; i < maxN; i++ {
  63. list.Insert(Element(maxN - i))
  64. }
  65. for i := 0; i < maxN; i++ {
  66. if _, ok := list.Find(Element(maxN - i)); !ok {
  67. t.Errorf("failed to find element %d", maxN-i)
  68. }
  69. }
  70. })
  71. t.Run("sequential insert at end", func(t *testing.T) {
  72. list := New()
  73. for i := 0; i < maxN; i++ {
  74. list.Insert(Element(i))
  75. }
  76. for i := 0; i < maxN; i++ {
  77. if _, ok := list.Find(Element(i)); !ok {
  78. t.Errorf("failed to find element %d", i)
  79. }
  80. }
  81. })
  82. t.Run("random insert", func(t *testing.T) {
  83. list := New()
  84. rList := rand.Perm(maxN)
  85. for _, e := range rList {
  86. list.Insert(Element(e))
  87. }
  88. for _, e := range rList {
  89. if _, ok := list.Find(Element(e)); !ok {
  90. t.Errorf("failed to find element %d", e)
  91. }
  92. }
  93. })
  94. t.Run("boundary values", func(t *testing.T) {
  95. list := New()
  96. // Test with min/max int values
  97. list.Insert(Element(math.MinInt64))
  98. list.Insert(Element(math.MaxInt64))
  99. if _, ok := list.Find(Element(math.MinInt64)); !ok {
  100. t.Error("failed to find MinInt64")
  101. }
  102. if _, ok := list.Find(Element(math.MaxInt64)); !ok {
  103. t.Error("failed to find MaxInt64")
  104. }
  105. })
  106. t.Run("duplicate values", func(t *testing.T) {
  107. list := New()
  108. // Insert same value multiple times
  109. for i := 0; i < 10; i++ {
  110. list.Insert(Element(42))
  111. }
  112. // Should be able to find the value
  113. if _, ok := list.Find(Element(42)); !ok {
  114. t.Error("failed to find duplicate value")
  115. }
  116. // Count should reflect all insertions
  117. count := 0
  118. node, _ := list.Find(Element(42))
  119. for node != nil && node.GetKey() == 42 {
  120. count++
  121. node = list.Next(node)
  122. }
  123. if count != 10 {
  124. t.Errorf("expected 10 duplicate values, got %d", count)
  125. }
  126. })
  127. }
  128. func TestDelete(t *testing.T) {
  129. var list SkipList
  130. // Delete on empty list
  131. list.Delete(Element(0))
  132. list = New()
  133. list.Delete(Element(0))
  134. if !list.IsEmpty() {
  135. t.Fail()
  136. }
  137. // Delete elements at the beginning of the list.
  138. for i := 0; i < maxN; i++ {
  139. list.Insert(Element(i))
  140. }
  141. for i := 0; i < maxN; i++ {
  142. list.Delete(Element(i))
  143. }
  144. if !list.IsEmpty() {
  145. t.Fail()
  146. }
  147. list = New()
  148. // Delete elements at the end of the list.
  149. for i := 0; i < maxN; i++ {
  150. list.Insert(Element(i))
  151. }
  152. for i := 0; i < maxN; i++ {
  153. list.Delete(Element(maxN - i - 1))
  154. }
  155. if !list.IsEmpty() {
  156. t.Fail()
  157. }
  158. list = New()
  159. // Delete elements at random positions in the list.
  160. rList := rand.Perm(maxN)
  161. for _, e := range rList {
  162. list.Insert(Element(e))
  163. }
  164. for _, e := range rList {
  165. list.Delete(Element(e))
  166. }
  167. if !list.IsEmpty() {
  168. t.Fail()
  169. }
  170. }
  171. func TestFindGreaterOrEqual(t *testing.T) {
  172. eps := 0.00000001
  173. maxNumber := 1000.0
  174. var list SkipList
  175. var listPointer *SkipList
  176. // Test on empty list.
  177. if _, ok := listPointer.FindGreaterOrEqual(FloatElement(0)); ok {
  178. t.Fail()
  179. }
  180. list = NewEps(eps)
  181. for i := 0; i < maxN; i++ {
  182. list.Insert(FloatElement(rand.Float64() * maxNumber))
  183. }
  184. first := float64(list.GetSmallestNode().GetValue().(FloatElement))
  185. // Find the very first element. This is a special case in the implementation that needs testing!
  186. if v, ok := list.FindGreaterOrEqual(FloatElement(first - 2.0*eps)); ok {
  187. // We found an element different to the first one!
  188. if math.Abs(float64(v.GetValue().(FloatElement))-first) > eps {
  189. t.Fail()
  190. }
  191. } else {
  192. // No element found.
  193. t.Fail()
  194. }
  195. for i := 0; i < maxN; i++ {
  196. f := rand.Float64() * maxNumber
  197. if v, ok := list.FindGreaterOrEqual(FloatElement(f)); ok {
  198. // if f is v should be bigger than the element before
  199. lastV := float64(list.Prev(v).GetValue().(FloatElement))
  200. thisV := float64(v.GetValue().(FloatElement))
  201. isFirst := math.Abs(first-thisV) <= eps
  202. if !isFirst && lastV >= f {
  203. fmt.Printf("PrevV: %.8f\n f: %.8f\n\n", lastV, f)
  204. t.Fail()
  205. }
  206. // v should be bigger or equal to f
  207. // If we compare directly, we get an equal key with a difference on the 10th decimal point, which fails.
  208. if f-thisV > eps {
  209. fmt.Printf("f: %.8f\nv: %.8f\n\n", f, thisV)
  210. t.Fail()
  211. }
  212. } else {
  213. lastV := float64(list.GetLargestNode().GetValue().(FloatElement))
  214. // It is OK, to fail, as long as f is bigger than the last element.
  215. if f <= lastV {
  216. fmt.Printf("lastV: %.8f\n f: %.8f\n\n", lastV, f)
  217. t.Fail()
  218. }
  219. }
  220. }
  221. }
  222. func TestPrev(t *testing.T) {
  223. list := New()
  224. for i := 0; i < maxN; i++ {
  225. list.Insert(Element(i))
  226. }
  227. smallest := list.GetSmallestNode()
  228. largest := list.GetLargestNode()
  229. lastNode := largest
  230. node := lastNode
  231. for node != smallest {
  232. node = list.Prev(node)
  233. // Must always be incrementing here!
  234. if node.value.(Element) >= lastNode.value.(Element) {
  235. t.Fail()
  236. }
  237. // Next.Prev must always point to itself!
  238. if list.Prev(list.Next(node)) != node {
  239. t.Fail()
  240. }
  241. lastNode = node
  242. }
  243. if list.Prev(smallest) != largest {
  244. t.Fail()
  245. }
  246. }
  247. func TestNext(t *testing.T) {
  248. list := New()
  249. for i := 0; i < maxN; i++ {
  250. list.Insert(Element(i))
  251. }
  252. smallest := list.GetSmallestNode()
  253. largest := list.GetLargestNode()
  254. lastNode := smallest
  255. node := lastNode
  256. for node != largest {
  257. node = list.Next(node)
  258. // Must always be incrementing here!
  259. if node.value.(Element) <= lastNode.value.(Element) {
  260. t.Fail()
  261. }
  262. // Next.Prev must always point to itself!
  263. if list.Next(list.Prev(node)) != node {
  264. t.Fail()
  265. }
  266. lastNode = node
  267. }
  268. if list.Next(largest) != smallest {
  269. t.Fail()
  270. }
  271. }
  272. func TestChangeValue(t *testing.T) {
  273. list := New()
  274. for i := 0; i < maxN; i++ {
  275. list.Insert(ComplexElement{i, "value"})
  276. }
  277. for i := 0; i < maxN; i++ {
  278. // The key only looks at the int so the string doesn't matter here!
  279. f1, ok := list.Find(ComplexElement{i, ""})
  280. if !ok {
  281. t.Fail()
  282. }
  283. ok = list.ChangeValue(f1, ComplexElement{i, "different value"})
  284. if !ok {
  285. t.Fail()
  286. }
  287. f2, ok := list.Find(ComplexElement{i, ""})
  288. if !ok {
  289. t.Fail()
  290. }
  291. if f2.GetValue().(ComplexElement).S != "different value" {
  292. t.Fail()
  293. }
  294. if ok = list.ChangeValue(f2, ComplexElement{i + 5, "different key"}); ok {
  295. t.Fail()
  296. }
  297. }
  298. }
  299. func TestGetNodeCount(t *testing.T) {
  300. list := New()
  301. for i := 0; i < maxN; i++ {
  302. list.Insert(Element(i))
  303. }
  304. if list.GetNodeCount() != maxN {
  305. t.Fail()
  306. }
  307. }
  308. func TestString(t *testing.T) {
  309. list := NewSeed(1531889620180049576)
  310. for i := 0; i < 20; i++ {
  311. list.Insert(Element(i))
  312. }
  313. testString := ` --> [000] -> [002] -> [009] -> [010]
  314. 000: [---|001]
  315. 001: [000|002]
  316. 002: [001|003] -> [004]
  317. 003: [002|004]
  318. 004: [003|005] -> [005]
  319. 005: [004|006] -> [009]
  320. 006: [005|007]
  321. 007: [006|008]
  322. 008: [007|009]
  323. 009: [008|010] -> [010] -> [010]
  324. 010: [009|011] -> [012] -> [---] -> [---]
  325. 011: [010|012]
  326. 012: [011|013] -> [013]
  327. 013: [012|014] -> [---]
  328. 014: [013|015]
  329. 015: [014|016]
  330. 016: [015|017]
  331. 017: [016|018]
  332. 018: [017|019]
  333. 019: [018|---]
  334. --> [019] -> [013] -> [010] -> [010]
  335. `
  336. if list.String() != testString {
  337. t.Fail()
  338. }
  339. }
  340. func TestInfiniteLoop(t *testing.T) {
  341. list := New()
  342. list.Insert(Element(1))
  343. if _, ok := list.Find(Element(2)); ok {
  344. t.Fail()
  345. }
  346. if _, ok := list.FindGreaterOrEqual(Element(2)); ok {
  347. t.Fail()
  348. }
  349. }
  350. for i := 0; i < maxN; i++ {
  351. // The key only looks at the int so the string doesn't matter here!
  352. f1, ok := list.Find(ComplexElement{i, ""})
  353. if !ok {
  354. t.Fail()
  355. }
  356. ok = list.ChangeValue(f1, ComplexElement{i, "different value"})
  357. if !ok {
  358. t.Fail()
  359. }
  360. f2, ok := list.Find(ComplexElement{i, ""})
  361. if !ok {
  362. t.Fail()
  363. }
  364. if f2.GetValue().(ComplexElement).S != "different value" {
  365. t.Fail()
  366. }
  367. if ok = list.ChangeValue(f2, ComplexElement{i + 5, "different key"}); ok {
  368. t.Fail()
  369. }
  370. }
  371. }
  372. func TestGetNodeCount(t *testing.T) {
  373. list := New()
  374. for i := 0; i < maxN; i++ {
  375. list.Insert(Element(i))
  376. }
  377. if list.GetNodeCount() != maxN {
  378. t.Fail()
  379. }
  380. }
  381. func TestString(t *testing.T) {
  382. list := NewSeed(1531889620180049576)
  383. for i := 0; i < 20; i++ {
  384. list.Insert(Element(i))
  385. }
  386. testString := ` --> [000] -> [002] -> [009] -> [010]
  387. 000: [---|001]
  388. 001: [000|002]
  389. 002: [001|003] -> [004]
  390. 003: [002|004]
  391. 004: [003|005] -> [005]
  392. 005: [004|006] -> [009]
  393. 006: [005|007]
  394. 007: [006|008]
  395. 008: [007|009]
  396. 009: [008|010] -> [010] -> [010]
  397. 010: [009|011] -> [012] -> [---] -> [---]
  398. 011: [010|012]
  399. 012: [011|013] -> [013]
  400. 013: [012|014] -> [---]
  401. 014: [013|015]
  402. 015: [014|016]
  403. 016: [015|017]
  404. 017: [016|018]
  405. 018: [017|019]
  406. 019: [018|---]
  407. --> [019] -> [013] -> [010] -> [010]
  408. `
  409. if list.String() != testString {
  410. t.Fail()
  411. }
  412. }
  413. func TestInfiniteLoop(t *testing.T) {
  414. list := New()
  415. list.Insert(Element(1))
  416. if _, ok := list.Find(Element(2)); ok {
  417. t.Fail()
  418. }
  419. if _, ok := list.FindGreaterOrEqual(Element(2)); ok {
  420. t.Fail()
  421. }
  422. }