go-hep.org/x/hep@v0.38.1/hbook/ntup/ntuple_test.go (about)

     1  // Copyright ©2016 The go-hep 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 ntup
     6  
     7  import (
     8  	"database/sql"
     9  	"reflect"
    10  	"testing"
    11  
    12  	"go-hep.org/x/hep/csvutil/csvdriver"
    13  	"go-hep.org/x/hep/hbook"
    14  )
    15  
    16  var (
    17  	nt *Ntuple
    18  )
    19  
    20  func TestScanH1D(t *testing.T) {
    21  	h := hbook.NewH1D(10, 0, 10)
    22  	h, err := nt.ScanH1D("x", h)
    23  	if err != nil {
    24  		t.Errorf("error running query: %v\n", err)
    25  	}
    26  	want := struct {
    27  		entries int64
    28  		len     int
    29  		mean    float64
    30  		rms     float64
    31  	}{
    32  		entries: 10,
    33  		len:     10,
    34  		mean:    4.5,
    35  		rms:     5.338539126015656,
    36  	}
    37  
    38  	if h.Entries() != want.entries {
    39  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.entries)
    40  	}
    41  	if h.Len() != want.len {
    42  		t.Errorf("error. got %v bins. want=%d\n", h.Len(), want.len)
    43  	}
    44  
    45  	for i := range h.Len() {
    46  		v := h.Value(i)
    47  		if v != 1 {
    48  			t.Errorf("error bin(%d)=%v. want=1\n", i, v)
    49  		}
    50  	}
    51  
    52  	if mean := h.XMean(); mean != want.mean {
    53  		t.Errorf("error: mean=%v. want=%v\n", mean, want.mean)
    54  	}
    55  	if rms := h.XRMS(); rms != want.rms {
    56  		t.Errorf("error: rms=%v. want=%v\n", rms, want.rms)
    57  	}
    58  }
    59  
    60  func TestScanH1DWithoutH1(t *testing.T) {
    61  	want := hbook.NewH1D(100, 0, nextULP(9))
    62  	for i := range 10 {
    63  		want.Fill(float64(i), 1)
    64  	}
    65  
    66  	h, err := nt.ScanH1D("x", nil)
    67  	if err != nil {
    68  		t.Errorf("error running query: %v\n", err)
    69  	}
    70  	if h.Entries() != want.Entries() {
    71  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.Entries())
    72  	}
    73  	if h.Len() != want.Len() {
    74  		t.Errorf("error. got %v bins. want=%d\n", h.Len(), want.Len())
    75  	}
    76  
    77  	for i := range h.Len() {
    78  		v := h.Value(i)
    79  		if v != want.Value(i) {
    80  			t.Errorf("error bin(%d)=%v. want=%v\n", i, v, want.Value(i))
    81  		}
    82  	}
    83  
    84  	if mean := h.XMean(); mean != want.XMean() {
    85  		t.Errorf("error: mean=%v. want=%v\n", mean, want.XMean())
    86  	}
    87  	if rms := h.XRMS(); rms != want.XRMS() {
    88  		t.Errorf("error: rms=%v. want=%v\n", rms, want.XRMS())
    89  	}
    90  }
    91  
    92  func TestScanH1DWhere(t *testing.T) {
    93  	for _, where := range []string{
    94  		"x where (id > 4 && id < 10)",
    95  		"x WHERE (id > 4 && id < 10)",
    96  		"x where (id > 4 && id < 10) order by id();",
    97  		"x WHERE (id > 4 && id < 10) ORDER by id();",
    98  		"x WHERE (id > 4 && id < 10) order by id();",
    99  		"x where (id > 4 && id < 10) ORDER by id();",
   100  	} {
   101  		t.Run("", func(t *testing.T) {
   102  			h := hbook.NewH1D(10, 0, 10)
   103  			h, err := nt.ScanH1D(where, h)
   104  			if err != nil {
   105  				t.Errorf("error running query: %v\n", err)
   106  			}
   107  
   108  			want := struct {
   109  				entries int64
   110  				len     int
   111  				mean    float64
   112  				rms     float64
   113  			}{
   114  				entries: 5,
   115  				len:     10,
   116  				mean:    7,
   117  				rms:     7.14142842854285,
   118  			}
   119  
   120  			if h.Entries() != want.entries {
   121  				t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.entries)
   122  			}
   123  			if h.Len() != want.len {
   124  				t.Errorf("error. got %v bins. want=%d\n", h.Len(), want.len)
   125  			}
   126  
   127  			for i := range h.Len() {
   128  				v := h.Value(i)
   129  				want := float64(0)
   130  				if i > 4 {
   131  					want = 1
   132  				}
   133  				if v != want {
   134  					t.Errorf("error bin(%d)=%v. want=%v\n", i, v, want)
   135  				}
   136  			}
   137  
   138  			if mean := h.XMean(); mean != want.mean {
   139  				t.Errorf("error: mean=%v. want=%v\n", mean, want.mean)
   140  			}
   141  			if rms := h.XRMS(); rms != want.rms {
   142  				t.Errorf("error: rms=%v. want=%v\n", rms, want.rms)
   143  			}
   144  		})
   145  	}
   146  }
   147  
   148  func TestScanH1DInt(t *testing.T) {
   149  	h := hbook.NewH1D(10, 0, 10)
   150  	h, err := nt.ScanH1D("id", h)
   151  	if err != nil {
   152  		t.Errorf("error running query: %v\n", err)
   153  	}
   154  	want := struct {
   155  		entries int64
   156  		len     int
   157  		mean    float64
   158  		rms     float64
   159  	}{
   160  		entries: 10,
   161  		len:     10,
   162  		mean:    4.5,
   163  		rms:     5.338539126015656,
   164  	}
   165  
   166  	if h.Entries() != want.entries {
   167  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.entries)
   168  	}
   169  	if h.Len() != want.len {
   170  		t.Errorf("error. got %v bins. want=%d\n", h.Len(), want.len)
   171  	}
   172  
   173  	for i := range h.Len() {
   174  		v := h.Value(i)
   175  		if v != 1 {
   176  			t.Errorf("error bin(%d)=%v. want=1\n", i, v)
   177  		}
   178  	}
   179  
   180  	if mean := h.XMean(); mean != want.mean {
   181  		t.Errorf("error: mean=%v. want=%v\n", mean, want.mean)
   182  	}
   183  	if rms := h.XRMS(); rms != want.rms {
   184  		t.Errorf("error: rms=%v. want=%v\n", rms, want.rms)
   185  	}
   186  }
   187  
   188  func TestScanH2D(t *testing.T) {
   189  	want := hbook.NewH2D(10, 0, 10, 10, 0, 10)
   190  	for i := range 10 {
   191  		v := float64(i)
   192  		want.Fill(v, v, 1)
   193  	}
   194  
   195  	h := hbook.NewH2D(10, 0, 10, 10, 0, 10)
   196  	h, err := nt.ScanH2D("id, x", h)
   197  	if err != nil {
   198  		t.Errorf("error running query: %v\n", err)
   199  	}
   200  
   201  	if h.Entries() != want.Entries() {
   202  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.Entries())
   203  	}
   204  
   205  	type gridXYZer interface {
   206  		Dims() (c, r int)
   207  		Z(c, r int) float64
   208  		X(c int) float64
   209  		Y(r int) float64
   210  	}
   211  
   212  	cmpGrid := func(a, b gridXYZer) {
   213  		ac, ar := a.Dims()
   214  		bc, br := b.Dims()
   215  		if ac != bc {
   216  			t.Fatalf("got=%d want=%d", ac, bc)
   217  		}
   218  		if ar != br {
   219  			t.Fatalf("got=%d want=%d", ar, br)
   220  		}
   221  		for i := range ar {
   222  			ay := a.Y(i)
   223  			by := b.Y(i)
   224  			if ay != by {
   225  				t.Fatalf("got=%v. want=%v", ay, by)
   226  			}
   227  			for j := range ac {
   228  				if i == 0 {
   229  					ax := a.X(j)
   230  					bx := b.X(j)
   231  					if ax != bx {
   232  						t.Fatalf("got=%v. want=%v", ax, bx)
   233  					}
   234  				}
   235  				az := a.Z(j, i)
   236  				bz := b.Z(j, i)
   237  				if az != bz {
   238  					t.Fatalf("got=%v. want=%v", az, bz)
   239  				}
   240  			}
   241  		}
   242  	}
   243  
   244  	cmpGrid(h.GridXYZ(), want.GridXYZ())
   245  
   246  	if mean := h.XMean(); mean != want.XMean() {
   247  		t.Errorf("error: mean=%v. want=%v\n", mean, want.XMean())
   248  	}
   249  	if rms := h.XRMS(); rms != want.XRMS() {
   250  		t.Errorf("error: rms=%v. want=%v\n", rms, want.XRMS())
   251  	}
   252  }
   253  
   254  func TestScanH2DWithoutH2D(t *testing.T) {
   255  	want := hbook.NewH2D(100, 0, nextULP(9), 100, 0, nextULP(9))
   256  	for i := range 10 {
   257  		v := float64(i)
   258  		want.Fill(v, v, 1)
   259  	}
   260  
   261  	h, err := nt.ScanH2D("id, x", nil)
   262  	if err != nil {
   263  		t.Errorf("error running query: %v\n", err)
   264  	}
   265  
   266  	if h.Entries() != want.Entries() {
   267  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.Entries())
   268  	}
   269  
   270  	type gridXYZer interface {
   271  		Dims() (c, r int)
   272  		Z(c, r int) float64
   273  		X(c int) float64
   274  		Y(r int) float64
   275  	}
   276  
   277  	cmpGrid := func(a, b gridXYZer) {
   278  		ac, ar := a.Dims()
   279  		bc, br := b.Dims()
   280  		if ac != bc {
   281  			t.Fatalf("got=%d want=%d", ac, bc)
   282  		}
   283  		if ar != br {
   284  			t.Fatalf("got=%d want=%d", ar, br)
   285  		}
   286  		for i := range ar {
   287  			ay := a.Y(i)
   288  			by := b.Y(i)
   289  			if ay != by {
   290  				t.Fatalf("got=%v. want=%v", ay, by)
   291  			}
   292  			for j := range ac {
   293  				if i == 0 {
   294  					ax := a.X(j)
   295  					bx := b.X(j)
   296  					if ax != bx {
   297  						t.Fatalf("got=%v. want=%v", ax, bx)
   298  					}
   299  				}
   300  				az := a.Z(j, i)
   301  				bz := b.Z(j, i)
   302  				if az != bz {
   303  					t.Fatalf("got=%v. want=%v", az, bz)
   304  				}
   305  			}
   306  		}
   307  	}
   308  
   309  	cmpGrid(h.GridXYZ(), want.GridXYZ())
   310  
   311  	if mean := h.XMean(); mean != want.XMean() {
   312  		t.Errorf("error: mean=%v. want=%v\n", mean, want.XMean())
   313  	}
   314  	if rms := h.XRMS(); rms != want.XRMS() {
   315  		t.Errorf("error: rms=%v. want=%v\n", rms, want.XRMS())
   316  	}
   317  }
   318  
   319  func TestScan(t *testing.T) {
   320  	h := hbook.NewH1D(10, 0, 10)
   321  	err := nt.Scan("id, x", func(id int64, x float64) error {
   322  		h.Fill(x, 1)
   323  		return nil
   324  	})
   325  	if err != nil {
   326  		t.Errorf("error running query: %v\n", err)
   327  	}
   328  	want := struct {
   329  		entries int64
   330  		len     int
   331  		mean    float64
   332  		rms     float64
   333  	}{
   334  		entries: 10,
   335  		len:     10,
   336  		mean:    4.5,
   337  		rms:     5.338539126015656,
   338  	}
   339  
   340  	if h.Entries() != want.entries {
   341  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.entries)
   342  	}
   343  	if h.Len() != want.len {
   344  		t.Errorf("error. got %v bins. want=%d\n", h.Len(), want.len)
   345  	}
   346  
   347  	for i := range h.Len() {
   348  		v := h.Value(i)
   349  		if v != 1 {
   350  			t.Errorf("error bin(%d)=%v. want=1\n", i, v)
   351  		}
   352  	}
   353  
   354  	if mean := h.XMean(); mean != want.mean {
   355  		t.Errorf("error: mean=%v. want=%v\n", mean, want.mean)
   356  	}
   357  	if rms := h.XRMS(); rms != want.rms {
   358  		t.Errorf("error: rms=%v. want=%v\n", rms, want.rms)
   359  	}
   360  }
   361  
   362  func TestScanH1DFromCSVWithCommas(t *testing.T) {
   363  	db, err := sql.Open("csv", "testdata/simple-comma.csv")
   364  	if err != nil {
   365  		t.Fatalf("error opening CSV db: %v\n", err)
   366  	}
   367  	defer db.Close()
   368  
   369  	nt, err := Open(db, "csv")
   370  	if err != nil {
   371  		t.Fatalf("error opening ntuple: %v\n", err)
   372  	}
   373  
   374  	h := hbook.NewH1D(10, 0, 10)
   375  	h, err = nt.ScanH1D("var2", h)
   376  	if err != nil {
   377  		t.Errorf("error running query: %v\n", err)
   378  	}
   379  	want := struct {
   380  		entries int64
   381  		len     int
   382  		mean    float64
   383  		rms     float64
   384  	}{
   385  		entries: 10,
   386  		len:     10,
   387  		mean:    4.5,
   388  		rms:     5.338539126015656,
   389  	}
   390  
   391  	if h.Entries() != want.entries {
   392  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.entries)
   393  	}
   394  	if h.Len() != want.len {
   395  		t.Errorf("error. got %v bins. want=%d\n", h.Len(), want.len)
   396  	}
   397  
   398  	for i := range h.Len() {
   399  		v := h.Value(i)
   400  		if v != 1 {
   401  			t.Errorf("error bin(%d)=%v. want=1\n", i, v)
   402  		}
   403  	}
   404  
   405  	if mean := h.XMean(); mean != want.mean {
   406  		t.Errorf("error: mean=%v. want=%v\n", mean, want.mean)
   407  	}
   408  	if rms := h.XRMS(); rms != want.rms {
   409  		t.Errorf("error: rms=%v. want=%v\n", rms, want.rms)
   410  	}
   411  }
   412  
   413  func TestScanH1DFromCSV(t *testing.T) {
   414  	db, err := csvdriver.Conn{
   415  		File:    "testdata/simple.csv",
   416  		Comma:   ';',
   417  		Comment: '#',
   418  	}.Open()
   419  	if err != nil {
   420  		t.Fatalf("error opening CSV db: %v\n", err)
   421  	}
   422  	defer db.Close()
   423  
   424  	nt, err := Open(db, "csv")
   425  	if err != nil {
   426  		t.Fatalf("error opening ntuple: %v\n", err)
   427  	}
   428  
   429  	h := hbook.NewH1D(10, 0, 10)
   430  	h, err = nt.ScanH1D("var2", h)
   431  	if err != nil {
   432  		t.Errorf("error running query: %v\n", err)
   433  	}
   434  	want := struct {
   435  		entries int64
   436  		len     int
   437  		mean    float64
   438  		rms     float64
   439  	}{
   440  		entries: 10,
   441  		len:     10,
   442  		mean:    4.5,
   443  		rms:     5.338539126015656,
   444  	}
   445  
   446  	if h.Entries() != want.entries {
   447  		t.Errorf("error. got %v entries. want=%v\n", h.Entries(), want.entries)
   448  	}
   449  	if h.Len() != want.len {
   450  		t.Errorf("error. got %v bins. want=%d\n", h.Len(), want.len)
   451  	}
   452  
   453  	for i := range h.Len() {
   454  		v := h.Value(i)
   455  		if v != 1 {
   456  			t.Errorf("error bin(%d)=%v. want=1\n", i, v)
   457  		}
   458  	}
   459  
   460  	if mean := h.XMean(); mean != want.mean {
   461  		t.Errorf("error: mean=%v. want=%v\n", mean, want.mean)
   462  	}
   463  	if rms := h.XRMS(); rms != want.rms {
   464  		t.Errorf("error: rms=%v. want=%v\n", rms, want.rms)
   465  	}
   466  }
   467  
   468  func TestScanInvalid(t *testing.T) {
   469  	for _, tc := range []struct {
   470  		name string
   471  		fct  any
   472  	}{
   473  		{
   474  			name: "nil func",
   475  			fct:  nil,
   476  		},
   477  		{
   478  			name: "not a func",
   479  			fct:  0,
   480  		},
   481  		{
   482  			name: "0-arity",
   483  			fct:  func() {},
   484  		},
   485  		{
   486  			name: "invalid func",
   487  			fct:  func() int { return 0 },
   488  		},
   489  		{
   490  			name: "2-arity",
   491  			fct:  func() (int, error) { return 1, nil },
   492  		},
   493  	} {
   494  		t.Run(tc.name, func(t *testing.T) {
   495  			err := nt.Scan("id, x", tc.fct)
   496  			if err == nil {
   497  				t.Fatalf("expected an error")
   498  			}
   499  		})
   500  	}
   501  }
   502  
   503  func TestCreate(t *testing.T) {
   504  	db, err := sql.Open("ql", "memory://ntuple.db")
   505  	if err != nil {
   506  		t.Fatalf("error creating db: %v\n", err)
   507  	}
   508  	defer db.Close()
   509  
   510  	const ntname = "ntup"
   511  	nt, err := Create(db, ntname, int64(0), float64(0))
   512  	if err != nil {
   513  		t.Fatalf("error creating ntuple: %v\n", err)
   514  	}
   515  
   516  	if nt.Name() != ntname {
   517  		t.Errorf("invalid ntuple name. got=%q want=%q\n", nt.Name(), ntname)
   518  	}
   519  
   520  	descr := []struct {
   521  		n string
   522  		t reflect.Type
   523  	}{
   524  		{
   525  			n: "var1",
   526  			t: reflect.TypeOf(int64(0)),
   527  		},
   528  		{
   529  			n: "var2",
   530  			t: reflect.TypeOf(float64(0)),
   531  		},
   532  	}
   533  	if len(nt.Cols()) != len(descr) {
   534  		t.Fatalf("invalid cols. got=%d. want=%d\n", len(nt.Cols()), len(descr))
   535  	}
   536  
   537  	for i := range descr {
   538  		col := nt.Cols()[i]
   539  		exp := descr[i]
   540  		if col.Name() != exp.n {
   541  			t.Errorf("col[%d]: invalid name. got=%q. want=%q\n",
   542  				i, col.Name(), exp.n,
   543  			)
   544  		}
   545  		if col.Type() != exp.t {
   546  			t.Errorf("col[%d]: invalid type. got=%v. want=%v\n",
   547  				i, col.Type(), exp.t,
   548  			)
   549  		}
   550  	}
   551  }
   552  
   553  func TestCreateFromStruct(t *testing.T) {
   554  	db, err := sql.Open("ql", "memory://ntuple-struct.db")
   555  	if err != nil {
   556  		t.Fatalf("error creating db: %v\n", err)
   557  	}
   558  	defer db.Close()
   559  
   560  	type dataType struct {
   561  		I  int64
   562  		F  float64
   563  		FF float64 `rio:"ff" hbook:"-"`
   564  		S  string  `rio:"STR" hbook:"str"`
   565  	}
   566  
   567  	const ntname = "ntup"
   568  	nt, err := Create(db, ntname, dataType{})
   569  	if err != nil {
   570  		t.Fatalf("error creating ntuple: %v\n", err)
   571  	}
   572  
   573  	if nt.Name() != ntname {
   574  		t.Errorf("invalid ntuple name. got=%q want=%q\n", nt.Name(), ntname)
   575  	}
   576  
   577  	descr := []struct {
   578  		n string
   579  		t reflect.Type
   580  	}{
   581  		{
   582  			n: "I",
   583  			t: reflect.TypeOf(int64(0)),
   584  		},
   585  		{
   586  			n: "F",
   587  			t: reflect.TypeOf(float64(0)),
   588  		},
   589  		{
   590  			n: "ff",
   591  			t: reflect.TypeOf(float64(0)),
   592  		},
   593  		{
   594  			n: "str",
   595  			t: reflect.TypeOf(""),
   596  		},
   597  	}
   598  	if len(nt.Cols()) != len(descr) {
   599  		t.Fatalf("invalid cols. got=%d. want=%d\n", len(nt.Cols()), len(descr))
   600  	}
   601  
   602  	for i := range descr {
   603  		col := nt.Cols()[i]
   604  		exp := descr[i]
   605  		if col.Name() != exp.n {
   606  			t.Errorf("col[%d]: invalid name. got=%q. want=%q\n",
   607  				i, col.Name(), exp.n,
   608  			)
   609  		}
   610  		if col.Type() != exp.t {
   611  			t.Errorf("col[%d]: invalid type. got=%v. want=%v\n",
   612  				i, col.Type(), exp.t,
   613  			)
   614  		}
   615  	}
   616  }
   617  
   618  func TestCreateInvalid(t *testing.T) {
   619  	for _, tc := range []struct {
   620  		name string
   621  		err  error
   622  		cols []any
   623  	}{
   624  		{
   625  			name: "missing-col-def.db",
   626  			err:  ErrMissingColDef,
   627  		},
   628  		{
   629  			name: "one-value.db",
   630  			cols: []any{int64(0)},
   631  		},
   632  		{
   633  			name: "err-chan.db",
   634  			cols: []any{make(chan int)},
   635  			err:  errChanType,
   636  		},
   637  		{
   638  			name: "err-struct-chan.db",
   639  			cols: []any{func() any {
   640  				type Person struct {
   641  					Field chan int
   642  				}
   643  				return Person{Field: make(chan int)}
   644  			}(),
   645  			},
   646  			err: errChanType,
   647  		},
   648  		//		{
   649  		//			name: "err-iface.db",
   650  		//			cols: []any{(io.Writer)(os.Stdout)},
   651  		//			err:  errIfaceType,
   652  		//		},
   653  		//		{
   654  		//			name: "err-eface.db",
   655  		//			cols: []any{any(nil)},
   656  		//			err:  errIfaceType,
   657  		//		},
   658  		{
   659  			name: "err-map.db",
   660  			cols: []any{make(map[string]int)},
   661  			err:  errMapType,
   662  		},
   663  		{
   664  			name: "err-struct-map.db",
   665  			cols: []any{func() any {
   666  				type Person struct {
   667  					Field map[string]int
   668  				}
   669  				return Person{Field: make(map[string]int)}
   670  			}(),
   671  			},
   672  			err: errMapType,
   673  		},
   674  		{
   675  			name: "err-slice.db",
   676  			cols: []any{make([]int, 2)},
   677  			err:  errSliceType,
   678  		},
   679  		{
   680  			name: "err-struct-slice.db",
   681  			cols: []any{func() any {
   682  				type Person struct {
   683  					Field []int
   684  				}
   685  				return Person{Field: make([]int, 2)}
   686  			}(),
   687  			},
   688  			err: errSliceType,
   689  		},
   690  		{
   691  			name: "err-struct.db",
   692  			cols: []any{func() any {
   693  				type Name struct {
   694  					Name string
   695  				}
   696  				type Person struct {
   697  					Name Name
   698  				}
   699  				var p Person
   700  				p.Name.Name = "bob"
   701  				return p
   702  			}(),
   703  			},
   704  			err: errStructType,
   705  		},
   706  		{
   707  			name: "err-estruct.db",
   708  			cols: []any{func() any {
   709  				type Name struct{}
   710  				type Anon struct {
   711  					Name Name
   712  				}
   713  				var v Anon
   714  				return v
   715  			}(),
   716  			},
   717  			err: errStructType,
   718  		},
   719  	} {
   720  		t.Run(tc.name, func(t *testing.T) {
   721  			db, err := sql.Open("ql", "memory://"+tc.name)
   722  			if err != nil {
   723  				t.Fatalf("error creating db: %v\n", err)
   724  			}
   725  			defer db.Close()
   726  
   727  			const ntname = "ntup"
   728  			nt, err := Create(db, ntname, tc.cols...)
   729  			if tc.err != nil && err == nil {
   730  				t.Fatalf("expected an error")
   731  			}
   732  			if err != tc.err {
   733  				t.Fatalf("got=%v. want=%v", err, tc.err)
   734  			}
   735  			if nt != nil {
   736  				defer func() {
   737  					err = nt.DB().Close()
   738  					if err != nil {
   739  						t.Fatal(err)
   740  					}
   741  				}()
   742  			}
   743  		})
   744  	}
   745  }
   746  
   747  func init() {
   748  	var err error
   749  	db, err := sql.Open("ql", "memory://mem.db")
   750  	if err != nil {
   751  		panic(err)
   752  	}
   753  
   754  	tx, err := db.Begin()
   755  	if err != nil {
   756  		panic(err)
   757  	}
   758  	_, err = tx.Exec("create table data (id int, x float64);")
   759  	if err != nil {
   760  		panic(err)
   761  	}
   762  
   763  	for i := range 10 {
   764  		x := float64(i)
   765  		_, err = tx.Exec("insert into data values($1, $2);", i, x)
   766  		if err != nil {
   767  			panic(err)
   768  		}
   769  	}
   770  
   771  	err = tx.Commit()
   772  	if err != nil {
   773  		panic(err)
   774  	}
   775  
   776  	nt, err = Open(db, "data")
   777  	if err != nil {
   778  		panic(err)
   779  	}
   780  }