// // tank // // Import and Playlist Daemon for autoradio project // // // Copyright (C) 2017-2018 Christian Pointner <equinox@helsinki.at> // // 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" "io" "os" "os/user" "path/filepath" // "reflect" // "sort" "testing" // "time" // "github.com/coreos/bbolt" ) var ( testBasePath = "run/aura-tank_testing" testDBType = "sqlite3" testDBConnection = "/run/aura-tank_testing/.db.sqlite" testGroup1 = "test1" testGroup2 = "test2" testUser1 = "user1" testUser2 = "user2" ) func stringInSlice(slice []string, search string) bool { for _, element := range slice { if element == search { return true } } return false } 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) testDBConnection = filepath.Join(testBasePath, ".db.sqlite") os.Exit(m.Run()) } // // Testing // func TestOpen(t *testing.T) { // base-path is non-existing directory cfg := &Config{} cfg.BasePath = "/nonexistend/" cfg.DB.Type = testDBType cfg.DB.Connection = testDBConnection if _, err := NewStore(cfg); err == nil { t.Fatalf("opening store in nonexisting directory should throw an error") } cfg.BasePath = testBasePath // exisiting but non-database file if err := os.MkdirAll(testBasePath, 0700); err != nil { t.Fatalf("unexpected error: %v", err) } if f, err := os.Create(testDBConnection); err != nil { t.Fatalf("unexpected error: %v", err) } else { io.WriteString(f, "this is not a sqlite db.") f.Close() } if _, err := NewStore(cfg); err == nil { t.Fatalf("opening store using a invalid database should throw an error") } // create new db and reopen it os.Remove(testDBConnection) store, err := NewStore(cfg) if err != nil { t.Fatalf("creating new store failed: %v", err) } store.Close() store, err = NewStore(cfg) if err != nil { t.Fatalf("re-opening existing store failed: %v", err) } store.Close() } func TestMigrations(t *testing.T) { cfg := &Config{} cfg.BasePath = testBasePath cfg.DB.Type = testDBType cfg.DB.Connection = testDBConnection os.Remove(testDBConnection) store, err := NewStore(cfg) if err != nil { t.Fatalf("creating new store failed: %v", err) } // TODO: This is only true for now!! if store.revision != initialMigrationID { t.Fatalf("for now new databases should have revision %q: got %q", initialMigrationID, store.revision) } store.Close() // TODO: needs more testing!!!! } // // 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) // } // }