Skip to content
Snippets Groups Projects
Commit e0405579 authored by Christian Pointner's avatar Christian Pointner
Browse files

files methods are almost done now (needs some tests)

parent 88c8f638
No related branches found
No related tags found
No related merge requests found
......@@ -37,7 +37,7 @@ format:
$(GOCMD) fmt
test:
$(GOCMD) test
$(GOCMD) test -v
bench:
$(GOCMD) test -bench=.
......
......@@ -38,7 +38,7 @@ func getFilesBucket(tx *bolt.Tx, group string) (files *bolt.Bucket, err error) {
}
if gb == nil {
if !tx.Writable() {
return // for read-only transactions this function might return nil for files
return // for read-only transactions this function might return files = nil
}
if gb, err = createGroup(tx, group); err != nil {
return
......@@ -57,7 +57,7 @@ func (st *Store) ListFiles(group string) (files Files, err error) {
if err != nil {
return err
}
if fb == nil {
if fb == nil { // this is a read-only transaction getFilesBucket might return fb = nil
return nil
}
files = make(Files)
......@@ -84,26 +84,70 @@ func (st *Store) CreateFile(group string, file File) (id uint64, err error) {
if id, err = getNextID(tx); err != nil {
return err
}
v, err := json.Marshal(file)
bFile, err := json.Marshal(file)
if err != nil {
return err
}
return fb.Put(itob(id), v)
return fb.Put(itob(id), bFile)
})
return
}
func (st *Store) GetFile(group string, id uint64) (File, error) {
// TODO: implement this
return File{}, ErrNotImplented
func (st *Store) GetFile(group string, id uint64) (file File, err error) {
err = st.db.View(func(tx *bolt.Tx) error {
fb, err := getFilesBucket(tx, group)
if err != nil {
return err
}
if fb == nil { // this is a read-only transaction getFilesBucket might return fb = nil
return ErrNotFound
}
bFile := fb.Get(itob(id))
if bFile == nil {
return ErrNotFound
}
return json.Unmarshal(bFile, &file)
})
return
}
func (st *Store) UpdateFile(group string, id uint64, new File) error {
// TODO: implement this
return ErrNotImplented
func (st *Store) UpdateFile(group string, id uint64, file File) (err error) {
err = st.db.Update(func(tx *bolt.Tx) error {
fb, err := getFilesBucket(tx, group)
if err != nil {
return err
}
bFile := fb.Get(itob(id))
if bFile == nil {
return ErrNotFound
}
bFile, err = json.Marshal(file)
if err != nil {
return err
}
return fb.Put(itob(id), bFile)
})
return
}
func (st *Store) DeleteFile(group string, id uint64) error {
// TODO: implement this
return ErrNotImplented
func (st *Store) DeleteFile(group string, id uint64) (err error) {
err = st.db.Update(func(tx *bolt.Tx) error {
fb, err := getFilesBucket(tx, group)
if err != nil {
return err
}
bFile := fb.Get(itob(id))
if bFile == nil {
return ErrNotFound
}
var file File
if err = json.Unmarshal(bFile, &file); err != nil {
return err
}
if len(file.UsedBy) > 0 {
return ErrFileInUse
}
return fb.Delete(itob(id))
})
return
}
......@@ -43,6 +43,8 @@ var (
testDBPath = "/run/aura-tank_testing/.db.bolt"
testGroup1 = "test1"
testGroup2 = "test2"
testUser1 = "user1"
testUser2 = "user2"
)
func stringInSlice(slice []string, search string) bool {
......@@ -276,3 +278,66 @@ func TestFilesListAndCreate(t *testing.T) {
t.Fatalf("creating file in not existing group '%s' should create that group but ListGroups returned : %q", testGroup1, groups)
}
}
func TestNewAndChangedFile(t *testing.T) {
file := NewFile(testUser1)
if file.Created.User != testUser1 {
t.Fatalf("new file should be created by user '%s' but is: '%s'", testUser1, file.Created.User)
}
age := time.Since(file.Created.Timestamp)
if age < 0 || age > 3*time.Second {
t.Fatalf("new file timestamp is off: %s", file.Created.Timestamp)
}
if file.LastChanged.User != "" || !file.LastChanged.Timestamp.IsZero() {
t.Fatalf("new file's changed value should be empty but is: %+v", file.LastChanged)
}
orig := *file
file.Changed(testUser2)
if file.Created.User != orig.Created.User {
t.Fatalf("marking file as changed shouldn't change Created.User or Created.Timestamp, was '%+v' but is now '%+v'", orig.Created, file.Created)
}
if file.LastChanged.User != testUser2 {
t.Fatalf("changed file should have changed by user '%s' but is: '%s'", testUser2, file.LastChanged.User)
}
age = time.Since(file.LastChanged.Timestamp)
if age < 0 || age > 3*time.Second {
t.Fatalf("changed file timestamp is off: %s", file.LastChanged.Timestamp)
}
}
func TestFilesCreateAndGet(t *testing.T) {
os.Remove(testDBPath)
store, err := NewStore(&Config{testBasePath})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
_, err = store.GetFile(testGroup1, InvalidID)
if err != ErrNotFound {
t.Fatalf("getting file in not-existing group should return ErrNotFound, but GetFile returned: %v", err)
}
expected := NewFile(testUser1)
fileID, err := store.CreateFile(testGroup1, *expected)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
_, err = store.GetFile(testGroup1, fileID)
//file, err := store.GetFile(testGroup1, fileID)
if err != nil {
t.Fatalf("getting existing file from store shouldn't return an error, but GetFile returned: %v", err)
}
// This does not work because DeepEqual does not use time.Equal when comparing timestamps...
// if !reflect.DeepEqual(expected, file) {
// t.Fatalf("GetFile returned different file than expected. Got %v, expected %v", file, expected)
// }
_, err = store.GetFile(testGroup1, InvalidID)
if err != ErrNotFound {
t.Fatalf("getting file not-existing file in existing group should return ErrNotFound, but GetFile returned: %v", err)
}
}
......@@ -50,6 +50,9 @@ var (
ErrNotImplented = errors.New("not implemented")
ErrNotFound = errors.New("not found")
ErrFileInUse = errors.New("file is in use by at least one playlist")
InvalidID = uint64(0)
)
// TODO: use conversion to binary because it is faster...
......@@ -100,7 +103,18 @@ type File struct {
Metadata FileMetadata `json:"m"`
Size uint64 `json:"s"`
UsedBy []uint64 `json:"ub"`
Dirty bool `json:"d"`
}
func NewFile(user string) (f *File) {
f = &File{}
f.Created.User = user
f.Created.Timestamp = time.Now()
return
}
func (f *File) Changed(user string) {
f.LastChanged.User = user
f.LastChanged.Timestamp = time.Now()
}
type Files map[uint64]File
......@@ -112,4 +126,16 @@ type Playlist struct {
// TODO: playlist storage layout
}
func NewPlaylist(user string) (p *Playlist) {
p = &Playlist{}
p.Created.User = user
p.Created.Timestamp = time.Now()
return
}
func (p *Playlist) Changed(user string) {
p.LastChanged.User = user
p.LastChanged.Timestamp = time.Now()
}
type Playlists map[uint64]Playlist
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment