github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/ldbstore_test.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package storage
    26  
    27  import (
    28  	"bytes"
    29  	"context"
    30  	"fmt"
    31  	"io/ioutil"
    32  	"os"
    33  	"sync"
    34  	"testing"
    35  	"time"
    36  
    37  	"github.com/ethereum/go-ethereum/common"
    38  	"github.com/ethereum/go-ethereum/swarm/chunk"
    39  	"github.com/ethereum/go-ethereum/swarm/log"
    40  	"github.com/ethereum/go-ethereum/swarm/storage/mock/mem"
    41  
    42  	ldberrors "github.com/syndtr/goleveldb/leveldb/errors"
    43  )
    44  
    45  type testDbStore struct {
    46  	*LDBStore
    47  	dir string
    48  }
    49  
    50  func newTestDbStore(mock bool, trusted bool) (*testDbStore, func(), error) {
    51  	dir, err := ioutil.TempDir("", "bzz-storage-test")
    52  	if err != nil {
    53  		return nil, func() {}, err
    54  	}
    55  
    56  	var db *LDBStore
    57  	storeparams := NewDefaultStoreParams()
    58  	params := NewLDBStoreParams(storeparams, dir)
    59  	params.Po = testPoFunc
    60  
    61  	if mock {
    62  		globalStore := mem.NewGlobalStore()
    63  		addr := common.HexToAddress("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")
    64  		mockStore := globalStore.NewNodeStore(addr)
    65  
    66  		db, err = NewMockDbStore(params, mockStore)
    67  	} else {
    68  		db, err = NewLDBStore(params)
    69  	}
    70  
    71  	cleanup := func() {
    72  		if db != nil {
    73  			db.Close()
    74  		}
    75  		err = os.RemoveAll(dir)
    76  		if err != nil {
    77  			panic(fmt.Sprintf("db cleanup failed: %v", err))
    78  		}
    79  	}
    80  
    81  	return &testDbStore{db, dir}, cleanup, err
    82  }
    83  
    84  func testPoFunc(k Address) (ret uint8) {
    85  	basekey := make([]byte, 32)
    86  	return uint8(Proximity(basekey[:], k[:]))
    87  }
    88  
    89  func (db *testDbStore) close() {
    90  	db.Close()
    91  	err := os.RemoveAll(db.dir)
    92  	if err != nil {
    93  		panic(err)
    94  	}
    95  }
    96  
    97  func testDbStoreRandom(n int, processors int, chunksize int64, mock bool, t *testing.T) {
    98  	db, cleanup, err := newTestDbStore(mock, true)
    99  	defer cleanup()
   100  	if err != nil {
   101  		t.Fatalf("init dbStore failed: %v", err)
   102  	}
   103  	testStoreRandom(db, processors, n, chunksize, t)
   104  }
   105  
   106  func testDbStoreCorrect(n int, processors int, chunksize int64, mock bool, t *testing.T) {
   107  	db, cleanup, err := newTestDbStore(mock, false)
   108  	defer cleanup()
   109  	if err != nil {
   110  		t.Fatalf("init dbStore failed: %v", err)
   111  	}
   112  	testStoreCorrect(db, processors, n, chunksize, t)
   113  }
   114  
   115  func TestDbStoreRandom_1(t *testing.T) {
   116  	testDbStoreRandom(1, 1, 0, false, t)
   117  }
   118  
   119  func TestDbStoreCorrect_1(t *testing.T) {
   120  	testDbStoreCorrect(1, 1, 4096, false, t)
   121  }
   122  
   123  func TestDbStoreRandom_1_5k(t *testing.T) {
   124  	testDbStoreRandom(8, 5000, 0, false, t)
   125  }
   126  
   127  func TestDbStoreRandom_8_5k(t *testing.T) {
   128  	testDbStoreRandom(8, 5000, 0, false, t)
   129  }
   130  
   131  func TestDbStoreCorrect_1_5k(t *testing.T) {
   132  	testDbStoreCorrect(1, 5000, 4096, false, t)
   133  }
   134  
   135  func TestDbStoreCorrect_8_5k(t *testing.T) {
   136  	testDbStoreCorrect(8, 5000, 4096, false, t)
   137  }
   138  
   139  func TestMockDbStoreRandom_1(t *testing.T) {
   140  	testDbStoreRandom(1, 1, 0, true, t)
   141  }
   142  
   143  func TestMockDbStoreCorrect_1(t *testing.T) {
   144  	testDbStoreCorrect(1, 1, 4096, true, t)
   145  }
   146  
   147  func TestMockDbStoreRandom_1_5k(t *testing.T) {
   148  	testDbStoreRandom(8, 5000, 0, true, t)
   149  }
   150  
   151  func TestMockDbStoreRandom_8_5k(t *testing.T) {
   152  	testDbStoreRandom(8, 5000, 0, true, t)
   153  }
   154  
   155  func TestMockDbStoreCorrect_1_5k(t *testing.T) {
   156  	testDbStoreCorrect(1, 5000, 4096, true, t)
   157  }
   158  
   159  func TestMockDbStoreCorrect_8_5k(t *testing.T) {
   160  	testDbStoreCorrect(8, 5000, 4096, true, t)
   161  }
   162  
   163  func testDbStoreNotFound(t *testing.T, mock bool) {
   164  	db, cleanup, err := newTestDbStore(mock, false)
   165  	defer cleanup()
   166  	if err != nil {
   167  		t.Fatalf("init dbStore failed: %v", err)
   168  	}
   169  
   170  	_, err = db.Get(context.TODO(), ZeroAddr)
   171  	if err != ErrChunkNotFound {
   172  		t.Errorf("Expected ErrChunkNotFound, got %v", err)
   173  	}
   174  }
   175  
   176  func TestDbStoreNotFound(t *testing.T) {
   177  	testDbStoreNotFound(t, false)
   178  }
   179  func TestMockDbStoreNotFound(t *testing.T) {
   180  	testDbStoreNotFound(t, true)
   181  }
   182  
   183  func testIterator(t *testing.T, mock bool) {
   184  	var chunkcount int = 32
   185  	var i int
   186  	var poc uint
   187  	chunkkeys := NewAddressCollection(chunkcount)
   188  	chunkkeys_results := NewAddressCollection(chunkcount)
   189  
   190  	db, cleanup, err := newTestDbStore(mock, false)
   191  	defer cleanup()
   192  	if err != nil {
   193  		t.Fatalf("init dbStore failed: %v", err)
   194  	}
   195  
   196  	chunks := GenerateRandomChunks(chunk.DefaultSize, chunkcount)
   197  
   198  	wg := &sync.WaitGroup{}
   199  	wg.Add(len(chunks))
   200  	for i = 0; i < len(chunks); i++ {
   201  		db.Put(context.TODO(), chunks[i])
   202  		chunkkeys[i] = chunks[i].Addr
   203  		j := i
   204  		go func() {
   205  			defer wg.Done()
   206  			<-chunks[j].dbStoredC
   207  		}()
   208  	}
   209  
   210  //
   211  
   212  	for i = 0; i < len(chunkkeys); i++ {
   213  		log.Trace(fmt.Sprintf("Chunk array pos %d/%d: '%v'", i, chunkcount, chunkkeys[i]))
   214  	}
   215  	wg.Wait()
   216  	i = 0
   217  	for poc = 0; poc <= 255; poc++ {
   218  		err := db.SyncIterator(0, uint64(chunkkeys.Len()), uint8(poc), func(k Address, n uint64) bool {
   219  			log.Trace(fmt.Sprintf("Got key %v number %d poc %d", k, n, uint8(poc)))
   220  			chunkkeys_results[n-1] = k
   221  			i++
   222  			return true
   223  		})
   224  		if err != nil {
   225  			t.Fatalf("Iterator call failed: %v", err)
   226  		}
   227  	}
   228  
   229  	for i = 0; i < chunkcount; i++ {
   230  		if !bytes.Equal(chunkkeys[i], chunkkeys_results[i]) {
   231  			t.Fatalf("Chunk put #%d key '%v' does not match iterator's key '%v'", i, chunkkeys[i], chunkkeys_results[i])
   232  		}
   233  	}
   234  
   235  }
   236  
   237  func TestIterator(t *testing.T) {
   238  	testIterator(t, false)
   239  }
   240  func TestMockIterator(t *testing.T) {
   241  	testIterator(t, true)
   242  }
   243  
   244  func benchmarkDbStorePut(n int, processors int, chunksize int64, mock bool, b *testing.B) {
   245  	db, cleanup, err := newTestDbStore(mock, true)
   246  	defer cleanup()
   247  	if err != nil {
   248  		b.Fatalf("init dbStore failed: %v", err)
   249  	}
   250  	benchmarkStorePut(db, processors, n, chunksize, b)
   251  }
   252  
   253  func benchmarkDbStoreGet(n int, processors int, chunksize int64, mock bool, b *testing.B) {
   254  	db, cleanup, err := newTestDbStore(mock, true)
   255  	defer cleanup()
   256  	if err != nil {
   257  		b.Fatalf("init dbStore failed: %v", err)
   258  	}
   259  	benchmarkStoreGet(db, processors, n, chunksize, b)
   260  }
   261  
   262  func BenchmarkDbStorePut_1_500(b *testing.B) {
   263  	benchmarkDbStorePut(500, 1, 4096, false, b)
   264  }
   265  
   266  func BenchmarkDbStorePut_8_500(b *testing.B) {
   267  	benchmarkDbStorePut(500, 8, 4096, false, b)
   268  }
   269  
   270  func BenchmarkDbStoreGet_1_500(b *testing.B) {
   271  	benchmarkDbStoreGet(500, 1, 4096, false, b)
   272  }
   273  
   274  func BenchmarkDbStoreGet_8_500(b *testing.B) {
   275  	benchmarkDbStoreGet(500, 8, 4096, false, b)
   276  }
   277  
   278  func BenchmarkMockDbStorePut_1_500(b *testing.B) {
   279  	benchmarkDbStorePut(500, 1, 4096, true, b)
   280  }
   281  
   282  func BenchmarkMockDbStorePut_8_500(b *testing.B) {
   283  	benchmarkDbStorePut(500, 8, 4096, true, b)
   284  }
   285  
   286  func BenchmarkMockDbStoreGet_1_500(b *testing.B) {
   287  	benchmarkDbStoreGet(500, 1, 4096, true, b)
   288  }
   289  
   290  func BenchmarkMockDbStoreGet_8_500(b *testing.B) {
   291  	benchmarkDbStoreGet(500, 8, 4096, true, b)
   292  }
   293  
   294  //
   295  //
   296  func TestLDBStoreWithoutCollectGarbage(t *testing.T) {
   297  	capacity := 50
   298  	n := 10
   299  
   300  	ldb, cleanup := newLDBStore(t)
   301  	ldb.setCapacity(uint64(capacity))
   302  	defer cleanup()
   303  
   304  	chunks := []*Chunk{}
   305  	for i := 0; i < n; i++ {
   306  		c := GenerateRandomChunk(chunk.DefaultSize)
   307  		chunks = append(chunks, c)
   308  		log.Trace("generate random chunk", "idx", i, "chunk", c)
   309  	}
   310  
   311  	for i := 0; i < n; i++ {
   312  		go ldb.Put(context.TODO(), chunks[i])
   313  	}
   314  
   315  //
   316  	for i := 0; i < n; i++ {
   317  		<-chunks[i].dbStoredC
   318  	}
   319  
   320  	log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt)
   321  
   322  	for i := 0; i < n; i++ {
   323  		ret, err := ldb.Get(context.TODO(), chunks[i].Addr)
   324  		if err != nil {
   325  			t.Fatal(err)
   326  		}
   327  
   328  		if !bytes.Equal(ret.SData, chunks[i].SData) {
   329  			t.Fatal("expected to get the same data back, but got smth else")
   330  		}
   331  
   332  		log.Info("got back chunk", "chunk", ret)
   333  	}
   334  
   335  	if ldb.entryCnt != uint64(n+1) {
   336  		t.Fatalf("expected entryCnt to be equal to %v, but got %v", n+1, ldb.entryCnt)
   337  	}
   338  
   339  	if ldb.accessCnt != uint64(2*n+1) {
   340  		t.Fatalf("expected accessCnt to be equal to %v, but got %v", n+1, ldb.accessCnt)
   341  	}
   342  }
   343  
   344  //
   345  //
   346  func TestLDBStoreCollectGarbage(t *testing.T) {
   347  	capacity := 500
   348  	n := 2000
   349  
   350  	ldb, cleanup := newLDBStore(t)
   351  	ldb.setCapacity(uint64(capacity))
   352  	defer cleanup()
   353  
   354  	chunks := []*Chunk{}
   355  	for i := 0; i < n; i++ {
   356  		c := GenerateRandomChunk(chunk.DefaultSize)
   357  		chunks = append(chunks, c)
   358  		log.Trace("generate random chunk", "idx", i, "chunk", c)
   359  	}
   360  
   361  	for i := 0; i < n; i++ {
   362  		ldb.Put(context.TODO(), chunks[i])
   363  	}
   364  
   365  //
   366  	for i := 0; i < n; i++ {
   367  		<-chunks[i].dbStoredC
   368  	}
   369  
   370  	log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt)
   371  
   372  //
   373  	time.Sleep(5 * time.Second)
   374  
   375  	var missing int
   376  	for i := 0; i < n; i++ {
   377  		ret, err := ldb.Get(context.TODO(), chunks[i].Addr)
   378  		if err == ErrChunkNotFound || err == ldberrors.ErrNotFound {
   379  			missing++
   380  			continue
   381  		}
   382  		if err != nil {
   383  			t.Fatal(err)
   384  		}
   385  
   386  		if !bytes.Equal(ret.SData, chunks[i].SData) {
   387  			t.Fatal("expected to get the same data back, but got smth else")
   388  		}
   389  
   390  		log.Trace("got back chunk", "chunk", ret)
   391  	}
   392  
   393  	if missing < n-capacity {
   394  		t.Fatalf("gc failure: expected to miss %v chunks, but only %v are actually missing", n-capacity, missing)
   395  	}
   396  
   397  	log.Info("ldbstore", "total", n, "missing", missing, "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt)
   398  }
   399  
   400  //
   401  func TestLDBStoreAddRemove(t *testing.T) {
   402  	ldb, cleanup := newLDBStore(t)
   403  	ldb.setCapacity(200)
   404  	defer cleanup()
   405  
   406  	n := 100
   407  
   408  	chunks := []*Chunk{}
   409  	for i := 0; i < n; i++ {
   410  		c := GenerateRandomChunk(chunk.DefaultSize)
   411  		chunks = append(chunks, c)
   412  		log.Trace("generate random chunk", "idx", i, "chunk", c)
   413  	}
   414  
   415  	for i := 0; i < n; i++ {
   416  		go ldb.Put(context.TODO(), chunks[i])
   417  	}
   418  
   419  //
   420  	for i := 0; i < n; i++ {
   421  		<-chunks[i].dbStoredC
   422  	}
   423  
   424  	for i := 0; i < n; i++ {
   425  //
   426  		if i%2 == 0 {
   427  
   428  			key := chunks[i].Addr
   429  			ikey := getIndexKey(key)
   430  
   431  			var indx dpaDBIndex
   432  			ldb.tryAccessIdx(ikey, &indx)
   433  
   434  			ldb.delete(indx.Idx, ikey, ldb.po(key))
   435  		}
   436  	}
   437  
   438  	log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt)
   439  
   440  	for i := 0; i < n; i++ {
   441  		ret, err := ldb.Get(context.TODO(), chunks[i].Addr)
   442  
   443  		if i%2 == 0 {
   444  //
   445  			if err == nil || ret != nil {
   446  				t.Fatal("expected chunk to be missing, but got no error")
   447  			}
   448  		} else {
   449  //
   450  			if err != nil {
   451  				t.Fatalf("expected no error, but got %s", err)
   452  			}
   453  
   454  			if !bytes.Equal(ret.SData, chunks[i].SData) {
   455  				t.Fatal("expected to get the same data back, but got smth else")
   456  			}
   457  		}
   458  	}
   459  }
   460  
   461  //
   462  func TestLDBStoreRemoveThenCollectGarbage(t *testing.T) {
   463  	capacity := 10
   464  
   465  	ldb, cleanup := newLDBStore(t)
   466  	ldb.setCapacity(uint64(capacity))
   467  
   468  	n := 7
   469  
   470  	chunks := []*Chunk{}
   471  	for i := 0; i < capacity; i++ {
   472  		c := GenerateRandomChunk(chunk.DefaultSize)
   473  		chunks = append(chunks, c)
   474  		log.Trace("generate random chunk", "idx", i, "chunk", c)
   475  	}
   476  
   477  	for i := 0; i < n; i++ {
   478  		ldb.Put(context.TODO(), chunks[i])
   479  	}
   480  
   481  //
   482  	for i := 0; i < n; i++ {
   483  		<-chunks[i].dbStoredC
   484  	}
   485  
   486  //
   487  	for i := 0; i < n; i++ {
   488  		key := chunks[i].Addr
   489  		ikey := getIndexKey(key)
   490  
   491  		var indx dpaDBIndex
   492  		ldb.tryAccessIdx(ikey, &indx)
   493  
   494  		ldb.delete(indx.Idx, ikey, ldb.po(key))
   495  	}
   496  
   497  	log.Info("ldbstore", "entrycnt", ldb.entryCnt, "accesscnt", ldb.accessCnt)
   498  
   499  	cleanup()
   500  
   501  	ldb, cleanup = newLDBStore(t)
   502  	ldb.setCapacity(uint64(capacity))
   503  
   504  	n = 10
   505  
   506  	for i := 0; i < n; i++ {
   507  		ldb.Put(context.TODO(), chunks[i])
   508  	}
   509  
   510  //
   511  	for i := 0; i < n; i++ {
   512  		<-chunks[i].dbStoredC
   513  	}
   514  
   515  //
   516  	idx := 0
   517  	ret, err := ldb.Get(context.TODO(), chunks[idx].Addr)
   518  	if err == nil || ret != nil {
   519  		t.Fatal("expected first chunk to be missing, but got no error")
   520  	}
   521  
   522  //
   523  	idx = 9
   524  	ret, err = ldb.Get(context.TODO(), chunks[idx].Addr)
   525  	if err != nil {
   526  		t.Fatalf("expected no error, but got %s", err)
   527  	}
   528  
   529  	if !bytes.Equal(ret.SData, chunks[idx].SData) {
   530  		t.Fatal("expected to get the same data back, but got smth else")
   531  	}
   532  }