Skip to content
Snippets Groups Projects
store_test.go 12.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Christian Pointner's avatar
    Christian Pointner committed
    //
    //  tank
    //
    //  Import and Playlist Daemon for autoradio project
    //
    //
    
    //  Copyright (C) 2017-2018 Christian Pointner <equinox@helsinki.at>
    
    Christian Pointner's avatar
    Christian Pointner committed
    //
    //  This file is part of tank.
    //
    //  tank is free software: you can redistribute it and/or modify
    //  it under the terms of the GNU General Public License as published by
    //  the Free Software Foundation, either version 3 of the License, or
    //  any later version.
    //
    //  tank is distributed in the hope that it will be useful,
    //  but WITHOUT ANY WARRANTY; without even the implied warranty of
    //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    //  GNU General Public License for more details.
    //
    //  You should have received a copy of the GNU General Public License
    //  along with tank. If not, see <http://www.gnu.org/licenses/>.
    //
    
    package store
    
    import (
    	"fmt"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	//	"io"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	"os"
    	"os/user"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	//	"reflect"
    	//	"sort"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	"testing"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	//	"time"
    	//	"github.com/coreos/bbolt"
    
    	testBasePath = "run/aura-tank_testing"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	testDBPath   = "/run/aura-tank_testing/.db.sqlite"
    
    Christian Pointner's avatar
    Christian Pointner committed
    	testGroup1   = "test1"
    	testGroup2   = "test2"
    
    	testUser1    = "user1"
    	testUser2    = "user2"
    
    Christian Pointner's avatar
    Christian Pointner committed
    func stringInSlice(slice []string, search string) bool {
    	for _, element := range slice {
    		if element == search {
    			return true
    		}
    	}
    	return false
    }
    
    
    Christian Pointner's avatar
    Christian Pointner committed
    func TestMain(m *testing.M) {
    	u, err := user.Current()
    	if err != nil {
    		os.Exit(-1)
    	}
    
    	testBasePath = fmt.Sprintf("/run/user/%s/aura-tank_testing", u.Uid)
    
    Christian Pointner's avatar
    Christian Pointner committed
    	testDBPath = filepath.Join(testBasePath, ".db.sqlite")
    
    Christian Pointner's avatar
    Christian Pointner committed
    	os.Exit(m.Run())
    }
    
    //
    // Testing
    //
    
    
    Christian Pointner's avatar
    Christian Pointner committed
    // func TestOpen(t *testing.T) {
    // 	// base-path is non-existing directory
    // 	if _, err := NewStore(&Config{"/nonexistend/"}); err == nil {
    // 		t.Fatalf("opening store in nonexisting directory should throw an error")
    // 	}
    
    // 	// store db-path is a directory
    // 	os.Remove(testDBPath)
    // 	if err := os.MkdirAll(testDBPath, 0700); err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    // 	if _, err := NewStore(&Config{testBasePath}); err == nil {
    // 		t.Fatalf("opening store using a directory should throw an error")
    // 	}
    
    // 	// exisiting but non-database file
    // 	os.Remove(testDBPath)
    // 	if f, err := os.Create(testDBPath); err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	} else {
    // 		io.WriteString(f, "this is not a sqlite db.")
    // 		f.Close()
    // 	}
    // 	if _, err := NewStore(&Config{testBasePath}); err == nil {
    // 		t.Fatalf("opening store using a invalid database should throw an error")
    // 	}
    
    // 	// bolt db no info bucket
    // 	os.Remove(testDBPath)
    // 	if db, err := bolt.Open(testDBPath, 0600, &bolt.Options{Timeout: 100 * time.Millisecond}); err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	} else {
    // 		db.Close()
    // 	}
    // 	if _, err := NewStore(&Config{testBasePath}); err == nil {
    // 		t.Fatalf("opening store without an info bucket should throw an error")
    // 	}
    
    // 	// bolt db no version key
    // 	os.Remove(testDBPath)
    // 	if db, err := bolt.Open(testDBPath, 0600, &bolt.Options{Timeout: 100 * time.Millisecond}); err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	} else {
    // 		err = db.Update(func(tx *bolt.Tx) error {
    // 			if _, err := tx.CreateBucket([]byte(infoBn)); err != nil {
    // 				return err
    // 			}
    // 			return nil
    // 		})
    // 		if err != nil {
    // 			t.Fatalf("unexpected error: %v", err)
    // 		}
    // 		if err = db.Close(); err != nil {
    // 			t.Fatalf("unexpected error: %v", err)
    // 		}
    // 	}
    // 	if _, err := NewStore(&Config{testBasePath}); err == nil {
    // 		t.Fatalf("opening store without a database version should throw an error")
    // 	}
    
    // 	// bolt db wrong version
    // 	if db, err := bolt.Open(testDBPath, 0600, &bolt.Options{Timeout: 100 * time.Millisecond}); err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	} else {
    // 		err = db.Update(func(tx *bolt.Tx) error {
    // 			b := tx.Bucket([]byte(infoBn))
    // 			if err := b.Put([]byte(storeVersionKey), itob(0)); err != nil {
    // 				return err
    // 			}
    // 			return nil
    // 		})
    // 		if err != nil {
    // 			t.Fatalf("unexpected error: %v", err)
    // 		}
    // 		if err = db.Close(); err != nil {
    // 			t.Fatalf("unexpected error: %v", err)
    // 		}
    // 	}
    // 	if _, err := NewStore(&Config{testBasePath}); err == nil {
    // 		t.Fatalf("opening store with wrong database version should throw an error")
    // 	}
    
    // 	// TODO: add checks for
    // 	//    - missing/wrong buckets (ie. store intregrity)
    
    // 	// create new bolt-db and reopen it
    // 	os.Remove(testDBPath)
    // 	store, err := NewStore(&Config{testBasePath})
    // 	if err != nil {
    // 		t.Fatalf("creating new store failed: %v", err)
    // 	}
    // 	store.Close()
    
    // 	store, err = NewStore(&Config{testBasePath})
    // 	if err != nil {
    // 		t.Fatalf("re-opening existing store failed: %v", err)
    // 	}
    // 	if _, err := NewStore(&Config{testBasePath}); err == nil {
    // 		t.Fatalf("opening already opened database should throw an error")
    // 	}
    // 	store.Close()
    // }
    
    // // Groups
    // //
    
    // func TestGroups(t *testing.T) {
    // 	os.Remove(testDBPath)
    // 	store, err := NewStore(&Config{testBasePath})
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	groups, err := store.ListGroups()
    // 	if err != nil {
    // 		t.Fatalf("listing groups failed: %v", err)
    // 	}
    // 	if len(groups) != 1 && groups[0] != publicGroupBn {
    // 		t.Fatalf("a newly created store should contain a single group '%s' but ListGroups returned: %q", publicGroupBn, groups)
    // 	}
    
    // 	if err = store.createGroup(testGroup1); err != nil {
    // 		t.Fatalf("creating group failed: %v", err)
    // 	}
    // 	groups, err = store.ListGroups()
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    // 	groupsSorted := sort.StringSlice(groups)
    // 	groupsSorted.Sort()
    
    // 	groupsExpected := sort.StringSlice([]string{publicGroupBn, testGroup1})
    // 	groupsExpected.Sort()
    
    // 	if !reflect.DeepEqual(groupsSorted, groupsExpected) {
    // 		t.Fatalf("store should contain groups %q but ListGroups returned: %q", groupsExpected, groupsSorted)
    // 	}
    
    // 	if err = store.createGroup(testGroup2); err != nil {
    // 		t.Fatalf("creating group failed: %v", err)
    // 	}
    // 	groups, err = store.ListGroups()
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    // 	groupsSorted = sort.StringSlice(groups)
    // 	groupsSorted.Sort()
    
    // 	groupsExpected = sort.StringSlice([]string{publicGroupBn, testGroup1, testGroup2})
    // 	groupsExpected.Sort()
    
    // 	if !reflect.DeepEqual(groupsSorted, groupsExpected) {
    // 		t.Fatalf("store should contain groups %q but ListGroups returned: %q", groupsExpected, groupsSorted)
    // 	}
    // }
    
    // // Files
    // //
    
    // func TestFilesListAndCreate(t *testing.T) {
    // 	os.Remove(testDBPath)
    // 	store, err := NewStore(&Config{testBasePath})
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	files, err := store.ListFiles(publicGroupBn)
    // 	if err != nil {
    // 		t.Fatalf("listing files of public group failed: %v", err)
    // 	}
    // 	if len(files) != 0 {
    // 		t.Fatalf("a newly created store should contain no files in public group but ListFiles returned: %v", files)
    // 	}
    
    // 	files, err = store.ListFiles("notexistend")
    // 	if err != nil {
    // 		t.Fatalf("listing files of not existing group shouldn't throw an error but returned: %v", err)
    // 	}
    // 	if len(files) != 0 {
    // 		t.Fatalf("listing files of not existing group should return and empty list but ListFiles returned: %v", files)
    // 	}
    
    // 	_, err = store.CreateFile(publicGroupBn, File{})
    // 	if err != nil {
    // 		t.Fatalf("creating file in public group failed: %v", err)
    // 	}
    
    // 	files, err = store.ListFiles(publicGroupBn)
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    // 	if len(files) != 1 {
    // 		t.Fatalf("ListFiles should return a single file but returned: %v", files)
    // 	}
    
    // 	_, err = store.CreateFile(testGroup1, File{})
    // 	if err != nil {
    // 		t.Fatalf("creating file in not existing group shouldn't throw an error but CreateFile returned: %v", err)
    // 	}
    
    // 	groups, err := store.ListGroups()
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    // 	if !stringInSlice(groups, testGroup1) {
    // 		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 not-existing file in existing group should return ErrNotFound, but GetFile returned: %v", err)
    // 	}
    // }
    
    // func TestFilesUpdate(t *testing.T) {
    // 	os.Remove(testDBPath)
    // 	store, err := NewStore(&Config{testBasePath})
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	err = store.UpdateFile(testGroup1, InvalidID, File{})
    // 	if err != ErrNotFound {
    // 		t.Fatalf("updateing not-existing file should return ErrNotFound, but UpdateFile returned: %v", err)
    // 	}
    
    // 	orig := NewFile(testUser1)
    // 	fileID, err := store.CreateFile(testGroup1, *orig)
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	updated := *orig
    // 	updated.Changed(testUser2)
    
    // 	err = store.UpdateFile(testGroup1, fileID, updated)
    // 	if err != nil {
    // 		t.Fatalf("updating file failed, UpdateFile returned: %v", err)
    // 	}
    
    // 	// TODO: check if file was successfully updated
    // }
    
    // func TestFilesDelete(t *testing.T) {
    // 	os.Remove(testDBPath)
    // 	store, err := NewStore(&Config{testBasePath})
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	err = store.DeleteFile(testGroup1, InvalidID)
    // 	if err != ErrNotFound {
    // 		t.Fatalf("deleting not-existing file should return ErrNotFound, but DeleteFile returned: %v", err)
    // 	}
    
    // 	file := NewFile(testUser1)
    // 	fileID, err := store.CreateFile(testGroup1, *file)
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	err = store.DeleteFile(testGroup1, fileID)
    // 	if err != nil {
    // 		t.Fatalf("deleting file failed, UpdateFile returned: %v", err)
    // 	}
    
    // 	err = store.DeleteFile(testGroup1, fileID)
    // 	if err != ErrNotFound {
    // 		t.Fatalf("repeated deletion of file should return ErrNotFound, but UpdateFile returned: %v", err)
    // 	}
    
    // 	// test file usage
    // 	fileID, err = store.CreateFile(testGroup1, *file)
    // 	if err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	file.UsedBy = []uint64{42}
    // 	file.Changed(testUser1)
    // 	if err = store.UpdateFile(testGroup1, fileID, *file); err != nil {
    // 		t.Fatalf("unexpected error: %v", err)
    // 	}
    
    // 	err = store.DeleteFile(testGroup1, fileID)
    // 	if err != ErrFileInUse {
    // 		t.Fatalf("deleting  file should return ErrFileInUse, but DeleteFile returned: %v", err)
    // 	}
    // }