github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/tests/bradfitz/sql_test.go (about) 1 //go:build (linux || darwin || windows || freebsd || illumos) && !sqlite3_nosys 2 3 package bradfitz 4 5 // Adapted from: https://github.com/bradfitz/go-sql-test 6 7 import ( 8 "database/sql" 9 "fmt" 10 "math/rand" 11 "path/filepath" 12 "sync" 13 "testing" 14 15 _ "github.com/ncruces/go-sqlite3/driver" 16 _ "github.com/ncruces/go-sqlite3/embed" 17 _ "github.com/ncruces/go-sqlite3/tests/testcfg" 18 ) 19 20 type Tester interface { 21 RunTest(*testing.T, func(params)) 22 } 23 24 var ( 25 sqlite Tester = sqliteDB{} 26 ) 27 28 const TablePrefix = "gosqltest_" 29 30 type sqliteDB struct{} 31 32 type params struct { 33 dbType Tester 34 *testing.T 35 *sql.DB 36 } 37 38 func (t params) mustExec(sql string, args ...interface{}) sql.Result { 39 res, err := t.DB.Exec(sql, args...) 40 if err != nil { 41 t.Fatalf("Error running %q: %v", sql, err) 42 } 43 return res 44 } 45 46 func (sqliteDB) RunTest(t *testing.T, fn func(params)) { 47 db, err := sql.Open("sqlite3", "file:"+ 48 filepath.Join(t.TempDir(), "foo.db")+ 49 "?_pragma=busy_timeout(10000)&_pragma=synchronous(off)") 50 if err != nil { 51 t.Fatalf("foo.db open fail: %v", err) 52 } 53 fn(params{sqlite, t, db}) 54 if err := db.Close(); err != nil { 55 t.Fatalf("foo.db close fail: %v", err) 56 } 57 } 58 59 func TestBlobs_SQLite(t *testing.T) { sqlite.RunTest(t, testBlobs) } 60 61 func testBlobs(t params) { 62 var blob = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 63 t.mustExec("create table " + TablePrefix + "foo (id integer primary key, bar blob)") 64 t.mustExec("insert into "+TablePrefix+"foo (id, bar) values(?,?)", 0, blob) 65 66 want := fmt.Sprintf("%x", blob) 67 68 b := make([]byte, 16) 69 err := t.QueryRow("select bar from "+TablePrefix+"foo where id = ?", 0).Scan(&b) 70 got := fmt.Sprintf("%x", b) 71 if err != nil { 72 t.Errorf("[]byte scan: %v", err) 73 } else if got != want { 74 t.Errorf("for []byte, got %q; want %q", got, want) 75 } 76 77 err = t.QueryRow("select bar from "+TablePrefix+"foo where id = ?", 0).Scan(&got) 78 want = string(blob) 79 if err != nil { 80 t.Errorf("string scan: %v", err) 81 } else if got != want { 82 t.Errorf("for string, got %q; want %q", got, want) 83 } 84 } 85 86 func TestManyQueryRow_SQLite(t *testing.T) { sqlite.RunTest(t, testManyQueryRow) } 87 88 func testManyQueryRow(t params) { 89 if testing.Short() { 90 t.Skip("skipping in short mode") 91 } 92 t.mustExec("create table " + TablePrefix + "foo (id integer primary key, name varchar(50))") 93 t.mustExec("insert into "+TablePrefix+"foo (id, name) values(?,?)", 1, "bob") 94 var name string 95 for i := 0; i < 10000; i++ { 96 err := t.QueryRow("select name from "+TablePrefix+"foo where id = ?", 1).Scan(&name) 97 if err != nil || name != "bob" { 98 t.Fatalf("on query %d: err=%v, name=%q", i, err, name) 99 } 100 } 101 } 102 103 func TestTxQuery_SQLite(t *testing.T) { sqlite.RunTest(t, testTxQuery) } 104 105 func testTxQuery(t params) { 106 tx, err := t.Begin() 107 if err != nil { 108 t.Fatal(err) 109 } 110 defer tx.Rollback() 111 112 _, err = tx.Exec("create table " + TablePrefix + "foo (id integer primary key, name varchar(50))") 113 if err != nil { 114 t.Logf("cannot drop table "+TablePrefix+"foo: %s", err) 115 } 116 117 _, err = tx.Exec("insert into "+TablePrefix+"foo (id, name) values(?,?)", 1, "bob") 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 r, err := tx.Query("select name from "+TablePrefix+"foo where id = ?", 1) 123 if err != nil { 124 t.Fatal(err) 125 } 126 defer r.Close() 127 128 if !r.Next() { 129 if r.Err() != nil { 130 t.Fatal(err) 131 } 132 t.Fatal("expected one row") 133 } 134 135 var name string 136 err = r.Scan(&name) 137 if err != nil { 138 t.Fatal(err) 139 } 140 } 141 142 func TestPreparedStmt_SQLite(t *testing.T) { sqlite.RunTest(t, testPreparedStmt) } 143 144 func testPreparedStmt(t params) { 145 if testing.Short() { 146 t.Skip("skipping in short mode") 147 } 148 149 t.mustExec("CREATE TABLE " + TablePrefix + "t (count INT)") 150 sel, err := t.Prepare("SELECT count FROM " + TablePrefix + "t ORDER BY count DESC") 151 if err != nil { 152 t.Fatalf("prepare 1: %v", err) 153 } 154 ins, err := t.Prepare("INSERT INTO " + TablePrefix + "t (count) VALUES (?)") 155 if err != nil { 156 t.Fatalf("prepare 2: %v", err) 157 } 158 159 for n := 1; n <= 3; n++ { 160 if _, err := ins.Exec(n); err != nil { 161 t.Fatalf("insert(%d) = %v", n, err) 162 } 163 } 164 165 const nRuns = 10 166 var wg sync.WaitGroup 167 for i := 0; i < nRuns; i++ { 168 wg.Add(1) 169 go func() { 170 defer wg.Done() 171 for j := 0; j < 10; j++ { 172 count := 0 173 if err := sel.QueryRow().Scan(&count); err != nil && err != sql.ErrNoRows { 174 t.Errorf("Query: %v", err) 175 return 176 } 177 if _, err := ins.Exec(rand.Intn(100)); err != nil { 178 t.Errorf("Insert: %v", err) 179 return 180 } 181 } 182 }() 183 } 184 wg.Wait() 185 }