unit-test return the right errors for locked DBs

This commit is contained in:
Chakib Ben Ziane 2018-12-04 05:02:47 +01:00
parent 77a48ca9cb
commit bd5b8ee815
3 changed files with 65 additions and 39 deletions

View File

@ -6,6 +6,7 @@ package database
import ( import (
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"gomark/logging" "gomark/logging"
"gomark/tree" "gomark/tree"
@ -78,16 +79,24 @@ type DsnOptions map[string]string
type DBError struct { type DBError struct {
// Database object where error occured // Database object where error occured
D *DB DBName string
// Error that occured // Error that occured
Err error Err error
} }
func (e DBError) Error() string { func DBErr(dbName string, err error) DBError {
return fmt.Sprintf("<%s>: %s", e.D.Name, e.Err) return DBError{Err: err}
} }
func (e DBError) Error() string {
return fmt.Sprintf("<%s>: %s", e.DBName, e.Err)
}
var (
ErrVfsLocked = errors.New("vfs locked")
)
type Opener interface { type Opener interface {
Open(driver string, dsn string) error Open(driver string, dsn string) error
} }
@ -208,6 +217,7 @@ func New(name string, dbPath string, dbFormat string, opts ...DsnOptions) *DB {
} }
//TODO: try unlock at the browser level !
func (db *DB) tryUnlock() error { func (db *DB) tryUnlock() error {
log.Debug("Unlocking ...") log.Debug("Unlocking ...")
@ -239,12 +249,11 @@ func (db *DB) Init() (*DB, error) {
locked, err := db.Locked() locked, err := db.Locked()
if err != nil { if err != nil {
return nil, DBError{D: db, Err: err} return nil, DBError{DBName: db.Name, Err: err}
} }
if locked { if locked {
log.Warningf("<%s> is locked !", db.Path) return nil, DBErr(db.Name, ErrVfsLocked)
db.tryUnlock()
} }
} }
@ -256,13 +265,13 @@ func (db *DB) Init() (*DB, error) {
// Secondary lock check provided by sqlx Ping() method // Secondary lock check provided by sqlx Ping() method
if err != nil && sqlErr.Code == sqlite3.ErrBusy { if err != nil && sqlErr.Code == sqlite3.ErrBusy {
return nil, DBError{D: db, Err: err} return nil, DBError{DBName: db.Name, Err: err}
} }
// Return all other errors // Return all other errors
if err != nil { if err != nil {
return nil, DBError{D: db, Err: err} return nil, DBError{DBName: db.Name, Err: err}
} }
return db, nil return db, nil
@ -273,20 +282,20 @@ func (db *DB) InitSchema() error {
// Populate db schema // Populate db schema
tx, err := db.Handle.Begin() tx, err := db.Handle.Begin()
if err != nil { if err != nil {
return DBError{D: db, Err: err} return DBError{DBName: db.Name, Err: err}
} }
stmt, err := tx.Prepare(QCreateGomarkDBSchema) stmt, err := tx.Prepare(QCreateGomarkDBSchema)
if err != nil { if err != nil {
return DBError{D: db, Err: err} return DBError{DBName: db.Name, Err: err}
} }
if _, err = stmt.Exec(); err != nil { if _, err = stmt.Exec(); err != nil {
return DBError{D: db, Err: err} return DBError{DBName: db.Name, Err: err}
} }
if err = tx.Commit(); err != nil { if err = tx.Commit(); err != nil {
return DBError{D: db, Err: err} return DBError{DBName: db.Name, Err: err}
} }
log.Debugf("<%s> initialized", db.Name) log.Debugf("<%s> initialized", db.Name)

View File

@ -72,11 +72,11 @@ func TestNew(t *testing.T) {
} }
type AlwaysLockedChecker struct { type AlwaysLockedChecker struct {
err error locked bool
} }
func (f *AlwaysLockedChecker) Locked() (bool, error) { func (f *AlwaysLockedChecker) Locked() (bool, error) {
return true, nil return f.locked, nil
} }
type LockedSQLXOpener struct { type LockedSQLXOpener struct {
@ -99,42 +99,57 @@ func TestInitLocked(t *testing.T) {
err: sqlite3.Error{Code: sqlite3.ErrBusy}, err: sqlite3.Error{Code: sqlite3.ErrBusy},
} }
lockChecker := &AlwaysLockedChecker{} lockCheckerTrue := &AlwaysLockedChecker{locked: true}
lockCheckerFalse := &AlwaysLockedChecker{locked: false}
t.Run("VFSLockChecker", func(t *testing.T) {
testDB := &DB{ testDB := &DB{
Name: "test", Name: "test",
Path: "file:test", Path: "file:test",
EngineMode: DriverDefault, EngineMode: DriverDefault,
LockChecker: lockCheckerTrue,
SQLXOpener: lockedOpener, SQLXOpener: lockedOpener,
Type: DBTypeRegularFile, Type: DBTypeRegularFile,
LockChecker: lockChecker,
} }
_, err := testDB.Init() _, err := testDB.Init()
if err != nil { if err == nil {
t.Log(err) t.Fail()
}
t.Run("VFSLockChecker", func(t *testing.T) { if err != DBErr(testDB.Name, ErrVfsLocked) {
t.Fail()
t.Error("TODO") }
}) })
t.Run("SQLXLockChecker", func(t *testing.T) { t.Run("SQLXLockChecker", func(t *testing.T) {
e, _ := err.(DBError).Err.(sqlite3.Error) testDB := &DB{
Name: "test",
Path: "file:test",
EngineMode: DriverDefault,
LockChecker: lockCheckerFalse,
SQLXOpener: lockedOpener,
Type: DBTypeRegularFile,
}
if e.Code == sqlite3.ErrBusy { _, err := testDB.Init()
t.Error("should handle locked database")
} else { if err == nil {
t.Fail()
}
e, _ := err.(DBError).Err.(sqlite3.Error)
if e.Code != sqlite3.ErrBusy {
t.Fail() t.Fail()
} }
t.Error("TODO")
}) })
}
} }
func TestGomarkDBCeate(t *testing.T) { func TestGomarkDBCeate(t *testing.T) {

View File

@ -140,6 +140,8 @@ func NewFFBrowser() IBrowser {
bookmarkPath, bookmarkPath,
database.DBTypeFileDSN, opts).Init() database.DBTypeFileDSN, opts).Init()
if err != nil { if err != nil {
//Check Lock Error
log.Fatal(err) log.Fatal(err)
} }