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