From 09a0ce04ce27d4297513e28c5ab8a6d603b9de1b Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Wed, 24 Apr 2024 15:49:45 +0100 Subject: [PATCH] Test more. (#84) Also, fix the progress callback and disable a slow example. --- .github/workflows/test.yml | 27 ++++++--------- README.md | 6 ++-- conn.go | 4 +-- driver/driver_test.go | 2 ++ driver/example_test.go | 2 ++ embed/sqlite3.wasm | Bin 1337796 -> 1337787 bytes ext/lines/lines_test.go | 2 +- sqlite3/locking_mode.patch | 14 -------- tests/backup_test.go | 2 ++ tests/bradfitz/sql_test.go | 2 ++ tests/db_test.go | 32 ++++++++++++------ tests/parallel/parallel_test.go | 2 ++ tests/testdata/f2fs.sh | 2 +- tests/wal_test.go | 10 ++++++ vfs/README.md | 21 ++++++------ vfs/lock_test.go | 2 ++ vfs/tests/mptest/mptest_test.go | 2 ++ vfs/tests/mptest/testdata/mptest.wasm.bz2 | 4 +-- .../speedtest1/testdata/speedtest1.wasm.bz2 | 4 +-- 19 files changed, 78 insertions(+), 62 deletions(-) delete mode 100644 sqlite3/locking_mode.patch diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 630bd83..656ea40 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,7 +52,8 @@ jobs: if: matrix.os == 'ubuntu-latest' - name: Test no locks - run: go test -v -tags sqlite3_nosys ./tests -run TestDB_nolock + run: go test -v -tags sqlite3_nosys ./... + if: matrix.os == 'ubuntu-latest' - name: Test GORM run: gormlite/test.sh @@ -123,21 +124,7 @@ jobs: - name: Test run: go test -v ./... - test-386: - runs-on: ubuntu-latest - needs: test - - steps: - - uses: actions/checkout@v4 - with: { lfs: 'true' } - - - uses: actions/setup-go@v5 - with: { go-version: stable } - - - name: Test - run: GOARCH=386 go test -v -short ./... - - test-arm: + test-qemu: runs-on: ubuntu-latest needs: test @@ -150,5 +137,11 @@ jobs: - uses: docker/setup-qemu-action@v3 - - name: Test + - name: Test 386 + run: GOARCH=386 go test -v -short ./... + + - name: Test arm64 run: GOARCH=arm64 go test -v -short ./... + + - name: Test riscv64 + run: GOARCH=riscv64 go test -v -short ./... diff --git a/README.md b/README.md index 967ba23..01fbaa9 100644 --- a/README.md +++ b/README.md @@ -87,9 +87,11 @@ This project aims for [high test coverage](https://github.com/ncruces/go-sqlite3 It also benefits greatly from [SQLite's](https://sqlite.org/testing.html) and [wazero's](https://tetrate.io/blog/introducing-wazero-from-tetrate/#:~:text=Rock%2Dsolid%20test%20approach) thorough testing. +Every commit is [tested](.github/workflows/test.yml) on +Linux (amd64/arm64/386/riscv64), macOS (amd64/arm64), Windows, FreeBSD and illumos. + The Go VFS is tested by running SQLite's -[mptest](https://github.com/sqlite/sqlite/blob/master/mptest/mptest.c) -on Linux, macOS, Windows, FreeBSD and illumos. +[mptest](https://github.com/sqlite/sqlite/blob/master/mptest/mptest.c). ### Performance diff --git a/conn.go b/conn.go index d3fa380..fc2d765 100644 --- a/conn.go +++ b/conn.go @@ -348,8 +348,8 @@ func (c *Conn) checkInterrupt() { } func progressCallback(ctx context.Context, mod api.Module, pDB uint32) (interrupt uint32) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.commit != nil { - if c.interrupt != nil && c.interrupt.Err() != nil { + if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.interrupt != nil { + if c.interrupt.Err() != nil { interrupt = 1 } } diff --git a/driver/driver_test.go b/driver/driver_test.go index b839316..1c8c2ed 100644 --- a/driver/driver_test.go +++ b/driver/driver_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package driver import ( diff --git a/driver/example_test.go b/driver/example_test.go index 85352bc..161c338 100644 --- a/driver/example_test.go +++ b/driver/example_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package driver_test // Adapted from: https://go.dev/doc/tutorial/database-access diff --git a/embed/sqlite3.wasm b/embed/sqlite3.wasm index 2f36b2948d459958509396948142e5ce19a25291..a7057dd804fb1b3e941e0fc27e2b91b4743ea614 100755 GIT binary patch delta 22693 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 delta 22909 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%0A%zw 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 - if( pPager->noLock ) return 0; -- return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap); -+ if( pMethods->iVersion>=2 && pMethods->xShmMap ) return 1; -+ pPager->exclusiveMode = 1; -+ return 1; - } - - /* diff --git a/tests/backup_test.go b/tests/backup_test.go index cb9ab8b..980ed4c 100644 --- a/tests/backup_test.go +++ b/tests/backup_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package tests import ( diff --git a/tests/bradfitz/sql_test.go b/tests/bradfitz/sql_test.go index 8c10a8b..2e0e8ae 100644 --- a/tests/bradfitz/sql_test.go +++ b/tests/bradfitz/sql_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package bradfitz // Adapted from: https://github.com/bradfitz/go-sql-test diff --git a/tests/db_test.go b/tests/db_test.go index 6f32fc2..ed89bf1 100644 --- a/tests/db_test.go +++ b/tests/db_test.go @@ -10,6 +10,7 @@ import ( "github.com/ncruces/go-sqlite3" _ "github.com/ncruces/go-sqlite3/embed" _ "github.com/ncruces/go-sqlite3/tests/testcfg" + "github.com/ncruces/go-sqlite3/vfs" _ "github.com/ncruces/go-sqlite3/vfs/adiantum" _ "github.com/ncruces/go-sqlite3/vfs/memdb" ) @@ -26,18 +27,19 @@ func TestDB_memory(t *testing.T) { } func TestDB_file(t *testing.T) { + if !vfs.SupportsFileLocking { + t.Skip("skipping without locks") + } + t.Parallel() testDB(t, filepath.Join(t.TempDir(), "test.db")) } -func TestDB_nolock(t *testing.T) { - t.Parallel() - testDB(t, "file:"+ - filepath.ToSlash(filepath.Join(t.TempDir(), "test.db"))+ - "?nolock=1") -} - func TestDB_wal(t *testing.T) { + if !vfs.SupportsSharedMemory { + t.Skip("skipping without shared memory") + } + t.Parallel() tmp := filepath.Join(t.TempDir(), "test.db") err := os.WriteFile(tmp, waldb, 0666) @@ -48,6 +50,10 @@ func TestDB_wal(t *testing.T) { } func TestDB_utf16(t *testing.T) { + if !vfs.SupportsFileLocking { + t.Skip("skipping without locks") + } + t.Parallel() tmp := filepath.Join(t.TempDir(), "test.db") err := os.WriteFile(tmp, utf16db, 0666) @@ -64,9 +70,15 @@ func TestDB_memdb(t *testing.T) { func TestDB_adiantum(t *testing.T) { t.Parallel() - testDB(t, "file:"+ - filepath.ToSlash(filepath.Join(t.TempDir(), "test.db"))+ - "?vfs=adiantum&textkey=correct+horse+battery+staple") + tmp := filepath.Join(t.TempDir(), "test.db") + testDB(t, "file:"+filepath.ToSlash(tmp)+"?nolock=1"+ + "&vfs=adiantum&textkey=correct+horse+battery+staple") +} + +func TestDB_nolock(t *testing.T) { + t.Parallel() + tmp := filepath.Join(t.TempDir(), "test.db") + testDB(t, "file:"+filepath.ToSlash(tmp)+"?nolock=1") } func testDB(t testing.TB, name string) { diff --git a/tests/parallel/parallel_test.go b/tests/parallel/parallel_test.go index 6c8064f..e42c13a 100644 --- a/tests/parallel/parallel_test.go +++ b/tests/parallel/parallel_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package tests import ( diff --git a/tests/testdata/f2fs.sh b/tests/testdata/f2fs.sh index 8ac7bb1..0802eb0 100755 --- a/tests/testdata/f2fs.sh +++ b/tests/testdata/f2fs.sh @@ -14,7 +14,7 @@ sudo mount -nv -o loop f2fs.img f2fs/ mkdir -p f2fs/tmp/ go test -c "$ROOT/tests" -coverpkg github.com/ncruces/go-sqlite3/... -TMPDIR=f2fs/tmp/ ./tests.test -test.v -test.short -test.coverprofile cover.out +TMPDIR=$PWD/f2fs/tmp/ ./tests.test -test.v -test.short -test.coverprofile cover.out go tool cover -html cover.out sudo umount f2fs/ diff --git a/tests/wal_test.go b/tests/wal_test.go index 8f1fcdf..711fc88 100644 --- a/tests/wal_test.go +++ b/tests/wal_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package tests import ( @@ -22,6 +24,13 @@ func TestWAL_enter_exit(t *testing.T) { } defer db.Close() + if !vfs.SupportsSharedMemory { + err = db.Exec(`PRAGMA locking_mode=EXCLUSIVE`) + if err != nil { + t.Fatal(err) + } + } + err = db.Exec(` CREATE TABLE test (col); PRAGMA journal_mode=WAL; @@ -89,6 +98,7 @@ func TestConn_WalCheckpoint(t *testing.T) { }) err = db.Exec(` + PRAGMA locking_mode=EXCLUSIVE; PRAGMA journal_mode=WAL; CREATE TABLE test (col); `) diff --git a/vfs/README.md b/vfs/README.md index 9730f14..552a93b 100644 --- a/vfs/README.md +++ b/vfs/README.md @@ -24,7 +24,7 @@ OFD locks are fully compatible with POSIX advisory locks. On BSD Unixes, this module uses [BSD locks](https://man.freebsd.org/cgi/man.cgi?query=flock&sektion=2). -On BSD Unixes, BSD locks are fully compatible with POSIX advisory locks. +On BSD, these locks are fully compatible with POSIX advisory locks. However, concurrency is reduced with BSD locks (`BEGIN IMMEDIATE` behaves the same as `BEGIN EXCLUSIVE`). @@ -34,8 +34,7 @@ like SQLite. On all other platforms, file locking is not supported, and you must use [`nolock=1`](https://sqlite.org/uri.html#urinolock) (or [`immutable=1`](https://sqlite.org/uri.html#uriimmutable)) -to open database files. - +to open database files.\ To use the [`database/sql`](https://pkg.go.dev/database/sql) driver with `nolock=1` you must disable connection pooling by calling [`db.SetMaxOpenConns(1)`](https://pkg.go.dev/database/sql#DB.SetMaxOpenConns). @@ -53,16 +52,16 @@ To allow `mmap` to work, each connection needs to reserve up to 4GB of address s To limit the amount of address space each connection needs, use [`WithMemoryLimitPages`](../tests/testcfg/testcfg.go). -On all other platforms, [WAL](https://sqlite.org/wal.html) support is +On Windows and BSD, [WAL](https://sqlite.org/wal.html) support is [limited](https://sqlite.org/wal.html#noshm). - -To work around this limitation, SQLite is [patched](sqlite3/locking_mode.patch) -to automatically use `EXCLUSIVE` locking mode for WAL databases on such platforms. - -To use the [`database/sql`](https://pkg.go.dev/database/sql) driver -with `EXCLUSIVE` locking mode you should disable connection pooling by calling +`EXCLUSIVE` locking mode can be set to create, read, and write WAL databases.\ +To use `EXCLUSIVE` locking mode with the +[`database/sql`](https://pkg.go.dev/database/sql) driver +you must disable connection pooling by calling [`db.SetMaxOpenConns(1)`](https://pkg.go.dev/database/sql#DB.SetMaxOpenConns). +On all other platforms, where file locking is not supported, WAL mode does not work. + You can use [`vfs.SupportsSharedMemory`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs#SupportsSharedMemory) to check if your platform supports shared memory. @@ -77,4 +76,4 @@ The VFS can be customized with a few build tags: - `sqlite3_flock` forces the use of BSD locks; it can be used on macOS to test the BSD locking implementation. - `sqlite3_nosys` prevents importing [`x/sys`](https://pkg.go.dev/golang.org/x/sys); disables locking _and_ shared memory on all platforms. -- `sqlite3_noshm` disables shared memory on all platforms. \ No newline at end of file +- `sqlite3_noshm` disables shared memory on all platforms. diff --git a/vfs/lock_test.go b/vfs/lock_test.go index 6cf359c..30abdfe 100644 --- a/vfs/lock_test.go +++ b/vfs/lock_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package vfs import ( diff --git a/vfs/tests/mptest/mptest_test.go b/vfs/tests/mptest/mptest_test.go index 2fca6b7..33919aa 100644 --- a/vfs/tests/mptest/mptest_test.go +++ b/vfs/tests/mptest/mptest_test.go @@ -1,3 +1,5 @@ +//go:build !sqlite3_nosys + package mptest import ( diff --git a/vfs/tests/mptest/testdata/mptest.wasm.bz2 b/vfs/tests/mptest/testdata/mptest.wasm.bz2 index 85a069f..957e694 100644 --- a/vfs/tests/mptest/testdata/mptest.wasm.bz2 +++ b/vfs/tests/mptest/testdata/mptest.wasm.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afe1db5aea2a3ab996370fa85052cafaae10ab4b2f8154885da2c1d2a8503840 -size 470240 +oid sha256:3fc3e666b2bb3e0e27622d43ab35f802111c59155c592a7c822f09d1229e8700 +size 470668 diff --git a/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 b/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 index d953c0c..75b4de2 100644 --- a/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 +++ b/vfs/tests/speedtest1/testdata/speedtest1.wasm.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4f9ed81c9497a9d8b91517416d122ae04c2c517d3e0612d869e128dcee3fa81 -size 483519 +oid sha256:4573183e549df979c07040d92c3b2de72b5dd49ad0d8e779de63ed95fba4e898 +size 484084