github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/testutil/db.go (about)

     1  // Copyright (c) 2014, Suryandaru Triandana <syndtr@gmail.com>
     2  // All rights reserved.
     3  //
     4  // Use of this source code is governed by a BSD-style license that can be
     5  // found in the LICENSE file.
     6  
     7  package testutil
     8  
     9  import (
    10  	"fmt"
    11  	"math/rand"
    12  
    13  	. "github.com/insionng/yougam/libraries/onsi/gomega"
    14  
    15  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors"
    16  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/iterator"
    17  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/util"
    18  )
    19  
    20  type DB interface{}
    21  
    22  type Put interface {
    23  	TestPut(key []byte, value []byte) error
    24  }
    25  
    26  type Delete interface {
    27  	TestDelete(key []byte) error
    28  }
    29  
    30  type Find interface {
    31  	TestFind(key []byte) (rkey, rvalue []byte, err error)
    32  }
    33  
    34  type Get interface {
    35  	TestGet(key []byte) (value []byte, err error)
    36  }
    37  
    38  type Has interface {
    39  	TestHas(key []byte) (ret bool, err error)
    40  }
    41  
    42  type NewIterator interface {
    43  	TestNewIterator(slice *util.Range) iterator.Iterator
    44  }
    45  
    46  type DBAct int
    47  
    48  func (a DBAct) String() string {
    49  	switch a {
    50  	case DBNone:
    51  		return "none"
    52  	case DBPut:
    53  		return "put"
    54  	case DBOverwrite:
    55  		return "overwrite"
    56  	case DBDelete:
    57  		return "delete"
    58  	case DBDeleteNA:
    59  		return "delete_na"
    60  	}
    61  	return "unknown"
    62  }
    63  
    64  const (
    65  	DBNone DBAct = iota
    66  	DBPut
    67  	DBOverwrite
    68  	DBDelete
    69  	DBDeleteNA
    70  )
    71  
    72  type DBTesting struct {
    73  	Rand *rand.Rand
    74  	DB   interface {
    75  		Get
    76  		Put
    77  		Delete
    78  	}
    79  	PostFn             func(t *DBTesting)
    80  	Deleted, Present   KeyValue
    81  	Act, LastAct       DBAct
    82  	ActKey, LastActKey []byte
    83  }
    84  
    85  func (t *DBTesting) post() {
    86  	if t.PostFn != nil {
    87  		t.PostFn(t)
    88  	}
    89  }
    90  
    91  func (t *DBTesting) setAct(act DBAct, key []byte) {
    92  	t.LastAct, t.Act = t.Act, act
    93  	t.LastActKey, t.ActKey = t.ActKey, key
    94  }
    95  
    96  func (t *DBTesting) text() string {
    97  	return fmt.Sprintf("last action was <%v> %q, <%v> %q", t.LastAct, t.LastActKey, t.Act, t.ActKey)
    98  }
    99  
   100  func (t *DBTesting) Text() string {
   101  	return "DBTesting " + t.text()
   102  }
   103  
   104  func (t *DBTesting) TestPresentKV(key, value []byte) {
   105  	rvalue, err := t.DB.TestGet(key)
   106  	Expect(err).ShouldNot(HaveOccurred(), "Get on key %q, %s", key, t.text())
   107  	Expect(rvalue).Should(Equal(value), "Value for key %q, %s", key, t.text())
   108  }
   109  
   110  func (t *DBTesting) TestAllPresent() {
   111  	t.Present.IterateShuffled(t.Rand, func(i int, key, value []byte) {
   112  		t.TestPresentKV(key, value)
   113  	})
   114  }
   115  
   116  func (t *DBTesting) TestDeletedKey(key []byte) {
   117  	_, err := t.DB.TestGet(key)
   118  	Expect(err).Should(Equal(errors.ErrNotFound), "Get on deleted key %q, %s", key, t.text())
   119  }
   120  
   121  func (t *DBTesting) TestAllDeleted() {
   122  	t.Deleted.IterateShuffled(t.Rand, func(i int, key, value []byte) {
   123  		t.TestDeletedKey(key)
   124  	})
   125  }
   126  
   127  func (t *DBTesting) TestAll() {
   128  	dn := t.Deleted.Len()
   129  	pn := t.Present.Len()
   130  	ShuffledIndex(t.Rand, dn+pn, 1, func(i int) {
   131  		if i >= dn {
   132  			key, value := t.Present.Index(i - dn)
   133  			t.TestPresentKV(key, value)
   134  		} else {
   135  			t.TestDeletedKey(t.Deleted.KeyAt(i))
   136  		}
   137  	})
   138  }
   139  
   140  func (t *DBTesting) Put(key, value []byte) {
   141  	if new := t.Present.PutU(key, value); new {
   142  		t.setAct(DBPut, key)
   143  	} else {
   144  		t.setAct(DBOverwrite, key)
   145  	}
   146  	t.Deleted.Delete(key)
   147  	err := t.DB.TestPut(key, value)
   148  	Expect(err).ShouldNot(HaveOccurred(), t.Text())
   149  	t.TestPresentKV(key, value)
   150  	t.post()
   151  }
   152  
   153  func (t *DBTesting) PutRandom() bool {
   154  	if t.Deleted.Len() > 0 {
   155  		i := t.Rand.Intn(t.Deleted.Len())
   156  		key, value := t.Deleted.Index(i)
   157  		t.Put(key, value)
   158  		return true
   159  	}
   160  	return false
   161  }
   162  
   163  func (t *DBTesting) Delete(key []byte) {
   164  	if exist, value := t.Present.Delete(key); exist {
   165  		t.setAct(DBDelete, key)
   166  		t.Deleted.PutU(key, value)
   167  	} else {
   168  		t.setAct(DBDeleteNA, key)
   169  	}
   170  	err := t.DB.TestDelete(key)
   171  	Expect(err).ShouldNot(HaveOccurred(), t.Text())
   172  	t.TestDeletedKey(key)
   173  	t.post()
   174  }
   175  
   176  func (t *DBTesting) DeleteRandom() bool {
   177  	if t.Present.Len() > 0 {
   178  		i := t.Rand.Intn(t.Present.Len())
   179  		t.Delete(t.Present.KeyAt(i))
   180  		return true
   181  	}
   182  	return false
   183  }
   184  
   185  func (t *DBTesting) RandomAct(round int) {
   186  	for i := 0; i < round; i++ {
   187  		if t.Rand.Int()%2 == 0 {
   188  			t.PutRandom()
   189  		} else {
   190  			t.DeleteRandom()
   191  		}
   192  	}
   193  }
   194  
   195  func DoDBTesting(t *DBTesting) {
   196  	if t.Rand == nil {
   197  		t.Rand = NewRand()
   198  	}
   199  
   200  	t.DeleteRandom()
   201  	t.PutRandom()
   202  	t.DeleteRandom()
   203  	t.DeleteRandom()
   204  	for i := t.Deleted.Len() / 2; i >= 0; i-- {
   205  		t.PutRandom()
   206  	}
   207  	t.RandomAct((t.Deleted.Len() + t.Present.Len()) * 10)
   208  
   209  	// Additional iterator testing
   210  	if db, ok := t.DB.(NewIterator); ok {
   211  		iter := db.TestNewIterator(nil)
   212  		Expect(iter.Error()).NotTo(HaveOccurred())
   213  
   214  		it := IteratorTesting{
   215  			KeyValue: t.Present,
   216  			Iter:     iter,
   217  		}
   218  
   219  		DoIteratorTesting(&it)
   220  		iter.Release()
   221  	}
   222  }