github.com/tidwall/buntdb@v1.3.0/buntdb_test.go (about)

     1  package buntdb
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"math/rand"
     9  	"os"
    10  	"strconv"
    11  	"strings"
    12  	"sync"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/tidwall/assert"
    17  	"github.com/tidwall/lotsa"
    18  )
    19  
    20  func testOpen(t testing.TB) *DB {
    21  	if err := os.RemoveAll("data.db"); err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	return testReOpen(t, nil)
    25  }
    26  func testReOpen(t testing.TB, db *DB) *DB {
    27  	return testReOpenDelay(t, db, 0)
    28  }
    29  
    30  func testReOpenDelay(t testing.TB, db *DB, dur time.Duration) *DB {
    31  	if db != nil {
    32  		if err := db.Close(); err != nil {
    33  			t.Fatal(err)
    34  		}
    35  	}
    36  	time.Sleep(dur)
    37  	db, err := Open("data.db")
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	return db
    42  }
    43  
    44  func testClose(db *DB) {
    45  	_ = db.Close()
    46  	_ = os.RemoveAll("data.db")
    47  }
    48  
    49  func TestBackgroudOperations(t *testing.T) {
    50  	db := testOpen(t)
    51  	defer testClose(db)
    52  	for i := 0; i < 1000; i++ {
    53  		if err := db.Update(func(tx *Tx) error {
    54  			for j := 0; j < 200; j++ {
    55  				if _, _, err := tx.Set(fmt.Sprintf("hello%d", j), "planet", nil); err != nil {
    56  					return err
    57  				}
    58  			}
    59  			if _, _, err := tx.Set("hi", "world", &SetOptions{Expires: true, TTL: time.Second / 2}); err != nil {
    60  				return err
    61  			}
    62  			return nil
    63  		}); err != nil {
    64  			t.Fatal(err)
    65  		}
    66  	}
    67  	n := 0
    68  	err := db.View(func(tx *Tx) error {
    69  		var err error
    70  		n, err = tx.Len()
    71  		return err
    72  	})
    73  	if err != nil {
    74  		t.Fatal(err)
    75  	}
    76  	if n != 201 {
    77  		t.Fatalf("expecting '%v', got '%v'", 201, n)
    78  	}
    79  	time.Sleep(time.Millisecond * 1500)
    80  	db = testReOpen(t, db)
    81  	defer testClose(db)
    82  	n = 0
    83  	err = db.View(func(tx *Tx) error {
    84  		var err error
    85  		n, err = tx.Len()
    86  		return err
    87  	})
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	if n != 200 {
    92  		t.Fatalf("expecting '%v', got '%v'", 200, n)
    93  	}
    94  }
    95  func TestSaveLoad(t *testing.T) {
    96  	db, _ := Open(":memory:")
    97  	defer db.Close()
    98  	if err := db.Update(func(tx *Tx) error {
    99  		for i := 0; i < 20; i++ {
   100  			_, _, err := tx.Set(fmt.Sprintf("key:%d", i), fmt.Sprintf("planet:%d", i), nil)
   101  			if err != nil {
   102  				return err
   103  			}
   104  		}
   105  		return nil
   106  	}); err != nil {
   107  		t.Fatal(err)
   108  	}
   109  	f, err := os.Create("temp.db")
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	defer func() {
   114  		f.Close()
   115  		os.RemoveAll("temp.db")
   116  	}()
   117  	if err := db.Save(f); err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	if err := f.Close(); err != nil {
   121  		t.Fatal(err)
   122  	}
   123  	db.Close()
   124  	db, _ = Open(":memory:")
   125  	defer db.Close()
   126  	f, err = os.Open("temp.db")
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	defer f.Close()
   131  	if err := db.Load(f); err != nil {
   132  		t.Fatal(err)
   133  	}
   134  	if err := db.View(func(tx *Tx) error {
   135  		for i := 0; i < 20; i++ {
   136  			ex := fmt.Sprintf("planet:%d", i)
   137  			val, err := tx.Get(fmt.Sprintf("key:%d", i))
   138  			if err != nil {
   139  				return err
   140  			}
   141  			if ex != val {
   142  				t.Fatalf("expected %s, got %s", ex, val)
   143  			}
   144  		}
   145  		return nil
   146  	}); err != nil {
   147  		t.Fatal(err)
   148  	}
   149  }
   150  
   151  func TestMutatingIterator(t *testing.T) {
   152  	db := testOpen(t)
   153  	defer testClose(db)
   154  	count := 1000
   155  	if err := db.CreateIndex("ages", "user:*:age", IndexInt); err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	for i := 0; i < 10; i++ {
   160  		if err := db.Update(func(tx *Tx) error {
   161  			for j := 0; j < count; j++ {
   162  				key := fmt.Sprintf("user:%d:age", j)
   163  				val := fmt.Sprintf("%d", rand.Intn(100))
   164  				if _, _, err := tx.Set(key, val, nil); err != nil {
   165  					return err
   166  				}
   167  			}
   168  			return nil
   169  		}); err != nil {
   170  			t.Fatal(err)
   171  		}
   172  
   173  		if err := db.Update(func(tx *Tx) error {
   174  			return tx.Ascend("ages", func(key, val string) bool {
   175  				_, err := tx.Delete(key)
   176  				if err != ErrTxIterating {
   177  					t.Fatal("should not be able to call Delete while iterating.")
   178  				}
   179  				_, _, err = tx.Set(key, "", nil)
   180  				if err != ErrTxIterating {
   181  					t.Fatal("should not be able to call Set while iterating.")
   182  				}
   183  				return true
   184  			})
   185  		}); err != nil {
   186  			t.Fatal(err)
   187  		}
   188  	}
   189  }
   190  
   191  func TestCaseInsensitiveIndex(t *testing.T) {
   192  	db := testOpen(t)
   193  	defer testClose(db)
   194  	count := 1000
   195  	if err := db.Update(func(tx *Tx) error {
   196  		opts := &IndexOptions{
   197  			CaseInsensitiveKeyMatching: true,
   198  		}
   199  		return tx.CreateIndexOptions("ages", "User:*:age", opts, IndexInt)
   200  	}); err != nil {
   201  		t.Fatal(err)
   202  	}
   203  
   204  	if err := db.Update(func(tx *Tx) error {
   205  		for j := 0; j < count; j++ {
   206  			key := fmt.Sprintf("user:%d:age", j)
   207  			val := fmt.Sprintf("%d", rand.Intn(100))
   208  			if _, _, err := tx.Set(key, val, nil); err != nil {
   209  				return err
   210  			}
   211  		}
   212  		return nil
   213  	}); err != nil {
   214  		t.Fatal(err)
   215  	}
   216  
   217  	if err := db.View(func(tx *Tx) error {
   218  		var vals []string
   219  		err := tx.Ascend("ages", func(key, value string) bool {
   220  			vals = append(vals, value)
   221  			return true
   222  		})
   223  		if err != nil {
   224  			return err
   225  		}
   226  		if len(vals) != count {
   227  			return fmt.Errorf("expected '%v', got '%v'", count, len(vals))
   228  		}
   229  		return nil
   230  	}); err != nil {
   231  		t.Fatal(err)
   232  	}
   233  
   234  }
   235  
   236  func TestIndexTransaction(t *testing.T) {
   237  	db := testOpen(t)
   238  	defer testClose(db)
   239  	var errFine = errors.New("this is fine")
   240  	ascend := func(tx *Tx, index string) ([]string, error) {
   241  		var vals []string
   242  		if err := tx.Ascend(index, func(key, val string) bool {
   243  			vals = append(vals, key, val)
   244  			return true
   245  		}); err != nil {
   246  			return nil, err
   247  		}
   248  		return vals, nil
   249  	}
   250  	ascendEqual := func(tx *Tx, index string, vals []string) error {
   251  		vals2, err := ascend(tx, index)
   252  		if err != nil {
   253  			return err
   254  		}
   255  		if len(vals) != len(vals2) {
   256  			return errors.New("invalid size match")
   257  		}
   258  		for i := 0; i < len(vals); i++ {
   259  			if vals[i] != vals2[i] {
   260  				return errors.New("invalid order")
   261  			}
   262  		}
   263  		return nil
   264  	}
   265  	// test creating an index and adding items
   266  	if err := db.Update(func(tx *Tx) error {
   267  		tx.Set("1", "3", nil)
   268  		tx.Set("2", "2", nil)
   269  		tx.Set("3", "1", nil)
   270  		if err := tx.CreateIndex("idx1", "*", IndexInt); err != nil {
   271  			return err
   272  		}
   273  		if err := ascendEqual(tx, "idx1", []string{"3", "1", "2", "2", "1", "3"}); err != nil {
   274  			return err
   275  		}
   276  		return nil
   277  	}); err != nil {
   278  		t.Fatal(err)
   279  	}
   280  
   281  	// test to see if the items persisted from previous transaction
   282  	// test add item.
   283  	// test force rollback.
   284  	if err := db.Update(func(tx *Tx) error {
   285  		if err := ascendEqual(tx, "idx1", []string{"3", "1", "2", "2", "1", "3"}); err != nil {
   286  			return err
   287  		}
   288  		tx.Set("4", "0", nil)
   289  		if err := ascendEqual(tx, "idx1", []string{"4", "0", "3", "1", "2", "2", "1", "3"}); err != nil {
   290  			return err
   291  		}
   292  		return errFine
   293  	}); err != errFine {
   294  		t.Fatalf("expected '%v', got '%v'", errFine, err)
   295  	}
   296  
   297  	// test to see if the rollback happened
   298  	if err := db.View(func(tx *Tx) error {
   299  		if err := ascendEqual(tx, "idx1", []string{"3", "1", "2", "2", "1", "3"}); err != nil {
   300  			return err
   301  		}
   302  		return nil
   303  	}); err != nil {
   304  		t.Fatalf("expected '%v', got '%v'", nil, err)
   305  	}
   306  
   307  	// del item, drop index, rollback
   308  	if err := db.Update(func(tx *Tx) error {
   309  		if err := tx.DropIndex("idx1"); err != nil {
   310  			return err
   311  		}
   312  		return errFine
   313  	}); err != errFine {
   314  		t.Fatalf("expected '%v', got '%v'", errFine, err)
   315  	}
   316  
   317  	// test to see if the rollback happened
   318  	if err := db.View(func(tx *Tx) error {
   319  		if err := ascendEqual(tx, "idx1", []string{"3", "1", "2", "2", "1", "3"}); err != nil {
   320  			return err
   321  		}
   322  		return nil
   323  	}); err != nil {
   324  		t.Fatalf("expected '%v', got '%v'", nil, err)
   325  	}
   326  
   327  	various := func(reterr error) error {
   328  		// del item 3, add index 2, add item 4, test index 1 and 2.
   329  		// flushdb, test index 1 and 2.
   330  		// add item 1 and 2, add index 2 and 3, test index 2 and 3
   331  		return db.Update(func(tx *Tx) error {
   332  			tx.Delete("3")
   333  			tx.CreateIndex("idx2", "*", IndexInt)
   334  			tx.Set("4", "0", nil)
   335  			if err := ascendEqual(tx, "idx1", []string{"4", "0", "2", "2", "1", "3"}); err != nil {
   336  				return fmt.Errorf("err: %v", err)
   337  			}
   338  			if err := ascendEqual(tx, "idx2", []string{"4", "0", "2", "2", "1", "3"}); err != nil {
   339  				return fmt.Errorf("err: %v", err)
   340  			}
   341  			tx.DeleteAll()
   342  			if err := ascendEqual(tx, "idx1", []string{}); err != nil {
   343  				return fmt.Errorf("err: %v", err)
   344  			}
   345  			if err := ascendEqual(tx, "idx2", []string{}); err != nil {
   346  				return fmt.Errorf("err: %v", err)
   347  			}
   348  			tx.Set("1", "3", nil)
   349  			tx.Set("2", "2", nil)
   350  			tx.CreateIndex("idx1", "*", IndexInt)
   351  			tx.CreateIndex("idx2", "*", IndexInt)
   352  			if err := ascendEqual(tx, "idx1", []string{"2", "2", "1", "3"}); err != nil {
   353  				return fmt.Errorf("err: %v", err)
   354  			}
   355  			if err := ascendEqual(tx, "idx2", []string{"2", "2", "1", "3"}); err != nil {
   356  				return fmt.Errorf("err: %v", err)
   357  			}
   358  			return reterr
   359  		})
   360  	}
   361  	// various rollback
   362  	if err := various(errFine); err != errFine {
   363  		t.Fatalf("expected '%v', got '%v'", errFine, err)
   364  	}
   365  	// test to see if the rollback happened
   366  	if err := db.View(func(tx *Tx) error {
   367  		if err := ascendEqual(tx, "idx1", []string{"3", "1", "2", "2", "1", "3"}); err != nil {
   368  			return fmt.Errorf("err: %v", err)
   369  		}
   370  		if err := ascendEqual(tx, "idx2", []string{"3", "1", "2", "2", "1", "3"}); err != ErrNotFound {
   371  			return fmt.Errorf("err: %v", err)
   372  		}
   373  		return nil
   374  	}); err != nil {
   375  		t.Fatalf("expected '%v', got '%v'", nil, err)
   376  	}
   377  
   378  	// various commit
   379  	if err := various(nil); err != nil {
   380  		t.Fatalf("expected '%v', got '%v'", nil, err)
   381  	}
   382  
   383  	// test to see if the commit happened
   384  	if err := db.View(func(tx *Tx) error {
   385  		if err := ascendEqual(tx, "idx1", []string{"2", "2", "1", "3"}); err != nil {
   386  			return fmt.Errorf("err: %v", err)
   387  		}
   388  		if err := ascendEqual(tx, "idx2", []string{"2", "2", "1", "3"}); err != nil {
   389  			return fmt.Errorf("err: %v", err)
   390  		}
   391  		return nil
   392  	}); err != nil {
   393  		t.Fatalf("expected '%v', got '%v'", nil, err)
   394  	}
   395  }
   396  
   397  func TestDeleteAll(t *testing.T) {
   398  	db := testOpen(t)
   399  	defer testClose(db)
   400  
   401  	db.Update(func(tx *Tx) error {
   402  		tx.Set("hello1", "planet1", nil)
   403  		tx.Set("hello2", "planet2", nil)
   404  		tx.Set("hello3", "planet3", nil)
   405  		return nil
   406  	})
   407  	db.CreateIndex("all", "*", IndexString)
   408  	db.Update(func(tx *Tx) error {
   409  		tx.Set("hello1", "planet1.1", nil)
   410  		tx.DeleteAll()
   411  		tx.Set("bb", "11", nil)
   412  		tx.Set("aa", "**", nil)
   413  		tx.Delete("aa")
   414  		tx.Set("aa", "22", nil)
   415  		return nil
   416  	})
   417  	var res string
   418  	var res2 string
   419  	db.View(func(tx *Tx) error {
   420  		tx.Ascend("", func(key, val string) bool {
   421  			res += key + ":" + val + "\n"
   422  			return true
   423  		})
   424  		tx.Ascend("all", func(key, val string) bool {
   425  			res2 += key + ":" + val + "\n"
   426  			return true
   427  		})
   428  		return nil
   429  	})
   430  	if res != "aa:22\nbb:11\n" {
   431  		t.Fatal("fail")
   432  	}
   433  	if res2 != "bb:11\naa:22\n" {
   434  		t.Fatal("fail")
   435  	}
   436  	db = testReOpen(t, db)
   437  	defer testClose(db)
   438  	res = ""
   439  	res2 = ""
   440  	db.CreateIndex("all", "*", IndexString)
   441  	db.View(func(tx *Tx) error {
   442  		tx.Ascend("", func(key, val string) bool {
   443  			res += key + ":" + val + "\n"
   444  			return true
   445  		})
   446  		tx.Ascend("all", func(key, val string) bool {
   447  			res2 += key + ":" + val + "\n"
   448  			return true
   449  		})
   450  		return nil
   451  	})
   452  	if res != "aa:22\nbb:11\n" {
   453  		t.Fatal("fail")
   454  	}
   455  	if res2 != "bb:11\naa:22\n" {
   456  		t.Fatal("fail")
   457  	}
   458  	db.Update(func(tx *Tx) error {
   459  		tx.Set("1", "1", nil)
   460  		tx.Set("2", "2", nil)
   461  		tx.Set("3", "3", nil)
   462  		tx.Set("4", "4", nil)
   463  		return nil
   464  	})
   465  	err := db.Update(func(tx *Tx) error {
   466  		tx.Set("1", "a", nil)
   467  		tx.Set("5", "5", nil)
   468  		tx.Delete("2")
   469  		tx.Set("6", "6", nil)
   470  		tx.DeleteAll()
   471  		tx.Set("7", "7", nil)
   472  		tx.Set("8", "8", nil)
   473  		tx.Set("6", "c", nil)
   474  		return errors.New("please rollback")
   475  	})
   476  	if err == nil || err.Error() != "please rollback" {
   477  		t.Fatal("expecteding 'please rollback' error")
   478  	}
   479  
   480  	res = ""
   481  	res2 = ""
   482  	db.View(func(tx *Tx) error {
   483  		tx.Ascend("", func(key, val string) bool {
   484  			res += key + ":" + val + "\n"
   485  			return true
   486  		})
   487  		tx.Ascend("all", func(key, val string) bool {
   488  			res2 += key + ":" + val + "\n"
   489  			return true
   490  		})
   491  		return nil
   492  	})
   493  	if res != "1:1\n2:2\n3:3\n4:4\naa:22\nbb:11\n" {
   494  		t.Fatal("fail")
   495  	}
   496  	if res2 != "1:1\nbb:11\n2:2\naa:22\n3:3\n4:4\n" {
   497  		t.Fatal("fail")
   498  	}
   499  }
   500  
   501  func TestAscendEqual(t *testing.T) {
   502  	db := testOpen(t)
   503  	defer testClose(db)
   504  	if err := db.Update(func(tx *Tx) error {
   505  		for i := 0; i < 300; i++ {
   506  			_, _, err := tx.Set(fmt.Sprintf("key:%05dA", i), fmt.Sprintf("%d", i+1000), nil)
   507  			if err != nil {
   508  				return err
   509  			}
   510  			_, _, err = tx.Set(fmt.Sprintf("key:%05dB", i), fmt.Sprintf("%d", i+1000), nil)
   511  			if err != nil {
   512  				return err
   513  			}
   514  		}
   515  		return tx.CreateIndex("num", "*", IndexInt)
   516  	}); err != nil {
   517  		t.Fatal(err)
   518  	}
   519  	var res []string
   520  	if err := db.View(func(tx *Tx) error {
   521  		return tx.AscendEqual("", "key:00055A", func(key, value string) bool {
   522  			res = append(res, key)
   523  			return true
   524  		})
   525  	}); err != nil {
   526  		t.Fatal(err)
   527  	}
   528  	if len(res) != 1 {
   529  		t.Fatalf("expected %v, got %v", 1, len(res))
   530  	}
   531  	if res[0] != "key:00055A" {
   532  		t.Fatalf("expected %v, got %v", "key:00055A", res[0])
   533  	}
   534  	res = nil
   535  	if err := db.View(func(tx *Tx) error {
   536  		return tx.AscendEqual("num", "1125", func(key, value string) bool {
   537  			res = append(res, key)
   538  			return true
   539  		})
   540  	}); err != nil {
   541  		t.Fatal(err)
   542  	}
   543  	if len(res) != 2 {
   544  		t.Fatalf("expected %v, got %v", 2, len(res))
   545  	}
   546  	if res[0] != "key:00125A" {
   547  		t.Fatalf("expected %v, got %v", "key:00125A", res[0])
   548  	}
   549  	if res[1] != "key:00125B" {
   550  		t.Fatalf("expected %v, got %v", "key:00125B", res[1])
   551  	}
   552  }
   553  func TestDescendEqual(t *testing.T) {
   554  	db := testOpen(t)
   555  	defer testClose(db)
   556  	if err := db.Update(func(tx *Tx) error {
   557  		for i := 0; i < 300; i++ {
   558  			_, _, err := tx.Set(fmt.Sprintf("key:%05dA", i), fmt.Sprintf("%d", i+1000), nil)
   559  			if err != nil {
   560  				return err
   561  			}
   562  			_, _, err = tx.Set(fmt.Sprintf("key:%05dB", i), fmt.Sprintf("%d", i+1000), nil)
   563  			if err != nil {
   564  				return err
   565  			}
   566  		}
   567  		return tx.CreateIndex("num", "*", IndexInt)
   568  	}); err != nil {
   569  		t.Fatal(err)
   570  	}
   571  	var res []string
   572  	if err := db.View(func(tx *Tx) error {
   573  		return tx.DescendEqual("", "key:00055A", func(key, value string) bool {
   574  			res = append(res, key)
   575  			return true
   576  		})
   577  	}); err != nil {
   578  		t.Fatal(err)
   579  	}
   580  	if len(res) != 1 {
   581  		t.Fatalf("expected %v, got %v", 1, len(res))
   582  	}
   583  	if res[0] != "key:00055A" {
   584  		t.Fatalf("expected %v, got %v", "key:00055A", res[0])
   585  	}
   586  	res = nil
   587  	if err := db.View(func(tx *Tx) error {
   588  		return tx.DescendEqual("num", "1125", func(key, value string) bool {
   589  			res = append(res, key)
   590  			return true
   591  		})
   592  	}); err != nil {
   593  		t.Fatal(err)
   594  	}
   595  	if len(res) != 2 {
   596  		t.Fatalf("expected %v, got %v", 2, len(res))
   597  	}
   598  	if res[0] != "key:00125B" {
   599  		t.Fatalf("expected %v, got %v", "key:00125B", res[0])
   600  	}
   601  	if res[1] != "key:00125A" {
   602  		t.Fatalf("expected %v, got %v", "key:00125A", res[1])
   603  	}
   604  }
   605  func TestVariousTx(t *testing.T) {
   606  	db := testOpen(t)
   607  	defer testClose(db)
   608  	if err := db.Update(func(tx *Tx) error {
   609  		_, _, err := tx.Set("hello", "planet", nil)
   610  		return err
   611  	}); err != nil {
   612  		t.Fatal(err)
   613  	}
   614  	errBroken := errors.New("broken")
   615  	if err := db.Update(func(tx *Tx) error {
   616  		_, _, _ = tx.Set("hello", "world", nil)
   617  		return errBroken
   618  	}); err != errBroken {
   619  		t.Fatalf("did not correctly receive the user-defined transaction error.")
   620  	}
   621  	var val string
   622  	err := db.View(func(tx *Tx) error {
   623  		var err error
   624  		val, err = tx.Get("hello")
   625  		return err
   626  	})
   627  	if err != nil {
   628  		t.Fatal(err)
   629  	}
   630  	if val == "world" {
   631  		t.Fatal("a rollbacked transaction got through")
   632  	}
   633  	if val != "planet" {
   634  		t.Fatalf("expecting '%v', got '%v'", "planet", val)
   635  	}
   636  	if err := db.Update(func(tx *Tx) error {
   637  		tx.db = nil
   638  		if _, _, err := tx.Set("hello", "planet", nil); err != ErrTxClosed {
   639  			t.Fatal("expecting a tx closed error")
   640  		}
   641  		if _, err := tx.Delete("hello"); err != ErrTxClosed {
   642  			t.Fatal("expecting a tx closed error")
   643  		}
   644  		if _, err := tx.Get("hello"); err != ErrTxClosed {
   645  			t.Fatal("expecting a tx closed error")
   646  		}
   647  		tx.db = db
   648  		tx.writable = false
   649  		if _, _, err := tx.Set("hello", "planet", nil); err != ErrTxNotWritable {
   650  			t.Fatal("expecting a tx not writable error")
   651  		}
   652  		if _, err := tx.Delete("hello"); err != ErrTxNotWritable {
   653  			t.Fatal("expecting a tx not writable error")
   654  		}
   655  		tx.writable = true
   656  		if _, err := tx.Get("something"); err != ErrNotFound {
   657  			t.Fatalf("expecting not found error")
   658  		}
   659  		if _, err := tx.Delete("something"); err != ErrNotFound {
   660  			t.Fatalf("expecting not found error")
   661  		}
   662  		if _, _, err := tx.Set("var", "val", &SetOptions{Expires: true, TTL: 0}); err != nil {
   663  			t.Fatal(err)
   664  		}
   665  		if _, err := tx.Get("var"); err != ErrNotFound {
   666  			t.Fatalf("expecting not found error")
   667  		}
   668  		if _, err := tx.Delete("var"); err != ErrNotFound {
   669  			tx.unlock()
   670  			t.Fatalf("expecting not found error")
   671  		}
   672  		return nil
   673  	}); err != nil {
   674  		t.Fatal(err)
   675  	}
   676  
   677  	// test non-managed transactions
   678  	tx, err := db.Begin(true)
   679  	if err != nil {
   680  		t.Fatal(err)
   681  	}
   682  	defer tx.Rollback()
   683  	_, _, err = tx.Set("howdy", "world", nil)
   684  	if err != nil {
   685  		t.Fatal(err)
   686  	}
   687  	if err := tx.Commit(); err != nil {
   688  		t.Fatal(err)
   689  	}
   690  	tx, err = db.Begin(false)
   691  	if err != nil {
   692  		t.Fatal(err)
   693  	}
   694  	defer tx.Rollback()
   695  	v, err := tx.Get("howdy")
   696  	if err != nil {
   697  		t.Fatal(err)
   698  	}
   699  	if v != "world" {
   700  		t.Fatalf("expecting '%v', got '%v'", "world", v)
   701  	}
   702  	if err := tx.Rollback(); err != nil {
   703  		t.Fatal(err)
   704  	}
   705  	tx, err = db.Begin(true)
   706  	if err != nil {
   707  		t.Fatal(err)
   708  	}
   709  	defer tx.Rollback()
   710  	v, err = tx.Get("howdy")
   711  	if err != nil {
   712  		t.Fatal(err)
   713  	}
   714  	if v != "world" {
   715  		t.Fatalf("expecting '%v', got '%v'", "world", v)
   716  	}
   717  	_, err = tx.Delete("howdy")
   718  	if err != nil {
   719  		t.Fatal(err)
   720  	}
   721  	if err := tx.Commit(); err != nil {
   722  		t.Fatal(err)
   723  	}
   724  
   725  	// test for invalid commits
   726  	if err := db.Update(func(tx *Tx) error {
   727  		// we are going to do some hackery
   728  		defer func() {
   729  			if v := recover(); v != nil {
   730  				if v.(string) != "managed tx commit not allowed" {
   731  					t.Fatal(v.(string))
   732  				}
   733  			}
   734  		}()
   735  		return tx.Commit()
   736  	}); err != nil {
   737  		t.Fatal(err)
   738  	}
   739  
   740  	// test for invalid commits
   741  	if err := db.Update(func(tx *Tx) error {
   742  		// we are going to do some hackery
   743  		defer func() {
   744  			if v := recover(); v != nil {
   745  				if v.(string) != "managed tx rollback not allowed" {
   746  					t.Fatal(v.(string))
   747  				}
   748  			}
   749  		}()
   750  		return tx.Rollback()
   751  	}); err != nil {
   752  		t.Fatal(err)
   753  	}
   754  
   755  	// test for closed transactions
   756  	if err := db.Update(func(tx *Tx) error {
   757  		tx.db = nil
   758  		return nil
   759  	}); err != ErrTxClosed {
   760  		t.Fatal("expecting tx closed error")
   761  	}
   762  	db.mu.Unlock()
   763  
   764  	// test for invalid writes
   765  	if err := db.Update(func(tx *Tx) error {
   766  		tx.writable = false
   767  		return nil
   768  	}); err != ErrTxNotWritable {
   769  		t.Fatal("expecting tx not writable error")
   770  	}
   771  	db.mu.Unlock()
   772  	// test for closed transactions
   773  	if err := db.View(func(tx *Tx) error {
   774  		tx.db = nil
   775  		return nil
   776  	}); err != ErrTxClosed {
   777  		t.Fatal("expecting tx closed error")
   778  	}
   779  	db.mu.RUnlock()
   780  	// flush to unwritable file
   781  	if err := db.Update(func(tx *Tx) error {
   782  		_, _, err := tx.Set("var1", "val1", nil)
   783  		if err != nil {
   784  			t.Fatal(err)
   785  		}
   786  		return tx.db.file.Close()
   787  	}); err == nil {
   788  		t.Fatal("should not be able to commit when the file is closed")
   789  	}
   790  	db.file, err = os.OpenFile("data.db", os.O_CREATE|os.O_RDWR, 0666)
   791  	if err != nil {
   792  		t.Fatal(err)
   793  	}
   794  	if _, err := db.file.Seek(0, 2); err != nil {
   795  		t.Fatal(err)
   796  	}
   797  	db.buf = nil
   798  	if err := db.CreateIndex("blank", "*", nil); err != nil {
   799  		t.Fatal(err)
   800  	}
   801  	if err := db.CreateIndex("real", "*", IndexInt); err != nil {
   802  		t.Fatal(err)
   803  	}
   804  	// test scanning
   805  	if err := db.Update(func(tx *Tx) error {
   806  		less, err := tx.GetLess("junk")
   807  		if err != ErrNotFound {
   808  			t.Fatalf("expecting a not found, got %v", err)
   809  		}
   810  		if less != nil {
   811  			t.Fatal("expecting nil, got a less function")
   812  		}
   813  		less, err = tx.GetLess("blank")
   814  		if err != ErrNotFound {
   815  			t.Fatalf("expecting a not found, got %v", err)
   816  		}
   817  		if less != nil {
   818  			t.Fatal("expecting nil, got a less function")
   819  		}
   820  		less, err = tx.GetLess("real")
   821  		if err != nil {
   822  			return err
   823  		}
   824  		if less == nil {
   825  			t.Fatal("expecting a less function, got nil")
   826  		}
   827  		_, _, err = tx.Set("nothing", "here", nil)
   828  		return err
   829  	}); err != nil {
   830  		t.Fatal(err)
   831  	}
   832  	if err := db.View(func(tx *Tx) error {
   833  		s := ""
   834  		err := tx.Ascend("", func(key, val string) bool {
   835  			s += key + ":" + val + "\n"
   836  			return true
   837  		})
   838  		if err != nil {
   839  			return err
   840  		}
   841  		if s != "hello:planet\nnothing:here\n" {
   842  			t.Fatal("invalid scan")
   843  		}
   844  		tx.db = nil
   845  		err = tx.Ascend("", func(key, val string) bool { return true })
   846  		if err != ErrTxClosed {
   847  			tx.unlock()
   848  			t.Fatal("expecting tx closed error")
   849  		}
   850  		tx.db = db
   851  		err = tx.Ascend("na", func(key, val string) bool { return true })
   852  		if err != ErrNotFound {
   853  			t.Fatal("expecting not found error")
   854  		}
   855  		err = tx.Ascend("blank", func(key, val string) bool { return true })
   856  		if err != nil {
   857  			t.Fatal(err)
   858  		}
   859  		s = ""
   860  		err = tx.AscendLessThan("", "liger", func(key, val string) bool {
   861  			s += key + ":" + val + "\n"
   862  			return true
   863  		})
   864  		if err != nil {
   865  			return err
   866  		}
   867  		if s != "hello:planet\n" {
   868  			t.Fatal("invalid scan")
   869  		}
   870  
   871  		s = ""
   872  		err = tx.Descend("", func(key, val string) bool {
   873  			s += key + ":" + val + "\n"
   874  			return true
   875  		})
   876  		if err != nil {
   877  			return err
   878  		}
   879  		if s != "nothing:here\nhello:planet\n" {
   880  			t.Fatal("invalid scan")
   881  		}
   882  
   883  		s = ""
   884  		err = tx.DescendLessOrEqual("", "liger", func(key, val string) bool {
   885  			s += key + ":" + val + "\n"
   886  			return true
   887  		})
   888  		if err != nil {
   889  			return err
   890  		}
   891  
   892  		if s != "hello:planet\n" {
   893  			t.Fatal("invalid scan")
   894  		}
   895  
   896  		s = ""
   897  		err = tx.DescendGreaterThan("", "liger", func(key, val string) bool {
   898  			s += key + ":" + val + "\n"
   899  			return true
   900  		})
   901  		if err != nil {
   902  			return err
   903  		}
   904  
   905  		if s != "nothing:here\n" {
   906  			t.Fatal("invalid scan")
   907  		}
   908  		s = ""
   909  		err = tx.DescendRange("", "liger", "apple", func(key, val string) bool {
   910  			s += key + ":" + val + "\n"
   911  			return true
   912  		})
   913  		if err != nil {
   914  			return err
   915  		}
   916  		if s != "hello:planet\n" {
   917  			t.Fatal("invalid scan")
   918  		}
   919  		return nil
   920  	}); err != nil {
   921  		t.Fatal(err)
   922  	}
   923  
   924  	// test some spatial stuff
   925  	if err := db.CreateSpatialIndex("spat", "rect:*", IndexRect); err != nil {
   926  		t.Fatal(err)
   927  	}
   928  	if err := db.CreateSpatialIndex("junk", "rect:*", nil); err != nil {
   929  		t.Fatal(err)
   930  	}
   931  	err = db.Update(func(tx *Tx) error {
   932  		rect, err := tx.GetRect("spat")
   933  		if err != nil {
   934  			return err
   935  		}
   936  		if rect == nil {
   937  			t.Fatal("expecting a rect function, got nil")
   938  		}
   939  		rect, err = tx.GetRect("junk")
   940  		if err != ErrNotFound {
   941  			t.Fatalf("expecting a not found, got %v", err)
   942  		}
   943  		if rect != nil {
   944  			t.Fatal("expecting nil, got a rect function")
   945  		}
   946  		rect, err = tx.GetRect("na")
   947  		if err != ErrNotFound {
   948  			t.Fatalf("expecting a not found, got %v", err)
   949  		}
   950  		if rect != nil {
   951  			t.Fatal("expecting nil, got a rect function")
   952  		}
   953  		if _, _, err := tx.Set("rect:1", "[10 10],[20 20]", nil); err != nil {
   954  			return err
   955  		}
   956  		if _, _, err := tx.Set("rect:2", "[15 15],[25 25]", nil); err != nil {
   957  			return err
   958  		}
   959  		if _, _, err := tx.Set("shape:1", "[12 12],[25 25]", nil); err != nil {
   960  			return err
   961  		}
   962  		s := ""
   963  		err = tx.Intersects("spat", "[5 5],[13 13]", func(key, val string) bool {
   964  			s += key + ":" + val + "\n"
   965  			return true
   966  		})
   967  		if err != nil {
   968  			return err
   969  		}
   970  		if s != "rect:1:[10 10],[20 20]\n" {
   971  			t.Fatal("invalid scan")
   972  		}
   973  		tx.db = nil
   974  		err = tx.Intersects("spat", "[5 5],[13 13]", func(key, val string) bool {
   975  			return true
   976  		})
   977  		if err != ErrTxClosed {
   978  			t.Fatal("expecting tx closed error")
   979  		}
   980  		tx.db = db
   981  		err = tx.Intersects("", "[5 5],[13 13]", func(key, val string) bool {
   982  			return true
   983  		})
   984  		if err != nil {
   985  			t.Fatal(err)
   986  		}
   987  		err = tx.Intersects("na", "[5 5],[13 13]", func(key, val string) bool {
   988  			return true
   989  		})
   990  		if err != ErrNotFound {
   991  			t.Fatal("expecting not found error")
   992  		}
   993  		err = tx.Intersects("junk", "[5 5],[13 13]", func(key, val string) bool {
   994  			return true
   995  		})
   996  		if err != nil {
   997  			t.Fatal(err)
   998  		}
   999  		n, err := tx.Len()
  1000  		if err != nil {
  1001  			t.Fatal(err)
  1002  		}
  1003  		if n != 5 {
  1004  			t.Fatalf("expecting %v, got %v", 5, n)
  1005  		}
  1006  		tx.db = nil
  1007  		_, err = tx.Len()
  1008  		if err != ErrTxClosed {
  1009  			t.Fatal("expecting tx closed error")
  1010  		}
  1011  		tx.db = db
  1012  		return nil
  1013  	})
  1014  	if err != nil {
  1015  		t.Fatal(err)
  1016  	}
  1017  	// test after closing
  1018  	if err := db.Close(); err != nil {
  1019  		t.Fatal(err)
  1020  	}
  1021  
  1022  	if err := db.Update(func(tx *Tx) error { return nil }); err != ErrDatabaseClosed {
  1023  		t.Fatalf("should not be able to perform transactionso on a closed database.")
  1024  	}
  1025  }
  1026  
  1027  func TestNearby(t *testing.T) {
  1028  	rand.Seed(time.Now().UnixNano())
  1029  	N := 100000
  1030  	db, _ := Open(":memory:")
  1031  	db.CreateSpatialIndex("points", "*", IndexRect)
  1032  	db.Update(func(tx *Tx) error {
  1033  		for i := 0; i < N; i++ {
  1034  			p := Point(
  1035  				rand.Float64()*100,
  1036  				rand.Float64()*100,
  1037  				rand.Float64()*100,
  1038  				rand.Float64()*100,
  1039  			)
  1040  			tx.Set(fmt.Sprintf("p:%d", i), p, nil)
  1041  		}
  1042  		return nil
  1043  	})
  1044  	var keys, values []string
  1045  	var dists []float64
  1046  	var pdist float64
  1047  	var i int
  1048  	db.View(func(tx *Tx) error {
  1049  		tx.Nearby("points", Point(0, 0, 0, 0), func(key, value string, dist float64) bool {
  1050  			if i != 0 && dist < pdist {
  1051  				t.Fatal("out of order")
  1052  			}
  1053  			keys = append(keys, key)
  1054  			values = append(values, value)
  1055  			dists = append(dists, dist)
  1056  			pdist = dist
  1057  			i++
  1058  			return true
  1059  		})
  1060  		return nil
  1061  	})
  1062  	if len(keys) != N {
  1063  		t.Fatalf("expected '%v', got '%v'", N, len(keys))
  1064  	}
  1065  }
  1066  
  1067  func Example_descKeys() {
  1068  	db, _ := Open(":memory:")
  1069  	db.CreateIndex("name", "*", IndexString)
  1070  	db.Update(func(tx *Tx) error {
  1071  		tx.Set("user:100:first", "Tom", nil)
  1072  		tx.Set("user:100:last", "Johnson", nil)
  1073  		tx.Set("user:101:first", "Janet", nil)
  1074  		tx.Set("user:101:last", "Prichard", nil)
  1075  		tx.Set("user:102:first", "Alan", nil)
  1076  		tx.Set("user:102:last", "Cooper", nil)
  1077  		return nil
  1078  	})
  1079  	db.View(func(tx *Tx) error {
  1080  		tx.AscendKeys("user:101:*",
  1081  			func(key, value string) bool {
  1082  				fmt.Printf("%s: %s\n", key, value)
  1083  				return true
  1084  			})
  1085  		tx.AscendKeys("user:10?:*",
  1086  			func(key, value string) bool {
  1087  				fmt.Printf("%s: %s\n", key, value)
  1088  				return true
  1089  			})
  1090  		tx.AscendKeys("*2*",
  1091  			func(key, value string) bool {
  1092  				fmt.Printf("%s: %s\n", key, value)
  1093  				return true
  1094  			})
  1095  		tx.DescendKeys("user:101:*",
  1096  			func(key, value string) bool {
  1097  				fmt.Printf("%s: %s\n", key, value)
  1098  				return true
  1099  			})
  1100  		tx.DescendKeys("*",
  1101  			func(key, value string) bool {
  1102  				fmt.Printf("%s: %s\n", key, value)
  1103  				return true
  1104  			})
  1105  		return nil
  1106  	})
  1107  
  1108  	// Output:
  1109  	// user:101:first: Janet
  1110  	// user:101:last: Prichard
  1111  	// user:100:first: Tom
  1112  	// user:100:last: Johnson
  1113  	// user:101:first: Janet
  1114  	// user:101:last: Prichard
  1115  	// user:102:first: Alan
  1116  	// user:102:last: Cooper
  1117  	// user:102:first: Alan
  1118  	// user:102:last: Cooper
  1119  	// user:101:last: Prichard
  1120  	// user:101:first: Janet
  1121  	// user:102:last: Cooper
  1122  	// user:102:first: Alan
  1123  	// user:101:last: Prichard
  1124  	// user:101:first: Janet
  1125  	// user:100:last: Johnson
  1126  	// user:100:first: Tom
  1127  }
  1128  
  1129  func ExampleDesc() {
  1130  	db, _ := Open(":memory:")
  1131  	db.CreateIndex("last_name_age", "*", IndexJSON("name.last"), Desc(IndexJSON("age")))
  1132  	db.Update(func(tx *Tx) error {
  1133  		tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)
  1134  		tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil)
  1135  		tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil)
  1136  		tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil)
  1137  		tx.Set("5", `{"name":{"first":"Sam","last":"Anderson"},"age":51}`, nil)
  1138  		tx.Set("6", `{"name":{"first":"Melinda","last":"Prichard"},"age":44}`, nil)
  1139  		return nil
  1140  	})
  1141  	db.View(func(tx *Tx) error {
  1142  		tx.Ascend("last_name_age", func(key, value string) bool {
  1143  			fmt.Printf("%s: %s\n", key, value)
  1144  			return true
  1145  		})
  1146  		return nil
  1147  	})
  1148  
  1149  	// Output:
  1150  	//3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
  1151  	//5: {"name":{"first":"Sam","last":"Anderson"},"age":51}
  1152  	//4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
  1153  	//1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
  1154  	//2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
  1155  	//6: {"name":{"first":"Melinda","last":"Prichard"},"age":44}
  1156  }
  1157  
  1158  func ExampleDB_CreateIndex_jSON() {
  1159  	db, _ := Open(":memory:")
  1160  	db.CreateIndex("last_name", "*", IndexJSON("name.last"))
  1161  	db.CreateIndex("age", "*", IndexJSON("age"))
  1162  	db.Update(func(tx *Tx) error {
  1163  		tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)
  1164  		tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil)
  1165  		tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil)
  1166  		tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil)
  1167  		return nil
  1168  	})
  1169  	db.View(func(tx *Tx) error {
  1170  		fmt.Println("Order by last name")
  1171  		tx.Ascend("last_name", func(key, value string) bool {
  1172  			fmt.Printf("%s: %s\n", key, value)
  1173  			return true
  1174  		})
  1175  		fmt.Println("Order by age")
  1176  		tx.Ascend("age", func(key, value string) bool {
  1177  			fmt.Printf("%s: %s\n", key, value)
  1178  			return true
  1179  		})
  1180  		fmt.Println("Order by age range 30-50")
  1181  		tx.AscendRange("age", `{"age":30}`, `{"age":50}`, func(key, value string) bool {
  1182  			fmt.Printf("%s: %s\n", key, value)
  1183  			return true
  1184  		})
  1185  		return nil
  1186  	})
  1187  
  1188  	// Output:
  1189  	// Order by last name
  1190  	// 3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
  1191  	// 4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
  1192  	// 1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
  1193  	// 2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
  1194  	// Order by age
  1195  	// 4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
  1196  	// 1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
  1197  	// 2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
  1198  	// 3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
  1199  	// Order by age range 30-50
  1200  	// 1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
  1201  	// 2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
  1202  }
  1203  
  1204  func ExampleDB_CreateIndex_strings() {
  1205  	db, _ := Open(":memory:")
  1206  	db.CreateIndex("name", "*", IndexString)
  1207  	db.Update(func(tx *Tx) error {
  1208  		tx.Set("1", "Tom", nil)
  1209  		tx.Set("2", "Janet", nil)
  1210  		tx.Set("3", "Carol", nil)
  1211  		tx.Set("4", "Alan", nil)
  1212  		tx.Set("5", "Sam", nil)
  1213  		tx.Set("6", "Melinda", nil)
  1214  		return nil
  1215  	})
  1216  	db.View(func(tx *Tx) error {
  1217  		tx.Ascend("name", func(key, value string) bool {
  1218  			fmt.Printf("%s: %s\n", key, value)
  1219  			return true
  1220  		})
  1221  		return nil
  1222  	})
  1223  
  1224  	// Output:
  1225  	//4: Alan
  1226  	//3: Carol
  1227  	//2: Janet
  1228  	//6: Melinda
  1229  	//5: Sam
  1230  	//1: Tom
  1231  }
  1232  
  1233  func ExampleDB_CreateIndex_ints() {
  1234  	db, _ := Open(":memory:")
  1235  	db.CreateIndex("age", "*", IndexInt)
  1236  	db.Update(func(tx *Tx) error {
  1237  		tx.Set("1", "30", nil)
  1238  		tx.Set("2", "51", nil)
  1239  		tx.Set("3", "16", nil)
  1240  		tx.Set("4", "76", nil)
  1241  		tx.Set("5", "23", nil)
  1242  		tx.Set("6", "43", nil)
  1243  		return nil
  1244  	})
  1245  	db.View(func(tx *Tx) error {
  1246  		tx.Ascend("age", func(key, value string) bool {
  1247  			fmt.Printf("%s: %s\n", key, value)
  1248  			return true
  1249  		})
  1250  		return nil
  1251  	})
  1252  
  1253  	// Output:
  1254  	//3: 16
  1255  	//5: 23
  1256  	//1: 30
  1257  	//6: 43
  1258  	//2: 51
  1259  	//4: 76
  1260  }
  1261  func ExampleDB_CreateIndex_multipleFields() {
  1262  	db, _ := Open(":memory:")
  1263  	db.CreateIndex("last_name_age", "*", IndexJSON("name.last"), IndexJSON("age"))
  1264  	db.Update(func(tx *Tx) error {
  1265  		tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)
  1266  		tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil)
  1267  		tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil)
  1268  		tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil)
  1269  		tx.Set("5", `{"name":{"first":"Sam","last":"Anderson"},"age":51}`, nil)
  1270  		tx.Set("6", `{"name":{"first":"Melinda","last":"Prichard"},"age":44}`, nil)
  1271  		return nil
  1272  	})
  1273  	db.View(func(tx *Tx) error {
  1274  		tx.Ascend("last_name_age", func(key, value string) bool {
  1275  			fmt.Printf("%s: %s\n", key, value)
  1276  			return true
  1277  		})
  1278  		return nil
  1279  	})
  1280  
  1281  	// Output:
  1282  	//5: {"name":{"first":"Sam","last":"Anderson"},"age":51}
  1283  	//3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
  1284  	//4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
  1285  	//1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
  1286  	//6: {"name":{"first":"Melinda","last":"Prichard"},"age":44}
  1287  	//2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
  1288  }
  1289  
  1290  func TestNoExpiringItem(t *testing.T) {
  1291  	item := &dbItem{key: "key", val: "val"}
  1292  	if !item.expiresAt().Equal(maxTime) {
  1293  		t.Fatal("item.expiresAt() != maxTime")
  1294  	}
  1295  	if min, max := item.Rect(nil); min != nil || max != nil {
  1296  		t.Fatal("item min,max should both be nil")
  1297  	}
  1298  }
  1299  func TestAutoShrink(t *testing.T) {
  1300  	db := testOpen(t)
  1301  	defer testClose(db)
  1302  	for i := 0; i < 1000; i++ {
  1303  		err := db.Update(func(tx *Tx) error {
  1304  			for i := 0; i < 20; i++ {
  1305  				if _, _, err := tx.Set(fmt.Sprintf("HELLO:%d", i), "WORLD", nil); err != nil {
  1306  					return err
  1307  				}
  1308  			}
  1309  			return nil
  1310  		})
  1311  		if err != nil {
  1312  			t.Fatal(err)
  1313  		}
  1314  	}
  1315  	db = testReOpen(t, db)
  1316  	defer testClose(db)
  1317  	db.config.AutoShrinkMinSize = 64 * 1024 // 64K
  1318  	for i := 0; i < 2000; i++ {
  1319  		err := db.Update(func(tx *Tx) error {
  1320  			for i := 0; i < 20; i++ {
  1321  				if _, _, err := tx.Set(fmt.Sprintf("HELLO:%d", i), "WORLD", nil); err != nil {
  1322  					return err
  1323  				}
  1324  			}
  1325  			return nil
  1326  		})
  1327  		if err != nil {
  1328  			t.Fatal(err)
  1329  		}
  1330  	}
  1331  	time.Sleep(time.Second * 3)
  1332  	db = testReOpen(t, db)
  1333  	defer testClose(db)
  1334  	err := db.View(func(tx *Tx) error {
  1335  		n, err := tx.Len()
  1336  		if err != nil {
  1337  			return err
  1338  		}
  1339  		if n != 20 {
  1340  			t.Fatalf("expecting 20, got %v", n)
  1341  		}
  1342  		return nil
  1343  	})
  1344  	if err != nil {
  1345  		t.Fatal(err)
  1346  	}
  1347  }
  1348  
  1349  // test database format loading
  1350  func TestDatabaseFormat(t *testing.T) {
  1351  	// should succeed
  1352  	func() {
  1353  		resp := strings.Join([]string{
  1354  			"*3\r\n$3\r\nset\r\n$4\r\nvar1\r\n$4\r\n1234\r\n",
  1355  			"*3\r\n$3\r\nset\r\n$4\r\nvar2\r\n$4\r\n1234\r\n",
  1356  			"*2\r\n$3\r\ndel\r\n$4\r\nvar1\r\n",
  1357  			"*5\r\n$3\r\nset\r\n$3\r\nvar\r\n$3\r\nval\r\n$2\r\nex\r\n$2\r\n10\r\n",
  1358  		}, "")
  1359  		if err := os.RemoveAll("data.db"); err != nil {
  1360  			t.Fatal(err)
  1361  		}
  1362  		if err := ioutil.WriteFile("data.db", []byte(resp), 0666); err != nil {
  1363  			t.Fatal(err)
  1364  		}
  1365  		db := testOpen(t)
  1366  		defer testClose(db)
  1367  	}()
  1368  	testFormat := func(t *testing.T, expectValid bool, resp string, do func(db *DB) error) {
  1369  		t.Helper()
  1370  		os.RemoveAll("data.db")
  1371  		if err := ioutil.WriteFile("data.db", []byte(resp), 0666); err != nil {
  1372  			t.Fatal(err)
  1373  		}
  1374  		defer os.RemoveAll("data.db")
  1375  
  1376  		db, err := Open("data.db")
  1377  		if err == nil {
  1378  			if do != nil {
  1379  				if err := do(db); err != nil {
  1380  					t.Fatal(err)
  1381  				}
  1382  			}
  1383  			if err := db.Close(); err != nil {
  1384  				t.Fatal(err)
  1385  			}
  1386  		}
  1387  		if err == nil && !expectValid {
  1388  			t.Fatalf("expected invalid database")
  1389  		} else if err != nil && expectValid {
  1390  			t.Fatalf("expected valid database, got '%s'", err)
  1391  		}
  1392  	}
  1393  
  1394  	// basic valid commands
  1395  	testFormat(t, true, "*2\r\n$3\r\nDEL\r\n$5\r\nHELLO\r\n", nil)
  1396  	testFormat(t, true, "*3\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1397  	testFormat(t, true, "*1\r\n$7\r\nFLUSHDB\r\n", nil)
  1398  
  1399  	// commands with invalid names or arguments
  1400  	testFormat(t, false, "*3\r\n$3\r\nDEL\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1401  	testFormat(t, false, "*2\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n", nil)
  1402  	testFormat(t, false, "*1\r\n$6\r\nSET123\r\n", nil)
  1403  
  1404  	// partial tail commands should be ignored but allowed
  1405  	pcmd := "*3\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n"
  1406  	for i := 1; i < len(pcmd); i++ {
  1407  		cmd := "*3\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nJELLO\r\n"
  1408  		testFormat(t, true, cmd+pcmd[:len(pcmd)-i],
  1409  			func(db *DB) error {
  1410  				return db.View(func(tx *Tx) error {
  1411  					val, err := tx.Get("HELLO")
  1412  					if err != nil {
  1413  						return err
  1414  					}
  1415  					if val != "JELLO" {
  1416  						return fmt.Errorf("expected '%s', got '%s'", "JELLO", val)
  1417  					}
  1418  					return nil
  1419  				})
  1420  			})
  1421  	}
  1422  
  1423  	// commands with invalid formatting
  1424  	testFormat(t, false, "^3\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1425  	testFormat(t, false, "*3\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1426  	testFormat(t, false, "*\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1427  	testFormat(t, false, "*3\r\n^3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1428  	testFormat(t, false, "*3\r\n$\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1429  	testFormat(t, false, "*3\r\n$3\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1430  	testFormat(t, false, "*3\r\n$3SET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n", nil)
  1431  	testFormat(t, false, "*3\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n123\n", nil)
  1432  
  1433  	// commands with nuls
  1434  	testFormat(t, true, "\u0000*3\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nWORLD\r\n"+
  1435  		"\u0000\u0000*3\r\n$3\r\nSET\r\n$5\r\nHELLO\r\n$5\r\nJELLO\r\n\u0000", func(db *DB) error {
  1436  		return db.View(func(tx *Tx) error {
  1437  			val, err := tx.Get("HELLO")
  1438  			if err != nil {
  1439  				return err
  1440  			}
  1441  			if val != "JELLO" {
  1442  				return fmt.Errorf("expected '%s', got '%s'", "JELLO", val)
  1443  			}
  1444  			return nil
  1445  		})
  1446  	})
  1447  
  1448  }
  1449  
  1450  func TestInsertsAndDeleted(t *testing.T) {
  1451  	db := testOpen(t)
  1452  	defer testClose(db)
  1453  	if err := db.CreateIndex("any", "*", IndexString); err != nil {
  1454  		t.Fatal(err)
  1455  	}
  1456  	if err := db.CreateSpatialIndex("rect", "*", IndexRect); err != nil {
  1457  		t.Fatal(err)
  1458  	}
  1459  	if err := db.Update(func(tx *Tx) error {
  1460  		if _, _, err := tx.Set("item1", "value1", &SetOptions{Expires: true, TTL: time.Second}); err != nil {
  1461  			return err
  1462  		}
  1463  		if _, _, err := tx.Set("item2", "value2", nil); err != nil {
  1464  			return err
  1465  		}
  1466  		if _, _, err := tx.Set("item3", "value3", &SetOptions{Expires: true, TTL: time.Second}); err != nil {
  1467  			return err
  1468  		}
  1469  		return nil
  1470  	}); err != nil {
  1471  		t.Fatal(err)
  1472  	}
  1473  
  1474  	// test replacing items in the database
  1475  	if err := db.Update(func(tx *Tx) error {
  1476  		if _, _, err := tx.Set("item1", "nvalue1", nil); err != nil {
  1477  			return err
  1478  		}
  1479  		if _, _, err := tx.Set("item2", "nvalue2", nil); err != nil {
  1480  			return err
  1481  		}
  1482  		if _, err := tx.Delete("item3"); err != nil {
  1483  			return err
  1484  		}
  1485  		return nil
  1486  	}); err != nil {
  1487  		t.Fatal(err)
  1488  	}
  1489  }
  1490  
  1491  func TestInsertDoesNotMisuseIndex(t *testing.T) {
  1492  	db := testOpen(t)
  1493  	defer testClose(db)
  1494  	fail := func(a, b string) bool { t.Fatal("Misused index"); return false }
  1495  	if err := db.CreateIndex("some", "a*", fail); err != nil {
  1496  		// Only one item is eligible for the index, so no comparison is necessary.
  1497  		t.Fatal(err)
  1498  	}
  1499  	if err := db.Update(func(tx *Tx) error {
  1500  		if _, _, err := tx.Set("a", "1", nil); err != nil {
  1501  			return err
  1502  		}
  1503  		if _, _, err := tx.Set("b", "1", nil); err != nil {
  1504  			return err
  1505  		}
  1506  		return nil
  1507  	}); err != nil {
  1508  		t.Fatal(err)
  1509  	}
  1510  
  1511  	if err := db.Update(func(tx *Tx) error {
  1512  		_, _, err := tx.Set("b", "2", nil)
  1513  		return err
  1514  	}); err != nil {
  1515  		t.Fatal(err)
  1516  	}
  1517  }
  1518  
  1519  func TestDeleteDoesNotMisuseIndex(t *testing.T) {
  1520  	db := testOpen(t)
  1521  	defer testClose(db)
  1522  	fail := func(a, b string) bool { t.Fatal("Misused index"); return false }
  1523  	if err := db.CreateIndex("some", "a*", fail); err != nil {
  1524  		// Only one item is eligible for the index, so no comparison is necessary.
  1525  		t.Fatal(err)
  1526  	}
  1527  	if err := db.Update(func(tx *Tx) error {
  1528  		if _, _, err := tx.Set("a", "1", nil); err != nil {
  1529  			return err
  1530  		}
  1531  		if _, _, err := tx.Set("b", "1", nil); err != nil {
  1532  			return err
  1533  		}
  1534  		return nil
  1535  	}); err != nil {
  1536  		t.Fatal(err)
  1537  	}
  1538  
  1539  	if err := db.Update(func(tx *Tx) error {
  1540  		_, err := tx.Delete("b")
  1541  		return err
  1542  	}); err != nil {
  1543  		t.Fatal(err)
  1544  	}
  1545  }
  1546  
  1547  // test index compare functions
  1548  func TestIndexCompare(t *testing.T) {
  1549  	if !IndexFloat("1.5", "1.6") {
  1550  		t.Fatalf("expected true, got false")
  1551  	}
  1552  	if !IndexInt("-1", "2") {
  1553  		t.Fatalf("expected true, got false")
  1554  	}
  1555  	if !IndexUint("10", "25") {
  1556  		t.Fatalf("expected true, got false")
  1557  	}
  1558  	if !IndexBinary("Hello", "hello") {
  1559  		t.Fatalf("expected true, got false")
  1560  	}
  1561  	if IndexString("hello", "hello") {
  1562  		t.Fatalf("expected false, got true")
  1563  	}
  1564  	if IndexString("Hello", "hello") {
  1565  		t.Fatalf("expected false, got true")
  1566  	}
  1567  	if IndexString("hello", "Hello") {
  1568  		t.Fatalf("expected false, got true")
  1569  	}
  1570  	if !IndexString("gello", "Hello") {
  1571  		t.Fatalf("expected true, got false")
  1572  	}
  1573  	if IndexString("Hello", "gello") {
  1574  		t.Fatalf("expected false, got true")
  1575  	}
  1576  	if Rect(IndexRect("[1 2 3 4],[5 6 7 8]")) != "[1 2 3 4],[5 6 7 8]" {
  1577  		t.Fatalf("expected '%v', got '%v'", "[1 2 3 4],[5 6 7 8]", Rect(IndexRect("[1 2 3 4],[5 6 7 8]")))
  1578  	}
  1579  	if Rect(IndexRect("[1 2 3 4]")) != "[1 2 3 4]" {
  1580  		t.Fatalf("expected '%v', got '%v'", "[1 2 3 4]", Rect(IndexRect("[1 2 3 4]")))
  1581  	}
  1582  	if Rect(nil, nil) != "[]" {
  1583  		t.Fatalf("expected '%v', got '%v'", "", Rect(nil, nil))
  1584  	}
  1585  	if Point(1, 2, 3) != "[1 2 3]" {
  1586  		t.Fatalf("expected '%v', got '%v'", "[1 2 3]", Point(1, 2, 3))
  1587  	}
  1588  }
  1589  
  1590  // test opening a folder.
  1591  func TestOpeningAFolder(t *testing.T) {
  1592  	if err := os.RemoveAll("dir.tmp"); err != nil {
  1593  		t.Fatal(err)
  1594  	}
  1595  	if err := os.Mkdir("dir.tmp", 0700); err != nil {
  1596  		t.Fatal(err)
  1597  	}
  1598  	defer func() { _ = os.RemoveAll("dir.tmp") }()
  1599  	db, err := Open("dir.tmp")
  1600  	if err == nil {
  1601  		if err := db.Close(); err != nil {
  1602  			t.Fatal(err)
  1603  		}
  1604  		t.Fatalf("opening a directory should not be allowed")
  1605  	}
  1606  }
  1607  
  1608  // test opening an invalid resp file.
  1609  func TestOpeningInvalidDatabaseFile(t *testing.T) {
  1610  	if err := os.RemoveAll("data.db"); err != nil {
  1611  		t.Fatal(err)
  1612  	}
  1613  	if err := ioutil.WriteFile("data.db", []byte("invalid\r\nfile"), 0666); err != nil {
  1614  		t.Fatal(err)
  1615  	}
  1616  	defer func() { _ = os.RemoveAll("data.db") }()
  1617  	db, err := Open("data.db")
  1618  	if err == nil {
  1619  		if err := db.Close(); err != nil {
  1620  			t.Fatal(err)
  1621  		}
  1622  		t.Fatalf("invalid database should not be allowed")
  1623  	}
  1624  }
  1625  
  1626  // test closing a closed database.
  1627  func TestOpeningClosedDatabase(t *testing.T) {
  1628  	if err := os.RemoveAll("data.db"); err != nil {
  1629  		t.Fatal(err)
  1630  	}
  1631  	db, err := Open("data.db")
  1632  	if err != nil {
  1633  		t.Fatal(err)
  1634  	}
  1635  	defer func() { _ = os.RemoveAll("data.db") }()
  1636  	if err := db.Close(); err != nil {
  1637  		t.Fatal(err)
  1638  	}
  1639  	if err := db.Close(); err != ErrDatabaseClosed {
  1640  		t.Fatal("should not be able to close a closed database")
  1641  	}
  1642  	db, err = Open(":memory:")
  1643  	if err != nil {
  1644  		t.Fatal(err)
  1645  	}
  1646  	if err := db.Close(); err != nil {
  1647  		t.Fatal(err)
  1648  	}
  1649  	if err := db.Close(); err != ErrDatabaseClosed {
  1650  		t.Fatal("should not be able to close a closed database")
  1651  	}
  1652  }
  1653  
  1654  // test shrinking a database.
  1655  func TestShrink(t *testing.T) {
  1656  	db := testOpen(t)
  1657  	defer testClose(db)
  1658  	if err := db.Shrink(); err != nil {
  1659  		t.Fatal(err)
  1660  	}
  1661  	fi, err := os.Stat("data.db")
  1662  	if err != nil {
  1663  		t.Fatal(err)
  1664  	}
  1665  	if fi.Size() != 0 {
  1666  		t.Fatalf("expected %v, got %v", 0, fi.Size())
  1667  	}
  1668  	// add 10 items
  1669  	err = db.Update(func(tx *Tx) error {
  1670  		for i := 0; i < 10; i++ {
  1671  			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
  1672  				return err
  1673  			}
  1674  		}
  1675  		return nil
  1676  	})
  1677  	if err != nil {
  1678  		t.Fatal(err)
  1679  	}
  1680  	// add the same 10 items
  1681  	// this will create 10 duplicate log entries
  1682  	err = db.Update(func(tx *Tx) error {
  1683  		for i := 0; i < 10; i++ {
  1684  			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
  1685  				return err
  1686  			}
  1687  		}
  1688  		return nil
  1689  	})
  1690  	if err != nil {
  1691  		t.Fatal(err)
  1692  	}
  1693  	fi, err = os.Stat("data.db")
  1694  	if err != nil {
  1695  		t.Fatal(err)
  1696  	}
  1697  	sz1 := fi.Size()
  1698  	if sz1 == 0 {
  1699  		t.Fatalf("expected > 0, got %v", sz1)
  1700  	}
  1701  	if err := db.Shrink(); err != nil {
  1702  		t.Fatal(err)
  1703  	}
  1704  	fi, err = os.Stat("data.db")
  1705  	if err != nil {
  1706  		t.Fatal(err)
  1707  	}
  1708  	sz2 := fi.Size()
  1709  	if sz2 >= sz1 {
  1710  		t.Fatalf("expected < %v, got %v", sz1, sz2)
  1711  	}
  1712  	if err := db.Close(); err != nil {
  1713  		t.Fatal(err)
  1714  	}
  1715  	if err := db.Shrink(); err != ErrDatabaseClosed {
  1716  		t.Fatal("shrink on a closed databse should not be allowed")
  1717  	}
  1718  	// Now we will open a db that does not persist
  1719  	db, err = Open(":memory:")
  1720  	if err != nil {
  1721  		t.Fatal(err)
  1722  	}
  1723  	defer func() { _ = db.Close() }()
  1724  	// add 10 items
  1725  	err = db.Update(func(tx *Tx) error {
  1726  		for i := 0; i < 10; i++ {
  1727  			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
  1728  				return err
  1729  			}
  1730  		}
  1731  		return nil
  1732  	})
  1733  	if err != nil {
  1734  		t.Fatal(err)
  1735  	}
  1736  	// add the same 10 items
  1737  	// this will create 10 duplicate log entries
  1738  	err = db.Update(func(tx *Tx) error {
  1739  		for i := 0; i < 10; i++ {
  1740  			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
  1741  				return err
  1742  			}
  1743  		}
  1744  		return nil
  1745  	})
  1746  	if err != nil {
  1747  		t.Fatal(err)
  1748  	}
  1749  	err = db.View(func(tx *Tx) error {
  1750  		n, err := tx.Len()
  1751  		if err != nil {
  1752  			t.Fatal(err)
  1753  		}
  1754  		if n != 10 {
  1755  			t.Fatalf("expecting %v, got %v", 10, n)
  1756  		}
  1757  		return nil
  1758  	})
  1759  	if err != nil {
  1760  		t.Fatal(err)
  1761  	}
  1762  	// this should succeed even though it's basically a noop.
  1763  	if err := db.Shrink(); err != nil {
  1764  		t.Fatal(err)
  1765  	}
  1766  }
  1767  
  1768  func TestVariousIndexOperations(t *testing.T) {
  1769  	db := testOpen(t)
  1770  	defer testClose(db)
  1771  	// test creating an index with no index name.
  1772  	err := db.CreateIndex("", "", nil)
  1773  	if err == nil {
  1774  		t.Fatal("should not be able to create an index with no name")
  1775  	}
  1776  	// test creating an index with a name that has already been used.
  1777  	err = db.CreateIndex("hello", "", nil)
  1778  	if err != nil {
  1779  		t.Fatal(err)
  1780  	}
  1781  	err = db.CreateIndex("hello", "", nil)
  1782  	if err == nil {
  1783  		t.Fatal("should not be able to create a duplicate index")
  1784  	}
  1785  	err = db.Update(func(tx *Tx) error {
  1786  
  1787  		if _, _, err := tx.Set("user:1", "tom", nil); err != nil {
  1788  			return err
  1789  		}
  1790  		if _, _, err := tx.Set("user:2", "janet", nil); err != nil {
  1791  			return err
  1792  		}
  1793  		if _, _, err := tx.Set("alt:1", "from", nil); err != nil {
  1794  			return err
  1795  		}
  1796  		if _, _, err := tx.Set("alt:2", "there", nil); err != nil {
  1797  			return err
  1798  		}
  1799  		if _, _, err := tx.Set("rect:1", "[1 2],[3 4]", nil); err != nil {
  1800  			return err
  1801  		}
  1802  		if _, _, err := tx.Set("rect:2", "[5 6],[7 8]", nil); err != nil {
  1803  			return err
  1804  		}
  1805  		return nil
  1806  	})
  1807  	if err != nil {
  1808  		t.Fatal(err)
  1809  	}
  1810  	// test creating an index after adding items. use pattern matching. have some items in the match and some not.
  1811  	if err := db.CreateIndex("string", "user:*", IndexString); err != nil {
  1812  		t.Fatal(err)
  1813  	}
  1814  	// test creating a spatial index after adding items. use pattern matching. have some items in the match and some not.
  1815  	if err := db.CreateSpatialIndex("rect", "rect:*", IndexRect); err != nil {
  1816  		t.Fatal(err)
  1817  	}
  1818  	// test dropping an index
  1819  	if err := db.DropIndex("hello"); err != nil {
  1820  		t.Fatal(err)
  1821  	}
  1822  	// test dropping an index with no name
  1823  	if err := db.DropIndex(""); err == nil {
  1824  		t.Fatal("should not be allowed to drop an index with no name")
  1825  	}
  1826  	// test dropping an index with no name
  1827  	if err := db.DropIndex("na"); err == nil {
  1828  		t.Fatal("should not be allowed to drop an index that does not exist")
  1829  	}
  1830  	// test retrieving index names
  1831  	names, err := db.Indexes()
  1832  	if err != nil {
  1833  		t.Fatal(err)
  1834  	}
  1835  	if strings.Join(names, ",") != "rect,string" {
  1836  		t.Fatalf("expecting '%v', got '%v'", "rect,string", strings.Join(names, ","))
  1837  	}
  1838  	// test creating an index after closing database
  1839  	if err := db.Close(); err != nil {
  1840  		t.Fatal(err)
  1841  	}
  1842  	if err := db.CreateIndex("new-index", "", nil); err != ErrDatabaseClosed {
  1843  		t.Fatal("should not be able to create an index on a closed database")
  1844  	}
  1845  	// test getting index names after closing database
  1846  	if _, err := db.Indexes(); err != ErrDatabaseClosed {
  1847  		t.Fatal("should not be able to get index names on a closed database")
  1848  	}
  1849  	// test dropping an index after closing database
  1850  	if err := db.DropIndex("rect"); err != ErrDatabaseClosed {
  1851  		t.Fatal("should not be able to drop an index on a closed database")
  1852  	}
  1853  }
  1854  
  1855  func test(t *testing.T, a, b bool) {
  1856  	if a != b {
  1857  		t.Fatal("failed, bummer...")
  1858  	}
  1859  }
  1860  
  1861  func TestBasic(t *testing.T) {
  1862  	rand.Seed(time.Now().UnixNano())
  1863  	db := testOpen(t)
  1864  	defer testClose(db)
  1865  
  1866  	// create a simple index
  1867  	if err := db.CreateIndex("users", "fun:user:*", IndexString); err != nil {
  1868  		t.Fatal(err)
  1869  	}
  1870  
  1871  	// create a spatial index
  1872  	if err := db.CreateSpatialIndex("rects", "rect:*", IndexRect); err != nil {
  1873  		t.Fatal(err)
  1874  	}
  1875  	if true {
  1876  		err := db.Update(func(tx *Tx) error {
  1877  			if _, _, err := tx.Set("fun:user:0", "tom", nil); err != nil {
  1878  				return err
  1879  			}
  1880  			if _, _, err := tx.Set("fun:user:1", "Randi", nil); err != nil {
  1881  				return err
  1882  			}
  1883  			if _, _, err := tx.Set("fun:user:2", "jane", nil); err != nil {
  1884  				return err
  1885  			}
  1886  			if _, _, err := tx.Set("fun:user:4", "Janet", nil); err != nil {
  1887  				return err
  1888  			}
  1889  			if _, _, err := tx.Set("fun:user:5", "Paula", nil); err != nil {
  1890  				return err
  1891  			}
  1892  			if _, _, err := tx.Set("fun:user:6", "peter", nil); err != nil {
  1893  				return err
  1894  			}
  1895  			if _, _, err := tx.Set("fun:user:7", "Terri", nil); err != nil {
  1896  				return err
  1897  			}
  1898  			return nil
  1899  		})
  1900  		if err != nil {
  1901  			t.Fatal(err)
  1902  		}
  1903  		// add some random items
  1904  		start := time.Now()
  1905  		if err := db.Update(func(tx *Tx) error {
  1906  			for _, i := range rand.Perm(100) {
  1907  				if _, _, err := tx.Set(fmt.Sprintf("tag:%d", i+100), fmt.Sprintf("val:%d", rand.Int()%100+100), nil); err != nil {
  1908  					return err
  1909  				}
  1910  			}
  1911  			return nil
  1912  		}); err != nil {
  1913  			t.Fatal(err)
  1914  		}
  1915  		if false {
  1916  			println(time.Since(start).String(), db.keys.Len())
  1917  		}
  1918  		// add some random rects
  1919  		if err := db.Update(func(tx *Tx) error {
  1920  			if _, _, err := tx.Set("rect:1", Rect([]float64{10, 10}, []float64{20, 20}), nil); err != nil {
  1921  				return err
  1922  			}
  1923  			if _, _, err := tx.Set("rect:2", Rect([]float64{15, 15}, []float64{24, 24}), nil); err != nil {
  1924  				return err
  1925  			}
  1926  			if _, _, err := tx.Set("rect:3", Rect([]float64{17, 17}, []float64{27, 27}), nil); err != nil {
  1927  				return err
  1928  			}
  1929  			return nil
  1930  		}); err != nil {
  1931  			t.Fatal(err)
  1932  		}
  1933  	}
  1934  	// verify the data has been created
  1935  	buf := &bytes.Buffer{}
  1936  	err := db.View(func(tx *Tx) error {
  1937  		err := tx.Ascend("users", func(key, val string) bool {
  1938  			fmt.Fprintf(buf, "%s %s\n", key, val)
  1939  			return true
  1940  		})
  1941  		if err != nil {
  1942  			t.Fatal(err)
  1943  		}
  1944  		err = tx.AscendRange("", "tag:170", "tag:172", func(key, val string) bool {
  1945  			fmt.Fprintf(buf, "%s\n", key)
  1946  			return true
  1947  		})
  1948  		if err != nil {
  1949  			t.Fatal(err)
  1950  		}
  1951  		err = tx.AscendGreaterOrEqual("", "tag:195", func(key, val string) bool {
  1952  			fmt.Fprintf(buf, "%s\n", key)
  1953  			return true
  1954  		})
  1955  		if err != nil {
  1956  			t.Fatal(err)
  1957  		}
  1958  		err = tx.AscendGreaterOrEqual("", "rect:", func(key, val string) bool {
  1959  			if !strings.HasPrefix(key, "rect:") {
  1960  				return false
  1961  			}
  1962  			min, max := IndexRect(val)
  1963  			fmt.Fprintf(buf, "%s: %v,%v\n", key, min, max)
  1964  			return true
  1965  		})
  1966  		if err != nil {
  1967  			t.Fatal(err)
  1968  		}
  1969  		expect := make([]string, 2)
  1970  		n := 0
  1971  		err = tx.Intersects("rects", "[0 0],[15 15]", func(key, val string) bool {
  1972  			if n == 2 {
  1973  				t.Fatalf("too many rects where received, expecting only two")
  1974  			}
  1975  			min, max := IndexRect(val)
  1976  			s := fmt.Sprintf("%s: %v,%v\n", key, min, max)
  1977  			if key == "rect:1" {
  1978  				expect[0] = s
  1979  			} else if key == "rect:2" {
  1980  				expect[1] = s
  1981  			}
  1982  			n++
  1983  			return true
  1984  		})
  1985  		if err != nil {
  1986  			t.Fatal(err)
  1987  		}
  1988  		for _, s := range expect {
  1989  			if _, err := buf.WriteString(s); err != nil {
  1990  				return err
  1991  			}
  1992  		}
  1993  		return nil
  1994  	})
  1995  	if err != nil {
  1996  		t.Fatal(err)
  1997  	}
  1998  	res := `
  1999  fun:user:2 jane
  2000  fun:user:4 Janet
  2001  fun:user:5 Paula
  2002  fun:user:6 peter
  2003  fun:user:1 Randi
  2004  fun:user:7 Terri
  2005  fun:user:0 tom
  2006  tag:170
  2007  tag:171
  2008  tag:195
  2009  tag:196
  2010  tag:197
  2011  tag:198
  2012  tag:199
  2013  rect:1: [10 10],[20 20]
  2014  rect:2: [15 15],[24 24]
  2015  rect:3: [17 17],[27 27]
  2016  rect:1: [10 10],[20 20]
  2017  rect:2: [15 15],[24 24]
  2018  `
  2019  	res = strings.Replace(res, "\r", "", -1)
  2020  	if strings.TrimSpace(buf.String()) != strings.TrimSpace(res) {
  2021  		t.Fatalf("expected [%v], got [%v]", strings.TrimSpace(res), strings.TrimSpace(buf.String()))
  2022  	}
  2023  }
  2024  
  2025  func TestIndexAscend(t *testing.T) {
  2026  	rand.Seed(time.Now().UnixNano())
  2027  	db := testOpen(t)
  2028  	defer testClose(db)
  2029  
  2030  	// create a simple index
  2031  	if err := db.CreateIndex("usr", "usr:*", IndexInt); err != nil {
  2032  		t.Fatal(err)
  2033  	}
  2034  	if err := db.Update(func(tx *Tx) error {
  2035  		for i := 10; i > 0; i-- {
  2036  			tx.Set(fmt.Sprintf("usr:%d", i), fmt.Sprintf("%d", 10-i), nil)
  2037  		}
  2038  		return nil
  2039  	}); err != nil {
  2040  		t.Fatal(err)
  2041  	}
  2042  
  2043  	buf := &bytes.Buffer{}
  2044  	err := db.View(func(tx *Tx) error {
  2045  		tx.Ascend("usr", func(key, value string) bool {
  2046  			fmt.Fprintf(buf, "%s %s\n", key, value)
  2047  			return true
  2048  		})
  2049  		fmt.Fprintln(buf)
  2050  
  2051  		tx.AscendGreaterOrEqual("usr", "8", func(key, value string) bool {
  2052  			fmt.Fprintf(buf, "%s %s\n", key, value)
  2053  			return true
  2054  		})
  2055  		fmt.Fprintln(buf)
  2056  
  2057  		tx.AscendLessThan("usr", "3", func(key, value string) bool {
  2058  			fmt.Fprintf(buf, "%s %s\n", key, value)
  2059  			return true
  2060  		})
  2061  		fmt.Fprintln(buf)
  2062  
  2063  		tx.AscendRange("usr", "4", "8", func(key, value string) bool {
  2064  			fmt.Fprintf(buf, "%s %s\n", key, value)
  2065  			return true
  2066  		})
  2067  		return nil
  2068  	})
  2069  
  2070  	if err != nil {
  2071  		t.Fatal(err)
  2072  	}
  2073  
  2074  	res := `
  2075  usr:10 0
  2076  usr:9 1
  2077  usr:8 2
  2078  usr:7 3
  2079  usr:6 4
  2080  usr:5 5
  2081  usr:4 6
  2082  usr:3 7
  2083  usr:2 8
  2084  usr:1 9
  2085  
  2086  usr:2 8
  2087  usr:1 9
  2088  
  2089  usr:10 0
  2090  usr:9 1
  2091  usr:8 2
  2092  
  2093  usr:6 4
  2094  usr:5 5
  2095  usr:4 6
  2096  usr:3 7
  2097  `
  2098  	res = strings.Replace(res, "\r", "", -1)
  2099  	s1 := strings.TrimSpace(buf.String())
  2100  	s2 := strings.TrimSpace(res)
  2101  	if s1 != s2 {
  2102  		t.Fatalf("expected [%v], got [%v]", s1, s2)
  2103  	}
  2104  }
  2105  
  2106  func testRectStringer(min, max []float64) error {
  2107  	nmin, nmax := IndexRect(Rect(min, max))
  2108  	if len(nmin) != len(min) {
  2109  		return fmt.Errorf("rect=%v,%v, expect=%v,%v", nmin, nmax, min, max)
  2110  	}
  2111  	for i := 0; i < len(min); i++ {
  2112  		if min[i] != nmin[i] || max[i] != nmax[i] {
  2113  			return fmt.Errorf("rect=%v,%v, expect=%v,%v", nmin, nmax, min, max)
  2114  		}
  2115  	}
  2116  	return nil
  2117  }
  2118  func TestRectStrings(t *testing.T) {
  2119  	test(t, Rect(IndexRect(Point(1))) == "[1]", true)
  2120  	test(t, Rect(IndexRect(Point(1, 2, 3, 4))) == "[1 2 3 4]", true)
  2121  	test(t, Rect(IndexRect(Rect(IndexRect("[1 2],[1 2]")))) == "[1 2]", true)
  2122  	test(t, Rect(IndexRect(Rect(IndexRect("[1 2],[2 2]")))) == "[1 2],[2 2]", true)
  2123  	test(t, Rect(IndexRect(Rect(IndexRect("[1 2],[2 2],[3]")))) == "[1 2],[2 2]", true)
  2124  	test(t, Rect(IndexRect(Rect(IndexRect("[1 2]")))) == "[1 2]", true)
  2125  	test(t, Rect(IndexRect(Rect(IndexRect("[1.5 2 4.5 5.6]")))) == "[1.5 2 4.5 5.6]", true)
  2126  	test(t, Rect(IndexRect(Rect(IndexRect("[1.5 2 4.5 5.6 -1],[]")))) == "[1.5 2 4.5 5.6 -1]", true)
  2127  	test(t, Rect(IndexRect(Rect(IndexRect("[]")))) == "[]", true)
  2128  	test(t, Rect(IndexRect(Rect(IndexRect("")))) == "[]", true)
  2129  	if err := testRectStringer(nil, nil); err != nil {
  2130  		t.Fatal(err)
  2131  	}
  2132  	if err := testRectStringer([]float64{}, []float64{}); err != nil {
  2133  		t.Fatal(err)
  2134  	}
  2135  	if err := testRectStringer([]float64{1}, []float64{2}); err != nil {
  2136  		t.Fatal(err)
  2137  	}
  2138  	if err := testRectStringer([]float64{1, 2}, []float64{3, 4}); err != nil {
  2139  		t.Fatal(err)
  2140  	}
  2141  	if err := testRectStringer([]float64{1, 2, 3}, []float64{4, 5, 6}); err != nil {
  2142  		t.Fatal(err)
  2143  	}
  2144  	if err := testRectStringer([]float64{1, 2, 3, 4}, []float64{5, 6, 7, 8}); err != nil {
  2145  		t.Fatal(err)
  2146  	}
  2147  	if err := testRectStringer([]float64{1, 2, 3, 4, 5}, []float64{6, 7, 8, 9, 10}); err != nil {
  2148  		t.Fatal(err)
  2149  	}
  2150  }
  2151  
  2152  // TestTTLReOpen test setting a TTL and then immediately closing the database and
  2153  // then waiting the TTL before reopening. The key should not be accessible.
  2154  func TestTTLReOpen(t *testing.T) {
  2155  	ttl := time.Second * 3
  2156  	db := testOpen(t)
  2157  	defer testClose(db)
  2158  	err := db.Update(func(tx *Tx) error {
  2159  		if _, _, err := tx.Set("key1", "val1", &SetOptions{Expires: true, TTL: ttl}); err != nil {
  2160  			return err
  2161  		}
  2162  		return nil
  2163  	})
  2164  	if err != nil {
  2165  		t.Fatal(err)
  2166  	}
  2167  	db = testReOpenDelay(t, db, ttl/4)
  2168  	err = db.View(func(tx *Tx) error {
  2169  		val, err := tx.Get("key1")
  2170  		if err != nil {
  2171  			return err
  2172  		}
  2173  		if val != "val1" {
  2174  			t.Fatalf("expecting '%v', got '%v'", "val1", val)
  2175  		}
  2176  		return nil
  2177  	})
  2178  	if err != nil {
  2179  		t.Fatal(err)
  2180  	}
  2181  	db = testReOpenDelay(t, db, ttl-ttl/4)
  2182  	defer testClose(db)
  2183  	err = db.View(func(tx *Tx) error {
  2184  		val, err := tx.Get("key1")
  2185  		if err == nil || err != ErrNotFound || val != "" {
  2186  			t.Fatal("expecting not found")
  2187  		}
  2188  
  2189  		return nil
  2190  	})
  2191  	if err != nil {
  2192  		t.Fatal(err)
  2193  	}
  2194  }
  2195  
  2196  func TestTTL(t *testing.T) {
  2197  	db := testOpen(t)
  2198  	defer testClose(db)
  2199  	err := db.Update(func(tx *Tx) error {
  2200  		if _, _, err := tx.Set("key1", "val1", &SetOptions{Expires: true, TTL: time.Second}); err != nil {
  2201  			return err
  2202  		}
  2203  		if _, _, err := tx.Set("key2", "val2", nil); err != nil {
  2204  			return err
  2205  		}
  2206  		return nil
  2207  	})
  2208  	if err != nil {
  2209  		t.Fatal(err)
  2210  	}
  2211  	err = db.View(func(tx *Tx) error {
  2212  		dur1, err := tx.TTL("key1")
  2213  		if err != nil {
  2214  			t.Fatal(err)
  2215  		}
  2216  		if dur1 > time.Second || dur1 <= 0 {
  2217  			t.Fatalf("expecting between zero and one second, got '%v'", dur1)
  2218  		}
  2219  		dur1, err = tx.TTL("key2")
  2220  		if err != nil {
  2221  			t.Fatal(err)
  2222  		}
  2223  		if dur1 >= 0 {
  2224  			t.Fatalf("expecting a negative value, got '%v'", dur1)
  2225  		}
  2226  		return nil
  2227  	})
  2228  	if err != nil {
  2229  		t.Fatal(err)
  2230  	}
  2231  }
  2232  
  2233  func TestConfig(t *testing.T) {
  2234  	db := testOpen(t)
  2235  	defer testClose(db)
  2236  
  2237  	err := db.SetConfig(Config{SyncPolicy: SyncPolicy(-1)})
  2238  	if err == nil {
  2239  		t.Fatal("expecting a config syncpolicy error")
  2240  	}
  2241  	err = db.SetConfig(Config{SyncPolicy: SyncPolicy(3)})
  2242  	if err == nil {
  2243  		t.Fatal("expecting a config syncpolicy error")
  2244  	}
  2245  	err = db.SetConfig(Config{SyncPolicy: Never})
  2246  	if err != nil {
  2247  		t.Fatal(err)
  2248  	}
  2249  	err = db.SetConfig(Config{SyncPolicy: EverySecond})
  2250  	if err != nil {
  2251  		t.Fatal(err)
  2252  	}
  2253  	err = db.SetConfig(Config{AutoShrinkMinSize: 100, AutoShrinkPercentage: 200, SyncPolicy: Always})
  2254  	if err != nil {
  2255  		t.Fatal(err)
  2256  	}
  2257  
  2258  	var c Config
  2259  	if err := db.ReadConfig(&c); err != nil {
  2260  		t.Fatal(err)
  2261  	}
  2262  	if c.AutoShrinkMinSize != 100 || c.AutoShrinkPercentage != 200 && c.SyncPolicy != Always {
  2263  		t.Fatalf("expecting %v, %v, and %v, got %v, %v, and %v", 100, 200, Always, c.AutoShrinkMinSize, c.AutoShrinkPercentage, c.SyncPolicy)
  2264  	}
  2265  }
  2266  func testUint64Hex(n uint64) string {
  2267  	s := strconv.FormatUint(n, 16)
  2268  	s = "0000000000000000" + s
  2269  	return s[len(s)-16:]
  2270  }
  2271  func textHexUint64(s string) uint64 {
  2272  	n, _ := strconv.ParseUint(s, 16, 64)
  2273  	return n
  2274  }
  2275  func benchClose(t *testing.B, persist bool, db *DB) {
  2276  	if persist {
  2277  		if err := os.RemoveAll("data.db"); err != nil {
  2278  			t.Fatal(err)
  2279  		}
  2280  	}
  2281  	if err := db.Close(); err != nil {
  2282  		t.Fatal(err)
  2283  	}
  2284  }
  2285  
  2286  func benchOpenFillData(t *testing.B, N int,
  2287  	set, persist, random bool,
  2288  	geo bool,
  2289  	batch int) (db *DB, keys, vals []string) {
  2290  	///
  2291  	t.StopTimer()
  2292  	rand.Seed(time.Now().UnixNano())
  2293  	var err error
  2294  	if persist {
  2295  		if err := os.RemoveAll("data.db"); err != nil {
  2296  			t.Fatal(err)
  2297  		}
  2298  		db, err = Open("data.db")
  2299  	} else {
  2300  		db, err = Open(":memory:")
  2301  	}
  2302  	if err != nil {
  2303  		t.Fatal(err)
  2304  	}
  2305  	keys = make([]string, N)
  2306  	vals = make([]string, N)
  2307  	perm := rand.Perm(N)
  2308  	for i := 0; i < N; i++ {
  2309  		if random && set {
  2310  			keys[perm[i]] = testUint64Hex(uint64(i))
  2311  			vals[perm[i]] = strconv.FormatInt(rand.Int63()%1000+1000, 10)
  2312  		} else {
  2313  			keys[i] = testUint64Hex(uint64(i))
  2314  			vals[i] = strconv.FormatInt(rand.Int63()%1000+1000, 10)
  2315  		}
  2316  	}
  2317  	if set {
  2318  		t.StartTimer()
  2319  	}
  2320  	for i := 0; i < N; {
  2321  		err := db.Update(func(tx *Tx) error {
  2322  			var err error
  2323  			for j := 0; j < batch && i < N; j++ {
  2324  				_, _, err = tx.Set(keys[i], vals[i], nil)
  2325  				i++
  2326  			}
  2327  			return err
  2328  		})
  2329  		if err != nil {
  2330  			t.Fatal(err)
  2331  		}
  2332  	}
  2333  	if set {
  2334  		t.StopTimer()
  2335  	}
  2336  	var n uint64
  2337  	err = db.View(func(tx *Tx) error {
  2338  		err := tx.Ascend("", func(key, value string) bool {
  2339  			n2 := textHexUint64(key)
  2340  			if n2 != n {
  2341  				t.Fatalf("expecting '%v', got '%v'", n2, n)
  2342  			}
  2343  			n++
  2344  			return true
  2345  		})
  2346  		return err
  2347  	})
  2348  	if err != nil {
  2349  		t.Fatal(err)
  2350  	}
  2351  	if n != uint64(N) {
  2352  		t.Fatalf("expecting '%v', got '%v'", N, n)
  2353  	}
  2354  	t.StartTimer()
  2355  	return db, keys, vals
  2356  }
  2357  
  2358  func benchSetGet(t *testing.B, set, persist, random bool, batch int) {
  2359  	N := t.N
  2360  	for N > 0 {
  2361  		n := 0
  2362  		if N >= 100000 {
  2363  			n = 100000
  2364  		} else {
  2365  			n = N
  2366  		}
  2367  		func() {
  2368  			db, keys, _ := benchOpenFillData(t, n, set, persist, random, false, batch)
  2369  			defer benchClose(t, persist, db)
  2370  			if !set {
  2371  				for i := 0; i < n; {
  2372  					err := db.View(func(tx *Tx) error {
  2373  						var err error
  2374  						for j := 0; j < batch && i < n; j++ {
  2375  							_, err = tx.Get(keys[i])
  2376  							i++
  2377  						}
  2378  						return err
  2379  					})
  2380  					if err != nil {
  2381  						t.Fatal(err)
  2382  					}
  2383  				}
  2384  			}
  2385  		}()
  2386  		N -= n
  2387  	}
  2388  }
  2389  
  2390  // Set Persist
  2391  func Benchmark_Set_Persist_Random_1(t *testing.B) {
  2392  	benchSetGet(t, true, true, true, 1)
  2393  }
  2394  func Benchmark_Set_Persist_Random_10(t *testing.B) {
  2395  	benchSetGet(t, true, true, true, 10)
  2396  }
  2397  func Benchmark_Set_Persist_Random_100(t *testing.B) {
  2398  	benchSetGet(t, true, true, true, 100)
  2399  }
  2400  func Benchmark_Set_Persist_Sequential_1(t *testing.B) {
  2401  	benchSetGet(t, true, true, false, 1)
  2402  }
  2403  func Benchmark_Set_Persist_Sequential_10(t *testing.B) {
  2404  	benchSetGet(t, true, true, false, 10)
  2405  }
  2406  func Benchmark_Set_Persist_Sequential_100(t *testing.B) {
  2407  	benchSetGet(t, true, true, false, 100)
  2408  }
  2409  
  2410  // Set NoPersist
  2411  func Benchmark_Set_NoPersist_Random_1(t *testing.B) {
  2412  	benchSetGet(t, true, false, true, 1)
  2413  }
  2414  func Benchmark_Set_NoPersist_Random_10(t *testing.B) {
  2415  	benchSetGet(t, true, false, true, 10)
  2416  }
  2417  func Benchmark_Set_NoPersist_Random_100(t *testing.B) {
  2418  	benchSetGet(t, true, false, true, 100)
  2419  }
  2420  func Benchmark_Set_NoPersist_Sequential_1(t *testing.B) {
  2421  	benchSetGet(t, true, false, false, 1)
  2422  }
  2423  func Benchmark_Set_NoPersist_Sequential_10(t *testing.B) {
  2424  	benchSetGet(t, true, false, false, 10)
  2425  }
  2426  func Benchmark_Set_NoPersist_Sequential_100(t *testing.B) {
  2427  	benchSetGet(t, true, false, false, 100)
  2428  }
  2429  
  2430  // Get
  2431  func Benchmark_Get_1(t *testing.B) {
  2432  	benchSetGet(t, false, false, false, 1)
  2433  }
  2434  func Benchmark_Get_10(t *testing.B) {
  2435  	benchSetGet(t, false, false, false, 10)
  2436  }
  2437  func Benchmark_Get_100(t *testing.B) {
  2438  	benchSetGet(t, false, false, false, 100)
  2439  }
  2440  
  2441  func benchScan(t *testing.B, asc bool, count int) {
  2442  	N := count
  2443  	db, _, _ := benchOpenFillData(t, N, false, false, false, false, 100)
  2444  	defer benchClose(t, false, db)
  2445  	for i := 0; i < t.N; i++ {
  2446  		count := 0
  2447  		err := db.View(func(tx *Tx) error {
  2448  			if asc {
  2449  				return tx.Ascend("", func(key, val string) bool {
  2450  					count++
  2451  					return true
  2452  				})
  2453  			}
  2454  			return tx.Descend("", func(key, val string) bool {
  2455  				count++
  2456  				return true
  2457  			})
  2458  
  2459  		})
  2460  		if err != nil {
  2461  			t.Fatal(err)
  2462  		}
  2463  		if count != N {
  2464  			t.Fatalf("expecting '%v', got '%v'", N, count)
  2465  		}
  2466  	}
  2467  }
  2468  
  2469  func Benchmark_Ascend_1(t *testing.B) {
  2470  	benchScan(t, true, 1)
  2471  }
  2472  func Benchmark_Ascend_10(t *testing.B) {
  2473  	benchScan(t, true, 10)
  2474  }
  2475  func Benchmark_Ascend_100(t *testing.B) {
  2476  	benchScan(t, true, 100)
  2477  }
  2478  func Benchmark_Ascend_1000(t *testing.B) {
  2479  	benchScan(t, true, 1000)
  2480  }
  2481  func Benchmark_Ascend_10000(t *testing.B) {
  2482  	benchScan(t, true, 10000)
  2483  }
  2484  
  2485  func Benchmark_Descend_1(t *testing.B) {
  2486  	benchScan(t, false, 1)
  2487  }
  2488  func Benchmark_Descend_10(t *testing.B) {
  2489  	benchScan(t, false, 10)
  2490  }
  2491  func Benchmark_Descend_100(t *testing.B) {
  2492  	benchScan(t, false, 100)
  2493  }
  2494  func Benchmark_Descend_1000(t *testing.B) {
  2495  	benchScan(t, false, 1000)
  2496  }
  2497  func Benchmark_Descend_10000(t *testing.B) {
  2498  	benchScan(t, false, 10000)
  2499  }
  2500  
  2501  /*
  2502  func Benchmark_Spatial_2D(t *testing.B) {
  2503  	N := 100000
  2504  	db, _, _ := benchOpenFillData(t, N, true, true, false, true, 100)
  2505  	defer benchClose(t, false, db)
  2506  
  2507  }
  2508  */
  2509  func TestCoverCloseAlreadyClosed(t *testing.T) {
  2510  	db := testOpen(t)
  2511  	defer testClose(db)
  2512  	_ = db.file.Close()
  2513  	if err := db.Close(); err == nil {
  2514  		t.Fatal("expecting an error")
  2515  	}
  2516  }
  2517  
  2518  func TestCoverConfigClosed(t *testing.T) {
  2519  	db := testOpen(t)
  2520  	defer testClose(db)
  2521  	_ = db.Close()
  2522  	var config Config
  2523  	if err := db.ReadConfig(&config); err != ErrDatabaseClosed {
  2524  		t.Fatal("expecting database closed error")
  2525  	}
  2526  	if err := db.SetConfig(config); err != ErrDatabaseClosed {
  2527  		t.Fatal("expecting database closed error")
  2528  	}
  2529  }
  2530  func TestCoverShrinkShrink(t *testing.T) {
  2531  	db := testOpen(t)
  2532  	defer testClose(db)
  2533  	if err := db.Update(func(tx *Tx) error {
  2534  		for i := 0; i < 10000; i++ {
  2535  			_, _, err := tx.Set(fmt.Sprintf("%d", i), fmt.Sprintf("%d", i), nil)
  2536  			if err != nil {
  2537  				return err
  2538  			}
  2539  		}
  2540  		return nil
  2541  	}); err != nil {
  2542  		t.Fatal(err)
  2543  	}
  2544  	if err := db.Update(func(tx *Tx) error {
  2545  		for i := 250; i < 250+100; i++ {
  2546  			_, err := tx.Delete(fmt.Sprintf("%d", i))
  2547  			if err != nil {
  2548  				return err
  2549  			}
  2550  		}
  2551  		return nil
  2552  	}); err != nil {
  2553  		t.Fatal(err)
  2554  	}
  2555  	var err1, err2 error
  2556  	var wg sync.WaitGroup
  2557  	wg.Add(2)
  2558  	go func() {
  2559  		defer wg.Done()
  2560  		err1 = db.Shrink()
  2561  	}()
  2562  	go func() {
  2563  		defer wg.Done()
  2564  		err2 = db.Shrink()
  2565  	}()
  2566  	wg.Wait()
  2567  	//println(123)
  2568  	//fmt.Printf("%v\n%v\n", err1, err2)
  2569  	if err1 != ErrShrinkInProcess && err2 != ErrShrinkInProcess {
  2570  		t.Fatal("expecting a shrink in process error")
  2571  	}
  2572  	db = testReOpen(t, db)
  2573  	defer testClose(db)
  2574  	if err := db.View(func(tx *Tx) error {
  2575  		n, err := tx.Len()
  2576  		if err != nil {
  2577  			return err
  2578  		}
  2579  		if n != 9900 {
  2580  			t.Fatal("expecting 9900 items")
  2581  		}
  2582  		return nil
  2583  	}); err != nil {
  2584  		t.Fatal(err)
  2585  	}
  2586  }
  2587  
  2588  func TestPreviousItem(t *testing.T) {
  2589  	db := testOpen(t)
  2590  	defer testClose(db)
  2591  	err := db.Update(func(tx *Tx) error {
  2592  		_, _, err := tx.Set("hello", "world", nil)
  2593  		if err != nil {
  2594  			return err
  2595  		}
  2596  		prev, replaced, err := tx.Set("hello", "planet", nil)
  2597  		if err != nil {
  2598  			return err
  2599  		}
  2600  		if !replaced {
  2601  			t.Fatal("should be replaced")
  2602  		}
  2603  		if prev != "world" {
  2604  			t.Fatalf("expecting '%v', got '%v'", "world", prev)
  2605  		}
  2606  		return nil
  2607  	})
  2608  	if err != nil {
  2609  		t.Fatal(err)
  2610  	}
  2611  }
  2612  
  2613  func TestJSONIndex(t *testing.T) {
  2614  	db := testOpen(t)
  2615  	defer testClose(db)
  2616  
  2617  	_ = db.CreateIndex("last_name", "*", IndexJSON("name.last"))
  2618  	_ = db.CreateIndex("last_name_cs", "*", IndexJSONCaseSensitive("name.last"))
  2619  	_ = db.CreateIndex("age", "*", IndexJSON("age"))
  2620  	_ = db.CreateIndex("student", "*", IndexJSON("student"))
  2621  	_ = db.Update(func(tx *Tx) error {
  2622  		_, _, _ = tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38,"student":false}`, nil)
  2623  		_, _, _ = tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47,"student":true}`, nil)
  2624  		_, _, _ = tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52,"student":true}`, nil)
  2625  		_, _, _ = tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28,"student":false}`, nil)
  2626  		_, _, _ = tx.Set("5", `{"name":{"first":"bill","last":"frank"},"age":21,"student":true}`, nil)
  2627  		_, _, _ = tx.Set("6", `{"name":{"first":"sally","last":"randall"},"age":68,"student":false}`, nil)
  2628  		return nil
  2629  	})
  2630  	var keys []string
  2631  	_ = db.View(func(tx *Tx) error {
  2632  		_ = tx.Ascend("last_name_cs", func(key, value string) bool {
  2633  			//fmt.Printf("%s: %s\n", key, value)
  2634  			keys = append(keys, key)
  2635  			return true
  2636  		})
  2637  		_ = tx.Ascend("last_name", func(key, value string) bool {
  2638  			//fmt.Printf("%s: %s\n", key, value)
  2639  			keys = append(keys, key)
  2640  			return true
  2641  		})
  2642  		_ = tx.Ascend("age", func(key, value string) bool {
  2643  			//fmt.Printf("%s: %s\n", key, value)
  2644  			keys = append(keys, key)
  2645  			return true
  2646  		})
  2647  		_ = tx.Ascend("student", func(key, value string) bool {
  2648  			//fmt.Printf("%s: %s\n", key, value)
  2649  			keys = append(keys, key)
  2650  			return true
  2651  		})
  2652  		return nil
  2653  	})
  2654  	expect := "3,4,1,2,5,6,3,4,5,1,2,6,5,4,1,2,3,6,1,4,6,2,3,5"
  2655  	if strings.Join(keys, ",") != expect {
  2656  		t.Fatalf("expected %v, got %v", expect, strings.Join(keys, ","))
  2657  	}
  2658  }
  2659  
  2660  func TestOnExpiredSync(t *testing.T) {
  2661  	db := testOpen(t)
  2662  	defer testClose(db)
  2663  
  2664  	var config Config
  2665  	if err := db.ReadConfig(&config); err != nil {
  2666  		t.Fatal(err)
  2667  	}
  2668  	hits := make(chan int, 3)
  2669  	config.OnExpiredSync = func(key, value string, tx *Tx) error {
  2670  		n, err := strconv.Atoi(value)
  2671  		if err != nil {
  2672  			return err
  2673  		}
  2674  		defer func() { hits <- n }()
  2675  		if n >= 2 {
  2676  			_, err = tx.Delete(key)
  2677  			if err != ErrNotFound {
  2678  				return err
  2679  			}
  2680  			return nil
  2681  		}
  2682  		n++
  2683  		_, _, err = tx.Set(key, strconv.Itoa(n), &SetOptions{Expires: true, TTL: time.Millisecond * 100})
  2684  		return err
  2685  	}
  2686  	if err := db.SetConfig(config); err != nil {
  2687  		t.Fatal(err)
  2688  	}
  2689  	err := db.Update(func(tx *Tx) error {
  2690  		_, _, err := tx.Set("K", "0", &SetOptions{Expires: true, TTL: time.Millisecond * 100})
  2691  		return err
  2692  	})
  2693  	if err != nil {
  2694  		t.Fail()
  2695  	}
  2696  
  2697  	done := make(chan struct{})
  2698  	go func() {
  2699  		ticks := time.NewTicker(time.Millisecond * 50)
  2700  		defer ticks.Stop()
  2701  		for {
  2702  			select {
  2703  			case <-done:
  2704  				return
  2705  			case <-ticks.C:
  2706  				err := db.View(func(tx *Tx) error {
  2707  					v, err := tx.Get("K", true)
  2708  					if err != nil {
  2709  						return err
  2710  					}
  2711  					n, err := strconv.Atoi(v)
  2712  					if err != nil {
  2713  						return err
  2714  					}
  2715  					if n < 0 || n > 2 {
  2716  						t.Fail()
  2717  					}
  2718  					return nil
  2719  				})
  2720  				if err != nil {
  2721  					t.Fail()
  2722  				}
  2723  			}
  2724  		}
  2725  	}()
  2726  
  2727  OUTER1:
  2728  	for {
  2729  		select {
  2730  		case <-time.After(time.Second * 2):
  2731  			t.Fail()
  2732  		case v := <-hits:
  2733  			if v >= 2 {
  2734  				break OUTER1
  2735  			}
  2736  		}
  2737  	}
  2738  	err = db.View(func(tx *Tx) error {
  2739  		defer close(done)
  2740  		v, err := tx.Get("K")
  2741  		if err != nil {
  2742  			t.Fail()
  2743  			return err
  2744  		}
  2745  		if v != "2" {
  2746  			t.Fail()
  2747  		}
  2748  		return nil
  2749  	})
  2750  	if err != nil {
  2751  		t.Fail()
  2752  	}
  2753  }
  2754  
  2755  func TestTransactionLeak(t *testing.T) {
  2756  	// This tests an bug identified in Issue #69. When inside a Update
  2757  	// transaction, a Set after a Delete for a key that previously exists will
  2758  	// remove the key when the transaction was rolledback.
  2759  	buntDB, err := Open(":memory:")
  2760  	if err != nil {
  2761  		t.Fatal(err)
  2762  	}
  2763  	bd := buntDB
  2764  	err = bd.Update(func(tx *Tx) error {
  2765  		_, _, err := tx.Set("a", "a", nil)
  2766  		return err
  2767  	})
  2768  	if err != nil {
  2769  		t.Fatal(err)
  2770  	}
  2771  	bd.View(func(tx *Tx) error {
  2772  		val, err := tx.Get("a")
  2773  		if err != nil {
  2774  			return err
  2775  		}
  2776  		if val != "a" {
  2777  			return errors.New("mismatch")
  2778  		}
  2779  		return nil
  2780  	})
  2781  	if err != nil {
  2782  		t.Fatal(err)
  2783  	}
  2784  	bd.Update(func(tx *Tx) error {
  2785  		val, err := tx.Delete("a")
  2786  		if err != nil {
  2787  			return err
  2788  		}
  2789  		if val != "a" {
  2790  			return errors.New("mismatch")
  2791  		}
  2792  		val, err = tx.Get("a")
  2793  		if err != ErrNotFound {
  2794  			return fmt.Errorf("expected NotFound, got %v", err)
  2795  		}
  2796  		if val != "" {
  2797  			return errors.New("mismatch")
  2798  		}
  2799  		val, rep, err := tx.Set("a", "b", nil)
  2800  		if err != nil {
  2801  			return err
  2802  		}
  2803  		if rep {
  2804  			return errors.New("replaced")
  2805  		}
  2806  		if val != "" {
  2807  			return errors.New("mismatch")
  2808  		}
  2809  		val, err = tx.Get("a")
  2810  		if err != nil {
  2811  			return err
  2812  		}
  2813  		if val != "b" {
  2814  			return errors.New("mismatch")
  2815  		}
  2816  		return errors.New("rollback")
  2817  	})
  2818  	if err != nil {
  2819  		t.Fatal(err)
  2820  	}
  2821  	bd.View(func(tx *Tx) error {
  2822  		val, err := tx.Get("a")
  2823  		if err != nil {
  2824  			return err
  2825  		}
  2826  		if val != "a" {
  2827  			return errors.New("mismatch")
  2828  		}
  2829  		return nil
  2830  	})
  2831  	if err != nil {
  2832  		t.Fatal(err)
  2833  	}
  2834  }
  2835  
  2836  func TestReloadNotInvalid(t *testing.T) {
  2837  	rand.Seed(time.Now().UnixNano())
  2838  	os.RemoveAll("data.db")
  2839  	defer os.RemoveAll("data.db")
  2840  	start := time.Now()
  2841  	ii := 0
  2842  	for time.Since(start) < time.Second*5 {
  2843  		func() {
  2844  			db, err := Open("data.db")
  2845  			if err != nil {
  2846  				t.Fatal(err)
  2847  			}
  2848  			defer func() {
  2849  				if err := db.Close(); err != nil {
  2850  					panic(err)
  2851  				}
  2852  				// truncate at a random point in the file
  2853  				f, err := os.OpenFile("data.db", os.O_RDWR, 0666)
  2854  				if err != nil {
  2855  					panic(err)
  2856  				}
  2857  				defer f.Close()
  2858  				sz, err := f.Seek(0, 2)
  2859  				if err != nil {
  2860  					panic(err)
  2861  				}
  2862  				n := sz/2 + int64(rand.Intn(int(sz/2)))
  2863  				err = f.Truncate(n)
  2864  				if err != nil {
  2865  					panic(err)
  2866  				}
  2867  			}()
  2868  			N := 500
  2869  			lotsa.Ops(N, 16, func(i, t int) {
  2870  				if i == N/2 && ii&7 == 0 {
  2871  					if err := db.Shrink(); err != nil {
  2872  						panic(err)
  2873  					}
  2874  				}
  2875  				err := db.Update(func(tx *Tx) error {
  2876  					_, _, err := tx.Set(fmt.Sprintf("key:%d", i), fmt.Sprintf("val:%d", i), &SetOptions{
  2877  						Expires: true,
  2878  						TTL:     30,
  2879  					})
  2880  					return err
  2881  				})
  2882  				if err != nil {
  2883  					panic(err)
  2884  				}
  2885  			})
  2886  		}()
  2887  		ii++
  2888  	}
  2889  }
  2890  
  2891  func TestEstSize(t *testing.T) {
  2892  	t.Run("estIntSize", func(t *testing.T) {
  2893  		assert.Assert(estIntSize(0) == 1)
  2894  		assert.Assert(estIntSize(1) == 1)
  2895  		assert.Assert(estIntSize(9) == 1)
  2896  		assert.Assert(estIntSize(10) == 2)
  2897  		assert.Assert(estIntSize(11) == 2)
  2898  		assert.Assert(estIntSize(19) == 2)
  2899  		assert.Assert(estIntSize(20) == 2)
  2900  		assert.Assert(estIntSize(113) == 3)
  2901  		assert.Assert(estIntSize(3822) == 4)
  2902  		assert.Assert(estIntSize(-1) == 2)
  2903  		assert.Assert(estIntSize(-12) == 3)
  2904  		assert.Assert(estIntSize(-124) == 4)
  2905  	})
  2906  }
  2907  
  2908  func TestWrappedError(t *testing.T) {
  2909  	defer func() {
  2910  		if err, ok := recover().(error); ok {
  2911  			if strings.HasPrefix(err.Error(), "buntdb: ") {
  2912  				err := errors.Unwrap(err)
  2913  				if err.Error() != "my fake error" {
  2914  					t.Fatal("!")
  2915  				}
  2916  			}
  2917  		}
  2918  	}()
  2919  	panicErr(errors.New("my fake error"))
  2920  }