From cebbf42ff60a87f038ef03b3c5734817d41ef0d6 Mon Sep 17 00:00:00 2001 From: Lars Buitinck Date: Fri, 5 Jun 2015 16:02:14 +0200 Subject: [PATCH 1/5] Get reliable tempfile names from ioutil.TempFile Also makes them easier to spot (the tests tend to litter /tmp). --- sqlite3_fts3_test.go | 2 +- sqlite3_test.go | 55 ++++++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 28 deletions(-) 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..ee1ba0c 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,18 @@ 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) if option != "" { url = tempFilename + option } else { @@ -82,7 +83,7 @@ func TestOpen(t *testing.T) { } 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 +109,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 +148,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 +213,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 +274,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 +323,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 +406,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 +498,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 +536,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 +568,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 +628,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 +676,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 +782,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 +802,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 +843,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 +881,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 +948,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 +984,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 +1044,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) From 90505effc710691c8b0bda88365ee38de52f05c9 Mon Sep 17 00:00:00 2001 From: Lars Buitinck Date: Fri, 5 Jun 2015 16:03:38 +0200 Subject: [PATCH 2/5] Fix doc comment --- sqlite3.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From a3efcea001ff5a2fb956efc4272fea14e422086b Mon Sep 17 00:00:00 2001 From: Lars Buitinck Date: Fri, 5 Jun 2015 16:32:51 +0200 Subject: [PATCH 3/5] Clean up more tempfiles --- sqlite3_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/sqlite3_test.go b/sqlite3_test.go index ee1ba0c..f2d461b 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -32,6 +32,7 @@ func TempFilename(t *testing.T) string { func doTestOpen(t *testing.T, option string) (string, error) { var url string tempFilename := TempFilename(t) + defer os.Remove(tempFilename) if option != "" { url = tempFilename + option } else { From 5674e19d0587e09d0649f650671cb23627d20ba8 Mon Sep 17 00:00:00 2001 From: Lars Buitinck Date: Fri, 5 Jun 2015 16:33:25 +0200 Subject: [PATCH 4/5] Test read-only databases --- sqlite3_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sqlite3_test.go b/sqlite3_test.go index f2d461b..43f7b4f 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -83,6 +83,27 @@ 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(t) db, err := sql.Open("sqlite3", tempFilename) From 1ae6ca764d50a6a0f3d30009a287623337b534c7 Mon Sep 17 00:00:00 2001 From: Lars Buitinck Date: Fri, 5 Jun 2015 16:33:55 +0200 Subject: [PATCH 5/5] Cosmetics: use WaitGroup instead of channel in test --- sqlite3_test/sqltest.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) 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