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 }