mirror of
				https://github.com/nalgeon/redka.git
				synced 2025-10-31 19:32:38 +08:00 
			
		
		
		
	 818954d339
			
		
	
	818954d339
	
	
	
		
			
			Shared cache is discouraged. The supported alternative (and increasingly recommended by SQLite developers), is the memdb VFS (which I believe is supported by all drivers). I'm sure modernc has it, and mattn also does if compiled with SQLITE_ENABLE_DESERIALIZE, which became the default in 2021. https://github.com/ncruces/go-sqlite3/issues/94#issuecomment-2157679766
		
			
				
	
	
		
			1463 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1463 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package rlist_test
 | |
| 
 | |
| import (
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/nalgeon/redka"
 | |
| 	"github.com/nalgeon/redka/internal/core"
 | |
| 	"github.com/nalgeon/redka/internal/rlist"
 | |
| 	"github.com/nalgeon/redka/internal/testx"
 | |
| )
 | |
| 
 | |
| func TestDelete(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.Delete("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| 	t.Run("delete elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.Delete("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("delete multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "fou")
 | |
| 
 | |
| 		n, err := list.Delete("key", "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 9)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "one")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "thr")
 | |
| 		el2, _ := list.Get("key", 2)
 | |
| 		testx.AssertEqual(t, el2.String(), "fou")
 | |
| 	})
 | |
| 	t.Run("delete duplicate", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.Delete("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 4)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("elem not found", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.Delete("key", "none")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 1)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.Delete("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		sval, _ := db.Str().Get("key")
 | |
| 		testx.AssertEqual(t, sval.String(), "value")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestDeleteBack(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.DeleteBack("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| 	t.Run("delete elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.DeleteBack("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("delete multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "fou")
 | |
| 
 | |
| 		n, err := list.DeleteBack("key", "two", 2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 8)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 4)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "one")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "two")
 | |
| 		el2, _ := list.Get("key", 2)
 | |
| 		testx.AssertEqual(t, el2.String(), "thr")
 | |
| 		el3, _ := list.Get("key", 3)
 | |
| 		testx.AssertEqual(t, el3.String(), "fou")
 | |
| 	})
 | |
| 	t.Run("large count", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "fou")
 | |
| 
 | |
| 		n, err := list.DeleteBack("key", "two", 10)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 7)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 	})
 | |
| 	t.Run("delete duplicate", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.DeleteBack("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 3)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("elem not found", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.DeleteBack("key", "none", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 1)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.DeleteBack("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		sval, _ := db.Str().Get("key")
 | |
| 		testx.AssertEqual(t, sval.String(), "value")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestDeleteFront(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.DeleteFront("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| 	t.Run("delete elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.DeleteFront("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("delete multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "fou")
 | |
| 
 | |
| 		n, err := list.DeleteFront("key", "two", 2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 8)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 4)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "one")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "thr")
 | |
| 		el2, _ := list.Get("key", 2)
 | |
| 		testx.AssertEqual(t, el2.String(), "two")
 | |
| 		el3, _ := list.Get("key", 3)
 | |
| 		testx.AssertEqual(t, el3.String(), "fou")
 | |
| 	})
 | |
| 	t.Run("large count", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "fou")
 | |
| 
 | |
| 		n, err := list.DeleteFront("key", "two", 10)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 7)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 	})
 | |
| 	t.Run("delete duplicate", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.DeleteFront("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 3)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("elem not found", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.DeleteFront("key", "none", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 1)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.DeleteFront("key", "elem", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		sval, _ := db.Str().Get("key")
 | |
| 		testx.AssertEqual(t, sval.String(), "value")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestGet(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		_, err := list.Get("key", 0)
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| 	t.Run("single elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		elem, err := list.Get("key", 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 	})
 | |
| 	t.Run("multiple elems", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elem, err := list.Get("key", 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "one")
 | |
| 
 | |
| 		elem, err = list.Get("key", 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 
 | |
| 		elem, err = list.Get("key", 2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "thr")
 | |
| 	})
 | |
| 	t.Run("index out of bounds", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		_, err := list.Get("key", 1)
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| 	t.Run("negative index", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elem, err := list.Get("key", -2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		_, err := list.Get("key", 0)
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestInsertAfter(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.InsertAfter("key", "mark", "elem")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| 	t.Run("insert after first", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "mark")
 | |
| 
 | |
| 		n, err := list.InsertAfter("key", "mark", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 
 | |
| 		elem, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 	})
 | |
| 	t.Run("insert after middle", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.InsertAfter("key", "one", "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 3)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 
 | |
| 		elem, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 	})
 | |
| 	t.Run("elem not found", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 
 | |
| 		n, err := list.InsertAfter("key", "thr", "two")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 		testx.AssertEqual(t, n, -1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.InsertAfter("key", "mark", "elem")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		sval, _ := db.Str().Get("key")
 | |
| 		testx.AssertEqual(t, sval.String(), "value")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestInsertBefore(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.InsertBefore("key", "mark", "elem")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| 	t.Run("insert before first", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "mark")
 | |
| 
 | |
| 		n, err := list.InsertBefore("key", "mark", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 
 | |
| 		elem, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 	})
 | |
| 	t.Run("insert before middle", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.InsertBefore("key", "thr", "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 3)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 
 | |
| 		elem, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 	})
 | |
| 	t.Run("elem not found", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 
 | |
| 		n, err := list.InsertBefore("key", "thr", "two")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 		testx.AssertEqual(t, n, -1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.InsertBefore("key", "mark", "elem")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		sval, _ := db.Str().Get("key")
 | |
| 		testx.AssertEqual(t, sval.String(), "value")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestLen(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.Len("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| 	t.Run("single elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.Len("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 	})
 | |
| 	t.Run("multiple elems", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Len("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 4)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.Len("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestPushBack(t *testing.T) {
 | |
| 	t.Run("create key", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.PushBack("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 1)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("add elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 
 | |
| 		n, err := list.PushBack("key", "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 	})
 | |
| 	t.Run("add multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.PushBack("key", "one")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 		n, err = list.PushBack("key", "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 		n, err = list.PushBack("key", "thr")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 3)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 	})
 | |
| 	t.Run("add duplicate", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.PushBack("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 		n, err = list.PushBack("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.PushBack("key", 42)
 | |
| 		testx.AssertErr(t, err, core.ErrKeyType)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		_, err = list.Get("key", 0)
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 
 | |
| 		sval, _ := db.Str().Get("key")
 | |
| 		testx.AssertEqual(t, sval.String(), "value")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestPushFront(t *testing.T) {
 | |
| 	t.Run("create key", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.PushFront("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 1)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("add elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushFront("key", "one")
 | |
| 
 | |
| 		n, err := list.PushFront("key", "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 	})
 | |
| 	t.Run("add multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.PushFront("key", "one")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 		n, err = list.PushFront("key", "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 		n, err = list.PushFront("key", "thr")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 3)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 	})
 | |
| 	t.Run("add duplicate", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.PushFront("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 		n, err = list.PushFront("key", "elem")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.PushFront("key", 42)
 | |
| 		testx.AssertErr(t, err, core.ErrKeyType)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		_, err = list.Get("key", 0)
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 
 | |
| 		sval, _ := db.Str().Get("key")
 | |
| 		testx.AssertEqual(t, sval.String(), "value")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestPopBack(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		_, err := list.PopBack("key")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| 	t.Run("pop elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 
 | |
| 		elem, err := list.PopBack("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "one")
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("pop multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elem, err := list.PopBack("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "thr")
 | |
| 
 | |
| 		elem, err = list.PopBack("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 
 | |
| 		elem, err = list.PopBack("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "one")
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 6)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("pop duplicate", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		elem, err := list.PopBack("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 
 | |
| 		elem, err = list.PopBack("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 5)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		_, err := list.PopBack("key")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestPopBackPushFront(t *testing.T) {
 | |
| 	t.Run("src not found", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		_, err := list.PopBackPushFront("src", "dest")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| 	t.Run("pop elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("src", "elem")
 | |
| 
 | |
| 		elem, err := list.PopBackPushFront("src", "dest")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 
 | |
| 		srclen, _ := list.Len("src")
 | |
| 		testx.AssertEqual(t, srclen, 0)
 | |
| 
 | |
| 		dstlen, _ := list.Len("dest")
 | |
| 		testx.AssertEqual(t, dstlen, 1)
 | |
| 	})
 | |
| 	t.Run("pop multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("src", "one")
 | |
| 		_, _ = list.PushBack("src", "two")
 | |
| 		_, _ = list.PushBack("src", "thr")
 | |
| 
 | |
| 		elem, err := list.PopBackPushFront("src", "dest")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "thr")
 | |
| 		elem, _ = list.Get("dest", 0)
 | |
| 		testx.AssertEqual(t, elem.String(), "thr")
 | |
| 
 | |
| 		elem, err = list.PopBackPushFront("src", "dest")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 		elem, _ = list.Get("dest", 0)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 
 | |
| 		elem, err = list.PopBackPushFront("src", "dest")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "one")
 | |
| 		elem, _ = list.Get("dest", 0)
 | |
| 		testx.AssertEqual(t, elem.String(), "one")
 | |
| 
 | |
| 		srclen, _ := list.Len("src")
 | |
| 		testx.AssertEqual(t, srclen, 0)
 | |
| 		dstlen, _ := list.Len("dest")
 | |
| 		testx.AssertEqual(t, dstlen, 3)
 | |
| 	})
 | |
| 	t.Run("push to self", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elem, err := list.PopBackPushFront("key", "key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "thr")
 | |
| 
 | |
| 		elem, err = list.PopBackPushFront("key", "key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 7)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 
 | |
| 		elems, _ := list.Range("key", 0, 2)
 | |
| 		testx.AssertEqual(t, elems[0].String(), "two")
 | |
| 		testx.AssertEqual(t, elems[1].String(), "thr")
 | |
| 		testx.AssertEqual(t, elems[2].String(), "one")
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("src", "value")
 | |
| 
 | |
| 		_, err := list.PopBackPushFront("src", "dest")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestPopFront(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		_, err := list.PopFront("key")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| 	t.Run("pop elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 
 | |
| 		elem, err := list.PopFront("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "one")
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("pop multiple", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elem, err := list.PopFront("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "one")
 | |
| 
 | |
| 		elem, err = list.PopFront("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 
 | |
| 		elem, err = list.PopFront("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "thr")
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 6)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("pop duplicate", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 
 | |
| 		elem, err := list.PopFront("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 
 | |
| 		elem, err = list.PopFront("key")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 5)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		_, err := list.PopFront("key")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestRange(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		elems, err := list.Range("key", 0, 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 0)
 | |
| 	})
 | |
| 	t.Run("single elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		elems, err := list.Range("key", 0, 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 1)
 | |
| 		testx.AssertEqual(t, elems[0].String(), "elem")
 | |
| 	})
 | |
| 	t.Run("multiple elems", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elems, err := list.Range("key", 0, 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 2)
 | |
| 		testx.AssertEqual(t, elems[0].String(), "one")
 | |
| 		testx.AssertEqual(t, elems[1].String(), "two")
 | |
| 	})
 | |
| 	t.Run("start >= len", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 
 | |
| 		elems, err := list.Range("key", 2, 2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 0)
 | |
| 	})
 | |
| 	t.Run("start > stop > 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 
 | |
| 		elems, err := list.Range("key", 1, 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 0)
 | |
| 	})
 | |
| 	t.Run("0 > start > stop", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elems, err := list.Range("key", -1, -2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 0)
 | |
| 	})
 | |
| 	t.Run("stop > len", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elems, err := list.Range("key", 1, 5)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 2)
 | |
| 		testx.AssertEqual(t, elems[0].String(), "two")
 | |
| 		testx.AssertEqual(t, elems[1].String(), "thr")
 | |
| 	})
 | |
| 	t.Run("start < 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elems, err := list.Range("key", -2, 2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 2)
 | |
| 		testx.AssertEqual(t, elems[0].String(), "two")
 | |
| 		testx.AssertEqual(t, elems[1].String(), "thr")
 | |
| 	})
 | |
| 	t.Run("stop < 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elems, err := list.Range("key", 1, -1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 2)
 | |
| 		testx.AssertEqual(t, elems[0].String(), "two")
 | |
| 		testx.AssertEqual(t, elems[1].String(), "thr")
 | |
| 	})
 | |
| 	t.Run("start < 0 and stop < 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		elems, err := list.Range("key", -2, -1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 2)
 | |
| 		testx.AssertEqual(t, elems[0].String(), "two")
 | |
| 		testx.AssertEqual(t, elems[1].String(), "thr")
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		elems, err := list.Range("key", 0, 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, len(elems), 0)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestSet(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		err := list.Set("key", 0, "elem")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| 	t.Run("single elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 
 | |
| 		err := list.Set("key", 0, "two")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 2)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 
 | |
| 		elem, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, elem.String(), "two")
 | |
| 	})
 | |
| 	t.Run("multiple elems", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		err := list.Set("key", 1, "new")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 5)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 4)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "one")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "new")
 | |
| 		el2, _ := list.Get("key", 2)
 | |
| 		testx.AssertEqual(t, el2.String(), "two")
 | |
| 		el3, _ := list.Get("key", 3)
 | |
| 		testx.AssertEqual(t, el3.String(), "thr")
 | |
| 	})
 | |
| 	t.Run("index out of bounds", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		err := list.Set("key", 1, "new")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 1)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 
 | |
| 		elem, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, elem.String(), "elem")
 | |
| 	})
 | |
| 	t.Run("negative index", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		err := list.Set("key", -2, "new")
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 4)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 3)
 | |
| 
 | |
| 		elem, _ := list.Get("key", -2)
 | |
| 		testx.AssertEqual(t, elem.String(), "new")
 | |
| 		elem, _ = list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, elem.String(), "new")
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		err := list.Set("key", 0, "elem")
 | |
| 		testx.AssertErr(t, err, core.ErrNotFound)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestTrim(t *testing.T) {
 | |
| 	t.Run("empty list", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 
 | |
| 		n, err := list.Trim("key", 0, 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| 	t.Run("keep single elem", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "elem")
 | |
| 
 | |
| 		n, err := list.Trim("key", 0, 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 1)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 1)
 | |
| 	})
 | |
| 	t.Run("keep multiple elems", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 		_, _ = list.PushBack("key", "fou")
 | |
| 
 | |
| 		n, err := list.Trim("key", 1, 2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 2)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 6)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "two")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "thr")
 | |
| 	})
 | |
| 	t.Run("keep all elems", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 		_, _ = list.PushBack("key", "fou")
 | |
| 
 | |
| 		n, err := list.Trim("key", 0, 3)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 4)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 4)
 | |
| 	})
 | |
| 	t.Run("start >= len", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Trim("key", 3, 3)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 6)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("start > stop > 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Trim("key", 2, 1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 6)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("0 > start > stop", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Trim("key", -1, -2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 3)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 6)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 0)
 | |
| 	})
 | |
| 	t.Run("stop > len", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Trim("key", 1, 5)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 4)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "two")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "thr")
 | |
| 	})
 | |
| 	t.Run("start < 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Trim("key", -2, 2)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 4)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "two")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "thr")
 | |
| 	})
 | |
| 	t.Run("stop < 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Trim("key", 1, -1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 4)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "two")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "thr")
 | |
| 	})
 | |
| 	t.Run("start < 0 and stop < 0", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_, _ = list.PushBack("key", "one")
 | |
| 		_, _ = list.PushBack("key", "two")
 | |
| 		_, _ = list.PushBack("key", "thr")
 | |
| 
 | |
| 		n, err := list.Trim("key", -2, -1)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 1)
 | |
| 
 | |
| 		key, _ := db.Key().Get("key")
 | |
| 		testx.AssertEqual(t, key.Version, 4)
 | |
| 
 | |
| 		llen, _ := list.Len("key")
 | |
| 		testx.AssertEqual(t, llen, 2)
 | |
| 
 | |
| 		el0, _ := list.Get("key", 0)
 | |
| 		testx.AssertEqual(t, el0.String(), "two")
 | |
| 		el1, _ := list.Get("key", 1)
 | |
| 		testx.AssertEqual(t, el1.String(), "thr")
 | |
| 	})
 | |
| 	t.Run("key type mismatch", func(t *testing.T) {
 | |
| 		db, list := getDB(t)
 | |
| 		defer db.Close()
 | |
| 		_ = db.Str().Set("key", "value")
 | |
| 
 | |
| 		n, err := list.Trim("key", 0, 0)
 | |
| 		testx.AssertNoErr(t, err)
 | |
| 		testx.AssertEqual(t, n, 0)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func getDB(tb testing.TB) (*redka.DB, *rlist.DB) {
 | |
| 	tb.Helper()
 | |
| 	db, err := redka.Open("file:/data.db?vfs=memdb", nil)
 | |
| 	if err != nil {
 | |
| 		tb.Fatal(err)
 | |
| 	}
 | |
| 	return db, db.List()
 | |
| }
 |