377 lines
7.4 KiB
Go
377 lines
7.4 KiB
Go
package mdb
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestFullMapIndex(t *testing.T) {
|
|
|
|
// Test against the emailMap index.
|
|
run := func(name string, inner func(t *testing.T, db *DB) map[string]*User) {
|
|
testWithDB(t, name, func(t *testing.T, db *DB) {
|
|
expected := inner(t, db)
|
|
|
|
if err := db.Users.emailMap.EqualsMap(expected); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
db.Close()
|
|
db = OpenDB(db.root, true)
|
|
|
|
if err := db.Users.emailMap.EqualsMap(expected); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
run("insert", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
|
|
user2, err := db.Users.c.Insert(*user)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(*user, user2) {
|
|
t.Fatal(*user, user2)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
return users
|
|
})
|
|
|
|
// TODO: insert duplicate
|
|
|
|
run("delete", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
|
|
user2, err := db.Users.c.Insert(*user)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(*user, user2) {
|
|
t.Fatal(*user, user2)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
var id string
|
|
for key := range users {
|
|
id = key
|
|
break
|
|
}
|
|
|
|
delete(users, id)
|
|
db.Users.emailMap.Delete(id)
|
|
|
|
return users
|
|
})
|
|
|
|
run("update non-indexed field", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
|
|
user2, err := db.Users.c.Insert(*user)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(*user, user2) {
|
|
t.Fatal(*user, user2)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
var id string
|
|
for key := range users {
|
|
id = key
|
|
break
|
|
}
|
|
|
|
err := db.Users.emailMap.Update(id, func(u User) (User, error) {
|
|
u.Name = "UPDATED"
|
|
return u, nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
users[id].Name = "UPDATED"
|
|
|
|
return users
|
|
})
|
|
|
|
run("update indexed field", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
|
|
user2, err := db.Users.c.Insert(*user)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(*user, user2) {
|
|
t.Fatal(*user, user2)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
var id uint64
|
|
var email string
|
|
for key := range users {
|
|
email = key
|
|
id = users[key].ID
|
|
break
|
|
}
|
|
|
|
err := db.Users.c.Update(id, func(u User) (User, error) {
|
|
u.Email = "test@x.com"
|
|
return u, nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
user := users[email]
|
|
user.Email = "test@x.com"
|
|
delete(users, email)
|
|
users[user.Email] = user
|
|
|
|
return users
|
|
})
|
|
|
|
run("update change key error", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
if _, err := db.Users.c.Insert(*user); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
var email string
|
|
for key := range users {
|
|
email = key
|
|
break
|
|
}
|
|
|
|
err := db.Users.emailMap.Update(email, func(u User) (User, error) {
|
|
u.Email = "test@x.com"
|
|
return u, nil
|
|
})
|
|
if err != ErrMismatchedIDs {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return users
|
|
})
|
|
|
|
run("update function error", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
if _, err := db.Users.c.Insert(*user); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
var email string
|
|
for key := range users {
|
|
email = key
|
|
break
|
|
}
|
|
|
|
myErr := errors.New("hello")
|
|
|
|
err := db.Users.emailMap.Update(email, func(u User) (User, error) {
|
|
return u, myErr
|
|
})
|
|
if err != myErr {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return users
|
|
})
|
|
|
|
run("update ErrAbortUpdate", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
if _, err := db.Users.c.Insert(*user); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
var email string
|
|
for key := range users {
|
|
email = key
|
|
break
|
|
}
|
|
|
|
err := db.Users.emailMap.Update(email, func(u User) (User, error) {
|
|
return u, ErrAbortUpdate
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return users
|
|
})
|
|
|
|
run("update ErrNotFound", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
for i := uint64(1); i < 10; i++ {
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: fmt.Sprintf("a.%d@c.com", i),
|
|
Name: fmt.Sprintf("name.%d", i),
|
|
ExtID: fmt.Sprintf("EXTID.%d", i),
|
|
}
|
|
if _, err := db.Users.c.Insert(*user); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
users[user.Email] = user
|
|
}
|
|
|
|
var email string
|
|
for key := range users {
|
|
email = key
|
|
break
|
|
}
|
|
|
|
err := db.Users.emailMap.Update(email+"x", func(u User) (User, error) {
|
|
return u, nil
|
|
})
|
|
if err != ErrNotFound {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return users
|
|
})
|
|
|
|
run("insert conflict", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
user := &User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: "a@b.com",
|
|
Name: "a",
|
|
ExtID: "",
|
|
}
|
|
|
|
if _, err := db.Users.c.Insert(*user); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
users[user.Email] = user
|
|
|
|
user2 := User{
|
|
ID: db.Users.c.NextID(),
|
|
Email: "a@b.com",
|
|
Name: "someone else",
|
|
ExtID: "123",
|
|
}
|
|
|
|
_, err := db.Users.c.Insert(user2)
|
|
if !errors.Is(err, ErrDuplicate) {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return users
|
|
})
|
|
|
|
run("update conflict", func(t *testing.T, db *DB) map[string]*User {
|
|
users := map[string]*User{}
|
|
|
|
user1 := &User{ID: db.Users.c.NextID(), Email: "a@b.com", Name: "a"}
|
|
user2 := &User{ID: db.Users.c.NextID(), Email: "x@y.com", Name: "x"}
|
|
|
|
users[user1.Email] = user1
|
|
users[user2.Email] = user2
|
|
|
|
for _, u := range users {
|
|
if _, err := db.Users.c.Insert(*u); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
err := db.Users.c.Update(user2.ID, func(u User) (User, error) {
|
|
u.Email = "a@b.com"
|
|
return u, nil
|
|
})
|
|
if !errors.Is(err, ErrDuplicate) {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return users
|
|
})
|
|
// update conflict
|
|
}
|
|
|
|
func TestPartialMapIndex(t *testing.T) {
|
|
// insert into index
|
|
// insert into index conflict
|
|
// insert outside index
|
|
// insert and delete in index
|
|
// insert and delete outside index
|
|
// update outside index
|
|
// update into index
|
|
// update function error
|
|
// udpate ErrAbortUpdate
|
|
// update ErrNotFound
|
|
// update conflict in to in
|
|
// update conflict out to in
|
|
}
|