github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/chunker_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  	"encoding/binary"
    32  	"errors"
    33  	"fmt"
    34  	"io"
    35  	"testing"
    36  
    37  	"github.com/ethereum/go-ethereum/crypto/sha3"
    38  )
    39  
    40  /*
    41  
    42  */
    43  
    44  
    45  type test interface {
    46  	Fatalf(string, ...interface{})
    47  	Logf(string, ...interface{})
    48  }
    49  
    50  type chunkerTester struct {
    51  	inputs map[uint64][]byte
    52  	t      test
    53  }
    54  
    55  //
    56  //
    57  //
    58  type fakeChunkStore struct {
    59  }
    60  
    61  //
    62  func (f *fakeChunkStore) Put(context.Context, *Chunk) {
    63  }
    64  
    65  //
    66  func (f *fakeChunkStore) Get(context.Context, Address) (*Chunk, error) {
    67  	return nil, errors.New("FakeChunkStore doesn't support Get")
    68  }
    69  
    70  //
    71  func (f *fakeChunkStore) Close() {
    72  }
    73  
    74  func newTestHasherStore(chunkStore ChunkStore, hash string) *hasherStore {
    75  	return NewHasherStore(chunkStore, MakeHashFunc(hash), false)
    76  }
    77  
    78  func testRandomBrokenData(n int, tester *chunkerTester) {
    79  	data := io.LimitReader(rand.Reader, int64(n))
    80  	brokendata := brokenLimitReader(data, n, n/2)
    81  
    82  	buf := make([]byte, n)
    83  	_, err := brokendata.Read(buf)
    84  	if err == nil || err.Error() != "Broken reader" {
    85  		tester.t.Fatalf("Broken reader is not broken, hence broken. Returns: %v", err)
    86  	}
    87  
    88  	data = io.LimitReader(rand.Reader, int64(n))
    89  	brokendata = brokenLimitReader(data, n, n/2)
    90  
    91  	putGetter := newTestHasherStore(NewMapChunkStore(), SHA3Hash)
    92  
    93  	expectedError := fmt.Errorf("Broken reader")
    94  	addr, _, err := TreeSplit(context.TODO(), brokendata, int64(n), putGetter)
    95  	if err == nil || err.Error() != expectedError.Error() {
    96  		tester.t.Fatalf("Not receiving the correct error! Expected %v, received %v", expectedError, err)
    97  	}
    98  	tester.t.Logf(" Key = %v\n", addr)
    99  }
   100  
   101  func testRandomData(usePyramid bool, hash string, n int, tester *chunkerTester) Address {
   102  	if tester.inputs == nil {
   103  		tester.inputs = make(map[uint64][]byte)
   104  	}
   105  	input, found := tester.inputs[uint64(n)]
   106  	var data io.Reader
   107  	if !found {
   108  		data, input = generateRandomData(n)
   109  		tester.inputs[uint64(n)] = input
   110  	} else {
   111  		data = io.LimitReader(bytes.NewReader(input), int64(n))
   112  	}
   113  
   114  	putGetter := newTestHasherStore(NewMapChunkStore(), hash)
   115  
   116  	var addr Address
   117  	var wait func(context.Context) error
   118  	var err error
   119  	ctx := context.TODO()
   120  	if usePyramid {
   121  		addr, wait, err = PyramidSplit(ctx, data, putGetter, putGetter)
   122  	} else {
   123  		addr, wait, err = TreeSplit(ctx, data, int64(n), putGetter)
   124  	}
   125  	if err != nil {
   126  		tester.t.Fatalf(err.Error())
   127  	}
   128  	tester.t.Logf(" Key = %v\n", addr)
   129  	err = wait(ctx)
   130  	if err != nil {
   131  		tester.t.Fatalf(err.Error())
   132  	}
   133  
   134  	reader := TreeJoin(context.TODO(), addr, putGetter, 0)
   135  	output := make([]byte, n)
   136  	r, err := reader.Read(output)
   137  	if r != n || err != io.EOF {
   138  		tester.t.Fatalf("read error  read: %v  n = %v  err = %v\n", r, n, err)
   139  	}
   140  	if input != nil {
   141  		if !bytes.Equal(output, input) {
   142  			tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", input, output)
   143  		}
   144  	}
   145  
   146  //
   147  	for i := 1; i < n; i += 10000 {
   148  		readableLength := n - i
   149  		output := make([]byte, readableLength)
   150  		r, err := reader.ReadAt(output, int64(i))
   151  		if r != readableLength || err != io.EOF {
   152  			tester.t.Fatalf("readAt error with offset %v read: %v  n = %v  err = %v\n", i, r, readableLength, err)
   153  		}
   154  		if input != nil {
   155  			if !bytes.Equal(output, input[i:]) {
   156  				tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", input[i:], output)
   157  			}
   158  		}
   159  	}
   160  
   161  	return addr
   162  }
   163  
   164  func TestSha3ForCorrectness(t *testing.T) {
   165  	tester := &chunkerTester{t: t}
   166  
   167  	size := 4096
   168  	input := make([]byte, size+8)
   169  	binary.LittleEndian.PutUint64(input[:8], uint64(size))
   170  
   171  	io.LimitReader(bytes.NewReader(input[8:]), int64(size))
   172  
   173  	rawSha3 := sha3.NewKeccak256()
   174  	rawSha3.Reset()
   175  	rawSha3.Write(input)
   176  	rawSha3Output := rawSha3.Sum(nil)
   177  
   178  	sha3FromMakeFunc := MakeHashFunc(SHA3Hash)()
   179  	sha3FromMakeFunc.ResetWithLength(input[:8])
   180  	sha3FromMakeFunc.Write(input[8:])
   181  	sha3FromMakeFuncOutput := sha3FromMakeFunc.Sum(nil)
   182  
   183  	if len(rawSha3Output) != len(sha3FromMakeFuncOutput) {
   184  		tester.t.Fatalf("Original SHA3 and abstracted Sha3 has different length %v:%v\n", len(rawSha3Output), len(sha3FromMakeFuncOutput))
   185  	}
   186  
   187  	if !bytes.Equal(rawSha3Output, sha3FromMakeFuncOutput) {
   188  		tester.t.Fatalf("Original SHA3 and abstracted Sha3 mismatch %v:%v\n", rawSha3Output, sha3FromMakeFuncOutput)
   189  	}
   190  
   191  }
   192  
   193  func TestDataAppend(t *testing.T) {
   194  	sizes := []int{1, 1, 1, 4095, 4096, 4097, 1, 1, 1, 123456, 2345678, 2345678}
   195  	appendSizes := []int{4095, 4096, 4097, 1, 1, 1, 8191, 8192, 8193, 9000, 3000, 5000}
   196  
   197  	tester := &chunkerTester{t: t}
   198  	for i := range sizes {
   199  		n := sizes[i]
   200  		m := appendSizes[i]
   201  
   202  		if tester.inputs == nil {
   203  			tester.inputs = make(map[uint64][]byte)
   204  		}
   205  		input, found := tester.inputs[uint64(n)]
   206  		var data io.Reader
   207  		if !found {
   208  			data, input = generateRandomData(n)
   209  			tester.inputs[uint64(n)] = input
   210  		} else {
   211  			data = io.LimitReader(bytes.NewReader(input), int64(n))
   212  		}
   213  
   214  		chunkStore := NewMapChunkStore()
   215  		putGetter := newTestHasherStore(chunkStore, SHA3Hash)
   216  
   217  		ctx := context.TODO()
   218  		addr, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   219  		if err != nil {
   220  			tester.t.Fatalf(err.Error())
   221  		}
   222  		err = wait(ctx)
   223  		if err != nil {
   224  			tester.t.Fatalf(err.Error())
   225  		}
   226  
   227  //
   228  		appendInput, found := tester.inputs[uint64(m)]
   229  		var appendData io.Reader
   230  		if !found {
   231  			appendData, appendInput = generateRandomData(m)
   232  			tester.inputs[uint64(m)] = appendInput
   233  		} else {
   234  			appendData = io.LimitReader(bytes.NewReader(appendInput), int64(m))
   235  		}
   236  
   237  		putGetter = newTestHasherStore(chunkStore, SHA3Hash)
   238  		newAddr, wait, err := PyramidAppend(ctx, addr, appendData, putGetter, putGetter)
   239  		if err != nil {
   240  			tester.t.Fatalf(err.Error())
   241  		}
   242  		err = wait(ctx)
   243  		if err != nil {
   244  			tester.t.Fatalf(err.Error())
   245  		}
   246  
   247  		reader := TreeJoin(ctx, newAddr, putGetter, 0)
   248  		newOutput := make([]byte, n+m)
   249  		r, err := reader.Read(newOutput)
   250  		if r != (n + m) {
   251  			tester.t.Fatalf("read error  read: %v  n = %v  m = %v  err = %v\n", r, n, m, err)
   252  		}
   253  
   254  		newInput := append(input, appendInput...)
   255  		if !bytes.Equal(newOutput, newInput) {
   256  			tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", newInput, newOutput)
   257  		}
   258  	}
   259  }
   260  
   261  func TestRandomData(t *testing.T) {
   262  //
   263  //
   264  	sizes := []int{1, 60, 83, 179, 253, 1024, 4095, 4096, 4097, 8191, 8192, 8193, 12287, 12288, 12289, 524288, 524288 + 1, 524288 + 4097, 7 * 524288, 7*524288 + 1, 7*524288 + 4097}
   265  	tester := &chunkerTester{t: t}
   266  
   267  	for _, s := range sizes {
   268  		treeChunkerKey := testRandomData(false, SHA3Hash, s, tester)
   269  		pyramidChunkerKey := testRandomData(true, SHA3Hash, s, tester)
   270  		if treeChunkerKey.String() != pyramidChunkerKey.String() {
   271  			tester.t.Fatalf("tree chunker and pyramid chunker key mismatch for size %v\n TC: %v\n PC: %v\n", s, treeChunkerKey.String(), pyramidChunkerKey.String())
   272  		}
   273  	}
   274  
   275  	for _, s := range sizes {
   276  		treeChunkerKey := testRandomData(false, BMTHash, s, tester)
   277  		pyramidChunkerKey := testRandomData(true, BMTHash, s, tester)
   278  		if treeChunkerKey.String() != pyramidChunkerKey.String() {
   279  			tester.t.Fatalf("tree chunker and pyramid chunker key mismatch for size %v\n TC: %v\n PC: %v\n", s, treeChunkerKey.String(), pyramidChunkerKey.String())
   280  		}
   281  	}
   282  }
   283  
   284  func TestRandomBrokenData(t *testing.T) {
   285  	sizes := []int{1, 60, 83, 179, 253, 1024, 4095, 4096, 4097, 8191, 8192, 8193, 12287, 12288, 12289, 123456, 2345678}
   286  	tester := &chunkerTester{t: t}
   287  	for _, s := range sizes {
   288  		testRandomBrokenData(s, tester)
   289  	}
   290  }
   291  
   292  func benchReadAll(reader LazySectionReader) {
   293  	size, _ := reader.Size(context.TODO(), nil)
   294  	output := make([]byte, 1000)
   295  	for pos := int64(0); pos < size; pos += 1000 {
   296  		reader.ReadAt(output, pos)
   297  	}
   298  }
   299  
   300  func benchmarkSplitJoin(n int, t *testing.B) {
   301  	t.ReportAllocs()
   302  	for i := 0; i < t.N; i++ {
   303  		data := testDataReader(n)
   304  
   305  		putGetter := newTestHasherStore(NewMapChunkStore(), SHA3Hash)
   306  		ctx := context.TODO()
   307  		key, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   308  		if err != nil {
   309  			t.Fatalf(err.Error())
   310  		}
   311  		err = wait(ctx)
   312  		if err != nil {
   313  			t.Fatalf(err.Error())
   314  		}
   315  		reader := TreeJoin(ctx, key, putGetter, 0)
   316  		benchReadAll(reader)
   317  	}
   318  }
   319  
   320  func benchmarkSplitTreeSHA3(n int, t *testing.B) {
   321  	t.ReportAllocs()
   322  	for i := 0; i < t.N; i++ {
   323  		data := testDataReader(n)
   324  		putGetter := newTestHasherStore(&fakeChunkStore{}, SHA3Hash)
   325  
   326  		_, _, err := TreeSplit(context.TODO(), data, int64(n), putGetter)
   327  		if err != nil {
   328  			t.Fatalf(err.Error())
   329  		}
   330  	}
   331  }
   332  
   333  func benchmarkSplitTreeBMT(n int, t *testing.B) {
   334  	t.ReportAllocs()
   335  	for i := 0; i < t.N; i++ {
   336  		data := testDataReader(n)
   337  		putGetter := newTestHasherStore(&fakeChunkStore{}, BMTHash)
   338  
   339  		_, _, err := TreeSplit(context.TODO(), data, int64(n), putGetter)
   340  		if err != nil {
   341  			t.Fatalf(err.Error())
   342  		}
   343  	}
   344  }
   345  
   346  func benchmarkSplitPyramidSHA3(n int, t *testing.B) {
   347  	t.ReportAllocs()
   348  	for i := 0; i < t.N; i++ {
   349  		data := testDataReader(n)
   350  		putGetter := newTestHasherStore(&fakeChunkStore{}, SHA3Hash)
   351  
   352  		_, _, err := PyramidSplit(context.TODO(), data, putGetter, putGetter)
   353  		if err != nil {
   354  			t.Fatalf(err.Error())
   355  		}
   356  
   357  	}
   358  }
   359  
   360  func benchmarkSplitPyramidBMT(n int, t *testing.B) {
   361  	t.ReportAllocs()
   362  	for i := 0; i < t.N; i++ {
   363  		data := testDataReader(n)
   364  		putGetter := newTestHasherStore(&fakeChunkStore{}, BMTHash)
   365  
   366  		_, _, err := PyramidSplit(context.TODO(), data, putGetter, putGetter)
   367  		if err != nil {
   368  			t.Fatalf(err.Error())
   369  		}
   370  	}
   371  }
   372  
   373  func benchmarkSplitAppendPyramid(n, m int, t *testing.B) {
   374  	t.ReportAllocs()
   375  	for i := 0; i < t.N; i++ {
   376  		data := testDataReader(n)
   377  		data1 := testDataReader(m)
   378  
   379  		chunkStore := NewMapChunkStore()
   380  		putGetter := newTestHasherStore(chunkStore, SHA3Hash)
   381  
   382  		ctx := context.TODO()
   383  		key, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   384  		if err != nil {
   385  			t.Fatalf(err.Error())
   386  		}
   387  		err = wait(ctx)
   388  		if err != nil {
   389  			t.Fatalf(err.Error())
   390  		}
   391  
   392  		putGetter = newTestHasherStore(chunkStore, SHA3Hash)
   393  		_, wait, err = PyramidAppend(ctx, key, data1, putGetter, putGetter)
   394  		if err != nil {
   395  			t.Fatalf(err.Error())
   396  		}
   397  		err = wait(ctx)
   398  		if err != nil {
   399  			t.Fatalf(err.Error())
   400  		}
   401  	}
   402  }
   403  
   404  func BenchmarkSplitJoin_2(t *testing.B) { benchmarkSplitJoin(100, t) }
   405  func BenchmarkSplitJoin_3(t *testing.B) { benchmarkSplitJoin(1000, t) }
   406  func BenchmarkSplitJoin_4(t *testing.B) { benchmarkSplitJoin(10000, t) }
   407  func BenchmarkSplitJoin_5(t *testing.B) { benchmarkSplitJoin(100000, t) }
   408  func BenchmarkSplitJoin_6(t *testing.B) { benchmarkSplitJoin(1000000, t) }
   409  func BenchmarkSplitJoin_7(t *testing.B) { benchmarkSplitJoin(10000000, t) }
   410  
   411  //
   412  
   413  func BenchmarkSplitTreeSHA3_2(t *testing.B)  { benchmarkSplitTreeSHA3(100, t) }
   414  func BenchmarkSplitTreeSHA3_2h(t *testing.B) { benchmarkSplitTreeSHA3(500, t) }
   415  func BenchmarkSplitTreeSHA3_3(t *testing.B)  { benchmarkSplitTreeSHA3(1000, t) }
   416  func BenchmarkSplitTreeSHA3_3h(t *testing.B) { benchmarkSplitTreeSHA3(5000, t) }
   417  func BenchmarkSplitTreeSHA3_4(t *testing.B)  { benchmarkSplitTreeSHA3(10000, t) }
   418  func BenchmarkSplitTreeSHA3_4h(t *testing.B) { benchmarkSplitTreeSHA3(50000, t) }
   419  func BenchmarkSplitTreeSHA3_5(t *testing.B)  { benchmarkSplitTreeSHA3(100000, t) }
   420  func BenchmarkSplitTreeSHA3_6(t *testing.B)  { benchmarkSplitTreeSHA3(1000000, t) }
   421  func BenchmarkSplitTreeSHA3_7(t *testing.B)  { benchmarkSplitTreeSHA3(10000000, t) }
   422  
   423  //
   424  
   425  func BenchmarkSplitTreeBMT_2(t *testing.B)  { benchmarkSplitTreeBMT(100, t) }
   426  func BenchmarkSplitTreeBMT_2h(t *testing.B) { benchmarkSplitTreeBMT(500, t) }
   427  func BenchmarkSplitTreeBMT_3(t *testing.B)  { benchmarkSplitTreeBMT(1000, t) }
   428  func BenchmarkSplitTreeBMT_3h(t *testing.B) { benchmarkSplitTreeBMT(5000, t) }
   429  func BenchmarkSplitTreeBMT_4(t *testing.B)  { benchmarkSplitTreeBMT(10000, t) }
   430  func BenchmarkSplitTreeBMT_4h(t *testing.B) { benchmarkSplitTreeBMT(50000, t) }
   431  func BenchmarkSplitTreeBMT_5(t *testing.B)  { benchmarkSplitTreeBMT(100000, t) }
   432  func BenchmarkSplitTreeBMT_6(t *testing.B)  { benchmarkSplitTreeBMT(1000000, t) }
   433  func BenchmarkSplitTreeBMT_7(t *testing.B)  { benchmarkSplitTreeBMT(10000000, t) }
   434  
   435  //
   436  
   437  func BenchmarkSplitPyramidSHA3_2(t *testing.B)  { benchmarkSplitPyramidSHA3(100, t) }
   438  func BenchmarkSplitPyramidSHA3_2h(t *testing.B) { benchmarkSplitPyramidSHA3(500, t) }
   439  func BenchmarkSplitPyramidSHA3_3(t *testing.B)  { benchmarkSplitPyramidSHA3(1000, t) }
   440  func BenchmarkSplitPyramidSHA3_3h(t *testing.B) { benchmarkSplitPyramidSHA3(5000, t) }
   441  func BenchmarkSplitPyramidSHA3_4(t *testing.B)  { benchmarkSplitPyramidSHA3(10000, t) }
   442  func BenchmarkSplitPyramidSHA3_4h(t *testing.B) { benchmarkSplitPyramidSHA3(50000, t) }
   443  func BenchmarkSplitPyramidSHA3_5(t *testing.B)  { benchmarkSplitPyramidSHA3(100000, t) }
   444  func BenchmarkSplitPyramidSHA3_6(t *testing.B)  { benchmarkSplitPyramidSHA3(1000000, t) }
   445  func BenchmarkSplitPyramidSHA3_7(t *testing.B)  { benchmarkSplitPyramidSHA3(10000000, t) }
   446  
   447  //
   448  
   449  func BenchmarkSplitPyramidBMT_2(t *testing.B)  { benchmarkSplitPyramidBMT(100, t) }
   450  func BenchmarkSplitPyramidBMT_2h(t *testing.B) { benchmarkSplitPyramidBMT(500, t) }
   451  func BenchmarkSplitPyramidBMT_3(t *testing.B)  { benchmarkSplitPyramidBMT(1000, t) }
   452  func BenchmarkSplitPyramidBMT_3h(t *testing.B) { benchmarkSplitPyramidBMT(5000, t) }
   453  func BenchmarkSplitPyramidBMT_4(t *testing.B)  { benchmarkSplitPyramidBMT(10000, t) }
   454  func BenchmarkSplitPyramidBMT_4h(t *testing.B) { benchmarkSplitPyramidBMT(50000, t) }
   455  func BenchmarkSplitPyramidBMT_5(t *testing.B)  { benchmarkSplitPyramidBMT(100000, t) }
   456  func BenchmarkSplitPyramidBMT_6(t *testing.B)  { benchmarkSplitPyramidBMT(1000000, t) }
   457  func BenchmarkSplitPyramidBMT_7(t *testing.B)  { benchmarkSplitPyramidBMT(10000000, t) }
   458  
   459  //
   460  
   461  func BenchmarkSplitAppendPyramid_2(t *testing.B)  { benchmarkSplitAppendPyramid(100, 1000, t) }
   462  func BenchmarkSplitAppendPyramid_2h(t *testing.B) { benchmarkSplitAppendPyramid(500, 1000, t) }
   463  func BenchmarkSplitAppendPyramid_3(t *testing.B)  { benchmarkSplitAppendPyramid(1000, 1000, t) }
   464  func BenchmarkSplitAppendPyramid_4(t *testing.B)  { benchmarkSplitAppendPyramid(10000, 1000, t) }
   465  func BenchmarkSplitAppendPyramid_4h(t *testing.B) { benchmarkSplitAppendPyramid(50000, 1000, t) }
   466  func BenchmarkSplitAppendPyramid_5(t *testing.B)  { benchmarkSplitAppendPyramid(1000000, 1000, t) }
   467  func BenchmarkSplitAppendPyramid_6(t *testing.B)  { benchmarkSplitAppendPyramid(1000000, 1000, t) }
   468  func BenchmarkSplitAppendPyramid_7(t *testing.B)  { benchmarkSplitAppendPyramid(10000000, 1000, t) }
   469  
   470  //
   471  
   472  //
   473  //