unit-test return the right errors for locked DBs
This commit is contained in:
parent
77a48ca9cb
commit
bd5b8ee815
@ -6,6 +6,7 @@ package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gomark/logging"
|
||||
"gomark/tree"
|
||||
@ -78,16 +79,24 @@ type DsnOptions map[string]string
|
||||
|
||||
type DBError struct {
|
||||
// Database object where error occured
|
||||
D *DB
|
||||
DBName string
|
||||
|
||||
// Error that occured
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e DBError) Error() string {
|
||||
return fmt.Sprintf("<%s>: %s", e.D.Name, e.Err)
|
||||
func DBErr(dbName string, err error) DBError {
|
||||
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 {
|
||||
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 {
|
||||
log.Debug("Unlocking ...")
|
||||
|
||||
@ -239,12 +249,11 @@ func (db *DB) Init() (*DB, error) {
|
||||
locked, err := db.Locked()
|
||||
|
||||
if err != nil {
|
||||
return nil, DBError{D: db, Err: err}
|
||||
return nil, DBError{DBName: db.Name, Err: err}
|
||||
}
|
||||
|
||||
if locked {
|
||||
log.Warningf("<%s> is locked !", db.Path)
|
||||
db.tryUnlock()
|
||||
return nil, DBErr(db.Name, ErrVfsLocked)
|
||||
}
|
||||
|
||||
}
|
||||
@ -256,13 +265,13 @@ func (db *DB) Init() (*DB, error) {
|
||||
|
||||
// Secondary lock check provided by sqlx Ping() method
|
||||
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
|
||||
if err != nil {
|
||||
return nil, DBError{D: db, Err: err}
|
||||
return nil, DBError{DBName: db.Name, Err: err}
|
||||
}
|
||||
|
||||
return db, nil
|
||||
@ -273,20 +282,20 @@ func (db *DB) InitSchema() error {
|
||||
// Populate db schema
|
||||
tx, err := db.Handle.Begin()
|
||||
if err != nil {
|
||||
return DBError{D: db, Err: err}
|
||||
return DBError{DBName: db.Name, Err: err}
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(QCreateGomarkDBSchema)
|
||||
if err != nil {
|
||||
return DBError{D: db, Err: err}
|
||||
return DBError{DBName: db.Name, Err: err}
|
||||
}
|
||||
|
||||
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 {
|
||||
return DBError{D: db, Err: err}
|
||||
return DBError{DBName: db.Name, Err: err}
|
||||
}
|
||||
|
||||
log.Debugf("<%s> initialized", db.Name)
|
||||
|
@ -72,11 +72,11 @@ func TestNew(t *testing.T) {
|
||||
}
|
||||
|
||||
type AlwaysLockedChecker struct {
|
||||
err error
|
||||
locked bool
|
||||
}
|
||||
|
||||
func (f *AlwaysLockedChecker) Locked() (bool, error) {
|
||||
return true, nil
|
||||
return f.locked, nil
|
||||
}
|
||||
|
||||
type LockedSQLXOpener struct {
|
||||
@ -99,42 +99,57 @@ func TestInitLocked(t *testing.T) {
|
||||
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{
|
||||
Name: "test",
|
||||
Path: "file:test",
|
||||
EngineMode: DriverDefault,
|
||||
LockChecker: lockCheckerTrue,
|
||||
SQLXOpener: lockedOpener,
|
||||
Type: DBTypeRegularFile,
|
||||
LockChecker: lockChecker,
|
||||
}
|
||||
|
||||
_, err := testDB.Init()
|
||||
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
if err == nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
t.Run("VFSLockChecker", func(t *testing.T) {
|
||||
|
||||
t.Error("TODO")
|
||||
if err != DBErr(testDB.Name, ErrVfsLocked) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
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 {
|
||||
t.Error("should handle locked database")
|
||||
} else {
|
||||
_, err := testDB.Init()
|
||||
|
||||
if err == nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
e, _ := err.(DBError).Err.(sqlite3.Error)
|
||||
|
||||
if e.Code != sqlite3.ErrBusy {
|
||||
t.Fail()
|
||||
}
|
||||
t.Error("TODO")
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestGomarkDBCeate(t *testing.T) {
|
||||
|
@ -140,6 +140,8 @@ func NewFFBrowser() IBrowser {
|
||||
bookmarkPath,
|
||||
database.DBTypeFileDSN, opts).Init()
|
||||
if err != nil {
|
||||
|
||||
//Check Lock Error
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user