Repository: mattn/go-sqlite3
Pull request #207 (2015-06-05 14:37:44)

Several fixes, mostly to tests
Here's a series of small patches. The main one makes the tempfile generation in the tests more robust, as well as making the files easier to spot afterwards (the tests tend to leave a lot of tempfiles lying around). This might just solve the impossible-to-reproduce test failures that I've been seeing.


Patch:
diff --git a/sqlite3.go b/sqlite3.go
index 233e7e9..db65af5 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -269,7 +269,7 @@ func errorString(err Error) string {
 //   file:test.db?cache=shared&mode=memory
 //   :memory:
 //   file::memory:
-// go-sqlite handle especially query parameters.
+// go-sqlite3 adds the following query parameters to those used by SQLite:
 //   _loc=XXX
 //     Specify location of time format. It's possible to specify "auto".
 //   _busy_timeout=XXX


Test patch:
diff --git a/sqlite3_fts3_test.go b/sqlite3_fts3_test.go
index a1cd217..716a106 100644
--- a/sqlite3_fts3_test.go
+++ b/sqlite3_fts3_test.go
@@ -12,7 +12,7 @@ import (
 )
 
 func TestFTS3(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
diff --git a/sqlite3_test.go b/sqlite3_test.go
index 423f30e..43f7b4f 100644
--- a/sqlite3_test.go
+++ b/sqlite3_test.go
@@ -6,15 +6,13 @@
 package sqlite3
 
 import (
-	"crypto/rand"
 	"database/sql"
 	"database/sql/driver"
-	"encoding/hex"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"net/url"
 	"os"
-	"path/filepath"
 	"strings"
 	"testing"
 	"time"
@@ -22,15 +20,19 @@ import (
 	"github.com/mattn/go-sqlite3/sqlite3_test"
 )
 
-func TempFilename() string {
-	randBytes := make([]byte, 16)
-	rand.Read(randBytes)
-	return filepath.Join(os.TempDir(), "foo"+hex.EncodeToString(randBytes)+".db")
+func TempFilename(t *testing.T) string {
+	f, err := ioutil.TempFile("", "go-sqlite3-test-")
+	if err != nil {
+		t.Fatal(err)
+	}
+	f.Close()
+	return f.Name()
 }
 
 func doTestOpen(t *testing.T, option string) (string, error) {
 	var url string
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
+	defer os.Remove(tempFilename)
 	if option != "" {
 		url = tempFilename + option
 	} else {
@@ -81,8 +83,29 @@ func TestOpen(t *testing.T) {
 	}
 }
 
+func TestReadonly(t *testing.T) {
+	tempFilename := TempFilename(t)
+	defer os.Remove(tempFilename)
+
+	db1, err := sql.Open("sqlite3", "file:" + tempFilename)
+	if err != nil {
+		t.Fatal(err)
+	}
+	db1.Exec("CREATE TABLE test (x int, y float)")
+
+	db2, err := sql.Open("sqlite3", "file:" + tempFilename + "?mode=ro")
+	if err != nil {
+		t.Fatal(err)
+	}
+	_ = db2
+	_, err = db2.Exec("INSERT INTO test VALUES (1, 3.14)")
+	if err == nil {
+		t.Fatal("didn't expect INSERT into read-only database to work")
+	}
+}
+
 func TestClose(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -108,7 +131,7 @@ func TestClose(t *testing.T) {
 }
 
 func TestInsert(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -147,7 +170,7 @@ func TestInsert(t *testing.T) {
 }
 
 func TestUpdate(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -212,7 +235,7 @@ func TestUpdate(t *testing.T) {
 }
 
 func TestDelete(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -273,7 +296,7 @@ func TestDelete(t *testing.T) {
 }
 
 func TestBooleanRoundtrip(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -322,7 +345,7 @@ func TestBooleanRoundtrip(t *testing.T) {
 }
 
 func TestTimestamp(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -405,7 +428,7 @@ func TestTimestamp(t *testing.T) {
 }
 
 func TestBoolean(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -497,7 +520,7 @@ func TestBoolean(t *testing.T) {
 }
 
 func TestFloat32(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -535,7 +558,7 @@ func TestFloat32(t *testing.T) {
 }
 
 func TestNull(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -567,7 +590,7 @@ func TestNull(t *testing.T) {
 }
 
 func TestTransaction(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -627,7 +650,7 @@ func TestTransaction(t *testing.T) {
 }
 
 func TestWAL(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -675,7 +698,7 @@ func TestWAL(t *testing.T) {
 func TestTimezoneConversion(t *testing.T) {
 	zones := []string{"UTC", "US/Central", "US/Pacific", "Local"}
 	for _, tz := range zones {
-		tempFilename := TempFilename()
+		tempFilename := TempFilename(t)
 		db, err := sql.Open("sqlite3", tempFilename+"?_loc="+url.QueryEscape(tz))
 		if err != nil {
 			t.Fatal("Failed to open database:", err)
@@ -781,7 +804,7 @@ func TestSuite(t *testing.T) {
 // TODO: Execer & Queryer currently disabled
 // https://github.com/mattn/go-sqlite3/issues/82
 func TestExecer(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -801,7 +824,7 @@ func TestExecer(t *testing.T) {
 }
 
 func TestQueryer(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -842,7 +865,7 @@ func TestQueryer(t *testing.T) {
 }
 
 func TestStress(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -880,7 +903,7 @@ func TestStress(t *testing.T) {
 
 func TestDateTimeLocal(t *testing.T) {
 	zone := "Asia/Tokyo"
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename+"?_loc="+zone)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -947,7 +970,7 @@ func TestVersion(t *testing.T) {
 }
 
 func TestNumberNamedParams(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -983,7 +1006,7 @@ func TestNumberNamedParams(t *testing.T) {
 }
 
 func TestStringContainingZero(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
@@ -1043,7 +1066,7 @@ func (t TimeStamp) Value() (driver.Value, error) {
 }
 
 func TestDateTimeNow(t *testing.T) {
-	tempFilename := TempFilename()
+	tempFilename := TempFilename(t)
 	db, err := sql.Open("sqlite3", tempFilename)
 	if err != nil {
 		t.Fatal("Failed to open database:", err)
diff --git a/sqlite3_test/sqltest.go b/sqlite3_test/sqltest.go
index fc82782..06cfd0e 100644
--- a/sqlite3_test/sqltest.go
+++ b/sqlite3_test/sqltest.go
@@ -275,12 +275,11 @@ func TestPreparedStmt(t *testing.T) {
 	}
 
 	const nRuns = 10
-	ch := make(chan bool)
+	var wg sync.WaitGroup
 	for i := 0; i < nRuns; i++ {
+		wg.Add(1)
 		go func() {
-			defer func() {
-				ch <- true
-			}()
+			defer wg.Done()
 			for j := 0; j < 10; j++ {
 				count := 0
 				if err := sel.QueryRow().Scan(&count); err != nil && err != sql.ErrNoRows {
@@ -294,9 +293,7 @@ func TestPreparedStmt(t *testing.T) {
 			}
 		}()
 	}
-	for i := 0; i < nRuns; i++ {
-		<-ch
-	}
+	wg.Wait()
 }
 
 // Benchmarks need to use panic() since b.Error errors are lost when