github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/swarm/storage/chunker_test.go (about)

     1  // Copyright 2016 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package storage
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/rand"
    22  	"encoding/binary"
    23  	"errors"
    24  	"fmt"
    25  	"io"
    26  	"sync"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/SmartMeshFoundation/Spectrum/crypto/sha3"
    31  )
    32  
    33  /*
    34  Tests TreeChunker by splitting and joining a random byte slice
    35  */
    36  
    37  type test interface {
    38  	Fatalf(string, ...interface{})
    39  	Logf(string, ...interface{})
    40  }
    41  
    42  type chunkerTester struct {
    43  	inputs map[uint64][]byte
    44  	chunks map[string]*Chunk
    45  	t      test
    46  }
    47  
    48  func (self *chunkerTester) Split(chunker Splitter, data io.Reader, size int64, chunkC chan *Chunk, swg *sync.WaitGroup, expectedError error) (key Key, err error) {
    49  	// reset
    50  	self.chunks = make(map[string]*Chunk)
    51  
    52  	if self.inputs == nil {
    53  		self.inputs = make(map[uint64][]byte)
    54  	}
    55  
    56  	quitC := make(chan bool)
    57  	timeout := time.After(600 * time.Second)
    58  	if chunkC != nil {
    59  		go func() error {
    60  			for {
    61  				select {
    62  				case <-timeout:
    63  					return errors.New(("Split timeout error"))
    64  				case <-quitC:
    65  					return nil
    66  				case chunk := <-chunkC:
    67  					// self.chunks = append(self.chunks, chunk)
    68  					self.chunks[chunk.Key.String()] = chunk
    69  					if chunk.wg != nil {
    70  						chunk.wg.Done()
    71  					}
    72  				}
    73  
    74  			}
    75  		}()
    76  	}
    77  
    78  	key, err = chunker.Split(data, size, chunkC, swg, nil)
    79  	if err != nil && expectedError == nil {
    80  		err = fmt.Errorf("Split error: %v", err)
    81  	}
    82  
    83  	if chunkC != nil {
    84  		if swg != nil {
    85  			swg.Wait()
    86  		}
    87  		close(quitC)
    88  	}
    89  	return key, err
    90  }
    91  
    92  func (self *chunkerTester) Append(chunker Splitter, rootKey Key, data io.Reader, chunkC chan *Chunk, swg *sync.WaitGroup, expectedError error) (key Key, err error) {
    93  	quitC := make(chan bool)
    94  	timeout := time.After(60 * time.Second)
    95  	if chunkC != nil {
    96  		go func() error {
    97  			for {
    98  				select {
    99  				case <-timeout:
   100  					return errors.New(("Append timeout error"))
   101  				case <-quitC:
   102  					return nil
   103  				case chunk := <-chunkC:
   104  					if chunk != nil {
   105  						stored, success := self.chunks[chunk.Key.String()]
   106  						if !success {
   107  							// Requesting data
   108  							self.chunks[chunk.Key.String()] = chunk
   109  							if chunk.wg != nil {
   110  								chunk.wg.Done()
   111  							}
   112  						} else {
   113  							// getting data
   114  							chunk.SData = stored.SData
   115  							chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8]))
   116  							close(chunk.C)
   117  						}
   118  					}
   119  				}
   120  			}
   121  		}()
   122  	}
   123  
   124  	key, err = chunker.Append(rootKey, data, chunkC, swg, nil)
   125  	if err != nil && expectedError == nil {
   126  		err = fmt.Errorf("Append error: %v", err)
   127  	}
   128  
   129  	if chunkC != nil {
   130  		if swg != nil {
   131  			swg.Wait()
   132  		}
   133  		close(quitC)
   134  	}
   135  	return key, err
   136  }
   137  
   138  func (self *chunkerTester) Join(chunker Chunker, key Key, c int, chunkC chan *Chunk, quitC chan bool) LazySectionReader {
   139  	// reset but not the chunks
   140  
   141  	reader := chunker.Join(key, chunkC)
   142  
   143  	timeout := time.After(600 * time.Second)
   144  	i := 0
   145  	go func() error {
   146  		for {
   147  			select {
   148  			case <-timeout:
   149  				return errors.New(("Join timeout error"))
   150  			case chunk, ok := <-chunkC:
   151  				if !ok {
   152  					close(quitC)
   153  					return nil
   154  				}
   155  				// this just mocks the behaviour of a chunk store retrieval
   156  				stored, success := self.chunks[chunk.Key.String()]
   157  				if !success {
   158  					return errors.New(("Not found"))
   159  				}
   160  				chunk.SData = stored.SData
   161  				chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8]))
   162  				close(chunk.C)
   163  				i++
   164  			}
   165  		}
   166  	}()
   167  	return reader
   168  }
   169  
   170  func testRandomBrokenData(splitter Splitter, n int, tester *chunkerTester) {
   171  	data := io.LimitReader(rand.Reader, int64(n))
   172  	brokendata := brokenLimitReader(data, n, n/2)
   173  
   174  	buf := make([]byte, n)
   175  	_, err := brokendata.Read(buf)
   176  	if err == nil || err.Error() != "Broken reader" {
   177  		tester.t.Fatalf("Broken reader is not broken, hence broken. Returns: %v", err)
   178  	}
   179  
   180  	data = io.LimitReader(rand.Reader, int64(n))
   181  	brokendata = brokenLimitReader(data, n, n/2)
   182  
   183  	chunkC := make(chan *Chunk, 1000)
   184  	swg := &sync.WaitGroup{}
   185  
   186  	expectedError := fmt.Errorf("Broken reader")
   187  	key, err := tester.Split(splitter, brokendata, int64(n), chunkC, swg, expectedError)
   188  	if err == nil || err.Error() != expectedError.Error() {
   189  		tester.t.Fatalf("Not receiving the correct error! Expected %v, received %v", expectedError, err)
   190  	}
   191  	tester.t.Logf(" Key = %v\n", key)
   192  }
   193  
   194  func testRandomData(splitter Splitter, n int, tester *chunkerTester) Key {
   195  	if tester.inputs == nil {
   196  		tester.inputs = make(map[uint64][]byte)
   197  	}
   198  	input, found := tester.inputs[uint64(n)]
   199  	var data io.Reader
   200  	if !found {
   201  		data, input = testDataReaderAndSlice(n)
   202  		tester.inputs[uint64(n)] = input
   203  	} else {
   204  		data = io.LimitReader(bytes.NewReader(input), int64(n))
   205  	}
   206  
   207  	chunkC := make(chan *Chunk, 1000)
   208  	swg := &sync.WaitGroup{}
   209  
   210  	key, err := tester.Split(splitter, data, int64(n), chunkC, swg, nil)
   211  	if err != nil {
   212  		tester.t.Fatalf(err.Error())
   213  	}
   214  	tester.t.Logf(" Key = %v\n", key)
   215  
   216  	chunkC = make(chan *Chunk, 1000)
   217  	quitC := make(chan bool)
   218  
   219  	chunker := NewTreeChunker(NewChunkerParams())
   220  	reader := tester.Join(chunker, key, 0, chunkC, quitC)
   221  	output := make([]byte, n)
   222  	r, err := reader.Read(output)
   223  	if r != n || err != io.EOF {
   224  		tester.t.Fatalf("read error  read: %v  n = %v  err = %v\n", r, n, err)
   225  	}
   226  	if input != nil {
   227  		if !bytes.Equal(output, input) {
   228  			tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", input, output)
   229  		}
   230  	}
   231  	close(chunkC)
   232  	<-quitC
   233  
   234  	return key
   235  }
   236  
   237  func testRandomDataAppend(splitter Splitter, n, m int, tester *chunkerTester) {
   238  	if tester.inputs == nil {
   239  		tester.inputs = make(map[uint64][]byte)
   240  	}
   241  	input, found := tester.inputs[uint64(n)]
   242  	var data io.Reader
   243  	if !found {
   244  		data, input = testDataReaderAndSlice(n)
   245  		tester.inputs[uint64(n)] = input
   246  	} else {
   247  		data = io.LimitReader(bytes.NewReader(input), int64(n))
   248  	}
   249  
   250  	chunkC := make(chan *Chunk, 1000)
   251  	swg := &sync.WaitGroup{}
   252  
   253  	key, err := tester.Split(splitter, data, int64(n), chunkC, swg, nil)
   254  	if err != nil {
   255  		tester.t.Fatalf(err.Error())
   256  	}
   257  	tester.t.Logf(" Key = %v\n", key)
   258  
   259  	//create a append data stream
   260  	appendInput, found := tester.inputs[uint64(m)]
   261  	var appendData io.Reader
   262  	if !found {
   263  		appendData, appendInput = testDataReaderAndSlice(m)
   264  		tester.inputs[uint64(m)] = appendInput
   265  	} else {
   266  		appendData = io.LimitReader(bytes.NewReader(appendInput), int64(m))
   267  	}
   268  
   269  	chunkC = make(chan *Chunk, 1000)
   270  	swg = &sync.WaitGroup{}
   271  
   272  	newKey, err := tester.Append(splitter, key, appendData, chunkC, swg, nil)
   273  	if err != nil {
   274  		tester.t.Fatalf(err.Error())
   275  	}
   276  	tester.t.Logf(" NewKey = %v\n", newKey)
   277  
   278  	chunkC = make(chan *Chunk, 1000)
   279  	quitC := make(chan bool)
   280  
   281  	chunker := NewTreeChunker(NewChunkerParams())
   282  	reader := tester.Join(chunker, newKey, 0, chunkC, quitC)
   283  	newOutput := make([]byte, n+m)
   284  	r, err := reader.Read(newOutput)
   285  	if r != (n + m) {
   286  		tester.t.Fatalf("read error  read: %v  n = %v  err = %v\n", r, n, err)
   287  	}
   288  
   289  	newInput := append(input, appendInput...)
   290  	if !bytes.Equal(newOutput, newInput) {
   291  		tester.t.Fatalf("input and output mismatch\n IN: %v\nOUT: %v\n", newInput, newOutput)
   292  	}
   293  
   294  	close(chunkC)
   295  }
   296  
   297  func TestSha3ForCorrectness(t *testing.T) {
   298  	tester := &chunkerTester{t: t}
   299  
   300  	size := 4096
   301  	input := make([]byte, size+8)
   302  	binary.LittleEndian.PutUint64(input[:8], uint64(size))
   303  
   304  	io.LimitReader(bytes.NewReader(input[8:]), int64(size))
   305  
   306  	rawSha3 := sha3.NewKeccak256()
   307  	rawSha3.Reset()
   308  	rawSha3.Write(input)
   309  	rawSha3Output := rawSha3.Sum(nil)
   310  
   311  	sha3FromMakeFunc := MakeHashFunc(SHA3Hash)()
   312  	sha3FromMakeFunc.ResetWithLength(input[:8])
   313  	sha3FromMakeFunc.Write(input[8:])
   314  	sha3FromMakeFuncOutput := sha3FromMakeFunc.Sum(nil)
   315  
   316  	if len(rawSha3Output) != len(sha3FromMakeFuncOutput) {
   317  		tester.t.Fatalf("Original SHA3 and abstracted Sha3 has different length %v:%v\n", len(rawSha3Output), len(sha3FromMakeFuncOutput))
   318  	}
   319  
   320  	if !bytes.Equal(rawSha3Output, sha3FromMakeFuncOutput) {
   321  		tester.t.Fatalf("Original SHA3 and abstracted Sha3 mismatch %v:%v\n", rawSha3Output, sha3FromMakeFuncOutput)
   322  	}
   323  
   324  }
   325  
   326  func TestDataAppend(t *testing.T) {
   327  	sizes := []int{1, 1, 1, 4095, 4096, 4097, 1, 1, 1, 123456, 2345678, 2345678}
   328  	appendSizes := []int{4095, 4096, 4097, 1, 1, 1, 8191, 8192, 8193, 9000, 3000, 5000}
   329  
   330  	tester := &chunkerTester{t: t}
   331  	chunker := NewPyramidChunker(NewChunkerParams())
   332  	for i, s := range sizes {
   333  		testRandomDataAppend(chunker, s, appendSizes[i], tester)
   334  
   335  	}
   336  }
   337  
   338  func TestRandomData(t *testing.T) {
   339  	sizes := []int{1, 60, 83, 179, 253, 1024, 4095, 4096, 4097, 8191, 8192, 8193, 12287, 12288, 12289, 123456, 2345678}
   340  	tester := &chunkerTester{t: t}
   341  
   342  	chunker := NewTreeChunker(NewChunkerParams())
   343  	pyramid := NewPyramidChunker(NewChunkerParams())
   344  	for _, s := range sizes {
   345  		treeChunkerKey := testRandomData(chunker, s, tester)
   346  		pyramidChunkerKey := testRandomData(pyramid, s, tester)
   347  		if treeChunkerKey.String() != pyramidChunkerKey.String() {
   348  			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())
   349  		}
   350  	}
   351  
   352  	cp := NewChunkerParams()
   353  	cp.Hash = BMTHash
   354  	chunker = NewTreeChunker(cp)
   355  	pyramid = NewPyramidChunker(cp)
   356  	for _, s := range sizes {
   357  		treeChunkerKey := testRandomData(chunker, s, tester)
   358  		pyramidChunkerKey := testRandomData(pyramid, s, tester)
   359  		if treeChunkerKey.String() != pyramidChunkerKey.String() {
   360  			tester.t.Fatalf("tree chunker BMT and pyramid chunker BMT key mismatch for size %v \n TC: %v\n PC: %v\n", s, treeChunkerKey.String(), pyramidChunkerKey.String())
   361  		}
   362  	}
   363  
   364  }
   365  
   366  func TestRandomBrokenData(t *testing.T) {
   367  	sizes := []int{1, 60, 83, 179, 253, 1024, 4095, 4096, 4097, 8191, 8192, 8193, 12287, 12288, 12289, 123456, 2345678}
   368  	tester := &chunkerTester{t: t}
   369  	chunker := NewTreeChunker(NewChunkerParams())
   370  	for _, s := range sizes {
   371  		testRandomBrokenData(chunker, s, tester)
   372  	}
   373  }
   374  
   375  func benchReadAll(reader LazySectionReader) {
   376  	size, _ := reader.Size(nil)
   377  	output := make([]byte, 1000)
   378  	for pos := int64(0); pos < size; pos += 1000 {
   379  		reader.ReadAt(output, pos)
   380  	}
   381  }
   382  
   383  func benchmarkJoin(n int, t *testing.B) {
   384  	t.ReportAllocs()
   385  	for i := 0; i < t.N; i++ {
   386  		chunker := NewTreeChunker(NewChunkerParams())
   387  		tester := &chunkerTester{t: t}
   388  		data := testDataReader(n)
   389  
   390  		chunkC := make(chan *Chunk, 1000)
   391  		swg := &sync.WaitGroup{}
   392  
   393  		key, err := tester.Split(chunker, data, int64(n), chunkC, swg, nil)
   394  		if err != nil {
   395  			tester.t.Fatalf(err.Error())
   396  		}
   397  		chunkC = make(chan *Chunk, 1000)
   398  		quitC := make(chan bool)
   399  		reader := tester.Join(chunker, key, i, chunkC, quitC)
   400  		benchReadAll(reader)
   401  		close(chunkC)
   402  		<-quitC
   403  	}
   404  }
   405  
   406  func benchmarkSplitTreeSHA3(n int, t *testing.B) {
   407  	t.ReportAllocs()
   408  	for i := 0; i < t.N; i++ {
   409  		chunker := NewTreeChunker(NewChunkerParams())
   410  		tester := &chunkerTester{t: t}
   411  		data := testDataReader(n)
   412  		_, err := tester.Split(chunker, data, int64(n), nil, nil, nil)
   413  		if err != nil {
   414  			tester.t.Fatalf(err.Error())
   415  		}
   416  	}
   417  }
   418  
   419  func benchmarkSplitTreeBMT(n int, t *testing.B) {
   420  	t.ReportAllocs()
   421  	for i := 0; i < t.N; i++ {
   422  		cp := NewChunkerParams()
   423  		cp.Hash = BMTHash
   424  		chunker := NewTreeChunker(cp)
   425  		tester := &chunkerTester{t: t}
   426  		data := testDataReader(n)
   427  		_, err := tester.Split(chunker, data, int64(n), nil, nil, nil)
   428  		if err != nil {
   429  			tester.t.Fatalf(err.Error())
   430  		}
   431  	}
   432  }
   433  
   434  func benchmarkSplitPyramidSHA3(n int, t *testing.B) {
   435  	t.ReportAllocs()
   436  	for i := 0; i < t.N; i++ {
   437  		splitter := NewPyramidChunker(NewChunkerParams())
   438  		tester := &chunkerTester{t: t}
   439  		data := testDataReader(n)
   440  		_, err := tester.Split(splitter, data, int64(n), nil, nil, nil)
   441  		if err != nil {
   442  			tester.t.Fatalf(err.Error())
   443  		}
   444  	}
   445  }
   446  
   447  func benchmarkSplitPyramidBMT(n int, t *testing.B) {
   448  	t.ReportAllocs()
   449  	for i := 0; i < t.N; i++ {
   450  		cp := NewChunkerParams()
   451  		cp.Hash = BMTHash
   452  		splitter := NewPyramidChunker(cp)
   453  		tester := &chunkerTester{t: t}
   454  		data := testDataReader(n)
   455  		_, err := tester.Split(splitter, data, int64(n), nil, nil, nil)
   456  		if err != nil {
   457  			tester.t.Fatalf(err.Error())
   458  		}
   459  	}
   460  }
   461  
   462  func benchmarkAppendPyramid(n, m int, t *testing.B) {
   463  	t.ReportAllocs()
   464  	for i := 0; i < t.N; i++ {
   465  		chunker := NewPyramidChunker(NewChunkerParams())
   466  		tester := &chunkerTester{t: t}
   467  		data := testDataReader(n)
   468  		data1 := testDataReader(m)
   469  
   470  		chunkC := make(chan *Chunk, 1000)
   471  		swg := &sync.WaitGroup{}
   472  		key, err := tester.Split(chunker, data, int64(n), chunkC, swg, nil)
   473  		if err != nil {
   474  			tester.t.Fatalf(err.Error())
   475  		}
   476  
   477  		chunkC = make(chan *Chunk, 1000)
   478  		swg = &sync.WaitGroup{}
   479  
   480  		_, err = tester.Append(chunker, key, data1, chunkC, swg, nil)
   481  		if err != nil {
   482  			tester.t.Fatalf(err.Error())
   483  		}
   484  
   485  		close(chunkC)
   486  	}
   487  }
   488  
   489  func BenchmarkJoin_2(t *testing.B) { benchmarkJoin(100, t) }
   490  func BenchmarkJoin_3(t *testing.B) { benchmarkJoin(1000, t) }
   491  func BenchmarkJoin_4(t *testing.B) { benchmarkJoin(10000, t) }
   492  func BenchmarkJoin_5(t *testing.B) { benchmarkJoin(100000, t) }
   493  func BenchmarkJoin_6(t *testing.B) { benchmarkJoin(1000000, t) }
   494  func BenchmarkJoin_7(t *testing.B) { benchmarkJoin(10000000, t) }
   495  func BenchmarkJoin_8(t *testing.B) { benchmarkJoin(100000000, t) }
   496  
   497  func BenchmarkSplitTreeSHA3_2(t *testing.B)  { benchmarkSplitTreeSHA3(100, t) }
   498  func BenchmarkSplitTreeSHA3_2h(t *testing.B) { benchmarkSplitTreeSHA3(500, t) }
   499  func BenchmarkSplitTreeSHA3_3(t *testing.B)  { benchmarkSplitTreeSHA3(1000, t) }
   500  func BenchmarkSplitTreeSHA3_3h(t *testing.B) { benchmarkSplitTreeSHA3(5000, t) }
   501  func BenchmarkSplitTreeSHA3_4(t *testing.B)  { benchmarkSplitTreeSHA3(10000, t) }
   502  func BenchmarkSplitTreeSHA3_4h(t *testing.B) { benchmarkSplitTreeSHA3(50000, t) }
   503  func BenchmarkSplitTreeSHA3_5(t *testing.B)  { benchmarkSplitTreeSHA3(100000, t) }
   504  func BenchmarkSplitTreeSHA3_6(t *testing.B)  { benchmarkSplitTreeSHA3(1000000, t) }
   505  func BenchmarkSplitTreeSHA3_7(t *testing.B)  { benchmarkSplitTreeSHA3(10000000, t) }
   506  func BenchmarkSplitTreeSHA3_8(t *testing.B)  { benchmarkSplitTreeSHA3(100000000, t) }
   507  
   508  func BenchmarkSplitTreeBMT_2(t *testing.B)  { benchmarkSplitTreeBMT(100, t) }
   509  func BenchmarkSplitTreeBMT_2h(t *testing.B) { benchmarkSplitTreeBMT(500, t) }
   510  func BenchmarkSplitTreeBMT_3(t *testing.B)  { benchmarkSplitTreeBMT(1000, t) }
   511  func BenchmarkSplitTreeBMT_3h(t *testing.B) { benchmarkSplitTreeBMT(5000, t) }
   512  func BenchmarkSplitTreeBMT_4(t *testing.B)  { benchmarkSplitTreeBMT(10000, t) }
   513  func BenchmarkSplitTreeBMT_4h(t *testing.B) { benchmarkSplitTreeBMT(50000, t) }
   514  func BenchmarkSplitTreeBMT_5(t *testing.B)  { benchmarkSplitTreeBMT(100000, t) }
   515  func BenchmarkSplitTreeBMT_6(t *testing.B)  { benchmarkSplitTreeBMT(1000000, t) }
   516  func BenchmarkSplitTreeBMT_7(t *testing.B)  { benchmarkSplitTreeBMT(10000000, t) }
   517  func BenchmarkSplitTreeBMT_8(t *testing.B)  { benchmarkSplitTreeBMT(100000000, t) }
   518  
   519  func BenchmarkSplitPyramidSHA3_2(t *testing.B)  { benchmarkSplitPyramidSHA3(100, t) }
   520  func BenchmarkSplitPyramidSHA3_2h(t *testing.B) { benchmarkSplitPyramidSHA3(500, t) }
   521  func BenchmarkSplitPyramidSHA3_3(t *testing.B)  { benchmarkSplitPyramidSHA3(1000, t) }
   522  func BenchmarkSplitPyramidSHA3_3h(t *testing.B) { benchmarkSplitPyramidSHA3(5000, t) }
   523  func BenchmarkSplitPyramidSHA3_4(t *testing.B)  { benchmarkSplitPyramidSHA3(10000, t) }
   524  func BenchmarkSplitPyramidSHA3_4h(t *testing.B) { benchmarkSplitPyramidSHA3(50000, t) }
   525  func BenchmarkSplitPyramidSHA3_5(t *testing.B)  { benchmarkSplitPyramidSHA3(100000, t) }
   526  func BenchmarkSplitPyramidSHA3_6(t *testing.B)  { benchmarkSplitPyramidSHA3(1000000, t) }
   527  func BenchmarkSplitPyramidSHA3_7(t *testing.B)  { benchmarkSplitPyramidSHA3(10000000, t) }
   528  func BenchmarkSplitPyramidSHA3_8(t *testing.B)  { benchmarkSplitPyramidSHA3(100000000, t) }
   529  
   530  func BenchmarkSplitPyramidBMT_2(t *testing.B)  { benchmarkSplitPyramidBMT(100, t) }
   531  func BenchmarkSplitPyramidBMT_2h(t *testing.B) { benchmarkSplitPyramidBMT(500, t) }
   532  func BenchmarkSplitPyramidBMT_3(t *testing.B)  { benchmarkSplitPyramidBMT(1000, t) }
   533  func BenchmarkSplitPyramidBMT_3h(t *testing.B) { benchmarkSplitPyramidBMT(5000, t) }
   534  func BenchmarkSplitPyramidBMT_4(t *testing.B)  { benchmarkSplitPyramidBMT(10000, t) }
   535  func BenchmarkSplitPyramidBMT_4h(t *testing.B) { benchmarkSplitPyramidBMT(50000, t) }
   536  func BenchmarkSplitPyramidBMT_5(t *testing.B)  { benchmarkSplitPyramidBMT(100000, t) }
   537  func BenchmarkSplitPyramidBMT_6(t *testing.B)  { benchmarkSplitPyramidBMT(1000000, t) }
   538  func BenchmarkSplitPyramidBMT_7(t *testing.B)  { benchmarkSplitPyramidBMT(10000000, t) }
   539  func BenchmarkSplitPyramidBMT_8(t *testing.B)  { benchmarkSplitPyramidBMT(100000000, t) }
   540  
   541  func BenchmarkAppendPyramid_2(t *testing.B)  { benchmarkAppendPyramid(100, 1000, t) }
   542  func BenchmarkAppendPyramid_2h(t *testing.B) { benchmarkAppendPyramid(500, 1000, t) }
   543  func BenchmarkAppendPyramid_3(t *testing.B)  { benchmarkAppendPyramid(1000, 1000, t) }
   544  func BenchmarkAppendPyramid_4(t *testing.B)  { benchmarkAppendPyramid(10000, 1000, t) }
   545  func BenchmarkAppendPyramid_4h(t *testing.B) { benchmarkAppendPyramid(50000, 1000, t) }
   546  func BenchmarkAppendPyramid_5(t *testing.B)  { benchmarkAppendPyramid(1000000, 1000, t) }
   547  func BenchmarkAppendPyramid_6(t *testing.B)  { benchmarkAppendPyramid(1000000, 1000, t) }
   548  func BenchmarkAppendPyramid_7(t *testing.B)  { benchmarkAppendPyramid(10000000, 1000, t) }
   549  func BenchmarkAppendPyramid_8(t *testing.B)  { benchmarkAppendPyramid(100000000, 1000, t) }
   550  
   551  // go test -timeout 20m -cpu 4 -bench=./swarm/storage -run no
   552  // If you dont add the timeout argument above .. the benchmark will timeout and dump