package skiplist import ( "bytes" "math/rand" "strconv" "testing" ) const ( maxN = 10000 ) var ( memStore = newMemStore() ) func TestReverseInsert(t *testing.T) { list := NewSeed(100, memStore) list.InsertByKey([]byte("zzz"), 0, []byte("zzz")) list.DeleteByKey([]byte("zzz")) list.InsertByKey([]byte("aaa"), 0, []byte("aaa")) if list.IsEmpty() { t.Fail() } } func TestInsertAndFind(t *testing.T) { k0 := []byte("0") var list *SkipList var listPointer *SkipList listPointer.InsertByKey(k0, 0, k0) if _, _, ok, _ := listPointer.Find(k0); ok { t.Fail() } list = New(memStore) if _, _, ok, _ := list.Find(k0); ok { t.Fail() } if !list.IsEmpty() { t.Fail() } // Test at the beginning of the list. for i := 0; i < maxN; i++ { key := []byte(strconv.Itoa(maxN - i)) list.InsertByKey(key, 0, key) } for i := 0; i < maxN; i++ { key := []byte(strconv.Itoa(maxN - i)) if _, _, ok, _ := list.Find(key); !ok { t.Fail() } } list = New(memStore) // Test at the end of the list. for i := 0; i < maxN; i++ { key := []byte(strconv.Itoa(i)) list.InsertByKey(key, 0, key) } for i := 0; i < maxN; i++ { key := []byte(strconv.Itoa(i)) if _, _, ok, _ := list.Find(key); !ok { t.Fail() } } list = New(memStore) // Test at random positions in the list. rList := rand.Perm(maxN) for _, e := range rList { key := []byte(strconv.Itoa(e)) // println("insert", e) list.InsertByKey(key, 0, key) } for _, e := range rList { key := []byte(strconv.Itoa(e)) // println("find", e) if _, _, ok, _ := list.Find(key); !ok { t.Fail() } } // println("print list") // list.println() } func Element(x int) []byte { return []byte(strconv.Itoa(x)) } func TestDelete(t *testing.T) { k0 := []byte("0") var list *SkipList // Delete on empty list list.DeleteByKey(k0) list = New(memStore) list.DeleteByKey(k0) if !list.IsEmpty() { t.Fail() } list.InsertByKey(k0, 0, k0) list.DeleteByKey(k0) if !list.IsEmpty() { t.Fail() } // Delete elements at the beginning of the list. for i := 0; i < maxN; i++ { list.InsertByKey(Element(i), 0, Element(i)) } for i := 0; i < maxN; i++ { list.DeleteByKey(Element(i)) } if !list.IsEmpty() { t.Fail() } list = New(memStore) // Delete elements at the end of the list. for i := 0; i < maxN; i++ { list.InsertByKey(Element(i), 0, Element(i)) } for i := 0; i < maxN; i++ { list.DeleteByKey(Element(maxN - i - 1)) } if !list.IsEmpty() { t.Fail() } list = New(memStore) // Delete elements at random positions in the list. rList := rand.Perm(maxN) for _, e := range rList { list.InsertByKey(Element(e), 0, Element(e)) } for _, e := range rList { list.DeleteByKey(Element(e)) } if !list.IsEmpty() { t.Fail() } } func TestNext(t *testing.T) { list := New(memStore) for i := 0; i < maxN; i++ { list.InsertByKey(Element(i), 0, Element(i)) } smallest, _ := list.GetSmallestNode() largest, _ := list.GetLargestNode() lastNode := smallest node := lastNode for node != largest { node, _ = list.Next(node) // Must always be incrementing here! if bytes.Compare(node.Key, lastNode.Key) <= 0 { t.Fail() } // Next.Prev must always point to itself! prevNode, _ := list.Prev(node) nextNode, _ := list.Next(prevNode) if nextNode != node { t.Fail() } lastNode = node } if nextNode, _ := list.Next(largest); nextNode != smallest { t.Fail() } } func TestPrev(t *testing.T) { list := New(memStore) for i := 0; i < maxN; i++ { list.InsertByKey(Element(i), 0, Element(i)) } smallest, _ := list.GetSmallestNode() largest, _ := list.GetLargestNode() lastNode := largest node := lastNode for node != smallest { node, _ = list.Prev(node) // Must always be incrementing here! if bytes.Compare(node.Key, lastNode.Key) >= 0 { t.Fail() } // Next.Prev must always point to itself! nextNode, _ := list.Next(node) prevNode, _ := list.Prev(nextNode) if prevNode != node { t.Fail() } lastNode = node } if prevNode, _ := list.Prev(smallest); prevNode != largest { t.Fail() } } func TestFindGreaterOrEqual(t *testing.T) { maxNumber := maxN * 100 var list *SkipList var listPointer *SkipList // Test on empty list. if _, _, ok, _ := listPointer.FindGreaterOrEqual(Element(0)); ok { t.Errorf("found element 0 in an empty list") } list = New(memStore) for i := 0; i < maxN; i++ { list.InsertByKey(Element(rand.Intn(maxNumber)), 0, Element(i)) } for i := 0; i < maxN; i++ { key := Element(rand.Intn(maxNumber)) if _, v, ok, _ := list.FindGreaterOrEqual(key); ok { // if f is v should be bigger than the element before if v.Prev != nil && bytes.Compare(key, v.Prev.Key) < 0 { t.Errorf("PrevV: %s\n key: %s\n\n", string(v.Prev.Key), string(key)) } // v should be bigger or equal to f // If we compare directly, we get an equal key with a difference on the 10th decimal point, which fails. if bytes.Compare(v.Key, key) < 0 { t.Errorf("v: %s\n key: %s\n\n", string(v.Key), string(key)) } } else { lastNode, _ := list.GetLargestNode() lastV := lastNode.GetValue() // It is OK, to fail, as long as f is bigger than the last element. if bytes.Compare(key, lastV) <= 0 { t.Errorf("lastV: %s\n key: %s\n\n", string(lastV), string(key)) } } } } func TestChangeValue(t *testing.T) { list := New(memStore) for i := 0; i < maxN; i++ { list.InsertByKey(Element(i), 0, []byte("value")) } for i := 0; i < maxN; i++ { // The key only looks at the int so the string doesn't matter here! _, f1, ok, _ := list.Find(Element(i)) if !ok { t.Fail() } err := list.ChangeValue(f1, []byte("different value")) if err != nil { t.Fail() } _, f2, ok, _ := list.Find(Element(i)) if !ok { t.Fail() } if bytes.Compare(f2.GetValue(), []byte("different value")) != 0 { t.Fail() } } }