1package buntdb
2
3import (
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
17func 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}
23func testReOpen(t testing.TB, db *DB) *DB {
24	return testReOpenDelay(t, db, 0)
25}
26
27func 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
41func testClose(db *DB) {
42	_ = db.Close()
43	_ = os.RemoveAll("data.db")
44}
45
46func 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}
92func 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
148func 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
188func 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
233func 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
394func 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
498func 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}
550func 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}
602func 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
1024func Example_descKeys() {
1025	db, _ := Open(":memory:")
1026	db.CreateIndex("name", "*", IndexString)
1027	db.Update(func(tx *Tx) error {
1028		tx.Set("user:100:first", "Tom", nil)
1029		tx.Set("user:100:last", "Johnson", nil)
1030		tx.Set("user:101:first", "Janet", nil)
1031		tx.Set("user:101:last", "Prichard", nil)
1032		tx.Set("user:102:first", "Alan", nil)
1033		tx.Set("user:102:last", "Cooper", nil)
1034		return nil
1035	})
1036	db.View(func(tx *Tx) error {
1037		tx.AscendKeys("user:101:*",
1038			func(key, value string) bool {
1039				fmt.Printf("%s: %s\n", key, value)
1040				return true
1041			})
1042		tx.AscendKeys("user:10?:*",
1043			func(key, value string) bool {
1044				fmt.Printf("%s: %s\n", key, value)
1045				return true
1046			})
1047		tx.AscendKeys("*2*",
1048			func(key, value string) bool {
1049				fmt.Printf("%s: %s\n", key, value)
1050				return true
1051			})
1052		tx.DescendKeys("user:101:*",
1053			func(key, value string) bool {
1054				fmt.Printf("%s: %s\n", key, value)
1055				return true
1056			})
1057		tx.DescendKeys("*",
1058			func(key, value string) bool {
1059				fmt.Printf("%s: %s\n", key, value)
1060				return true
1061			})
1062		return nil
1063	})
1064	// Output:
1065	//user:101:first: Janet
1066	//user:101:last: Prichard
1067	//user:100:first: Tom
1068	//user:100:last: Johnson
1069	//user:101:first: Janet
1070	//user:101:last: Prichard
1071	//user:102:first: Alan
1072	//user:102:last: Cooper
1073	//user:102:first: Alan
1074	//user:102:last: Cooper
1075	//user:101:last: Prichard
1076	//user:101:first: Janet
1077	//user:102:last: Cooper
1078	//user:102:first: Alan
1079	//user:101:last: Prichard
1080	//user:101:first: Janet
1081	//user:100:last: Johnson
1082	//user:100:first: Tom
1083}
1084
1085func ExampleDesc() {
1086	db, _ := Open(":memory:")
1087	db.CreateIndex("last_name_age", "*", IndexJSON("name.last"), Desc(IndexJSON("age")))
1088	db.Update(func(tx *Tx) error {
1089		tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)
1090		tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil)
1091		tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil)
1092		tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil)
1093		tx.Set("5", `{"name":{"first":"Sam","last":"Anderson"},"age":51}`, nil)
1094		tx.Set("6", `{"name":{"first":"Melinda","last":"Prichard"},"age":44}`, nil)
1095		return nil
1096	})
1097	db.View(func(tx *Tx) error {
1098		tx.Ascend("last_name_age", func(key, value string) bool {
1099			fmt.Printf("%s: %s\n", key, value)
1100			return true
1101		})
1102		return nil
1103	})
1104
1105	// Output:
1106	//3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
1107	//5: {"name":{"first":"Sam","last":"Anderson"},"age":51}
1108	//4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
1109	//1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
1110	//2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
1111	//6: {"name":{"first":"Melinda","last":"Prichard"},"age":44}
1112}
1113
1114func ExampleDB_CreateIndex_jSON() {
1115	db, _ := Open(":memory:")
1116	db.CreateIndex("last_name", "*", IndexJSON("name.last"))
1117	db.CreateIndex("age", "*", IndexJSON("age"))
1118	db.Update(func(tx *Tx) error {
1119		tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)
1120		tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil)
1121		tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil)
1122		tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil)
1123		return nil
1124	})
1125	db.View(func(tx *Tx) error {
1126		fmt.Println("Order by last name")
1127		tx.Ascend("last_name", func(key, value string) bool {
1128			fmt.Printf("%s: %s\n", key, value)
1129			return true
1130		})
1131		fmt.Println("Order by age")
1132		tx.Ascend("age", func(key, value string) bool {
1133			fmt.Printf("%s: %s\n", key, value)
1134			return true
1135		})
1136		fmt.Println("Order by age range 30-50")
1137		tx.AscendRange("age", `{"age":30}`, `{"age":50}`, func(key, value string) bool {
1138			fmt.Printf("%s: %s\n", key, value)
1139			return true
1140		})
1141		return nil
1142	})
1143
1144	// Output:
1145	// Order by last name
1146	// 3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
1147	// 4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
1148	// 1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
1149	// 2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
1150	// Order by age
1151	// 4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
1152	// 1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
1153	// 2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
1154	// 3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
1155	// Order by age range 30-50
1156	// 1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
1157	// 2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
1158}
1159
1160func ExampleDB_CreateIndex_strings() {
1161	db, _ := Open(":memory:")
1162	db.CreateIndex("name", "*", IndexString)
1163	db.Update(func(tx *Tx) error {
1164		tx.Set("1", "Tom", nil)
1165		tx.Set("2", "Janet", nil)
1166		tx.Set("3", "Carol", nil)
1167		tx.Set("4", "Alan", nil)
1168		tx.Set("5", "Sam", nil)
1169		tx.Set("6", "Melinda", nil)
1170		return nil
1171	})
1172	db.View(func(tx *Tx) error {
1173		tx.Ascend("name", func(key, value string) bool {
1174			fmt.Printf("%s: %s\n", key, value)
1175			return true
1176		})
1177		return nil
1178	})
1179
1180	// Output:
1181	//4: Alan
1182	//3: Carol
1183	//2: Janet
1184	//6: Melinda
1185	//5: Sam
1186	//1: Tom
1187}
1188
1189func ExampleDB_CreateIndex_ints() {
1190	db, _ := Open(":memory:")
1191	db.CreateIndex("age", "*", IndexInt)
1192	db.Update(func(tx *Tx) error {
1193		tx.Set("1", "30", nil)
1194		tx.Set("2", "51", nil)
1195		tx.Set("3", "16", nil)
1196		tx.Set("4", "76", nil)
1197		tx.Set("5", "23", nil)
1198		tx.Set("6", "43", nil)
1199		return nil
1200	})
1201	db.View(func(tx *Tx) error {
1202		tx.Ascend("age", func(key, value string) bool {
1203			fmt.Printf("%s: %s\n", key, value)
1204			return true
1205		})
1206		return nil
1207	})
1208
1209	// Output:
1210	//3: 16
1211	//5: 23
1212	//1: 30
1213	//6: 43
1214	//2: 51
1215	//4: 76
1216}
1217func ExampleDB_CreateIndex_multipleFields() {
1218	db, _ := Open(":memory:")
1219	db.CreateIndex("last_name_age", "*", IndexJSON("name.last"), IndexJSON("age"))
1220	db.Update(func(tx *Tx) error {
1221		tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)
1222		tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil)
1223		tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil)
1224		tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil)
1225		tx.Set("5", `{"name":{"first":"Sam","last":"Anderson"},"age":51}`, nil)
1226		tx.Set("6", `{"name":{"first":"Melinda","last":"Prichard"},"age":44}`, nil)
1227		return nil
1228	})
1229	db.View(func(tx *Tx) error {
1230		tx.Ascend("last_name_age", func(key, value string) bool {
1231			fmt.Printf("%s: %s\n", key, value)
1232			return true
1233		})
1234		return nil
1235	})
1236
1237	// Output:
1238	//5: {"name":{"first":"Sam","last":"Anderson"},"age":51}
1239	//3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
1240	//4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
1241	//1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
1242	//6: {"name":{"first":"Melinda","last":"Prichard"},"age":44}
1243	//2: {"name":{"first":"Janet","last":"Prichard"},"age":47}
1244}
1245
1246func TestNoExpiringItem(t *testing.T) {
1247	item := &dbItem{key: "key", val: "val"}
1248	if !item.expiresAt().Equal(maxTime) {
1249		t.Fatal("item.expiresAt() != maxTime")
1250	}
1251	if min, max := item.Rect(nil); min != nil || max != nil {
1252		t.Fatal("item min,max should both be nil")
1253	}
1254}
1255func TestAutoShrink(t *testing.T) {
1256	db := testOpen(t)
1257	defer testClose(db)
1258	for i := 0; i < 1000; i++ {
1259		err := db.Update(func(tx *Tx) error {
1260			for i := 0; i < 20; i++ {
1261				if _, _, err := tx.Set(fmt.Sprintf("HELLO:%d", i), "WORLD", nil); err != nil {
1262					return err
1263				}
1264			}
1265			return nil
1266		})
1267		if err != nil {
1268			t.Fatal(err)
1269		}
1270	}
1271	db = testReOpen(t, db)
1272	defer testClose(db)
1273	db.config.AutoShrinkMinSize = 64 * 1024 // 64K
1274	for i := 0; i < 2000; i++ {
1275		err := db.Update(func(tx *Tx) error {
1276			for i := 0; i < 20; i++ {
1277				if _, _, err := tx.Set(fmt.Sprintf("HELLO:%d", i), "WORLD", nil); err != nil {
1278					return err
1279				}
1280			}
1281			return nil
1282		})
1283		if err != nil {
1284			t.Fatal(err)
1285		}
1286	}
1287	time.Sleep(time.Second * 3)
1288	db = testReOpen(t, db)
1289	defer testClose(db)
1290	err := db.View(func(tx *Tx) error {
1291		n, err := tx.Len()
1292		if err != nil {
1293			return err
1294		}
1295		if n != 20 {
1296			t.Fatalf("expecting 20, got %v", n)
1297		}
1298		return nil
1299	})
1300	if err != nil {
1301		t.Fatal(err)
1302	}
1303}
1304
1305// test database format loading
1306func TestDatabaseFormat(t *testing.T) {
1307	// should succeed
1308	func() {
1309		resp := strings.Join([]string{
1310			"*3\r\n$3\r\nset\r\n$4\r\nvar1\r\n$4\r\n1234\r\n",
1311			"*3\r\n$3\r\nset\r\n$4\r\nvar2\r\n$4\r\n1234\r\n",
1312			"*2\r\n$3\r\ndel\r\n$4\r\nvar1\r\n",
1313			"*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",
1314		}, "")
1315		if err := os.RemoveAll("data.db"); err != nil {
1316			t.Fatal(err)
1317		}
1318		if err := ioutil.WriteFile("data.db", []byte(resp), 0666); err != nil {
1319			t.Fatal(err)
1320		}
1321		db := testOpen(t)
1322		defer testClose(db)
1323	}()
1324	testBadFormat := func(resp string) {
1325		if err := os.RemoveAll("data.db"); err != nil {
1326			t.Fatal(err)
1327		}
1328		if err := ioutil.WriteFile("data.db", []byte(resp), 0666); err != nil {
1329			t.Fatal(err)
1330		}
1331		db, err := Open("data.db")
1332		if err == nil {
1333			if err := db.Close(); err != nil {
1334				t.Fatal(err)
1335			}
1336			if err := os.RemoveAll("data.db"); err != nil {
1337				t.Fatal(err)
1338			}
1339			t.Fatalf("invalid database should not be allowed")
1340		}
1341	}
1342	testBadFormat("*3\r")
1343	testBadFormat("*3\n")
1344	testBadFormat("*a\r\n")
1345	testBadFormat("*2\r\n")
1346	testBadFormat("*2\r\n%3")
1347	testBadFormat("*2\r\n$")
1348	testBadFormat("*2\r\n$3\r\n")
1349	testBadFormat("*2\r\n$3\r\ndel")
1350	testBadFormat("*2\r\n$3\r\ndel\r\r")
1351	testBadFormat("*0\r\n*2\r\n$3\r\ndel\r\r")
1352	testBadFormat("*1\r\n$3\r\nnop\r\n")
1353	testBadFormat("*1\r\n$3\r\ndel\r\n")
1354	testBadFormat("*1\r\n$3\r\nset\r\n")
1355	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")
1356	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")
1357	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")
1358	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")
1359	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")
1360	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")
1361	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")
1362}
1363
1364func TestInsertsAndDeleted(t *testing.T) {
1365	db := testOpen(t)
1366	defer testClose(db)
1367	if err := db.CreateIndex("any", "*", IndexString); err != nil {
1368		t.Fatal(err)
1369	}
1370	if err := db.CreateSpatialIndex("rect", "*", IndexRect); err != nil {
1371		t.Fatal(err)
1372	}
1373	if err := db.Update(func(tx *Tx) error {
1374		if _, _, err := tx.Set("item1", "value1", &SetOptions{Expires: true, TTL: time.Second}); err != nil {
1375			return err
1376		}
1377		if _, _, err := tx.Set("item2", "value2", nil); err != nil {
1378			return err
1379		}
1380		if _, _, err := tx.Set("item3", "value3", &SetOptions{Expires: true, TTL: time.Second}); err != nil {
1381			return err
1382		}
1383		return nil
1384	}); err != nil {
1385		t.Fatal(err)
1386	}
1387
1388	// test replacing items in the database
1389	if err := db.Update(func(tx *Tx) error {
1390		if _, _, err := tx.Set("item1", "nvalue1", nil); err != nil {
1391			return err
1392		}
1393		if _, _, err := tx.Set("item2", "nvalue2", nil); err != nil {
1394			return err
1395		}
1396		if _, err := tx.Delete("item3"); err != nil {
1397			return err
1398		}
1399		return nil
1400	}); err != nil {
1401		t.Fatal(err)
1402	}
1403}
1404
1405// test index compare functions
1406func TestIndexCompare(t *testing.T) {
1407	if !IndexFloat("1.5", "1.6") {
1408		t.Fatalf("expected true, got false")
1409	}
1410	if !IndexInt("-1", "2") {
1411		t.Fatalf("expected true, got false")
1412	}
1413	if !IndexUint("10", "25") {
1414		t.Fatalf("expected true, got false")
1415	}
1416	if !IndexBinary("Hello", "hello") {
1417		t.Fatalf("expected true, got false")
1418	}
1419	if IndexString("hello", "hello") {
1420		t.Fatalf("expected false, got true")
1421	}
1422	if IndexString("Hello", "hello") {
1423		t.Fatalf("expected false, got true")
1424	}
1425	if IndexString("hello", "Hello") {
1426		t.Fatalf("expected false, got true")
1427	}
1428	if !IndexString("gello", "Hello") {
1429		t.Fatalf("expected true, got false")
1430	}
1431	if IndexString("Hello", "gello") {
1432		t.Fatalf("expected false, got true")
1433	}
1434	if Rect(IndexRect("[1 2 3 4],[5 6 7 8]")) != "[1 2 3 4],[5 6 7 8]" {
1435		t.Fatalf("expected '%v', got '%v'", "[1 2 3 4],[5 6 7 8]", Rect(IndexRect("[1 2 3 4],[5 6 7 8]")))
1436	}
1437	if Rect(IndexRect("[1 2 3 4]")) != "[1 2 3 4]" {
1438		t.Fatalf("expected '%v', got '%v'", "[1 2 3 4]", Rect(IndexRect("[1 2 3 4]")))
1439	}
1440	if Rect(nil, nil) != "[]" {
1441		t.Fatalf("expected '%v', got '%v'", "", Rect(nil, nil))
1442	}
1443	if Point(1, 2, 3) != "[1 2 3]" {
1444		t.Fatalf("expected '%v', got '%v'", "[1 2 3]", Point(1, 2, 3))
1445	}
1446}
1447
1448// test opening a folder.
1449func TestOpeningAFolder(t *testing.T) {
1450	if err := os.RemoveAll("dir.tmp"); err != nil {
1451		t.Fatal(err)
1452	}
1453	if err := os.Mkdir("dir.tmp", 0700); err != nil {
1454		t.Fatal(err)
1455	}
1456	defer func() { _ = os.RemoveAll("dir.tmp") }()
1457	db, err := Open("dir.tmp")
1458	if err == nil {
1459		if err := db.Close(); err != nil {
1460			t.Fatal(err)
1461		}
1462		t.Fatalf("opening a directory should not be allowed")
1463	}
1464}
1465
1466// test opening an invalid resp file.
1467func TestOpeningInvalidDatabaseFile(t *testing.T) {
1468	if err := os.RemoveAll("data.db"); err != nil {
1469		t.Fatal(err)
1470	}
1471	if err := ioutil.WriteFile("data.db", []byte("invalid\r\nfile"), 0666); err != nil {
1472		t.Fatal(err)
1473	}
1474	defer func() { _ = os.RemoveAll("data.db") }()
1475	db, err := Open("data.db")
1476	if err == nil {
1477		if err := db.Close(); err != nil {
1478			t.Fatal(err)
1479		}
1480		t.Fatalf("invalid database should not be allowed")
1481	}
1482}
1483
1484// test closing a closed database.
1485func TestOpeningClosedDatabase(t *testing.T) {
1486	if err := os.RemoveAll("data.db"); err != nil {
1487		t.Fatal(err)
1488	}
1489	db, err := Open("data.db")
1490	if err != nil {
1491		t.Fatal(err)
1492	}
1493	defer func() { _ = os.RemoveAll("data.db") }()
1494	if err := db.Close(); err != nil {
1495		t.Fatal(err)
1496	}
1497	if err := db.Close(); err != ErrDatabaseClosed {
1498		t.Fatal("should not be able to close a closed database")
1499	}
1500	db, err = Open(":memory:")
1501	if err != nil {
1502		t.Fatal(err)
1503	}
1504	if err := db.Close(); err != nil {
1505		t.Fatal(err)
1506	}
1507	if err := db.Close(); err != ErrDatabaseClosed {
1508		t.Fatal("should not be able to close a closed database")
1509	}
1510}
1511
1512// test shrinking a database.
1513func TestShrink(t *testing.T) {
1514	db := testOpen(t)
1515	defer testClose(db)
1516	if err := db.Shrink(); err != nil {
1517		t.Fatal(err)
1518	}
1519	fi, err := os.Stat("data.db")
1520	if err != nil {
1521		t.Fatal(err)
1522	}
1523	if fi.Size() != 0 {
1524		t.Fatalf("expected %v, got %v", 0, fi.Size())
1525	}
1526	// add 10 items
1527	err = db.Update(func(tx *Tx) error {
1528		for i := 0; i < 10; i++ {
1529			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
1530				return err
1531			}
1532		}
1533		return nil
1534	})
1535	if err != nil {
1536		t.Fatal(err)
1537	}
1538	// add the same 10 items
1539	// this will create 10 duplicate log entries
1540	err = db.Update(func(tx *Tx) error {
1541		for i := 0; i < 10; i++ {
1542			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
1543				return err
1544			}
1545		}
1546		return nil
1547	})
1548	if err != nil {
1549		t.Fatal(err)
1550	}
1551	fi, err = os.Stat("data.db")
1552	if err != nil {
1553		t.Fatal(err)
1554	}
1555	sz1 := fi.Size()
1556	if sz1 == 0 {
1557		t.Fatalf("expected > 0, got %v", sz1)
1558	}
1559	if err := db.Shrink(); err != nil {
1560		t.Fatal(err)
1561	}
1562	fi, err = os.Stat("data.db")
1563	if err != nil {
1564		t.Fatal(err)
1565	}
1566	sz2 := fi.Size()
1567	if sz2 >= sz1 {
1568		t.Fatalf("expected < %v, got %v", sz1, sz2)
1569	}
1570	if err := db.Close(); err != nil {
1571		t.Fatal(err)
1572	}
1573	if err := db.Shrink(); err != ErrDatabaseClosed {
1574		t.Fatal("shrink on a closed databse should not be allowed")
1575	}
1576	// Now we will open a db that does not persist
1577	db, err = Open(":memory:")
1578	if err != nil {
1579		t.Fatal(err)
1580	}
1581	defer func() { _ = db.Close() }()
1582	// add 10 items
1583	err = db.Update(func(tx *Tx) error {
1584		for i := 0; i < 10; i++ {
1585			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
1586				return err
1587			}
1588		}
1589		return nil
1590	})
1591	if err != nil {
1592		t.Fatal(err)
1593	}
1594	// add the same 10 items
1595	// this will create 10 duplicate log entries
1596	err = db.Update(func(tx *Tx) error {
1597		for i := 0; i < 10; i++ {
1598			if _, _, err := tx.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i), nil); err != nil {
1599				return err
1600			}
1601		}
1602		return nil
1603	})
1604	if err != nil {
1605		t.Fatal(err)
1606	}
1607	err = db.View(func(tx *Tx) error {
1608		n, err := tx.Len()
1609		if err != nil {
1610			t.Fatal(err)
1611		}
1612		if n != 10 {
1613			t.Fatalf("expecting %v, got %v", 10, n)
1614		}
1615		return nil
1616	})
1617	if err != nil {
1618		t.Fatal(err)
1619	}
1620	// this should succeed even though it's basically a noop.
1621	if err := db.Shrink(); err != nil {
1622		t.Fatal(err)
1623	}
1624}
1625
1626func TestVariousIndexOperations(t *testing.T) {
1627	db := testOpen(t)
1628	defer testClose(db)
1629	// test creating an index with no index name.
1630	err := db.CreateIndex("", "", nil)
1631	if err == nil {
1632		t.Fatal("should not be able to create an index with no name")
1633	}
1634	// test creating an index with a name that has already been used.
1635	err = db.CreateIndex("hello", "", nil)
1636	if err != nil {
1637		t.Fatal(err)
1638	}
1639	err = db.CreateIndex("hello", "", nil)
1640	if err == nil {
1641		t.Fatal("should not be able to create a duplicate index")
1642	}
1643	err = db.Update(func(tx *Tx) error {
1644
1645		if _, _, err := tx.Set("user:1", "tom", nil); err != nil {
1646			return err
1647		}
1648		if _, _, err := tx.Set("user:2", "janet", nil); err != nil {
1649			return err
1650		}
1651		if _, _, err := tx.Set("alt:1", "from", nil); err != nil {
1652			return err
1653		}
1654		if _, _, err := tx.Set("alt:2", "there", nil); err != nil {
1655			return err
1656		}
1657		if _, _, err := tx.Set("rect:1", "[1 2],[3 4]", nil); err != nil {
1658			return err
1659		}
1660		if _, _, err := tx.Set("rect:2", "[5 6],[7 8]", nil); err != nil {
1661			return err
1662		}
1663		return nil
1664	})
1665	if err != nil {
1666		t.Fatal(err)
1667	}
1668	// test creating an index after adding items. use pattern matching. have some items in the match and some not.
1669	if err := db.CreateIndex("string", "user:*", IndexString); err != nil {
1670		t.Fatal(err)
1671	}
1672	// test creating a spatial index after adding items. use pattern matching. have some items in the match and some not.
1673	if err := db.CreateSpatialIndex("rect", "rect:*", IndexRect); err != nil {
1674		t.Fatal(err)
1675	}
1676	// test dropping an index
1677	if err := db.DropIndex("hello"); err != nil {
1678		t.Fatal(err)
1679	}
1680	// test dropping an index with no name
1681	if err := db.DropIndex(""); err == nil {
1682		t.Fatal("should not be allowed to drop an index with no name")
1683	}
1684	// test dropping an index with no name
1685	if err := db.DropIndex("na"); err == nil {
1686		t.Fatal("should not be allowed to drop an index that does not exist")
1687	}
1688	// test retrieving index names
1689	names, err := db.Indexes()
1690	if err != nil {
1691		t.Fatal(err)
1692	}
1693	if strings.Join(names, ",") != "rect,string" {
1694		t.Fatalf("expecting '%v', got '%v'", "rect,string", strings.Join(names, ","))
1695	}
1696	// test creating an index after closing database
1697	if err := db.Close(); err != nil {
1698		t.Fatal(err)
1699	}
1700	if err := db.CreateIndex("new-index", "", nil); err != ErrDatabaseClosed {
1701		t.Fatal("should not be able to create an index on a closed database")
1702	}
1703	// test getting index names after closing database
1704	if _, err := db.Indexes(); err != ErrDatabaseClosed {
1705		t.Fatal("should not be able to get index names on a closed database")
1706	}
1707	// test dropping an index after closing database
1708	if err := db.DropIndex("rect"); err != ErrDatabaseClosed {
1709		t.Fatal("should not be able to drop an index on a closed database")
1710	}
1711}
1712
1713func test(t *testing.T, a, b bool) {
1714	if a != b {
1715		t.Fatal("failed, bummer...")
1716	}
1717}
1718
1719func TestBasic(t *testing.T) {
1720	rand.Seed(time.Now().UnixNano())
1721	db := testOpen(t)
1722	defer testClose(db)
1723
1724	// create a simple index
1725	if err := db.CreateIndex("users", "fun:user:*", IndexString); err != nil {
1726		t.Fatal(err)
1727	}
1728
1729	// create a spatial index
1730	if err := db.CreateSpatialIndex("rects", "rect:*", IndexRect); err != nil {
1731		t.Fatal(err)
1732	}
1733	if true {
1734		err := db.Update(func(tx *Tx) error {
1735			if _, _, err := tx.Set("fun:user:0", "tom", nil); err != nil {
1736				return err
1737			}
1738			if _, _, err := tx.Set("fun:user:1", "Randi", nil); err != nil {
1739				return err
1740			}
1741			if _, _, err := tx.Set("fun:user:2", "jane", nil); err != nil {
1742				return err
1743			}
1744			if _, _, err := tx.Set("fun:user:4", "Janet", nil); err != nil {
1745				return err
1746			}
1747			if _, _, err := tx.Set("fun:user:5", "Paula", nil); err != nil {
1748				return err
1749			}
1750			if _, _, err := tx.Set("fun:user:6", "peter", nil); err != nil {
1751				return err
1752			}
1753			if _, _, err := tx.Set("fun:user:7", "Terri", nil); err != nil {
1754				return err
1755			}
1756			return nil
1757		})
1758		if err != nil {
1759			t.Fatal(err)
1760		}
1761		// add some random items
1762		start := time.Now()
1763		if err := db.Update(func(tx *Tx) error {
1764			for _, i := range rand.Perm(100) {
1765				if _, _, err := tx.Set(fmt.Sprintf("tag:%d", i+100), fmt.Sprintf("val:%d", rand.Int()%100+100), nil); err != nil {
1766					return err
1767				}
1768			}
1769			return nil
1770		}); err != nil {
1771			t.Fatal(err)
1772		}
1773		if false {
1774			println(time.Now().Sub(start).String(), db.keys.Len())
1775		}
1776		// add some random rects
1777		if err := db.Update(func(tx *Tx) error {
1778			if _, _, err := tx.Set("rect:1", Rect([]float64{10, 10}, []float64{20, 20}), nil); err != nil {
1779				return err
1780			}
1781			if _, _, err := tx.Set("rect:2", Rect([]float64{15, 15}, []float64{24, 24}), nil); err != nil {
1782				return err
1783			}
1784			if _, _, err := tx.Set("rect:3", Rect([]float64{17, 17}, []float64{27, 27}), nil); err != nil {
1785				return err
1786			}
1787			return nil
1788		}); err != nil {
1789			t.Fatal(err)
1790		}
1791	}
1792	// verify the data has been created
1793	buf := &bytes.Buffer{}
1794	err := db.View(func(tx *Tx) error {
1795		err := tx.Ascend("users", func(key, val string) bool {
1796			fmt.Fprintf(buf, "%s %s\n", key, val)
1797			return true
1798		})
1799		if err != nil {
1800			t.Fatal(err)
1801		}
1802		err = tx.AscendRange("", "tag:170", "tag:172", func(key, val string) bool {
1803			fmt.Fprintf(buf, "%s\n", key)
1804			return true
1805		})
1806		if err != nil {
1807			t.Fatal(err)
1808		}
1809		err = tx.AscendGreaterOrEqual("", "tag:195", func(key, val string) bool {
1810			fmt.Fprintf(buf, "%s\n", key)
1811			return true
1812		})
1813		if err != nil {
1814			t.Fatal(err)
1815		}
1816		err = tx.AscendGreaterOrEqual("", "rect:", func(key, val string) bool {
1817			if !strings.HasPrefix(key, "rect:") {
1818				return false
1819			}
1820			min, max := IndexRect(val)
1821			fmt.Fprintf(buf, "%s: %v,%v\n", key, min, max)
1822			return true
1823		})
1824		expect := make([]string, 2)
1825		n := 0
1826		err = tx.Intersects("rects", "[0 0],[15 15]", func(key, val string) bool {
1827			if n == 2 {
1828				t.Fatalf("too many rects where received, expecting only two")
1829			}
1830			min, max := IndexRect(val)
1831			s := fmt.Sprintf("%s: %v,%v\n", key, min, max)
1832			if key == "rect:1" {
1833				expect[0] = s
1834			} else if key == "rect:2" {
1835				expect[1] = s
1836			}
1837			n++
1838			return true
1839		})
1840		if err != nil {
1841			t.Fatal(err)
1842		}
1843		for _, s := range expect {
1844			if _, err := buf.WriteString(s); err != nil {
1845				return err
1846			}
1847		}
1848		return nil
1849	})
1850	if err != nil {
1851		t.Fatal(err)
1852	}
1853	res := `
1854fun:user:2 jane
1855fun:user:4 Janet
1856fun:user:5 Paula
1857fun:user:6 peter
1858fun:user:1 Randi
1859fun:user:7 Terri
1860fun:user:0 tom
1861tag:170
1862tag:171
1863tag:195
1864tag:196
1865tag:197
1866tag:198
1867tag:199
1868rect:1: [10 10],[20 20]
1869rect:2: [15 15],[24 24]
1870rect:3: [17 17],[27 27]
1871rect:1: [10 10],[20 20]
1872rect:2: [15 15],[24 24]
1873`
1874	res = strings.Replace(res, "\r", "", -1)
1875	if strings.TrimSpace(buf.String()) != strings.TrimSpace(res) {
1876		t.Fatalf("expected [%v], got [%v]", strings.TrimSpace(res), strings.TrimSpace(buf.String()))
1877	}
1878}
1879
1880func TestIndexAscend(t *testing.T) {
1881	rand.Seed(time.Now().UnixNano())
1882	db := testOpen(t)
1883	defer testClose(db)
1884
1885	// create a simple index
1886	if err := db.CreateIndex("usr", "usr:*", IndexInt); err != nil {
1887		t.Fatal(err)
1888	}
1889	if err := db.Update(func(tx *Tx) error {
1890		for i := 10; i > 0; i-- {
1891			tx.Set(fmt.Sprintf("usr:%d", i), fmt.Sprintf("%d", 10-i), nil)
1892		}
1893		return nil
1894	}); err != nil {
1895		t.Fatal(err)
1896	}
1897
1898	buf := &bytes.Buffer{}
1899	err := db.View(func(tx *Tx) error {
1900		tx.Ascend("usr", func(key, value string) bool {
1901			fmt.Fprintf(buf, "%s %s\n", key, value)
1902			return true
1903		})
1904		fmt.Fprintln(buf)
1905
1906		tx.AscendGreaterOrEqual("usr", "8", func(key, value string) bool {
1907			fmt.Fprintf(buf, "%s %s\n", key, value)
1908			return true
1909		})
1910		fmt.Fprintln(buf)
1911
1912		tx.AscendLessThan("usr", "3", func(key, value string) bool {
1913			fmt.Fprintf(buf, "%s %s\n", key, value)
1914			return true
1915		})
1916		fmt.Fprintln(buf)
1917
1918		tx.AscendRange("usr", "4", "8", func(key, value string) bool {
1919			fmt.Fprintf(buf, "%s %s\n", key, value)
1920			return true
1921		})
1922		return nil
1923	})
1924
1925	if err != nil {
1926		t.Fatal(err)
1927	}
1928
1929	res := `
1930usr:10 0
1931usr:9 1
1932usr:8 2
1933usr:7 3
1934usr:6 4
1935usr:5 5
1936usr:4 6
1937usr:3 7
1938usr:2 8
1939usr:1 9
1940
1941usr:2 8
1942usr:1 9
1943
1944usr:10 0
1945usr:9 1
1946usr:8 2
1947
1948usr:6 4
1949usr:5 5
1950usr:4 6
1951usr:3 7
1952`
1953	res = strings.Replace(res, "\r", "", -1)
1954	s1 := strings.TrimSpace(buf.String())
1955	s2 := strings.TrimSpace(res)
1956	if s1 != s2 {
1957		t.Fatalf("expected [%v], got [%v]", s1, s2)
1958	}
1959}
1960
1961func testRectStringer(min, max []float64) error {
1962	nmin, nmax := IndexRect(Rect(min, max))
1963	if len(nmin) != len(min) {
1964		return fmt.Errorf("rect=%v,%v, expect=%v,%v", nmin, nmax, min, max)
1965	}
1966	for i := 0; i < len(min); i++ {
1967		if min[i] != nmin[i] || max[i] != nmax[i] {
1968			return fmt.Errorf("rect=%v,%v, expect=%v,%v", nmin, nmax, min, max)
1969		}
1970	}
1971	return nil
1972}
1973func TestRectStrings(t *testing.T) {
1974	test(t, Rect(IndexRect(Point(1))) == "[1]", true)
1975	test(t, Rect(IndexRect(Point(1, 2, 3, 4))) == "[1 2 3 4]", true)
1976	test(t, Rect(IndexRect(Rect(IndexRect("[1 2],[1 2]")))) == "[1 2]", true)
1977	test(t, Rect(IndexRect(Rect(IndexRect("[1 2],[2 2]")))) == "[1 2],[2 2]", true)
1978	test(t, Rect(IndexRect(Rect(IndexRect("[1 2],[2 2],[3]")))) == "[1 2],[2 2]", true)
1979	test(t, Rect(IndexRect(Rect(IndexRect("[1 2]")))) == "[1 2]", true)
1980	test(t, Rect(IndexRect(Rect(IndexRect("[1.5 2 4.5 5.6]")))) == "[1.5 2 4.5 5.6]", true)
1981	test(t, Rect(IndexRect(Rect(IndexRect("[1.5 2 4.5 5.6 -1],[]")))) == "[1.5 2 4.5 5.6 -1]", true)
1982	test(t, Rect(IndexRect(Rect(IndexRect("[]")))) == "[]", true)
1983	test(t, Rect(IndexRect(Rect(IndexRect("")))) == "[]", true)
1984	if err := testRectStringer(nil, nil); err != nil {
1985		t.Fatal(err)
1986	}
1987	if err := testRectStringer([]float64{}, []float64{}); err != nil {
1988		t.Fatal(err)
1989	}
1990	if err := testRectStringer([]float64{1}, []float64{2}); err != nil {
1991		t.Fatal(err)
1992	}
1993	if err := testRectStringer([]float64{1, 2}, []float64{3, 4}); err != nil {
1994		t.Fatal(err)
1995	}
1996	if err := testRectStringer([]float64{1, 2, 3}, []float64{4, 5, 6}); err != nil {
1997		t.Fatal(err)
1998	}
1999	if err := testRectStringer([]float64{1, 2, 3, 4}, []float64{5, 6, 7, 8}); err != nil {
2000		t.Fatal(err)
2001	}
2002	if err := testRectStringer([]float64{1, 2, 3, 4, 5}, []float64{6, 7, 8, 9, 10}); err != nil {
2003		t.Fatal(err)
2004	}
2005}
2006
2007// TestTTLReOpen test setting a TTL and then immediately closing the database and
2008// then waiting the TTL before reopening. The key should not be accessible.
2009func TestTTLReOpen(t *testing.T) {
2010	ttl := time.Second * 3
2011	db := testOpen(t)
2012	defer testClose(db)
2013	err := db.Update(func(tx *Tx) error {
2014		if _, _, err := tx.Set("key1", "val1", &SetOptions{Expires: true, TTL: ttl}); err != nil {
2015			return err
2016		}
2017		return nil
2018	})
2019	if err != nil {
2020		t.Fatal(err)
2021	}
2022	db = testReOpenDelay(t, db, ttl/4)
2023	err = db.View(func(tx *Tx) error {
2024		val, err := tx.Get("key1")
2025		if err != nil {
2026			return err
2027		}
2028		if val != "val1" {
2029			t.Fatalf("expecting '%v', got '%v'", "val1", val)
2030		}
2031		return nil
2032	})
2033	if err != nil {
2034		t.Fatal(err)
2035	}
2036	db = testReOpenDelay(t, db, ttl-ttl/4)
2037	defer testClose(db)
2038	err = db.View(func(tx *Tx) error {
2039		val, err := tx.Get("key1")
2040		if err == nil || err != ErrNotFound || val != "" {
2041			t.Fatal("expecting not found")
2042		}
2043
2044		return nil
2045	})
2046	if err != nil {
2047		t.Fatal(err)
2048	}
2049}
2050
2051func TestTTL(t *testing.T) {
2052	db := testOpen(t)
2053	defer testClose(db)
2054	err := db.Update(func(tx *Tx) error {
2055		if _, _, err := tx.Set("key1", "val1", &SetOptions{Expires: true, TTL: time.Second}); err != nil {
2056			return err
2057		}
2058		if _, _, err := tx.Set("key2", "val2", nil); err != nil {
2059			return err
2060		}
2061		return nil
2062	})
2063	if err != nil {
2064		t.Fatal(err)
2065	}
2066	err = db.View(func(tx *Tx) error {
2067		dur1, err := tx.TTL("key1")
2068		if err != nil {
2069			t.Fatal(err)
2070		}
2071		if dur1 > time.Second || dur1 <= 0 {
2072			t.Fatalf("expecting between zero and one second, got '%v'", dur1)
2073		}
2074		dur1, err = tx.TTL("key2")
2075		if err != nil {
2076			t.Fatal(err)
2077		}
2078		if dur1 >= 0 {
2079			t.Fatalf("expecting a negative value, got '%v'", dur1)
2080		}
2081		return nil
2082	})
2083	if err != nil {
2084		t.Fatal(err)
2085	}
2086}
2087
2088func TestConfig(t *testing.T) {
2089	db := testOpen(t)
2090	defer testClose(db)
2091
2092	err := db.SetConfig(Config{SyncPolicy: SyncPolicy(-1)})
2093	if err == nil {
2094		t.Fatal("expecting a config syncpolicy error")
2095	}
2096	err = db.SetConfig(Config{SyncPolicy: SyncPolicy(3)})
2097	if err == nil {
2098		t.Fatal("expecting a config syncpolicy error")
2099	}
2100	err = db.SetConfig(Config{SyncPolicy: Never})
2101	if err != nil {
2102		t.Fatal(err)
2103	}
2104	err = db.SetConfig(Config{SyncPolicy: EverySecond})
2105	if err != nil {
2106		t.Fatal(err)
2107	}
2108	err = db.SetConfig(Config{AutoShrinkMinSize: 100, AutoShrinkPercentage: 200, SyncPolicy: Always})
2109	if err != nil {
2110		t.Fatal(err)
2111	}
2112
2113	var c Config
2114	if err := db.ReadConfig(&c); err != nil {
2115		t.Fatal(err)
2116	}
2117	if c.AutoShrinkMinSize != 100 || c.AutoShrinkPercentage != 200 && c.SyncPolicy != Always {
2118		t.Fatalf("expecting %v, %v, and %v, got %v, %v, and %v", 100, 200, Always, c.AutoShrinkMinSize, c.AutoShrinkPercentage, c.SyncPolicy)
2119	}
2120}
2121func testUint64Hex(n uint64) string {
2122	s := strconv.FormatUint(n, 16)
2123	s = "0000000000000000" + s
2124	return s[len(s)-16:]
2125}
2126func textHexUint64(s string) uint64 {
2127	n, _ := strconv.ParseUint(s, 16, 64)
2128	return n
2129}
2130func benchClose(t *testing.B, persist bool, db *DB) {
2131	if persist {
2132		if err := os.RemoveAll("data.db"); err != nil {
2133			t.Fatal(err)
2134		}
2135	}
2136	if err := db.Close(); err != nil {
2137		t.Fatal(err)
2138	}
2139}
2140
2141func benchOpenFillData(t *testing.B, N int,
2142	set, persist, random bool,
2143	geo bool,
2144	batch int) (db *DB, keys, vals []string) {
2145	///
2146	t.StopTimer()
2147	rand.Seed(time.Now().UnixNano())
2148	var err error
2149	if persist {
2150		if err := os.RemoveAll("data.db"); err != nil {
2151			t.Fatal(err)
2152		}
2153		db, err = Open("data.db")
2154	} else {
2155		db, err = Open(":memory:")
2156	}
2157	if err != nil {
2158		t.Fatal(err)
2159	}
2160	keys = make([]string, N)
2161	vals = make([]string, N)
2162	perm := rand.Perm(N)
2163	for i := 0; i < N; i++ {
2164		if random && set {
2165			keys[perm[i]] = testUint64Hex(uint64(i))
2166			vals[perm[i]] = strconv.FormatInt(rand.Int63()%1000+1000, 10)
2167		} else {
2168			keys[i] = testUint64Hex(uint64(i))
2169			vals[i] = strconv.FormatInt(rand.Int63()%1000+1000, 10)
2170		}
2171	}
2172	if set {
2173		t.StartTimer()
2174	}
2175	for i := 0; i < N; {
2176		err := db.Update(func(tx *Tx) error {
2177			var err error
2178			for j := 0; j < batch && i < N; j++ {
2179				_, _, err = tx.Set(keys[i], vals[i], nil)
2180				i++
2181			}
2182			return err
2183		})
2184		if err != nil {
2185			t.Fatal(err)
2186		}
2187	}
2188	if set {
2189		t.StopTimer()
2190	}
2191	var n uint64
2192	err = db.View(func(tx *Tx) error {
2193		err := tx.Ascend("", func(key, value string) bool {
2194			n2 := textHexUint64(key)
2195			if n2 != n {
2196				t.Fatalf("expecting '%v', got '%v'", n2, n)
2197			}
2198			n++
2199			return true
2200		})
2201		return err
2202	})
2203	if err != nil {
2204		t.Fatal(err)
2205	}
2206	if n != uint64(N) {
2207		t.Fatalf("expecting '%v', got '%v'", N, n)
2208	}
2209	t.StartTimer()
2210	return db, keys, vals
2211}
2212
2213func benchSetGet(t *testing.B, set, persist, random bool, batch int) {
2214	N := t.N
2215	for N > 0 {
2216		n := 0
2217		if N >= 100000 {
2218			n = 100000
2219		} else {
2220			n = N
2221		}
2222		func() {
2223			db, keys, _ := benchOpenFillData(t, n, set, persist, random, false, batch)
2224			defer benchClose(t, persist, db)
2225			if !set {
2226				for i := 0; i < n; {
2227					err := db.View(func(tx *Tx) error {
2228						var err error
2229						for j := 0; j < batch && i < n; j++ {
2230							_, err = tx.Get(keys[i])
2231							i++
2232						}
2233						return err
2234					})
2235					if err != nil {
2236						t.Fatal(err)
2237					}
2238				}
2239			}
2240		}()
2241		N -= n
2242	}
2243}
2244
2245// Set Persist
2246func Benchmark_Set_Persist_Random_1(t *testing.B) {
2247	benchSetGet(t, true, true, true, 1)
2248}
2249func Benchmark_Set_Persist_Random_10(t *testing.B) {
2250	benchSetGet(t, true, true, true, 10)
2251}
2252func Benchmark_Set_Persist_Random_100(t *testing.B) {
2253	benchSetGet(t, true, true, true, 100)
2254}
2255func Benchmark_Set_Persist_Sequential_1(t *testing.B) {
2256	benchSetGet(t, true, true, false, 1)
2257}
2258func Benchmark_Set_Persist_Sequential_10(t *testing.B) {
2259	benchSetGet(t, true, true, false, 10)
2260}
2261func Benchmark_Set_Persist_Sequential_100(t *testing.B) {
2262	benchSetGet(t, true, true, false, 100)
2263}
2264
2265// Set NoPersist
2266func Benchmark_Set_NoPersist_Random_1(t *testing.B) {
2267	benchSetGet(t, true, false, true, 1)
2268}
2269func Benchmark_Set_NoPersist_Random_10(t *testing.B) {
2270	benchSetGet(t, true, false, true, 10)
2271}
2272func Benchmark_Set_NoPersist_Random_100(t *testing.B) {
2273	benchSetGet(t, true, false, true, 100)
2274}
2275func Benchmark_Set_NoPersist_Sequential_1(t *testing.B) {
2276	benchSetGet(t, true, false, false, 1)
2277}
2278func Benchmark_Set_NoPersist_Sequential_10(t *testing.B) {
2279	benchSetGet(t, true, false, false, 10)
2280}
2281func Benchmark_Set_NoPersist_Sequential_100(t *testing.B) {
2282	benchSetGet(t, true, false, false, 100)
2283}
2284
2285// Get
2286func Benchmark_Get_1(t *testing.B) {
2287	benchSetGet(t, false, false, false, 1)
2288}
2289func Benchmark_Get_10(t *testing.B) {
2290	benchSetGet(t, false, false, false, 10)
2291}
2292func Benchmark_Get_100(t *testing.B) {
2293	benchSetGet(t, false, false, false, 100)
2294}
2295
2296func benchScan(t *testing.B, asc bool, count int) {
2297	N := count
2298	db, _, _ := benchOpenFillData(t, N, false, false, false, false, 100)
2299	defer benchClose(t, false, db)
2300	for i := 0; i < t.N; i++ {
2301		count := 0
2302		err := db.View(func(tx *Tx) error {
2303			if asc {
2304				return tx.Ascend("", func(key, val string) bool {
2305					count++
2306					return true
2307				})
2308			}
2309			return tx.Descend("", func(key, val string) bool {
2310				count++
2311				return true
2312			})
2313
2314		})
2315		if err != nil {
2316			t.Fatal(err)
2317		}
2318		if count != N {
2319			t.Fatalf("expecting '%v', got '%v'", N, count)
2320		}
2321	}
2322}
2323
2324func Benchmark_Ascend_1(t *testing.B) {
2325	benchScan(t, true, 1)
2326}
2327func Benchmark_Ascend_10(t *testing.B) {
2328	benchScan(t, true, 10)
2329}
2330func Benchmark_Ascend_100(t *testing.B) {
2331	benchScan(t, true, 100)
2332}
2333func Benchmark_Ascend_1000(t *testing.B) {
2334	benchScan(t, true, 1000)
2335}
2336func Benchmark_Ascend_10000(t *testing.B) {
2337	benchScan(t, true, 10000)
2338}
2339
2340func Benchmark_Descend_1(t *testing.B) {
2341	benchScan(t, false, 1)
2342}
2343func Benchmark_Descend_10(t *testing.B) {
2344	benchScan(t, false, 10)
2345}
2346func Benchmark_Descend_100(t *testing.B) {
2347	benchScan(t, false, 100)
2348}
2349func Benchmark_Descend_1000(t *testing.B) {
2350	benchScan(t, false, 1000)
2351}
2352func Benchmark_Descend_10000(t *testing.B) {
2353	benchScan(t, false, 10000)
2354}
2355
2356/*
2357func Benchmark_Spatial_2D(t *testing.B) {
2358	N := 100000
2359	db, _, _ := benchOpenFillData(t, N, true, true, false, true, 100)
2360	defer benchClose(t, false, db)
2361
2362}
2363*/
2364func TestCoverCloseAlreadyClosed(t *testing.T) {
2365	db := testOpen(t)
2366	defer testClose(db)
2367	_ = db.file.Close()
2368	if err := db.Close(); err == nil {
2369		t.Fatal("expecting an error")
2370	}
2371}
2372
2373func TestCoverConfigClosed(t *testing.T) {
2374	db := testOpen(t)
2375	defer testClose(db)
2376	_ = db.Close()
2377	var config Config
2378	if err := db.ReadConfig(&config); err != ErrDatabaseClosed {
2379		t.Fatal("expecting database closed error")
2380	}
2381	if err := db.SetConfig(config); err != ErrDatabaseClosed {
2382		t.Fatal("expecting database closed error")
2383	}
2384}
2385func TestCoverShrinkShrink(t *testing.T) {
2386	db := testOpen(t)
2387	defer testClose(db)
2388	if err := db.Update(func(tx *Tx) error {
2389		for i := 0; i < 10000; i++ {
2390			_, _, err := tx.Set(fmt.Sprintf("%d", i), fmt.Sprintf("%d", i), nil)
2391			if err != nil {
2392				return err
2393			}
2394		}
2395		return nil
2396	}); err != nil {
2397		t.Fatal(err)
2398	}
2399	if err := db.Update(func(tx *Tx) error {
2400		for i := 250; i < 250+100; i++ {
2401			_, err := tx.Delete(fmt.Sprintf("%d", i))
2402			if err != nil {
2403				return err
2404			}
2405		}
2406		return nil
2407	}); err != nil {
2408		t.Fatal(err)
2409	}
2410	var err1, err2 error
2411	var wg sync.WaitGroup
2412	wg.Add(2)
2413	go func() {
2414		defer wg.Done()
2415		err1 = db.Shrink()
2416	}()
2417	go func() {
2418		defer wg.Done()
2419		err2 = db.Shrink()
2420	}()
2421	wg.Wait()
2422	//println(123)
2423	//fmt.Printf("%v\n%v\n", err1, err2)
2424	if err1 != ErrShrinkInProcess && err2 != ErrShrinkInProcess {
2425		t.Fatal("expecting a shrink in process error")
2426	}
2427	db = testReOpen(t, db)
2428	defer testClose(db)
2429	if err := db.View(func(tx *Tx) error {
2430		n, err := tx.Len()
2431		if err != nil {
2432			return err
2433		}
2434		if n != 9900 {
2435			t.Fatal("expecting 9900 items")
2436		}
2437		return nil
2438	}); err != nil {
2439		t.Fatal(err)
2440	}
2441}
2442
2443func TestPreviousItem(t *testing.T) {
2444	db := testOpen(t)
2445	defer testClose(db)
2446	err := db.Update(func(tx *Tx) error {
2447		_, _, err := tx.Set("hello", "world", nil)
2448		if err != nil {
2449			return err
2450		}
2451		prev, replaced, err := tx.Set("hello", "planet", nil)
2452		if err != nil {
2453			return err
2454		}
2455		if !replaced {
2456			t.Fatal("should be replaced")
2457		}
2458		if prev != "world" {
2459			t.Fatalf("expecting '%v', got '%v'", "world", prev)
2460		}
2461		return nil
2462	})
2463	if err != nil {
2464		t.Fatal(err)
2465	}
2466}
2467
2468func TestJSONIndex(t *testing.T) {
2469	db := testOpen(t)
2470	defer testClose(db)
2471
2472	_ = db.CreateIndex("last_name", "*", IndexJSON("name.last"))
2473	_ = db.CreateIndex("last_name_cs", "*", IndexJSONCaseSensitive("name.last"))
2474	_ = db.CreateIndex("age", "*", IndexJSON("age"))
2475	_ = db.CreateIndex("student", "*", IndexJSON("student"))
2476	_ = db.Update(func(tx *Tx) error {
2477		_, _, _ = tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38,"student":false}`, nil)
2478		_, _, _ = tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47,"student":true}`, nil)
2479		_, _, _ = tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52,"student":true}`, nil)
2480		_, _, _ = tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28,"student":false}`, nil)
2481		_, _, _ = tx.Set("5", `{"name":{"first":"bill","last":"frank"},"age":21,"student":true}`, nil)
2482		_, _, _ = tx.Set("6", `{"name":{"first":"sally","last":"randall"},"age":68,"student":false}`, nil)
2483		return nil
2484	})
2485	var keys []string
2486	_ = db.View(func(tx *Tx) error {
2487		_ = tx.Ascend("last_name_cs", func(key, value string) bool {
2488			//fmt.Printf("%s: %s\n", key, value)
2489			keys = append(keys, key)
2490			return true
2491		})
2492		_ = tx.Ascend("last_name", func(key, value string) bool {
2493			//fmt.Printf("%s: %s\n", key, value)
2494			keys = append(keys, key)
2495			return true
2496		})
2497		_ = tx.Ascend("age", func(key, value string) bool {
2498			//fmt.Printf("%s: %s\n", key, value)
2499			keys = append(keys, key)
2500			return true
2501		})
2502		_ = tx.Ascend("student", func(key, value string) bool {
2503			//fmt.Printf("%s: %s\n", key, value)
2504			keys = append(keys, key)
2505			return true
2506		})
2507		return nil
2508	})
2509	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"
2510	if strings.Join(keys, ",") != expect {
2511		t.Fatalf("expected %v, got %v", expect, strings.Join(keys, ","))
2512	}
2513}
2514