Files
sqlite3/vfs/lock_test.go

211 lines
5.1 KiB
Go
Raw Normal View History

2023-06-01 18:11:37 +01:00
package vfs
2023-01-30 08:12:12 +00:00
import (
"context"
"os"
2023-02-20 13:30:01 +00:00
"path/filepath"
2023-01-30 08:12:12 +00:00
"testing"
2023-03-29 15:01:25 +01:00
"github.com/ncruces/go-sqlite3/internal/util"
2023-05-12 12:13:06 +01:00
"github.com/tetratelabs/wazero/experimental/wazerotest"
2023-01-30 08:12:12 +00:00
)
func Test_vfsLock(t *testing.T) {
2024-05-02 23:22:43 +01:00
if !SupportsFileLocking {
t.Skip("skipping without locks")
}
2023-02-20 13:30:01 +00:00
name := filepath.Join(t.TempDir(), "test.db")
2023-02-10 17:14:43 +00:00
// Create a temporary file.
2023-02-20 13:30:01 +00:00
file1, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
2023-01-30 08:12:12 +00:00
if err != nil {
t.Fatal(err)
}
defer file1.Close()
2023-02-10 17:14:43 +00:00
// Open the temporary file again.
2023-01-30 08:12:12 +00:00
file2, err := os.OpenFile(name, os.O_RDWR, 0)
if err != nil {
t.Fatal(err)
}
defer file2.Close()
2023-02-10 17:14:43 +00:00
const (
pFile1 = 4
pFile2 = 16
pOutput = 32
)
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2024-04-26 16:25:45 +01:00
ctx := util.NewContext(context.TODO())
2023-02-10 17:14:43 +00:00
2023-05-18 16:00:34 +01:00
vfsFileRegister(ctx, mod, pFile1, &vfsFile{File: file1})
vfsFileRegister(ctx, mod, pFile2, &vfsFile{File: file2})
2023-03-07 03:51:07 +00:00
2023-03-29 15:01:25 +01:00
rc := vfsCheckReservedLock(ctx, mod, pFile1, pOutput)
2023-01-30 08:12:12 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got != 0 {
2023-01-30 08:12:12 +00:00
t.Error("file was locked")
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile2, pOutput)
2023-03-23 11:26:19 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got != 0 {
2023-03-23 11:26:19 +00:00
t.Error("file was locked")
}
2023-05-19 14:45:40 +01:00
rc = vfsFileControl(ctx, mod, pFile2, _FCNTL_LOCKSTATE, pOutput)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, pOutput); got != uint32(LOCK_NONE) {
t.Error("invalid lock state", got)
}
2023-01-30 08:12:12 +00:00
2023-05-19 03:04:07 +01:00
rc = vfsLock(ctx, mod, pFile2, LOCK_SHARED)
2023-01-30 08:12:12 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile1, pOutput)
2023-01-30 08:12:12 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got != 0 {
2023-01-30 08:12:12 +00:00
t.Error("file was locked")
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile2, pOutput)
2023-03-23 11:26:19 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got != 0 {
2023-03-23 11:26:19 +00:00
t.Error("file was locked")
}
2023-05-19 14:45:40 +01:00
rc = vfsFileControl(ctx, mod, pFile2, _FCNTL_LOCKSTATE, pOutput)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, pOutput); got != uint32(LOCK_SHARED) {
t.Error("invalid lock state", got)
}
2023-01-30 08:12:12 +00:00
2023-05-19 03:04:07 +01:00
rc = vfsLock(ctx, mod, pFile2, LOCK_RESERVED)
2023-02-10 17:14:43 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-05-19 03:04:07 +01:00
rc = vfsLock(ctx, mod, pFile2, LOCK_SHARED)
2023-01-30 08:12:12 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile1, pOutput)
2023-01-30 08:12:12 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got == 0 {
t.Log("file wasn't locked, locking is incompatible with SQLite")
2023-01-30 08:12:12 +00:00
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile2, pOutput)
2023-03-23 11:26:19 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got == 0 {
2023-03-23 11:26:19 +00:00
t.Error("file wasn't locked")
}
2023-05-19 14:45:40 +01:00
rc = vfsFileControl(ctx, mod, pFile2, _FCNTL_LOCKSTATE, pOutput)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, pOutput); got != uint32(LOCK_RESERVED) {
t.Error("invalid lock state", got)
}
2023-02-10 17:14:43 +00:00
2023-05-19 03:04:07 +01:00
rc = vfsLock(ctx, mod, pFile2, LOCK_EXCLUSIVE)
2023-02-10 17:14:43 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile1, pOutput)
2023-02-10 17:14:43 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got == 0 {
t.Log("file wasn't locked, locking is incompatible with SQLite")
2023-02-10 17:14:43 +00:00
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile2, pOutput)
2023-03-23 11:26:19 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got == 0 {
2023-03-23 11:26:19 +00:00
t.Error("file wasn't locked")
}
2023-05-19 14:45:40 +01:00
rc = vfsFileControl(ctx, mod, pFile2, _FCNTL_LOCKSTATE, pOutput)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, pOutput); got != uint32(LOCK_EXCLUSIVE) {
t.Error("invalid lock state", got)
}
2023-02-10 17:14:43 +00:00
2023-05-19 03:04:07 +01:00
rc = vfsLock(ctx, mod, pFile1, LOCK_SHARED)
2023-02-10 17:14:43 +00:00
if rc == _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile1, pOutput)
2023-02-23 13:29:51 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got == 0 {
t.Log("file wasn't locked, locking is incompatible with SQLite")
2023-02-23 13:29:51 +00:00
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile2, pOutput)
2023-03-23 11:26:19 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got == 0 {
2023-03-23 11:26:19 +00:00
t.Error("file wasn't locked")
}
2023-05-19 14:45:40 +01:00
rc = vfsFileControl(ctx, mod, pFile1, _FCNTL_LOCKSTATE, pOutput)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, pOutput); got != uint32(LOCK_NONE) {
t.Error("invalid lock state", got)
}
2023-02-23 13:29:51 +00:00
2023-05-19 03:04:07 +01:00
rc = vfsUnlock(ctx, mod, pFile2, LOCK_SHARED)
2023-02-10 17:14:43 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile1, pOutput)
2023-02-23 13:29:51 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got != 0 {
2023-02-23 13:29:51 +00:00
t.Error("file was locked")
}
2023-03-29 15:01:25 +01:00
rc = vfsCheckReservedLock(ctx, mod, pFile2, pOutput)
2023-03-23 11:26:19 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, pOutput); got != 0 {
2023-03-23 11:26:19 +00:00
t.Error("file was locked")
}
2023-02-23 13:29:51 +00:00
2023-05-19 03:04:07 +01:00
rc = vfsLock(ctx, mod, pFile1, LOCK_SHARED)
2023-02-10 17:14:43 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-05-19 14:45:40 +01:00
rc = vfsFileControl(ctx, mod, pFile1, _FCNTL_LOCKSTATE, pOutput)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, pOutput); got != uint32(LOCK_SHARED) {
t.Error("invalid lock state", got)
}
2023-01-30 08:12:12 +00:00
}