More tests.

This commit is contained in:
Nuno Cruces
2023-01-26 12:15:34 +00:00
parent 09c7c7af3f
commit 606163010a
5 changed files with 126 additions and 66 deletions

20
.github/coverage.html vendored
View File

@@ -65,7 +65,7 @@
<option value="file4">github.com/ncruces/go-sqlite3/stmt.go (27.2%)</option>
<option value="file5">github.com/ncruces/go-sqlite3/vfs.go (67.4%)</option>
<option value="file5">github.com/ncruces/go-sqlite3/vfs.go (74.7%)</option>
<option value="file6">github.com/ncruces/go-sqlite3/vfs_files.go (70.6%)</option>
@@ -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).
<span class="cov8" title="1">siz := uint32(len(abs) + 1)
if siz &gt; nFull </span><span class="cov0" title="0">{
if siz &gt; nFull </span><span class="cov8" title="1">{
return uint32(CANTOPEN_FULLPATH)
}</span>
<span class="cov8" title="1">if zFull == 0 </span><span class="cov0" title="0">{
@@ -873,13 +873,13 @@ func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32)
<span class="cov8" title="1">if err != nil </span><span class="cov0" title="0">{
return uint32(IOERR_DELETE)
}</span>
<span class="cov8" title="1">if syncDir != 0 </span><span class="cov0" title="0">{
<span class="cov8" title="1">if syncDir != 0 </span><span class="cov8" title="1">{
f, err := os.Open(filepath.Dir(path))
if err == nil </span><span class="cov0" title="0">{
if err == nil </span><span class="cov8" title="1">{
err = f.Sync()
f.Close()
}</span>
<span class="cov0" title="0">if err != nil </span><span class="cov0" title="0">{
<span class="cov8" title="1">if err != nil </span><span class="cov0" title="0">{
return uint32(IOERR_DELETE)
}</span>
}
@@ -897,7 +897,7 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags Ac
switch </span>{
case flags == ACCESS_EXISTS:<span class="cov8" title="1">
switch </span>{
case err == nil:<span class="cov0" title="0">
case err == nil:<span class="cov8" title="1">
res = 1</span>
case errors.Is(err, fs.ErrNotExist):<span class="cov8" title="1">
res = 0</span>
@@ -905,15 +905,15 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags Ac
return uint32(IOERR_ACCESS)</span>
}
case err == nil:<span class="cov0" title="0">
case err == nil:<span class="cov8" title="1">
var want fs.FileMode = syscall.S_IRUSR
if flags == ACCESS_READWRITE </span><span class="cov0" title="0">{
if flags == ACCESS_READWRITE </span><span class="cov8" title="1">{
want |= syscall.S_IWUSR
}</span>
<span class="cov0" title="0">if fi.IsDir() </span><span class="cov0" title="0">{
<span class="cov8" title="1">if fi.IsDir() </span><span class="cov8" title="1">{
want |= syscall.S_IXUSR
}</span>
<span class="cov0" title="0">if fi.Mode()&amp;want == want </span><span class="cov0" title="0">{
<span class="cov8" title="1">if fi.Mode()&amp;want == want </span><span class="cov8" title="1">{
res = 1
}</span> else<span class="cov0" title="0"> {
res = 0

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="108" height="20" role="img" aria-label="coverage: 59.0%"><title>coverage: 59.0%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="108" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="47" height="20" fill="#fe7d37"/><rect width="108" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="835" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">59.0%</text><text x="835" y="140" transform="scale(.1)" fill="#fff" textLength="370">59.0%</text></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="108" height="20" role="img" aria-label="coverage: 61.1%"><title>coverage: 61.1%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="108" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="47" height="20" fill="#fe7d37"/><rect width="108" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="835" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">61.1%</text><text x="835" y="140" transform="scale(.1)" fill="#fff" textLength="370">61.1%</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -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)

View File

@@ -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()

View File

@@ -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")
}
}