gitlab.com/cznic/sqlite.git@v1.0.0/all_test.go (about)

     1  // Copyright 2017 The Sqlite Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package sqlite // import "modernc.org/sqlite"
     6  
     7  import (
     8  	"bytes"
     9  	"database/sql"
    10  	"flag"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"os"
    14  	"path"
    15  	"path/filepath"
    16  	"runtime"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  )
    21  
    22  func caller(s string, va ...interface{}) {
    23  	if s == "" {
    24  		s = strings.Repeat("%v ", len(va))
    25  	}
    26  	_, fn, fl, _ := runtime.Caller(2)
    27  	fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl)
    28  	fmt.Fprintf(os.Stderr, s, va...)
    29  	fmt.Fprintln(os.Stderr)
    30  	_, fn, fl, _ = runtime.Caller(1)
    31  	fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl)
    32  	fmt.Fprintln(os.Stderr)
    33  	os.Stderr.Sync()
    34  }
    35  
    36  func dbg(s string, va ...interface{}) {
    37  	if s == "" {
    38  		s = strings.Repeat("%v ", len(va))
    39  	}
    40  	_, fn, fl, _ := runtime.Caller(1)
    41  	fmt.Fprintf(os.Stderr, "# dbg %s:%d: ", path.Base(fn), fl)
    42  	fmt.Fprintf(os.Stderr, s, va...)
    43  	fmt.Fprintln(os.Stderr)
    44  	os.Stderr.Sync()
    45  }
    46  
    47  func TODO(...interface{}) string { //TODOOK
    48  	_, fn, fl, _ := runtime.Caller(1)
    49  	return fmt.Sprintf("# TODO: %s:%d:\n", path.Base(fn), fl) //TODOOK
    50  }
    51  
    52  func use(...interface{}) {}
    53  
    54  func init() {
    55  	use(caller, dbg, TODO) //TODOOK
    56  }
    57  
    58  // ============================================================================
    59  
    60  var (
    61  	memTrace   = flag.Bool("memory.trace", false, "")
    62  	recsPerSec = flag.Bool("recs_per_sec_as_mbps", false, "Show records per second as MB/s.")
    63  )
    64  
    65  func tempDB(t testing.TB) (string, *sql.DB) {
    66  	dir, err := ioutil.TempDir("", "sqlite-test-")
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  
    71  	db, err := sql.Open(driverName, filepath.Join(dir, "tmp.db"))
    72  	if err != nil {
    73  		os.RemoveAll(dir)
    74  		t.Fatal(err)
    75  	}
    76  
    77  	return dir, db
    78  }
    79  
    80  func TestScalar(t *testing.T) {
    81  	dir, db := tempDB(t)
    82  
    83  	defer func() {
    84  		db.Close()
    85  		os.RemoveAll(dir)
    86  	}()
    87  
    88  	t1 := time.Date(2017, 4, 20, 1, 2, 3, 56789, time.UTC)
    89  	t2 := time.Date(2018, 5, 21, 2, 3, 4, 98765, time.UTC)
    90  	r, err := db.Exec(`
    91  	create table t(i int, f double, b bool, s text, t time);
    92  	insert into t values(12, 3.14, ?, "foo", ?), (34, 2.78, ?, "bar", ?);
    93  	`,
    94  		true, t1,
    95  		false, t2,
    96  	)
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  
   101  	n, err := r.RowsAffected()
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	if g, e := n, int64(2); g != e {
   107  		t.Fatal(g, e)
   108  	}
   109  
   110  	rows, err := db.Query("select * from t")
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	type rec struct {
   116  		i int
   117  		f float64
   118  		b bool
   119  		s string
   120  		t string
   121  	}
   122  	var a []rec
   123  	for rows.Next() {
   124  		var r rec
   125  		if err := rows.Scan(&r.i, &r.f, &r.b, &r.s, &r.t); err != nil {
   126  			t.Fatal(err)
   127  		}
   128  
   129  		a = append(a, r)
   130  	}
   131  	if err := rows.Err(); err != nil {
   132  		t.Fatal(err)
   133  	}
   134  
   135  	if g, e := len(a), 2; g != e {
   136  		t.Fatal(g, e)
   137  	}
   138  
   139  	if g, e := a[0], (rec{12, 3.14, true, "foo", t1.String()}); g != e {
   140  		t.Fatal(g, e)
   141  	}
   142  
   143  	if g, e := a[1], (rec{34, 2.78, false, "bar", t2.String()}); g != e {
   144  		t.Fatal(g, e)
   145  	}
   146  }
   147  
   148  func TestBlob(t *testing.T) {
   149  	dir, db := tempDB(t)
   150  
   151  	defer func() {
   152  		db.Close()
   153  		os.RemoveAll(dir)
   154  	}()
   155  
   156  	b1 := []byte(time.Now().String())
   157  	b2 := []byte("\x00foo\x00bar\x00")
   158  	if _, err := db.Exec(`
   159  	create table t(b blob);
   160  	insert into t values(?), (?);
   161  	`, b1, b2,
   162  	); err != nil {
   163  		t.Fatal(err)
   164  	}
   165  
   166  	rows, err := db.Query("select * from t")
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	type rec struct {
   172  		b []byte
   173  	}
   174  	var a []rec
   175  	for rows.Next() {
   176  		var r rec
   177  		if err := rows.Scan(&r.b); err != nil {
   178  			t.Fatal(err)
   179  		}
   180  
   181  		a = append(a, r)
   182  	}
   183  	if err := rows.Err(); err != nil {
   184  		t.Fatal(err)
   185  	}
   186  
   187  	if g, e := len(a), 2; g != e {
   188  		t.Fatal(g, e)
   189  	}
   190  
   191  	if g, e := a[0].b, b1; !bytes.Equal(g, e) {
   192  		t.Fatal(g, e)
   193  	}
   194  
   195  	if g, e := a[1].b, b2; !bytes.Equal(g, e) {
   196  		t.Fatal(g, e)
   197  	}
   198  }
   199  
   200  func BenchmarkInsertMemory(b *testing.B) {
   201  	db, err := sql.Open(driverName, "file::memory:")
   202  	if err != nil {
   203  		b.Fatal(err)
   204  	}
   205  
   206  	defer func() {
   207  		db.Close()
   208  	}()
   209  
   210  	if _, err := db.Exec(`
   211  	create table t(i int);
   212  	begin;
   213  	`); err != nil {
   214  		b.Fatal(err)
   215  	}
   216  
   217  	s, err := db.Prepare("insert into t values(?)")
   218  	if err != nil {
   219  		b.Fatal(err)
   220  	}
   221  
   222  	b.ResetTimer()
   223  	for i := 0; i < b.N; i++ {
   224  		if _, err := s.Exec(int64(i)); err != nil {
   225  			b.Fatal(err)
   226  		}
   227  	}
   228  	b.StopTimer()
   229  	if *recsPerSec {
   230  		b.SetBytes(1e6)
   231  	}
   232  	if _, err := db.Exec(`commit;`); err != nil {
   233  		b.Fatal(err)
   234  	}
   235  }
   236  
   237  func BenchmarkNextMemory(b *testing.B) {
   238  	db, err := sql.Open(driverName, "file::memory:")
   239  	if err != nil {
   240  		b.Fatal(err)
   241  	}
   242  
   243  	defer func() {
   244  		db.Close()
   245  	}()
   246  
   247  	if _, err := db.Exec(`
   248  	create table t(i int);
   249  	begin;
   250  	`); err != nil {
   251  		b.Fatal(err)
   252  	}
   253  
   254  	s, err := db.Prepare("insert into t values(?)")
   255  	if err != nil {
   256  		b.Fatal(err)
   257  	}
   258  
   259  	defer s.Close()
   260  
   261  	for i := 0; i < b.N; i++ {
   262  		if _, err := s.Exec(int64(i)); err != nil {
   263  			b.Fatal(err)
   264  		}
   265  	}
   266  	if _, err := db.Exec("commit"); err != nil {
   267  		b.Fatal(err)
   268  	}
   269  
   270  	r, err := db.Query("select * from t")
   271  	if err != nil {
   272  
   273  	}
   274  
   275  	defer r.Close()
   276  
   277  	b.ResetTimer()
   278  	for i := 0; i < b.N; i++ {
   279  		if !r.Next() {
   280  			b.Fatal(err)
   281  		}
   282  	}
   283  	b.StopTimer()
   284  	if *recsPerSec {
   285  		b.SetBytes(1e6)
   286  	}
   287  }
   288  
   289  // https://gitlab.com/cznic/sqlite/issues/11
   290  func TestIssue11(t *testing.T) {
   291  	const N = 6570
   292  	dir, db := tempDB(t)
   293  
   294  	defer func() {
   295  		db.Close()
   296  		os.RemoveAll(dir)
   297  	}()
   298  
   299  	if _, err := db.Exec(`
   300  	CREATE TABLE t1 (t INT);
   301  	BEGIN;
   302  `,
   303  	); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  
   307  	for i := 0; i < N; i++ {
   308  		if _, err := db.Exec("INSERT INTO t1 (t) VALUES (?)", i); err != nil {
   309  			t.Fatalf("#%v: %v", i, err)
   310  		}
   311  	}
   312  	if _, err := db.Exec("COMMIT;"); err != nil {
   313  		t.Fatal(err)
   314  	}
   315  }
   316  
   317  // https://gitlab.com/cznic/sqlite/issues/12
   318  func TestMemDB(t *testing.T) {
   319  	// Verify we can create out-of-the heap memory DB instance.
   320  	db, err := sql.Open(driverName, "file::memory:")
   321  	if err != nil {
   322  		t.Fatal(err)
   323  	}
   324  
   325  	defer func() {
   326  		db.Close()
   327  	}()
   328  
   329  	v := strings.Repeat("a", 1024)
   330  	if _, err := db.Exec(`
   331  	create table t(s string);
   332  	begin;
   333  	`); err != nil {
   334  		t.Fatal(err)
   335  	}
   336  
   337  	s, err := db.Prepare("insert into t values(?)")
   338  	if err != nil {
   339  		t.Fatal(err)
   340  	}
   341  
   342  	// Heap used to be fixed at 32MB.
   343  	for i := 0; i < (64<<20)/len(v); i++ {
   344  		if _, err := s.Exec(v); err != nil {
   345  			t.Fatalf("%v * %v= %v: %v", i, len(v), i*len(v), err)
   346  		}
   347  	}
   348  	if _, err := db.Exec(`commit;`); err != nil {
   349  		t.Fatal(err)
   350  	}
   351  }