235 lines
5.6 KiB
Go
235 lines
5.6 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 name 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.nameBTree.EqualsList(expected); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
db.Close()
|
|
db = OpenDB(db.root, true)
|
|
|
|
if err := db.Users.nameBTree.EqualsList(expected); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
run("empty", func(t *testing.T, db *DB) []*User {
|
|
return []*User{}
|
|
})
|
|
|
|
run("insert", func(t *testing.T, db *DB) (users []*User) {
|
|
users = append(users,
|
|
&User{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "xxx"},
|
|
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ggg"},
|
|
&User{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)
|
|
}
|
|
}
|
|
users[0], users[2] = users[2], users[0]
|
|
|
|
return users
|
|
})
|
|
|
|
run("insert duplicates", func(t *testing.T, db *DB) (users []*User) {
|
|
users = append(users,
|
|
&User{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "xxx"},
|
|
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "ggg"},
|
|
&User{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "xxx"})
|
|
|
|
for _, u := range users {
|
|
if _, err := db.Users.c.Insert(*u); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
users = []*User{users[1], users[0], users[2]}
|
|
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: "ccc"},
|
|
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "aaa"},
|
|
&User{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "bbb"})
|
|
|
|
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.Name = "ccc"
|
|
return u, nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
users[1].Name = "ccc"
|
|
|
|
users = []*User{users[2], users[0], users[1]}
|
|
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: "bbb"},
|
|
&User{ID: db.Users.c.NextID(), Email: "c@d.com", Name: "aaa"},
|
|
&User{ID: db.Users.c.NextID(), Email: "e@f.com", Name: "bbb"})
|
|
|
|
for _, u := range users {
|
|
if _, err := db.Users.c.Insert(*u); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
db.Users.c.Delete(users[1].ID)
|
|
users = []*User{users[0], users[2]}
|
|
return users
|
|
})
|
|
}
|
|
|
|
func TestBTreeIndex_load_ErrDuplicate(t *testing.T) {
|
|
testWithDB(t, "", func(t *testing.T, db *DB) {
|
|
idx := NewBTreeIndex(
|
|
db.Users.c,
|
|
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)
|
|
}
|
|
})
|
|
}
|