Add test.

This commit is contained in:
Nuno Cruces
2023-01-26 00:05:52 +00:00
parent acb2b2deac
commit d88a19f7e8
11 changed files with 159 additions and 181 deletions

31
.github/workflows/go.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
name: Go
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
- name: Build
run: go build -v ./...
- name: Test
run: go test -v ./...

3
.gitignore vendored
View File

@@ -16,5 +16,4 @@
tools
# Project
sqlite3/sqlite3*
embed/sqlite3.wasm
sqlite3/sqlite3*

View File

@@ -1,86 +0,0 @@
package bench_test
import (
"strconv"
"testing"
"crawshaw.io/sqlite"
)
func BenchmarkCrawshaw(b *testing.B) {
for n := 0; n < b.N; n++ {
crawshawTest()
}
}
func crawshawTest() {
db, err := sqlite.OpenConn(":memory:", 0)
if err != nil {
panic(err)
}
defer db.Close()
exec := func(sql string) error {
stmt, _, err := db.PrepareTransient(sql)
if err != nil {
return err
}
_, err = stmt.Step()
if err != nil {
return err
}
return stmt.Finalize()
}
err = exec(`CREATE TABLE users (id INTEGER PRIMARY KEY NOT NULL, name VARCHAR, age INTEGER, rating REAL)`)
if err != nil {
panic(err)
}
func() {
const N = 1_000_000
exec(`BEGIN`)
defer exec(`END`)
stmt, _, err := db.PrepareTransient(`INSERT INTO users (id, name, age, rating) VALUES (?, ?, ?, ?)`)
if err != nil {
panic(err)
}
defer stmt.Finalize()
for i := 0; i < N; i++ {
id := i + 1
name := "user " + strconv.Itoa(id)
age := 33 + id
rating := 0.13 * float64(id)
stmt.BindInt64(1, int64(id))
stmt.BindText(2, name)
stmt.BindInt64(3, int64(age))
stmt.BindFloat(4, rating)
}
}()
func() {
stmt, _, err := db.PrepareTransient(`SELECT id, name, age, rating FROM users ORDER BY id`)
if err != nil {
panic(err)
}
defer stmt.Finalize()
for {
if row, err := stmt.Step(); err != nil {
panic(err)
} else if !row {
break
}
id := stmt.ColumnInt(0)
name := stmt.ColumnText(1)
age := stmt.ColumnInt64(2)
rating := stmt.ColumnFloat(3)
if id < 1 || len(name) < 5 || age < 33 || rating < 0.13 {
panic("wrong row values")
}
}
}()
}

View File

@@ -1,84 +0,0 @@
package bench_test
import (
"strconv"
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
func init() {
db, err := sqlite3.Open(":memory:")
if err != nil {
panic(err)
}
err = db.Close()
if err != nil {
panic(err)
}
}
func BenchmarkWasm(b *testing.B) {
for n := 0; n < b.N; n++ {
wasmTest()
}
}
func wasmTest() {
db, err := sqlite3.Open(":memory:")
if err != nil {
panic(err)
}
defer db.Close()
err = db.Exec(`CREATE TABLE users (id INTEGER PRIMARY KEY NOT NULL, name VARCHAR, age INTEGER, rating REAL)`)
if err != nil {
panic(err)
}
func() {
const N = 1_000_000
db.Exec(`BEGIN`)
defer db.Exec(`END`)
stmt, _, err := db.Prepare(`INSERT INTO users (id, name, age, rating) VALUES (?, ?, ?, ?)`)
if err != nil {
panic(err)
}
defer stmt.Close()
for i := 0; i < N; i++ {
id := i + 1
name := "user " + strconv.Itoa(id)
age := 33 + id
rating := 0.13 * float64(id)
stmt.BindInt(1, id)
stmt.BindText(2, name)
stmt.BindInt64(3, int64(age))
stmt.BindFloat(4, rating)
}
}()
func() {
stmt, _, err := db.Prepare(`SELECT id, name, age, rating FROM users ORDER BY id`)
if err != nil {
panic(err)
}
defer stmt.Close()
for stmt.Step() {
id := stmt.ColumnInt(0)
name := stmt.ColumnText(1)
age := stmt.ColumnInt64(2)
rating := stmt.ColumnFloat(3)
if id < 1 || len(name) < 5 || age < 33 || rating < 0.13 {
panic("wrong row values")
}
}
if stmt.Err() != nil {
panic(err)
}
}()
}

View File

@@ -14,7 +14,7 @@ func main() {
log.Fatal(err)
}
err = db.Exec(`CREATE TABLE IF NOT EXISTS users (id int, name varchar(10))`)
err = db.Exec(`CREATE TABLE IF NOT EXISTS users (id INT, name VARCHAR(10))`)
if err != nil {
log.Fatal(err)
}
@@ -32,7 +32,7 @@ func main() {
for stmt.Step() {
fmt.Println(stmt.ColumnInt(0), stmt.ColumnText(1))
}
if stmt.Err() != nil {
if err := stmt.Err(); err != nil {
log.Fatal(err)
}

76
conn_test.go Normal file
View File

@@ -0,0 +1,76 @@
package sqlite3_test
import (
"os"
"path/filepath"
"testing"
"github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed"
)
func TestOpen_memory(t *testing.T) {
testOpen(t, ":memory:")
}
func TestOpen_file(t *testing.T) {
dir, err := os.MkdirTemp("", "sqlite3-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
testOpen(t, filepath.Join(dir, "test.db"))
}
func testOpen(t *testing.T, name string) {
db, err := sqlite3.Open(name)
if err != nil {
t.Fatal(err)
}
defer db.Close()
err = db.Exec(`CREATE TABLE IF NOT EXISTS users (id INT, name VARCHAR(10))`)
if err != nil {
t.Fatal(err)
}
err = db.Exec(`INSERT INTO users(id, name) VALUES(0, 'go'), (1, 'zig'), (2, 'whatever')`)
if err != nil {
t.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT id, name FROM users`)
if err != nil {
t.Fatal(err)
}
ids := []int{0, 1, 2}
names := []string{"go", "zig", "whatever"}
idx := 0
for ; stmt.Step(); idx++ {
if ids[idx] != stmt.ColumnInt(0) {
t.Errorf("expected %d got %d", ids[idx], stmt.ColumnInt(0))
}
if names[idx] != stmt.ColumnText(1) {
t.Errorf("expected %q got %q", names[idx], stmt.ColumnText(1))
}
}
if err := stmt.Err(); err != nil {
t.Fatal(err)
}
if idx != 3 {
t.Errorf("expected %d rows got %d", len(ids), idx)
}
err = stmt.Close()
if err != nil {
t.Fatal(err)
}
err = db.Close()
if err != nil {
t.Fatal(err)
}
}

View File

@@ -7,7 +7,7 @@ cd -P -- "$(dirname -- "$0")"
../sqlite3/download.sh
# build SQLite
zig cc --target=wasm32-wasi -flto -g0 -O2 \
zig cc --target=wasm32-wasi -flto -g0 -Os \
-o sqlite3.wasm ../sqlite3/*.c \
-mmutable-globals \
-mbulk-memory -mreference-types \

BIN
embed/sqlite3.wasm Executable file

Binary file not shown.

View File

@@ -2,6 +2,7 @@ package sqlite3
import (
"context"
"os"
"github.com/tetratelabs/wazero/api"
)
@@ -70,6 +71,11 @@ type vfsLocker interface {
CheckReservedLock() (bool, xErrorCode)
}
type vfsFileLocker struct {
*os.File
state vfsLockState
}
func vfsLock(ctx context.Context, mod api.Module, pFile uint32, eLock vfsLockState) uint32 {
if assert && (eLock == _NO_LOCK || eLock == _PENDING_LOCK) {
panic(assertErr + " [d4oxww]")

View File

@@ -12,11 +12,6 @@ func deleteOnClose(f *os.File) {
_ = os.Remove(f.Name())
}
type vfsFileLocker struct {
*os.File
state vfsLockState
}
func (l *vfsFileLocker) LockState() vfsLockState {
return l.state
}

View File

@@ -1,5 +1,46 @@
package sqlite3
import "os"
func deleteOnClose(f *os.File) {}
type vfsFileLocker = vfsNoopLocker
func (l *vfsFileLocker) LockState() vfsLockState {
return l.state
}
func (l *vfsFileLocker) LockShared() xErrorCode {
l.state = _SHARED_LOCK
return _OK
}
func (l *vfsFileLocker) LockReserved() xErrorCode {
l.state = _RESERVED_LOCK
return _OK
}
func (l *vfsFileLocker) LockPending() xErrorCode {
l.state = _PENDING_LOCK
return _OK
}
func (l *vfsFileLocker) LockExclusive() xErrorCode {
l.state = _EXCLUSIVE_LOCK
return _OK
}
func (l *vfsFileLocker) DowngradeLock() xErrorCode {
l.state = _SHARED_LOCK
return _OK
}
func (l *vfsFileLocker) Unlock() xErrorCode {
l.state = _NO_LOCK
return _OK
}
func (l *vfsFileLocker) CheckReservedLock() (bool, xErrorCode) {
if l.state >= _RESERVED_LOCK {
return true, _OK
}
return false, _OK
}