This repository has been archived on 2022-07-30. You can view files and clone it, but cannot push or open issues/pull-requests.
mdb/btreeindex_test.go

295 lines
7.0 KiB
Go

package mdb
import (
"reflect"
"testing"
)
func TestFullBTreeIndex(t *testing.T) {
// Test against the email index.
run := func(name string, inner func(t *testing.T, db *DB) []*User) {
testWithDB(t, name, func(t *testing.T, db *DB) {
expected := inner(t, db)
if err := db.Users.emailBTree.EqualsList(expected); err != nil {
t.Fatal(err)
}
db.Close()
db = OpenDB(db.root, true)
if err := db.Users.emailBTree.EqualsList(expected); err != nil {
t.Fatal(err)
}
})
}
run("insert", func(t *testing.T, db *DB) (users []*User) {
users = append(users,
&User{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc"})
for _, u := range users {
u2, err := db.Users.c.Insert(*u)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(u2, *u) {
t.Fatal(u2, *u)
}
}
return users
})
run("update", func(t *testing.T, db *DB) (users []*User) {
users = append(users,
&User{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
&User{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "eee"},
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc"})
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
err := db.Users.c.Update(users[2].ID, func(u User) (User, error) {
u.Email = "g@h.com"
return u, nil
})
if err != nil {
t.Fatal(err)
}
users[2].Email = "g@h.com"
return users
})
run("delete", func(t *testing.T, db *DB) (users []*User) {
users = append(users,
&User{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc"},
&User{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "eee"})
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
db.Users.c.Delete(users[0].ID)
users = users[1:]
return users
})
run("get not found", func(t *testing.T, db *DB) (users []*User) {
users = append(users,
&User{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc"},
&User{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "eee"})
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
if u, ok := db.Users.emailBTree.Get(User{Email: "g@h.com"}); ok {
t.Fatal(u, ok)
}
return users
})
run("min/max empty", func(t *testing.T, db *DB) (users []*User) {
if u, ok := db.Users.emailBTree.Min(); ok {
t.Fatal(u, ok)
}
if u, ok := db.Users.emailBTree.Max(); ok {
t.Fatal(u, ok)
}
return users
})
}
func TestPartialBTreeIndex(t *testing.T) {
// Test against the extID btree index.
run := func(name string, inner func(t *testing.T, db *DB) []*User) {
testWithDB(t, name, func(t *testing.T, db *DB) {
expected := inner(t, db)
if err := db.Users.extIDBTree.EqualsList(expected); err != nil {
t.Fatal(err)
}
db.Close()
db = OpenDB(db.root, true)
if err := db.Users.extIDBTree.EqualsList(expected); err != nil {
t.Fatal(err)
}
})
}
run("insert out", func(t *testing.T, db *DB) []*User {
users := []*User{
{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "xxx"},
{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ggg"},
{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "aaa"},
}
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
return []*User{}
})
run("insert in", func(t *testing.T, db *DB) []*User {
users := []*User{
{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "xxx"},
{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ggg", ExtID: "x"},
{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "aaa"},
}
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
return []*User{users[1]}
})
run("update out to out", func(t *testing.T, db *DB) []*User {
users := []*User{
{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc", ExtID: "A"},
{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "eee"},
{ID: db.Users.c.NextID(), Email: "g@h.com", Name: "ggg", ExtID: "B"},
}
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
err := db.Users.c.Update(users[0].ID, func(u User) (User, error) {
u.Name = "axa"
users[0].Name = "axa"
return u, nil
})
if err != nil {
t.Fatal(err)
}
return []*User{users[1], users[3]}
})
run("update in to in", func(t *testing.T, db *DB) []*User {
users := []*User{
{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc", ExtID: "A"},
{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "eee"},
{ID: db.Users.c.NextID(), Email: "g@h.com", Name: "ggg", ExtID: "B"},
}
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
err := db.Users.c.Update(users[1].ID, func(u User) (User, error) {
u.ExtID = "C"
users[1].ExtID = "C"
return u, nil
})
if err != nil {
t.Fatal(err)
}
return []*User{users[3], users[1]}
})
run("update out to in", func(t *testing.T, db *DB) []*User {
users := []*User{
{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc", ExtID: "A"},
{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "eee"},
{ID: db.Users.c.NextID(), Email: "g@h.com", Name: "ggg", ExtID: "B"},
}
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
err := db.Users.c.Update(users[2].ID, func(u User) (User, error) {
u.ExtID = "C"
users[2].ExtID = "C"
return u, nil
})
if err != nil {
t.Fatal(err)
}
return []*User{users[1], users[3], users[2]}
})
run("update in to out", func(t *testing.T, db *DB) []*User {
users := []*User{
{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "aaa"},
{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ccc", ExtID: "A"},
{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "eee"},
{ID: db.Users.c.NextID(), Email: "g@h.com", Name: "ggg", ExtID: "B"},
}
for _, u := range users {
if _, err := db.Users.c.Insert(*u); err != nil {
t.Fatal(err)
}
}
err := db.Users.c.Update(users[1].ID, func(u User) (User, error) {
u.ExtID = ""
users[1].ExtID = ""
return u, nil
})
if err != nil {
t.Fatal(err)
}
return []*User{users[3]}
})
}
func TestBTreeIndex_load_ErrDuplicate(t *testing.T) {
testWithDB(t, "", func(t *testing.T, db *DB) {
idx := NewBTreeIndex(
db.Users.c,
"extid",
func(lhs, rhs *User) bool { return lhs.ExtID < rhs.ExtID },
nil)
users := map[uint64]*User{
1: {ID: 1, Email: "x@y.com", Name: "xx", ExtID: "x"},
2: {ID: 2, Email: "a@b.com", Name: "aa", ExtID: "x"},
}
if err := idx.load(users); err != ErrDuplicate {
t.Fatal(err)
}
})
}