package storm import ( "io/ioutil" "os" "path/filepath" "testing" "github.com/asdine/storm/codec/gob" "github.com/boltdb/bolt" "github.com/stretchr/testify/assert" ) func TestSave(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := Open(filepath.Join(dir, "storm.db")) err := db.Save(&SimpleUser{ID: 10, Name: "John"}) assert.NoError(t, err) err = db.Save(&SimpleUser{Name: "John"}) assert.Error(t, err) assert.Equal(t, ErrZeroID, err) err = db.Save(&ClassicBadTags{ID: "id", PublicField: 100}) assert.Error(t, err) assert.Equal(t, ErrUnknownTag, err) err = db.Save(&UserWithNoID{Name: "John"}) assert.Error(t, err) assert.Equal(t, ErrNoID, err) err = db.Save(&UserWithIDField{ID: 10, Name: "John"}) assert.NoError(t, err) u := UserWithEmbeddedIDField{} u.ID = 150 u.Name = "Pete" u.Age = 10 err = db.Save(&u) assert.NoError(t, err) v := UserWithIDField{ID: 10, Name: "John"} err = db.Save(&v) assert.NoError(t, err) w := UserWithEmbeddedField{} w.ID = 150 w.Name = "John" err = db.Save(&w) assert.NoError(t, err) db.Bolt.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte("UserWithIDField")) assert.NotNil(t, bucket) i, err := toBytes(10, gob.Codec) assert.NoError(t, err) val := bucket.Get(i) assert.NotNil(t, val) content, err := db.Codec.Encode(&v) assert.NoError(t, err) assert.Equal(t, content, val) return nil }) } func TestSaveUnique(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := Open(filepath.Join(dir, "storm.db")) u1 := UniqueNameUser{ID: 10, Name: "John", age: 10} err := db.Save(&u1) assert.NoError(t, err) u2 := UniqueNameUser{ID: 11, Name: "John", age: 100} err = db.Save(&u2) assert.Error(t, err) assert.Equal(t, ErrAlreadyExists, err) // same id u3 := UniqueNameUser{ID: 10, Name: "Jake", age: 100} err = db.Save(&u3) assert.NoError(t, err) db.Bolt.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte("UniqueNameUser")) uniqueBucket := bucket.Bucket([]byte(indexPrefix + "Name")) assert.NotNil(t, uniqueBucket) id := uniqueBucket.Get([]byte("Jake")) i, err := toBytes(10, gob.Codec) assert.NoError(t, err) assert.Equal(t, i, id) id = uniqueBucket.Get([]byte("John")) assert.Nil(t, id) return nil }) } func TestSaveIndex(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := Open(filepath.Join(dir, "storm.db")) u1 := IndexedNameUser{ID: 10, Name: "John", age: 10} err := db.Save(&u1) assert.NoError(t, err) u1 = IndexedNameUser{ID: 10, Name: "John", age: 10} err = db.Save(&u1) assert.NoError(t, err) u2 := IndexedNameUser{ID: 11, Name: "John", age: 100} err = db.Save(&u2) assert.NoError(t, err) name1 := "Jake" name2 := "Jane" name3 := "James" for i := 0; i < 1000; i++ { u := IndexedNameUser{ID: i + 1} if i%2 == 0 { u.Name = name1 } else { u.Name = name2 } db.Save(&u) } var users []IndexedNameUser err = db.Find("Name", name1, &users) assert.NoError(t, err) assert.Len(t, users, 500) err = db.Find("Name", name2, &users) assert.NoError(t, err) assert.Len(t, users, 500) err = db.Find("Name", name3, &users) assert.Error(t, err) assert.Equal(t, ErrNotFound, err) err = db.Save(nil) assert.Error(t, err) assert.Equal(t, ErrBadType, err) } func TestSaveEmptyValues(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := Open(filepath.Join(dir, "storm.db")) defer db.Close() u := User{ ID: 10, } err := db.Save(&u) assert.NoError(t, err) var v User err = db.One("ID", 10, &v) assert.NoError(t, err) assert.Equal(t, 10, v.ID) u.Name = "John" u.Slug = "john" err = db.Save(&u) assert.NoError(t, err) err = db.One("Name", "John", &v) assert.NoError(t, err) assert.Equal(t, "John", v.Name) assert.Equal(t, "john", v.Slug) err = db.One("Slug", "john", &v) assert.NoError(t, err) assert.Equal(t, "John", v.Name) assert.Equal(t, "john", v.Slug) u.Name = "" u.Slug = "" err = db.Save(&u) assert.NoError(t, err) err = db.One("Name", "John", &v) assert.Error(t, err) err = db.One("Slug", "john", &v) assert.Error(t, err) } func TestSaveAutoIncrement(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := Open(filepath.Join(dir, "storm.db"), AutoIncrement()) defer db.Close() for i := 1; i < 10; i++ { s := SimpleUser{Name: "John"} err := db.Save(&s) assert.NoError(t, err) assert.Equal(t, i, s.ID) } u := UserWithUint64IDField{Name: "John"} err := db.Save(&u) assert.NoError(t, err) assert.Equal(t, uint64(1), u.ID) v := UserWithUint64IDField{} err = db.One("ID", uint64(1), &v) assert.NoError(t, err) assert.Equal(t, u, v) ui := UserWithIDField{Name: "John"} err = db.Save(&ui) assert.NoError(t, err) assert.Equal(t, 1, ui.ID) vi := UserWithIDField{} err = db.One("ID", 1, &vi) assert.NoError(t, err) assert.Equal(t, ui, vi) us := UserWithStringIDField{Name: "John"} err = db.Save(&us) assert.Error(t, err) assert.Equal(t, ErrZeroID, err) } func TestSaveDifferentBucketRoot(t *testing.T) { dir, _ := ioutil.TempDir(os.TempDir(), "storm") defer os.RemoveAll(dir) db, _ := Open(filepath.Join(dir, "storm.db"), AutoIncrement()) defer db.Close() assert.Len(t, db.rootBucket, 0) dbSub := db.From("sub") assert.NotEqual(t, dbSub, db) assert.Len(t, dbSub.rootBucket, 1) err := db.Save(&User{ID: 10, Name: "John"}) assert.NoError(t, err) err = dbSub.Save(&User{ID: 11, Name: "Paul"}) assert.NoError(t, err) var ( john User paul User ) err = db.One("Name", "John", &john) assert.NoError(t, err) err = db.One("Name", "Paul", &paul) assert.Error(t, err) err = dbSub.One("Name", "Paul", &paul) assert.NoError(t, err) err = dbSub.One("Name", "John", &john) assert.Error(t, err) }