safing-portbase/database/database_test.go
2019-06-27 13:29:56 +02:00

170 lines
2.9 KiB
Go

package database
import (
"fmt"
"io/ioutil"
"log"
"os"
"reflect"
"runtime/pprof"
"testing"
"time"
q "github.com/safing/portbase/database/query"
_ "github.com/safing/portbase/database/storage/badger"
_ "github.com/safing/portbase/database/storage/bbolt"
_ "github.com/safing/portbase/database/storage/fstree"
)
func makeKey(dbName, key string) string {
return fmt.Sprintf("%s:%s", dbName, key)
}
func testDatabase(t *testing.T, storageType string) {
dbName := fmt.Sprintf("testing-%s", storageType)
_, err := Register(&Database{
Name: dbName,
Description: fmt.Sprintf("Unit Test Database for %s", storageType),
StorageType: storageType,
PrimaryAPI: "",
})
if err != nil {
t.Fatal(err)
}
// hook
hook, err := RegisterHook(q.New(dbName).MustBeValid(), &HookBase{})
if err != nil {
t.Fatal(err)
}
// interface
db := NewInterface(nil)
// sub
sub, err := db.Subscribe(q.New(dbName).MustBeValid())
if err != nil {
t.Fatal(err)
}
A := NewExample(makeKey(dbName, "A"), "Herbert", 411)
err = A.Save()
if err != nil {
t.Fatal(err)
}
B := NewExample(makeKey(dbName, "B"), "Fritz", 347)
err = B.Save()
if err != nil {
t.Fatal(err)
}
C := NewExample(makeKey(dbName, "C"), "Norbert", 217)
err = C.Save()
if err != nil {
t.Fatal(err)
}
exists, err := db.Exists(makeKey(dbName, "A"))
if err != nil {
t.Fatal(err)
}
if !exists {
t.Fatalf("record %s should exist!", makeKey(dbName, "A"))
}
A1, err := GetExample(makeKey(dbName, "A"))
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(A, A1) {
log.Fatalf("A and A1 mismatch, A1: %v", A1)
}
query, err := q.New(dbName).Where(
q.And(
q.Where("Name", q.EndsWith, "bert"),
q.Where("Score", q.GreaterThan, 100),
),
).Check()
if err != nil {
t.Fatal(err)
}
it, err := db.Query(query)
if err != nil {
t.Fatal(err)
}
cnt := 0
for _ = range it.Next {
cnt++
}
if it.Err() != nil {
t.Fatal(it.Err())
}
if cnt != 2 {
t.Fatalf("expected two records, got %d", cnt)
}
err = hook.Cancel()
if err != nil {
t.Fatal(err)
}
err = sub.Cancel()
if err != nil {
t.Fatal(err)
}
}
func TestDatabaseSystem(t *testing.T) {
// panic after 10 seconds, to check for locks
go func() {
time.Sleep(10 * time.Second)
fmt.Println("===== TAKING TOO LONG - PRINTING STACK TRACES =====")
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
os.Exit(1)
}()
testDir, err := ioutil.TempDir("", "testing-")
if err != nil {
t.Fatal(err)
}
ok := SetLocation(testDir)
if !ok {
t.Fatal("database location already set")
}
err = Initialize()
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(testDir) // clean up
testDatabase(t, "badger")
testDatabase(t, "bbolt")
testDatabase(t, "fstree")
err = MaintainRecordStates()
if err != nil {
t.Fatal(err)
}
err = Maintain()
if err != nil {
t.Fatal(err)
}
err = MaintainThorough()
if err != nil {
t.Fatal(err)
}
err = Shutdown()
if err != nil {
t.Fatal(err)
}
}