github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/common_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  	"crypto/rand"
    31  	"flag"
    32  	"fmt"
    33  	"io"
    34  	"sync"
    35  	"testing"
    36  	"time"
    37  
    38  	"github.com/ethereum/go-ethereum/log"
    39  	colorable "github.com/mattn/go-colorable"
    40  )
    41  
    42  var (
    43  	loglevel = flag.Int("loglevel", 3, "verbosity of logs")
    44  )
    45  
    46  func init() {
    47  	flag.Parse()
    48  	log.PrintOrigins(true)
    49  	log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
    50  }
    51  
    52  type brokenLimitedReader struct {
    53  	lr    io.Reader
    54  	errAt int
    55  	off   int
    56  	size  int
    57  }
    58  
    59  func brokenLimitReader(data io.Reader, size int, errAt int) *brokenLimitedReader {
    60  	return &brokenLimitedReader{
    61  		lr:    data,
    62  		errAt: errAt,
    63  		size:  size,
    64  	}
    65  }
    66  
    67  func mputRandomChunks(store ChunkStore, processors int, n int, chunksize int64) (hs []Address) {
    68  	return mput(store, processors, n, GenerateRandomChunk)
    69  }
    70  
    71  func mput(store ChunkStore, processors int, n int, f func(i int64) *Chunk) (hs []Address) {
    72  	wg := sync.WaitGroup{}
    73  	wg.Add(processors)
    74  	c := make(chan *Chunk)
    75  	for i := 0; i < processors; i++ {
    76  		go func() {
    77  			defer wg.Done()
    78  			for chunk := range c {
    79  				wg.Add(1)
    80  				chunk := chunk
    81  				store.Put(context.TODO(), chunk)
    82  				go func() {
    83  					defer wg.Done()
    84  					<-chunk.dbStoredC
    85  				}()
    86  			}
    87  		}()
    88  	}
    89  	fa := f
    90  	if _, ok := store.(*MemStore); ok {
    91  		fa = func(i int64) *Chunk {
    92  			chunk := f(i)
    93  			chunk.markAsStored()
    94  			return chunk
    95  		}
    96  	}
    97  	for i := 0; i < n; i++ {
    98  		chunk := fa(int64(i))
    99  		hs = append(hs, chunk.Addr)
   100  		c <- chunk
   101  	}
   102  	close(c)
   103  	wg.Wait()
   104  	return hs
   105  }
   106  
   107  func mget(store ChunkStore, hs []Address, f func(h Address, chunk *Chunk) error) error {
   108  	wg := sync.WaitGroup{}
   109  	wg.Add(len(hs))
   110  	errc := make(chan error)
   111  
   112  	for _, k := range hs {
   113  		go func(h Address) {
   114  			defer wg.Done()
   115  			chunk, err := store.Get(context.TODO(), h)
   116  			if err != nil {
   117  				errc <- err
   118  				return
   119  			}
   120  			if f != nil {
   121  				err = f(h, chunk)
   122  				if err != nil {
   123  					errc <- err
   124  					return
   125  				}
   126  			}
   127  		}(k)
   128  	}
   129  	go func() {
   130  		wg.Wait()
   131  		close(errc)
   132  	}()
   133  	var err error
   134  	select {
   135  	case err = <-errc:
   136  	case <-time.NewTimer(5 * time.Second).C:
   137  		err = fmt.Errorf("timed out after 5 seconds")
   138  	}
   139  	return err
   140  }
   141  
   142  func testDataReader(l int) (r io.Reader) {
   143  	return io.LimitReader(rand.Reader, int64(l))
   144  }
   145  
   146  func (r *brokenLimitedReader) Read(buf []byte) (int, error) {
   147  	if r.off+len(buf) > r.errAt {
   148  		return 0, fmt.Errorf("Broken reader")
   149  	}
   150  	r.off += len(buf)
   151  	return r.lr.Read(buf)
   152  }
   153  
   154  func generateRandomData(l int) (r io.Reader, slice []byte) {
   155  	slice = make([]byte, l)
   156  	if _, err := rand.Read(slice); err != nil {
   157  		panic("rand error")
   158  	}
   159  	r = io.LimitReader(bytes.NewReader(slice), int64(l))
   160  	return
   161  }
   162  
   163  func testStoreRandom(m ChunkStore, processors int, n int, chunksize int64, t *testing.T) {
   164  	hs := mputRandomChunks(m, processors, n, chunksize)
   165  	err := mget(m, hs, nil)
   166  	if err != nil {
   167  		t.Fatalf("testStore failed: %v", err)
   168  	}
   169  }
   170  
   171  func testStoreCorrect(m ChunkStore, processors int, n int, chunksize int64, t *testing.T) {
   172  	hs := mputRandomChunks(m, processors, n, chunksize)
   173  	f := func(h Address, chunk *Chunk) error {
   174  		if !bytes.Equal(h, chunk.Addr) {
   175  			return fmt.Errorf("key does not match retrieved chunk Key")
   176  		}
   177  		hasher := MakeHashFunc(DefaultHash)()
   178  		hasher.ResetWithLength(chunk.SData[:8])
   179  		hasher.Write(chunk.SData[8:])
   180  		exp := hasher.Sum(nil)
   181  		if !bytes.Equal(h, exp) {
   182  			return fmt.Errorf("key is not hash of chunk data")
   183  		}
   184  		return nil
   185  	}
   186  	err := mget(m, hs, f)
   187  	if err != nil {
   188  		t.Fatalf("testStore failed: %v", err)
   189  	}
   190  }
   191  
   192  func benchmarkStorePut(store ChunkStore, processors int, n int, chunksize int64, b *testing.B) {
   193  	chunks := make([]*Chunk, n)
   194  	i := 0
   195  	f := func(dataSize int64) *Chunk {
   196  		chunk := GenerateRandomChunk(dataSize)
   197  		chunks[i] = chunk
   198  		i++
   199  		return chunk
   200  	}
   201  
   202  	mput(store, processors, n, f)
   203  
   204  	f = func(dataSize int64) *Chunk {
   205  		chunk := chunks[i]
   206  		i++
   207  		return chunk
   208  	}
   209  
   210  	b.ReportAllocs()
   211  	b.ResetTimer()
   212  
   213  	for j := 0; j < b.N; j++ {
   214  		i = 0
   215  		mput(store, processors, n, f)
   216  	}
   217  }
   218  
   219  func benchmarkStoreGet(store ChunkStore, processors int, n int, chunksize int64, b *testing.B) {
   220  	hs := mputRandomChunks(store, processors, n, chunksize)
   221  	b.ReportAllocs()
   222  	b.ResetTimer()
   223  	for i := 0; i < b.N; i++ {
   224  		err := mget(store, hs, nil)
   225  		if err != nil {
   226  			b.Fatalf("mget failed: %v", err)
   227  		}
   228  	}
   229  }