Files
sqlite3/vfs/vfs_test.go

343 lines
7.8 KiB
Go
Raw Normal View History

2023-06-01 18:11:37 +01:00
package vfs
2023-01-26 02:48:31 +00:00
import (
"bytes"
"context"
2023-01-26 12:15:34 +00:00
"errors"
"io/fs"
2023-05-19 14:45:40 +01:00
"math"
2023-01-26 12:15:34 +00:00
"os"
2023-10-16 12:26:25 +01:00
"os/user"
2023-01-28 12:47:39 +00:00
"path/filepath"
2023-02-21 12:51:52 +00:00
"syscall"
2023-01-26 02:48:31 +00:00
"testing"
"time"
2024-10-18 12:20:32 +01:00
"github.com/tetratelabs/wazero/experimental/wazerotest"
2023-03-29 15:01:25 +01:00
"github.com/ncruces/go-sqlite3/internal/util"
2023-01-26 02:48:31 +00:00
"github.com/ncruces/julianday"
)
func Test_vfsLocaltime(t *testing.T) {
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2023-03-07 03:51:07 +00:00
ctx := context.TODO()
2023-01-26 02:48:31 +00:00
2023-03-25 11:16:51 +00:00
tm := time.Now()
2023-03-29 15:01:25 +01:00
rc := vfsLocaltime(ctx, mod, 4, tm.Unix())
2023-01-26 02:48:31 +00:00
if rc != 0 {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if s := util.ReadUint32(mod, 4+0*4); int(s) != tm.Second() {
2023-01-26 12:15:34 +00:00
t.Error("wrong second")
2023-01-26 02:48:31 +00:00
}
2023-03-29 15:01:25 +01:00
if m := util.ReadUint32(mod, 4+1*4); int(m) != tm.Minute() {
2023-01-26 12:15:34 +00:00
t.Error("wrong minute")
2023-01-26 02:48:31 +00:00
}
2023-03-29 15:01:25 +01:00
if h := util.ReadUint32(mod, 4+2*4); int(h) != tm.Hour() {
2023-01-26 12:15:34 +00:00
t.Error("wrong hour")
2023-01-26 02:48:31 +00:00
}
2023-03-29 15:01:25 +01:00
if d := util.ReadUint32(mod, 4+3*4); int(d) != tm.Day() {
2023-01-26 12:15:34 +00:00
t.Error("wrong day")
2023-01-26 02:48:31 +00:00
}
2023-03-29 15:01:25 +01:00
if m := util.ReadUint32(mod, 4+4*4); time.Month(1+m) != tm.Month() {
2023-01-26 12:15:34 +00:00
t.Error("wrong month")
2023-01-26 02:48:31 +00:00
}
2023-03-29 15:01:25 +01:00
if y := util.ReadUint32(mod, 4+5*4); 1900+int(y) != tm.Year() {
2023-01-26 12:15:34 +00:00
t.Error("wrong year")
2023-01-26 02:48:31 +00:00
}
2023-03-29 15:01:25 +01:00
if w := util.ReadUint32(mod, 4+6*4); time.Weekday(w) != tm.Weekday() {
2023-01-26 12:15:34 +00:00
t.Error("wrong weekday")
2023-01-26 02:48:31 +00:00
}
2023-03-29 15:01:25 +01:00
if d := util.ReadUint32(mod, 4+7*4); int(d) != tm.YearDay()-1 {
2023-01-26 12:15:34 +00:00
t.Error("wrong yearday")
2023-01-26 02:48:31 +00:00
}
}
func Test_vfsRandomness(t *testing.T) {
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2023-03-20 11:02:34 +00:00
ctx := context.TODO()
2023-01-26 02:48:31 +00:00
2023-03-29 15:01:25 +01:00
rc := vfsRandomness(ctx, mod, 0, 16, 4)
2023-01-26 02:48:31 +00:00
if rc != 16 {
t.Fatal("returned", rc)
}
2023-02-06 01:01:17 +00:00
var zero [16]byte
2023-03-29 15:01:25 +01:00
if got := util.View(mod, 4, 16); bytes.Equal(got, zero[:]) {
2023-02-06 01:01:17 +00:00
t.Fatal("all zero")
2023-01-26 02:48:31 +00:00
}
}
func Test_vfsSleep(t *testing.T) {
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2023-03-07 03:51:07 +00:00
ctx := context.TODO()
2023-01-26 02:48:31 +00:00
2023-03-07 03:51:07 +00:00
now := time.Now()
2023-03-29 15:01:25 +01:00
rc := vfsSleep(ctx, mod, 0, 123456)
2023-01-26 02:48:31 +00:00
if rc != 0 {
t.Fatal("returned", rc)
}
want := 123456 * time.Microsecond
2023-03-07 03:51:07 +00:00
if got := time.Since(now); got < want {
2023-01-26 12:15:34 +00:00
t.Errorf("got %v, want %v", got, want)
2023-01-26 02:48:31 +00:00
}
}
func Test_vfsCurrentTime64(t *testing.T) {
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2023-03-07 03:51:07 +00:00
ctx := context.TODO()
2023-01-26 02:48:31 +00:00
now := time.Now()
time.Sleep(time.Millisecond)
2023-03-29 15:01:25 +01:00
rc := vfsCurrentTime64(ctx, mod, 0, 4)
2023-01-26 02:48:31 +00:00
if rc != 0 {
t.Fatal("returned", rc)
}
day, nsec := julianday.Date(now)
want := day*86_400_000 + nsec/1_000_000
2023-03-29 15:01:25 +01:00
if got := util.ReadUint64(mod, 4); float32(got) != float32(want) {
2023-01-26 12:15:34 +00:00
t.Errorf("got %v, want %v", got, want)
}
}
func Test_vfsFullPathname(t *testing.T) {
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2023-03-29 15:01:25 +01:00
util.WriteString(mod, 4, ".")
2023-03-07 03:51:07 +00:00
ctx := context.TODO()
2023-01-26 12:15:34 +00:00
2023-03-29 15:01:25 +01:00
rc := vfsFullPathname(ctx, mod, 0, 4, 0, 8)
if rc != _CANTOPEN_FULLPATH {
t.Errorf("returned %d, want %d", rc, _CANTOPEN_FULLPATH)
2023-01-26 12:15:34 +00:00
}
2023-03-29 15:01:25 +01:00
rc = vfsFullPathname(ctx, mod, 0, 4, _MAX_PATHNAME, 8)
2023-01-26 12:15:34 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-01-28 12:47:39 +00:00
want, _ := filepath.Abs(".")
2023-03-29 15:01:25 +01:00
if got := util.ReadString(mod, 8, _MAX_PATHNAME); got != want {
2023-01-28 12:47:39 +00:00
t.Errorf("got %v, want %v", got, want)
}
2023-01-26 12:15:34 +00:00
}
func Test_vfsDelete(t *testing.T) {
2023-02-20 13:30:01 +00:00
name := filepath.Join(t.TempDir(), "test.db")
file, err := os.Create(name)
2023-01-26 12:15:34 +00:00
if err != nil {
t.Fatal(err)
}
file.Close()
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2023-03-29 15:01:25 +01:00
util.WriteString(mod, 4, name)
2023-03-07 03:51:07 +00:00
ctx := context.TODO()
2023-01-26 12:15:34 +00:00
2023-03-29 15:01:25 +01:00
rc := vfsDelete(ctx, mod, 0, 4, 1)
2023-01-26 12:15:34 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
if _, err := os.Stat(name); !errors.Is(err, fs.ErrNotExist) {
2023-01-28 12:47:39 +00:00
t.Fatal("did not delete the file")
}
2023-03-29 15:01:25 +01:00
rc = vfsDelete(ctx, mod, 0, 4, 1)
if rc != _IOERR_DELETE_NOENT {
2023-01-28 12:47:39 +00:00
t.Fatal("returned", rc)
2023-01-26 12:15:34 +00:00
}
}
func Test_vfsAccess(t *testing.T) {
2023-02-21 12:51:52 +00:00
dir := t.TempDir()
2023-05-23 12:38:29 +01:00
file := filepath.Join(dir, "test.db")
2023-02-21 12:51:52 +00:00
if f, err := os.Create(file); err != nil {
t.Fatal(err)
} else {
f.Close()
}
if err := os.Chmod(file, syscall.S_IRUSR); err != nil {
t.Fatal(err)
}
2023-05-12 12:13:06 +01:00
mod := wazerotest.NewModule(wazerotest.NewMemory(wazerotest.PageSize))
2023-03-29 15:01:25 +01:00
util.WriteString(mod, 8, dir)
2023-03-07 03:51:07 +00:00
ctx := context.TODO()
2023-01-26 12:15:34 +00:00
2023-05-19 03:04:07 +01:00
rc := vfsAccess(ctx, mod, 0, 8, ACCESS_EXISTS, 4)
2023-01-26 12:15:34 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, 4); got != 1 {
2023-01-26 12:15:34 +00:00
t.Error("directory did not exist")
}
2023-05-19 03:04:07 +01:00
rc = vfsAccess(ctx, mod, 0, 8, ACCESS_READWRITE, 4)
2023-01-26 12:15:34 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, 4); got != 1 {
2023-01-26 12:15:34 +00:00
t.Error("can't access directory")
2023-01-26 02:48:31 +00:00
}
2023-02-21 12:51:52 +00:00
2023-05-24 02:13:52 +01:00
util.WriteString(mod, 8, file)
rc = vfsAccess(ctx, mod, 0, 8, ACCESS_READ, 4)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, 4); got != 1 {
t.Error("can't access file")
}
2023-10-16 12:26:25 +01:00
if usr, err := user.Current(); err == nil && usr.Uid == "0" {
t.Skip("skipping as root")
}
2023-03-29 15:01:25 +01:00
util.WriteString(mod, 8, file)
2023-05-19 03:04:07 +01:00
rc = vfsAccess(ctx, mod, 0, 8, ACCESS_READWRITE, 4)
2023-02-21 12:51:52 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, 4); got != 0 {
2023-02-21 12:51:52 +00:00
t.Error("can access file")
}
2023-01-26 02:48:31 +00:00
}
2023-01-29 02:11:41 +00:00
func Test_vfsFile(t *testing.T) {
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-01-29 02:11:41 +00:00
// Open a temporary file.
rc := vfsOpen(ctx, mod, 0, 0, 4, OPEN_CREATE|OPEN_EXCLUSIVE|OPEN_READWRITE|OPEN_DELETEONCLOSE, 0, 0)
2023-01-29 02:11:41 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-05-19 14:45:40 +01:00
// Check sector size.
if size := vfsSectorSize(ctx, mod, 4); size != _DEFAULT_SECTOR_SIZE {
t.Fatal("returned", size)
}
2023-01-29 02:11:41 +00:00
// Write stuff.
text := "Hello world!"
2023-03-29 15:01:25 +01:00
util.WriteString(mod, 16, text)
2024-04-11 12:00:17 +01:00
rc = vfsWrite(ctx, mod, 4, 16, int32(len(text)), 0)
2023-01-29 02:11:41 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
// Check file size.
2023-03-29 15:01:25 +01:00
rc = vfsFileSize(ctx, mod, 4, 16)
2023-01-29 02:11:41 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, 16); got != uint32(len(text)) {
2023-01-29 02:11:41 +00:00
t.Errorf("got %d", got)
}
// Partial read at offset.
2024-04-11 12:00:17 +01:00
rc = vfsRead(ctx, mod, 4, 16, int32(len(text)), 4)
2023-03-29 15:01:25 +01:00
if rc != _IOERR_SHORT_READ {
2023-01-29 02:11:41 +00:00
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadString(mod, 16, 64); got != text[4:] {
2023-01-29 02:11:41 +00:00
t.Errorf("got %q", got)
}
// Truncate the file.
2023-03-29 15:01:25 +01:00
rc = vfsTruncate(ctx, mod, 4, 4)
2023-01-29 02:11:41 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
// Check file size.
2023-03-29 15:01:25 +01:00
rc = vfsFileSize(ctx, mod, 4, 16)
2023-01-29 02:11:41 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadUint32(mod, 16); got != 4 {
2023-01-29 02:11:41 +00:00
t.Errorf("got %d", got)
}
// Read at offset.
2023-03-29 15:01:25 +01:00
rc = vfsRead(ctx, mod, 4, 32, 4, 0)
2023-01-29 02:11:41 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
2023-03-29 15:01:25 +01:00
if got := util.ReadString(mod, 32, 64); got != text[:4] {
2023-01-29 02:11:41 +00:00
t.Errorf("got %q", got)
}
// Close the file.
2023-03-29 15:01:25 +01:00
rc = vfsClose(ctx, mod, 4)
2023-01-29 02:11:41 +00:00
if rc != _OK {
t.Fatal("returned", rc)
}
}
2023-05-19 14:45:40 +01:00
func Test_vfsFile_psow(t *testing.T) {
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-05-19 14:45:40 +01:00
// Open a temporary file.
rc := vfsOpen(ctx, mod, 0, 0, 4, OPEN_CREATE|OPEN_EXCLUSIVE|OPEN_READWRITE|OPEN_DELETEONCLOSE, 0, 0)
2023-05-19 14:45:40 +01:00
if rc != _OK {
t.Fatal("returned", rc)
}
// Read powersafe overwrite.
util.WriteUint32(mod, 16, math.MaxUint32)
rc = vfsFileControl(ctx, mod, 4, _FCNTL_POWERSAFE_OVERWRITE, 16)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, 16); got == 0 {
t.Error("psow disabled")
}
// Unset powersafe overwrite.
util.WriteUint32(mod, 16, 0)
rc = vfsFileControl(ctx, mod, 4, _FCNTL_POWERSAFE_OVERWRITE, 16)
if rc != _OK {
t.Fatal("returned", rc)
}
// Read powersafe overwrite.
util.WriteUint32(mod, 16, math.MaxUint32)
rc = vfsFileControl(ctx, mod, 4, _FCNTL_POWERSAFE_OVERWRITE, 16)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, 16); got != 0 {
t.Error("psow enabled")
}
// Set powersafe overwrite.
util.WriteUint32(mod, 16, 1)
rc = vfsFileControl(ctx, mod, 4, _FCNTL_POWERSAFE_OVERWRITE, 16)
if rc != _OK {
t.Fatal("returned", rc)
}
// Read powersafe overwrite.
util.WriteUint32(mod, 16, math.MaxUint32)
rc = vfsFileControl(ctx, mod, 4, _FCNTL_POWERSAFE_OVERWRITE, 16)
if rc != _OK {
t.Fatal("returned", rc)
}
if got := util.ReadUint32(mod, 16); got == 0 {
t.Error("psow disabled")
}
// Close the file.
rc = vfsClose(ctx, mod, 4)
if rc != _OK {
t.Fatal("returned", rc)
}
}