github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/chunker_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:44</date>
    10  //</624450118346608640>
    11  
    12  
    13  package storage
    14  
    15  import (
    16  	"bytes"
    17  	"context"
    18  	"encoding/binary"
    19  	"fmt"
    20  	"io"
    21  	"testing"
    22  
    23  	"github.com/ethereum/go-ethereum/swarm/testutil"
    24  	"golang.org/x/crypto/sha3"
    25  )
    26  
    27  /*
    28  通过拆分和连接随机字节片测试TreeChunker
    29  **/
    30  
    31  
    32  type test interface {
    33  	Fatalf(string, ...interface{})
    34  	Logf(string, ...interface{})
    35  }
    36  
    37  type chunkerTester struct {
    38  	inputs map[uint64][]byte
    39  	t      test
    40  }
    41  
    42  func newTestHasherStore(store ChunkStore, hash string) *hasherStore {
    43  	return NewHasherStore(store, MakeHashFunc(hash), false)
    44  }
    45  
    46  func testRandomBrokenData(n int, tester *chunkerTester) {
    47  	data := testutil.RandomReader(1, n)
    48  	brokendata := brokenLimitReader(data, n, n/2)
    49  
    50  	buf := make([]byte, n)
    51  	_, err := brokendata.Read(buf)
    52  	if err == nil || err.Error() != "Broken reader" {
    53  		tester.t.Fatalf("Broken reader is not broken, hence broken. Returns: %v", err)
    54  	}
    55  
    56  	data = testutil.RandomReader(2, n)
    57  	brokendata = brokenLimitReader(data, n, n/2)
    58  
    59  	putGetter := newTestHasherStore(NewMapChunkStore(), SHA3Hash)
    60  
    61  	expectedError := fmt.Errorf("Broken reader")
    62  	ctx := context.Background()
    63  	key, _, err := TreeSplit(ctx, brokendata, int64(n), putGetter)
    64  	if err == nil || err.Error() != expectedError.Error() {
    65  		tester.t.Fatalf("Not receiving the correct error! Expected %v, received %v", expectedError, err)
    66  	}
    67  	tester.t.Logf(" Address = %v\n", key)
    68  }
    69  
    70  func testRandomData(usePyramid bool, hash string, n int, tester *chunkerTester) Address {
    71  	if tester.inputs == nil {
    72  		tester.inputs = make(map[uint64][]byte)
    73  	}
    74  	input, found := tester.inputs[uint64(n)]
    75  	var data io.Reader
    76  	if !found {
    77  		input = testutil.RandomBytes(1, n)
    78  		data = bytes.NewReader(input)
    79  		tester.inputs[uint64(n)] = input
    80  	} else {
    81  		data = io.LimitReader(bytes.NewReader(input), int64(n))
    82  	}
    83  
    84  	putGetter := newTestHasherStore(NewMapChunkStore(), hash)
    85  
    86  	var addr Address
    87  	var wait func(context.Context) error
    88  	var err error
    89  	ctx := context.TODO()
    90  	if usePyramid {
    91  		addr, wait, err = PyramidSplit(ctx, data, putGetter, putGetter)
    92  	} else {
    93  		addr, wait, err = TreeSplit(ctx, data, int64(n), putGetter)
    94  	}
    95  	if err != nil {
    96  		tester.t.Fatalf(err.Error())
    97  	}
    98  	tester.t.Logf(" Address = %v\n", addr)
    99  	err = wait(ctx)
   100  	if err != nil {
   101  		tester.t.Fatalf(err.Error())
   102  	}
   103  
   104  	reader := TreeJoin(ctx, addr, putGetter, 0)
   105  	output := make([]byte, n)
   106  	r, err := reader.Read(output)
   107  	if r != n || err != io.EOF {
   108  		tester.t.Fatalf("read error  read: %v  n = %v  err = %v\n", r, n, err)
   109  	}
   110  	if input != nil {
   111  		if !bytes.Equal(output, input) {
   112  			tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", input, output)
   113  		}
   114  	}
   115  
   116  //测试部分读取
   117  	for i := 1; i < n; i += 10000 {
   118  		readableLength := n - i
   119  		r, err := reader.ReadAt(output, int64(i))
   120  		if r != readableLength || err != io.EOF {
   121  			tester.t.Fatalf("readAt error with offset %v read: %v  n = %v  err = %v\n", i, r, readableLength, err)
   122  		}
   123  		if input != nil {
   124  			if !bytes.Equal(output[:readableLength], input[i:]) {
   125  				tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", input[i:], output[:readableLength])
   126  			}
   127  		}
   128  	}
   129  
   130  	return addr
   131  }
   132  
   133  func TestSha3ForCorrectness(t *testing.T) {
   134  	tester := &chunkerTester{t: t}
   135  
   136  	size := 4096
   137  	input := make([]byte, size+8)
   138  	binary.LittleEndian.PutUint64(input[:8], uint64(size))
   139  
   140  	io.LimitReader(bytes.NewReader(input[8:]), int64(size))
   141  
   142  	rawSha3 := sha3.NewLegacyKeccak256()
   143  	rawSha3.Reset()
   144  	rawSha3.Write(input)
   145  	rawSha3Output := rawSha3.Sum(nil)
   146  
   147  	sha3FromMakeFunc := MakeHashFunc(SHA3Hash)()
   148  	sha3FromMakeFunc.ResetWithLength(input[:8])
   149  	sha3FromMakeFunc.Write(input[8:])
   150  	sha3FromMakeFuncOutput := sha3FromMakeFunc.Sum(nil)
   151  
   152  	if len(rawSha3Output) != len(sha3FromMakeFuncOutput) {
   153  		tester.t.Fatalf("Original SHA3 and abstracted Sha3 has different length %v:%v\n", len(rawSha3Output), len(sha3FromMakeFuncOutput))
   154  	}
   155  
   156  	if !bytes.Equal(rawSha3Output, sha3FromMakeFuncOutput) {
   157  		tester.t.Fatalf("Original SHA3 and abstracted Sha3 mismatch %v:%v\n", rawSha3Output, sha3FromMakeFuncOutput)
   158  	}
   159  
   160  }
   161  
   162  func TestDataAppend(t *testing.T) {
   163  	sizes := []int{1, 1, 1, 4095, 4096, 4097, 1, 1, 1, 123456, 2345678, 2345678}
   164  	appendSizes := []int{4095, 4096, 4097, 1, 1, 1, 8191, 8192, 8193, 9000, 3000, 5000}
   165  
   166  	tester := &chunkerTester{t: t}
   167  	for i := range sizes {
   168  		n := sizes[i]
   169  		m := appendSizes[i]
   170  
   171  		if tester.inputs == nil {
   172  			tester.inputs = make(map[uint64][]byte)
   173  		}
   174  		input, found := tester.inputs[uint64(n)]
   175  		var data io.Reader
   176  		if !found {
   177  			input = testutil.RandomBytes(i, n)
   178  			data = bytes.NewReader(input)
   179  			tester.inputs[uint64(n)] = input
   180  		} else {
   181  			data = io.LimitReader(bytes.NewReader(input), int64(n))
   182  		}
   183  
   184  		store := NewMapChunkStore()
   185  		putGetter := newTestHasherStore(store, SHA3Hash)
   186  
   187  		ctx := context.TODO()
   188  		addr, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   189  		if err != nil {
   190  			tester.t.Fatalf(err.Error())
   191  		}
   192  		err = wait(ctx)
   193  		if err != nil {
   194  			tester.t.Fatalf(err.Error())
   195  		}
   196  //创建附加数据流
   197  		appendInput, found := tester.inputs[uint64(m)]
   198  		var appendData io.Reader
   199  		if !found {
   200  			appendInput = testutil.RandomBytes(i, m)
   201  			appendData = bytes.NewReader(appendInput)
   202  			tester.inputs[uint64(m)] = appendInput
   203  		} else {
   204  			appendData = io.LimitReader(bytes.NewReader(appendInput), int64(m))
   205  		}
   206  
   207  		putGetter = newTestHasherStore(store, SHA3Hash)
   208  		newAddr, wait, err := PyramidAppend(ctx, addr, appendData, putGetter, putGetter)
   209  		if err != nil {
   210  			tester.t.Fatalf(err.Error())
   211  		}
   212  		err = wait(ctx)
   213  		if err != nil {
   214  			tester.t.Fatalf(err.Error())
   215  		}
   216  
   217  		reader := TreeJoin(ctx, newAddr, putGetter, 0)
   218  		newOutput := make([]byte, n+m)
   219  		r, err := reader.Read(newOutput)
   220  		if r != (n + m) {
   221  			tester.t.Fatalf("read error  read: %v  n = %v  m = %v  err = %v\n", r, n, m, err)
   222  		}
   223  
   224  		newInput := append(input, appendInput...)
   225  		if !bytes.Equal(newOutput, newInput) {
   226  			tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", newInput, newOutput)
   227  		}
   228  	}
   229  }
   230  
   231  func TestRandomData(t *testing.T) {
   232  //这个测试可以验证文件到一个相对较短的长度,因为树分块器会大大减慢速度。
   233  //较长文件的验证由testlocalstore完成,并在swarm包中进行检索。
   234  //尺寸:=[]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
   235  	sizes := []int{1, 60, 83, 179, 253, 1024, 4095, 4097, 8191, 8192, 12288, 12289, 524288}
   236  	tester := &chunkerTester{t: t}
   237  
   238  	for _, s := range sizes {
   239  		treeChunkerAddress := testRandomData(false, SHA3Hash, s, tester)
   240  		pyramidChunkerAddress := testRandomData(true, SHA3Hash, s, tester)
   241  		if treeChunkerAddress.String() != pyramidChunkerAddress.String() {
   242  			tester.t.Fatalf("tree chunker and pyramid chunker key mismatch for size %v\n TC: %v\n PC: %v\n", s, treeChunkerAddress.String(), pyramidChunkerAddress.String())
   243  		}
   244  	}
   245  
   246  	for _, s := range sizes {
   247  		treeChunkerAddress := testRandomData(false, BMTHash, s, tester)
   248  		pyramidChunkerAddress := testRandomData(true, BMTHash, s, tester)
   249  		if treeChunkerAddress.String() != pyramidChunkerAddress.String() {
   250  			tester.t.Fatalf("tree chunker and pyramid chunker key mismatch for size %v\n TC: %v\n PC: %v\n", s, treeChunkerAddress.String(), pyramidChunkerAddress.String())
   251  		}
   252  	}
   253  }
   254  
   255  func TestRandomBrokenData(t *testing.T) {
   256  	sizes := []int{1, 60, 83, 179, 253, 1024, 4095, 4096, 4097, 8191, 8192, 8193, 12287, 12288, 12289, 123456, 2345678}
   257  	tester := &chunkerTester{t: t}
   258  	for _, s := range sizes {
   259  		testRandomBrokenData(s, tester)
   260  	}
   261  }
   262  
   263  func benchReadAll(reader LazySectionReader) {
   264  	size, _ := reader.Size(context.TODO(), nil)
   265  	output := make([]byte, 1000)
   266  	for pos := int64(0); pos < size; pos += 1000 {
   267  		reader.ReadAt(output, pos)
   268  	}
   269  }
   270  
   271  func benchmarkSplitJoin(n int, t *testing.B) {
   272  	t.ReportAllocs()
   273  	for i := 0; i < t.N; i++ {
   274  		data := testutil.RandomReader(i, n)
   275  
   276  		putGetter := newTestHasherStore(NewMapChunkStore(), SHA3Hash)
   277  		ctx := context.TODO()
   278  		key, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   279  		if err != nil {
   280  			t.Fatalf(err.Error())
   281  		}
   282  		err = wait(ctx)
   283  		if err != nil {
   284  			t.Fatalf(err.Error())
   285  		}
   286  		reader := TreeJoin(ctx, key, putGetter, 0)
   287  		benchReadAll(reader)
   288  	}
   289  }
   290  
   291  func benchmarkSplitTreeSHA3(n int, t *testing.B) {
   292  	t.ReportAllocs()
   293  	for i := 0; i < t.N; i++ {
   294  		data := testutil.RandomReader(i, n)
   295  		putGetter := newTestHasherStore(&FakeChunkStore{}, SHA3Hash)
   296  
   297  		ctx := context.Background()
   298  		_, wait, err := TreeSplit(ctx, data, int64(n), putGetter)
   299  		if err != nil {
   300  			t.Fatalf(err.Error())
   301  		}
   302  		err = wait(ctx)
   303  		if err != nil {
   304  			t.Fatalf(err.Error())
   305  		}
   306  
   307  	}
   308  }
   309  
   310  func benchmarkSplitTreeBMT(n int, t *testing.B) {
   311  	t.ReportAllocs()
   312  	for i := 0; i < t.N; i++ {
   313  		data := testutil.RandomReader(i, n)
   314  		putGetter := newTestHasherStore(&FakeChunkStore{}, BMTHash)
   315  
   316  		ctx := context.Background()
   317  		_, wait, err := TreeSplit(ctx, data, int64(n), putGetter)
   318  		if err != nil {
   319  			t.Fatalf(err.Error())
   320  		}
   321  		err = wait(ctx)
   322  		if err != nil {
   323  			t.Fatalf(err.Error())
   324  		}
   325  	}
   326  }
   327  
   328  func benchmarkSplitPyramidBMT(n int, t *testing.B) {
   329  	t.ReportAllocs()
   330  	for i := 0; i < t.N; i++ {
   331  		data := testutil.RandomReader(i, n)
   332  		putGetter := newTestHasherStore(&FakeChunkStore{}, BMTHash)
   333  
   334  		ctx := context.Background()
   335  		_, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   336  		if err != nil {
   337  			t.Fatalf(err.Error())
   338  		}
   339  		err = wait(ctx)
   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 := testutil.RandomReader(i, n)
   350  		putGetter := newTestHasherStore(&FakeChunkStore{}, SHA3Hash)
   351  
   352  		ctx := context.Background()
   353  		_, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   354  		if err != nil {
   355  			t.Fatalf(err.Error())
   356  		}
   357  		err = wait(ctx)
   358  		if err != nil {
   359  			t.Fatalf(err.Error())
   360  		}
   361  	}
   362  }
   363  
   364  func benchmarkSplitAppendPyramid(n, m int, t *testing.B) {
   365  	t.ReportAllocs()
   366  	for i := 0; i < t.N; i++ {
   367  		data := testutil.RandomReader(i, n)
   368  		data1 := testutil.RandomReader(t.N+i, m)
   369  
   370  		store := NewMapChunkStore()
   371  		putGetter := newTestHasherStore(store, SHA3Hash)
   372  
   373  		ctx := context.Background()
   374  		key, wait, err := PyramidSplit(ctx, data, putGetter, putGetter)
   375  		if err != nil {
   376  			t.Fatalf(err.Error())
   377  		}
   378  		err = wait(ctx)
   379  		if err != nil {
   380  			t.Fatalf(err.Error())
   381  		}
   382  
   383  		putGetter = newTestHasherStore(store, SHA3Hash)
   384  		_, wait, err = PyramidAppend(ctx, key, data1, putGetter, putGetter)
   385  		if err != nil {
   386  			t.Fatalf(err.Error())
   387  		}
   388  		err = wait(ctx)
   389  		if err != nil {
   390  			t.Fatalf(err.Error())
   391  		}
   392  	}
   393  }
   394  
   395  func BenchmarkSplitJoin_2(t *testing.B) { benchmarkSplitJoin(100, t) }
   396  func BenchmarkSplitJoin_3(t *testing.B) { benchmarkSplitJoin(1000, t) }
   397  func BenchmarkSplitJoin_4(t *testing.B) { benchmarkSplitJoin(10000, t) }
   398  func BenchmarkSplitJoin_5(t *testing.B) { benchmarkSplitJoin(100000, t) }
   399  func BenchmarkSplitJoin_6(t *testing.B) { benchmarkSplitJoin(1000000, t) }
   400  func BenchmarkSplitJoin_7(t *testing.B) { benchmarkSplitJoin(10000000, t) }
   401  
   402  //Func BenchmarkSplitJoin_8(t*testing.b)BenchmarkJoin(100000000,t)
   403  
   404  func BenchmarkSplitTreeSHA3_2(t *testing.B)  { benchmarkSplitTreeSHA3(100, t) }
   405  func BenchmarkSplitTreeSHA3_2h(t *testing.B) { benchmarkSplitTreeSHA3(500, t) }
   406  func BenchmarkSplitTreeSHA3_3(t *testing.B)  { benchmarkSplitTreeSHA3(1000, t) }
   407  func BenchmarkSplitTreeSHA3_3h(t *testing.B) { benchmarkSplitTreeSHA3(5000, t) }
   408  func BenchmarkSplitTreeSHA3_4(t *testing.B)  { benchmarkSplitTreeSHA3(10000, t) }
   409  func BenchmarkSplitTreeSHA3_4h(t *testing.B) { benchmarkSplitTreeSHA3(50000, t) }
   410  func BenchmarkSplitTreeSHA3_5(t *testing.B)  { benchmarkSplitTreeSHA3(100000, t) }
   411  func BenchmarkSplitTreeSHA3_6(t *testing.B)  { benchmarkSplitTreeSHA3(1000000, t) }
   412  func BenchmarkSplitTreeSHA3_7(t *testing.B)  { benchmarkSplitTreeSHA3(10000000, t) }
   413  
   414  //func基准点拆分图3_8(t*testing.b)基准点拆分图3(100000000,t)
   415  
   416  func BenchmarkSplitTreeBMT_2(t *testing.B)  { benchmarkSplitTreeBMT(100, t) }
   417  func BenchmarkSplitTreeBMT_2h(t *testing.B) { benchmarkSplitTreeBMT(500, t) }
   418  func BenchmarkSplitTreeBMT_3(t *testing.B)  { benchmarkSplitTreeBMT(1000, t) }
   419  func BenchmarkSplitTreeBMT_3h(t *testing.B) { benchmarkSplitTreeBMT(5000, t) }
   420  func BenchmarkSplitTreeBMT_4(t *testing.B)  { benchmarkSplitTreeBMT(10000, t) }
   421  func BenchmarkSplitTreeBMT_4h(t *testing.B) { benchmarkSplitTreeBMT(50000, t) }
   422  func BenchmarkSplitTreeBMT_5(t *testing.B)  { benchmarkSplitTreeBMT(100000, t) }
   423  func BenchmarkSplitTreeBMT_6(t *testing.B)  { benchmarkSplitTreeBMT(1000000, t) }
   424  func BenchmarkSplitTreeBMT_7(t *testing.B)  { benchmarkSplitTreeBMT(10000000, t) }
   425  
   426  //func基准拆分树b t_8(t*testing.b)基准拆分树b t(100000000,t)
   427  
   428  func BenchmarkSplitPyramidSHA3_2(t *testing.B)  { benchmarkSplitPyramidSHA3(100, t) }
   429  func BenchmarkSplitPyramidSHA3_2h(t *testing.B) { benchmarkSplitPyramidSHA3(500, t) }
   430  func BenchmarkSplitPyramidSHA3_3(t *testing.B)  { benchmarkSplitPyramidSHA3(1000, t) }
   431  func BenchmarkSplitPyramidSHA3_3h(t *testing.B) { benchmarkSplitPyramidSHA3(5000, t) }
   432  func BenchmarkSplitPyramidSHA3_4(t *testing.B)  { benchmarkSplitPyramidSHA3(10000, t) }
   433  func BenchmarkSplitPyramidSHA3_4h(t *testing.B) { benchmarkSplitPyramidSHA3(50000, t) }
   434  func BenchmarkSplitPyramidSHA3_5(t *testing.B)  { benchmarkSplitPyramidSHA3(100000, t) }
   435  func BenchmarkSplitPyramidSHA3_6(t *testing.B)  { benchmarkSplitPyramidSHA3(1000000, t) }
   436  func BenchmarkSplitPyramidSHA3_7(t *testing.B)  { benchmarkSplitPyramidSHA3(10000000, t) }
   437  
   438  //func基准拆分金字塔3_8(t*testing.b)基准拆分金字塔3(100000000,t)
   439  
   440  func BenchmarkSplitPyramidBMT_2(t *testing.B)  { benchmarkSplitPyramidBMT(100, t) }
   441  func BenchmarkSplitPyramidBMT_2h(t *testing.B) { benchmarkSplitPyramidBMT(500, t) }
   442  func BenchmarkSplitPyramidBMT_3(t *testing.B)  { benchmarkSplitPyramidBMT(1000, t) }
   443  func BenchmarkSplitPyramidBMT_3h(t *testing.B) { benchmarkSplitPyramidBMT(5000, t) }
   444  func BenchmarkSplitPyramidBMT_4(t *testing.B)  { benchmarkSplitPyramidBMT(10000, t) }
   445  func BenchmarkSplitPyramidBMT_4h(t *testing.B) { benchmarkSplitPyramidBMT(50000, t) }
   446  func BenchmarkSplitPyramidBMT_5(t *testing.B)  { benchmarkSplitPyramidBMT(100000, t) }
   447  func BenchmarkSplitPyramidBMT_6(t *testing.B)  { benchmarkSplitPyramidBMT(1000000, t) }
   448  func BenchmarkSplitPyramidBMT_7(t *testing.B)  { benchmarkSplitPyramidBMT(10000000, t) }
   449  
   450  //func基准点拆分金字塔bmt_8(t*testing.b)基准点拆分金字塔bmt(100000000,t)
   451  
   452  func BenchmarkSplitAppendPyramid_2(t *testing.B)  { benchmarkSplitAppendPyramid(100, 1000, t) }
   453  func BenchmarkSplitAppendPyramid_2h(t *testing.B) { benchmarkSplitAppendPyramid(500, 1000, t) }
   454  func BenchmarkSplitAppendPyramid_3(t *testing.B)  { benchmarkSplitAppendPyramid(1000, 1000, t) }
   455  func BenchmarkSplitAppendPyramid_4(t *testing.B)  { benchmarkSplitAppendPyramid(10000, 1000, t) }
   456  func BenchmarkSplitAppendPyramid_4h(t *testing.B) { benchmarkSplitAppendPyramid(50000, 1000, t) }
   457  func BenchmarkSplitAppendPyramid_5(t *testing.B)  { benchmarkSplitAppendPyramid(1000000, 1000, t) }
   458  func BenchmarkSplitAppendPyramid_6(t *testing.B)  { benchmarkSplitAppendPyramid(1000000, 1000, t) }
   459  func BenchmarkSplitAppendPyramid_7(t *testing.B)  { benchmarkSplitAppendPyramid(10000000, 1000, t) }
   460  
   461  //Func BenchmarkAppendPyramid_8(t*testing.b)BenchmarkAppendPyramid(100000000,1000,t)
   462  
   463  //通过测试-超时20M-CPU 4-工作台=/Swarm/存储-运行编号
   464  //如果不在上面添加超时参数..基准将超时并转储
   465