diff --git a/.github/coverage.html b/.github/coverage.html index d5becc1..520de4b 100644 --- a/.github/coverage.html +++ b/.github/coverage.html @@ -65,7 +65,7 @@ - + @@ -848,7 +848,7 @@ func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative, nFull // This might be buggy on Windows (the Windows VFS doesn't try). siz := uint32(len(abs) + 1) - if siz > nFull { + if siz > nFull { return uint32(CANTOPEN_FULLPATH) } if zFull == 0 { @@ -873,13 +873,13 @@ func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32) if err != nil { return uint32(IOERR_DELETE) } - if syncDir != 0 { + if syncDir != 0 { f, err := os.Open(filepath.Dir(path)) - if err == nil { + if err == nil { err = f.Sync() f.Close() } - if err != nil { + if err != nil { return uint32(IOERR_DELETE) } } @@ -897,7 +897,7 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags Ac switch { case flags == ACCESS_EXISTS: switch { - case err == nil: + case err == nil: res = 1 case errors.Is(err, fs.ErrNotExist): res = 0 @@ -905,15 +905,15 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags Ac return uint32(IOERR_ACCESS) } - case err == nil: + case err == nil: var want fs.FileMode = syscall.S_IRUSR - if flags == ACCESS_READWRITE { + if flags == ACCESS_READWRITE { want |= syscall.S_IWUSR } - if fi.IsDir() { + if fi.IsDir() { want |= syscall.S_IXUSR } - if fi.Mode()&want == want { + if fi.Mode()&want == want { res = 1 } else { res = 0 diff --git a/.github/coverage.svg b/.github/coverage.svg index f37c642..30cb327 100644 --- a/.github/coverage.svg +++ b/.github/coverage.svg @@ -1 +1 @@ -coverage: 59.0%coverage59.0% \ No newline at end of file +coverage: 61.1%coverage61.1% \ No newline at end of file diff --git a/conn_test.go b/conn_test.go index eb62896..57bb582 100644 --- a/conn_test.go +++ b/conn_test.go @@ -15,7 +15,7 @@ func TestConn_new(t *testing.T) { defer func() { _ = recover() }() db.new(math.MaxUint32) - t.Errorf("should have panicked") + t.Error("should have panicked") } func TestConn_newBytes(t *testing.T) { @@ -27,18 +27,18 @@ func TestConn_newBytes(t *testing.T) { ptr := db.newBytes(nil) if ptr != 0 { - t.Errorf("want nullptr got %x", ptr) + t.Errorf("got %x, want nullptr", ptr) } buf := []byte("sqlite3") ptr = db.newBytes(buf) if ptr == 0 { - t.Errorf("want a pointer got nullptr") + t.Fatal("got nullptr, want a pointer") } want := buf - if got, ok := db.memory.Read(ptr, uint32(len(want))); !ok || !bytes.Equal(want, got) { - t.Errorf("want %q got %q", want, got) + if got, ok := db.memory.Read(ptr, uint32(len(want))); !ok || !bytes.Equal(got, want) { + t.Errorf("got %q, want %q", got, want) } } @@ -51,18 +51,18 @@ func TestConn_newString(t *testing.T) { ptr := db.newString("") if ptr == 0 { - t.Errorf("want a pointer got nullptr") + t.Error("got nullptr, want a pointer") } str := "sqlite3\000sqlite3" ptr = db.newString(str) if ptr == 0 { - t.Errorf("want a pointer got nullptr") + t.Fatal("got nullptr, want a pointer") } want := str + "\000" - if got, ok := db.memory.Read(ptr, uint32(len(want))); !ok || want != string(got) { - t.Errorf("want %q got %q", want, got) + if got, ok := db.memory.Read(ptr, uint32(len(want))); !ok || string(got) != want { + t.Errorf("got %q, want %q", got, want) } } @@ -75,33 +75,33 @@ func TestConn_getString(t *testing.T) { ptr := db.newString("") if ptr == 0 { - t.Errorf("want a pointer got nullptr") + t.Error("got nullptr, want a pointer") } str := "sqlite3" + "\000 drop this" ptr = db.newString(str) if ptr == 0 { - t.Errorf("want a pointer got nullptr") + t.Fatal("got nullptr, want a pointer") } want := "sqlite3" - if got := db.getString(ptr, math.MaxUint32); want != got { - t.Errorf("want %q got %q", want, got) + if got := db.getString(ptr, math.MaxUint32); got != want { + t.Errorf("got %q, want %q", got, want) } if got := db.getString(ptr, 0); got != "" { - t.Errorf("want empty got %q", got) + t.Errorf("got %q, want empty", got) } func() { defer func() { _ = recover() }() db.getString(ptr, uint32(len(want)/2)) - t.Errorf("should have panicked") + t.Error("should have panicked") }() func() { defer func() { _ = recover() }() db.getString(0, math.MaxUint32) - t.Errorf("should have panicked") + t.Error("should have panicked") }() } @@ -116,7 +116,7 @@ func TestConn_free(t *testing.T) { ptr := db.new(0) if ptr == 0 { - t.Errorf("want a pointer got nullptr") + t.Error("got nullptr, want a pointer") } db.free(ptr) diff --git a/sqlite3_test.go b/sqlite3_test.go index 6775f3f..338cf80 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -34,10 +34,10 @@ func TestOpen_dir(t *testing.T) { t.Fatal("want sqlite3.Error") } if serr.Code != sqlite3.CANTOPEN { - t.Fatal("want sqlite3.CANTOPEN") + t.Error("want sqlite3.CANTOPEN") } if got := err.Error(); got != "sqlite3: unable to open database file" { - t.Fatal("got message: ", got) + t.Error("got message: ", got) } } @@ -69,17 +69,17 @@ func testOpen(t *testing.T, name string) { idx := 0 for ; stmt.Step(); idx++ { if ids[idx] != stmt.ColumnInt(0) { - t.Errorf("want %d got %d", ids[idx], stmt.ColumnInt(0)) + t.Errorf("got %d, want %d", stmt.ColumnInt(0), ids[idx]) } if names[idx] != stmt.ColumnText(1) { - t.Errorf("want %q got %q", names[idx], stmt.ColumnText(1)) + t.Errorf("got %q, want %q", stmt.ColumnText(1), names[idx]) } } if err := stmt.Err(); err != nil { t.Fatal(err) } if idx != 3 { - t.Errorf("want %d rows got %d", len(ids), idx) + t.Errorf("got %d rows, want %d", idx, len(ids)) } err = stmt.Close() diff --git a/vfs_test.go b/vfs_test.go index f286b28..856a2a5 100644 --- a/vfs_test.go +++ b/vfs_test.go @@ -3,7 +3,11 @@ package sqlite3 import ( "bytes" "context" + "errors" + "io/fs" "math/rand" + "os" + "path/filepath" "testing" "time" @@ -14,40 +18,35 @@ func Test_vfsLocaltime(t *testing.T) { memory := make(MockMemory, 128) module := &MockModule{&memory} - memory.Write(0, []byte("zero")) - rc := vfsLocaltime(context.TODO(), module, 0, 4) if rc != 0 { t.Fatal("returned", rc) } epoch := time.Unix(0, 0) - if z, _ := memory.Read(0, 4); !bytes.Equal(z, []byte("zero")) { - t.Fatal("overwrote zero address") - } if s, _ := memory.ReadUint32Le(4 + 0*4); int(s) != epoch.Second() { - t.Fatal("wrong second") + t.Error("wrong second") } if m, _ := memory.ReadUint32Le(4 + 1*4); int(m) != epoch.Minute() { - t.Fatal("wrong minute") + t.Error("wrong minute") } if h, _ := memory.ReadUint32Le(4 + 2*4); int(h) != epoch.Hour() { - t.Fatal("wrong hour") + t.Error("wrong hour") } if d, _ := memory.ReadUint32Le(4 + 3*4); int(d) != epoch.Day() { - t.Fatal("wrong day") + t.Error("wrong day") } if m, _ := memory.ReadUint32Le(4 + 4*4); time.Month(1+m) != epoch.Month() { - t.Fatal("wrong month") + t.Error("wrong month") } if y, _ := memory.ReadUint32Le(4 + 5*4); 1900+int(y) != epoch.Year() { - t.Fatal("wrong year") + t.Error("wrong year") } if w, _ := memory.ReadUint32Le(4 + 6*4); time.Weekday(w) != epoch.Weekday() { - t.Fatal("wrong weekday") + t.Error("wrong weekday") } if d, _ := memory.ReadUint32Le(4 + 7*4); int(d) != epoch.YearDay()-1 { - t.Fatal("wrong yearday") + t.Error("wrong yearday") } } @@ -55,24 +54,18 @@ func Test_vfsRandomness(t *testing.T) { memory := make(MockMemory, 128) module := &MockModule{&memory} - memory.Write(0, []byte("zero")) - rand.Seed(0) rc := vfsRandomness(context.TODO(), module, 0, 16, 4) if rc != 16 { t.Fatal("returned", rc) } - if z, _ := memory.Read(0, 4); !bytes.Equal(z, []byte("zero")) { - t.Fatal("overwrote zero address") - } - var want [16]byte rand.Seed(0) rand.Read(want[:]) if got, _ := memory.Read(4, 16); !bytes.Equal(got, want[:]) { - t.Fatalf("got %q, want %q", got, want) + t.Errorf("got %q, want %q", got, want) } } @@ -86,7 +79,7 @@ func Test_vfsSleep(t *testing.T) { want := 123456 * time.Microsecond if got := time.Since(start); got < want { - t.Fatalf("got %v, want %v", got, want) + t.Errorf("got %v, want %v", got, want) } } @@ -94,20 +87,15 @@ func Test_vfsCurrentTime(t *testing.T) { memory := make(MockMemory, 128) module := &MockModule{&memory} - memory.Write(0, []byte("zero")) - now := time.Now() rc := vfsCurrentTime(context.TODO(), module, 0, 4) if rc != 0 { t.Fatal("returned", rc) } - if z, _ := memory.Read(0, 4); !bytes.Equal(z, []byte("zero")) { - t.Fatal("overwrote zero address") - } want := julianday.Float(now) if got, _ := memory.ReadFloat64Le(4); float32(got) != float32(want) { - t.Fatalf("got %v, want %v", got, want) + t.Errorf("got %v, want %v", got, want) } } @@ -115,8 +103,6 @@ func Test_vfsCurrentTime64(t *testing.T) { memory := make(MockMemory, 128) module := &MockModule{&memory} - memory.Write(0, []byte("zero")) - now := time.Now() time.Sleep(time.Millisecond) rc := vfsCurrentTime64(context.TODO(), module, 0, 4) @@ -124,12 +110,86 @@ func Test_vfsCurrentTime64(t *testing.T) { t.Fatal("returned", rc) } - if z, _ := memory.Read(0, 4); !bytes.Equal(z, []byte("zero")) { - t.Fatal("overwrote zero address") - } day, nsec := julianday.Date(now) want := day*86_400_000 + nsec/1_000_000 if got, _ := memory.ReadUint64Le(4); int64(got)-want > 100 { - t.Fatalf("got %v, want %v", got, want) + t.Errorf("got %v, want %v", got, want) + } +} + +func Test_vfsFullPathname(t *testing.T) { + memory := make(MockMemory, 128+_MAX_PATHNAME) + module := &MockModule{&memory} + + memory.Write(4, []byte{'.', 0}) + + rc := vfsFullPathname(context.TODO(), module, 0, 4, 0, 8) + if rc != uint32(CANTOPEN_FULLPATH) { + t.Errorf("returned %d, want %d", rc, CANTOPEN_FULLPATH) + } + + rc = vfsFullPathname(context.TODO(), module, 0, 4, _MAX_PATHNAME, 8) + if rc != _OK { + t.Fatal("returned", rc) + } + + want, _ := filepath.Abs(".") + if got := getString(&memory, 8, _MAX_PATHNAME); got != want { + t.Errorf("got %v, want %v", got, want) + } +} + +func Test_vfsDelete(t *testing.T) { + memory := make(MockMemory, 128+_MAX_PATHNAME) + module := &MockModule{&memory} + + os.CreateTemp("", "sqlite3") + file, err := os.CreateTemp("", "sqlite3-") + if err != nil { + t.Fatal(err) + } + name := file.Name() + defer os.RemoveAll(name) + file.Close() + + memory.Write(4, []byte(name)) + + rc := vfsDelete(context.TODO(), module, 0, 4, 1) + if rc != _OK { + t.Fatal("returned", rc) + } + + if _, err := os.Stat(name); !errors.Is(err, fs.ErrNotExist) { + t.Error("did not delete the file") + } +} + +func Test_vfsAccess(t *testing.T) { + memory := make(MockMemory, 128+_MAX_PATHNAME) + module := &MockModule{&memory} + + os.CreateTemp("", "sqlite3") + dir, err := os.MkdirTemp("", "sqlite3-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + memory.Write(8, []byte(dir)) + + rc := vfsAccess(context.TODO(), module, 0, 8, ACCESS_EXISTS, 4) + if rc != _OK { + t.Fatal("returned", rc) + } + if got, ok := memory.ReadByte(4); !ok && got != 1 { + t.Error("directory did not exist") + } + + rc = vfsAccess(context.TODO(), module, 0, 8, ACCESS_READWRITE, 4) + if rc != _OK { + t.Fatal("returned", rc) + } + if got, ok := memory.ReadByte(4); !ok && got != 1 { + t.Error("can't access directory") } }