github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/stream/common_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 12:09:48</date> 10 //</624342675046273024> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package stream 29 30 import ( 31 "context" 32 crand "crypto/rand" 33 "errors" 34 "flag" 35 "fmt" 36 "io" 37 "io/ioutil" 38 "math/rand" 39 "os" 40 "strings" 41 "sync/atomic" 42 "testing" 43 "time" 44 45 "github.com/ethereum/go-ethereum/log" 46 "github.com/ethereum/go-ethereum/p2p/discover" 47 p2ptest "github.com/ethereum/go-ethereum/p2p/testing" 48 "github.com/ethereum/go-ethereum/swarm/network" 49 "github.com/ethereum/go-ethereum/swarm/network/simulation" 50 "github.com/ethereum/go-ethereum/swarm/pot" 51 "github.com/ethereum/go-ethereum/swarm/state" 52 "github.com/ethereum/go-ethereum/swarm/storage" 53 mockdb "github.com/ethereum/go-ethereum/swarm/storage/mock/db" 54 colorable "github.com/mattn/go-colorable" 55 ) 56 57 var ( 58 loglevel = flag.Int("loglevel", 2, "verbosity of logs") 59 nodes = flag.Int("nodes", 0, "number of nodes") 60 chunks = flag.Int("chunks", 0, "number of chunks") 61 useMockStore = flag.Bool("mockstore", false, "disabled mock store (default: enabled)") 62 longrunning = flag.Bool("longrunning", false, "do run long-running tests") 63 64 bucketKeyDB = simulation.BucketKey("db") 65 bucketKeyStore = simulation.BucketKey("store") 66 bucketKeyFileStore = simulation.BucketKey("filestore") 67 bucketKeyNetStore = simulation.BucketKey("netstore") 68 bucketKeyDelivery = simulation.BucketKey("delivery") 69 bucketKeyRegistry = simulation.BucketKey("registry") 70 71 chunkSize = 4096 72 pof = pot.DefaultPof(256) 73 ) 74 75 func init() { 76 flag.Parse() 77 rand.Seed(time.Now().UnixNano()) 78 79 log.PrintOrigins(true) 80 log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true)))) 81 } 82 83 func createGlobalStore() (string, *mockdb.GlobalStore, error) { 84 var globalStore *mockdb.GlobalStore 85 globalStoreDir, err := ioutil.TempDir("", "global.store") 86 if err != nil { 87 log.Error("Error initiating global store temp directory!", "err", err) 88 return "", nil, err 89 } 90 globalStore, err = mockdb.NewGlobalStore(globalStoreDir) 91 if err != nil { 92 log.Error("Error initiating global store!", "err", err) 93 return "", nil, err 94 } 95 return globalStoreDir, globalStore, nil 96 } 97 98 func newStreamerTester(t *testing.T) (*p2ptest.ProtocolTester, *Registry, *storage.LocalStore, func(), error) { 99 // 100 addr := network.RandomAddr() // 101 to := network.NewKademlia(addr.OAddr, network.NewKadParams()) 102 103 // 104 datadir, err := ioutil.TempDir("", "streamer") 105 if err != nil { 106 return nil, nil, nil, func() {}, err 107 } 108 removeDataDir := func() { 109 os.RemoveAll(datadir) 110 } 111 112 params := storage.NewDefaultLocalStoreParams() 113 params.Init(datadir) 114 params.BaseKey = addr.Over() 115 116 localStore, err := storage.NewTestLocalStoreForAddr(params) 117 if err != nil { 118 return nil, nil, nil, removeDataDir, err 119 } 120 121 db := storage.NewDBAPI(localStore) 122 delivery := NewDelivery(to, db) 123 streamer := NewRegistry(addr, delivery, db, state.NewInmemoryStore(), nil) 124 teardown := func() { 125 streamer.Close() 126 removeDataDir() 127 } 128 protocolTester := p2ptest.NewProtocolTester(t, network.NewNodeIDFromAddr(addr), 1, streamer.runProtocol) 129 130 err = waitForPeers(streamer, 1*time.Second, 1) 131 if err != nil { 132 return nil, nil, nil, nil, errors.New("timeout: peer is not created") 133 } 134 135 return protocolTester, streamer, localStore, teardown, nil 136 } 137 138 func waitForPeers(streamer *Registry, timeout time.Duration, expectedPeers int) error { 139 ticker := time.NewTicker(10 * time.Millisecond) 140 timeoutTimer := time.NewTimer(timeout) 141 for { 142 select { 143 case <-ticker.C: 144 if streamer.peersCount() >= expectedPeers { 145 return nil 146 } 147 case <-timeoutTimer.C: 148 return errors.New("timeout") 149 } 150 } 151 } 152 153 type roundRobinStore struct { 154 index uint32 155 stores []storage.ChunkStore 156 } 157 158 func newRoundRobinStore(stores ...storage.ChunkStore) *roundRobinStore { 159 return &roundRobinStore{ 160 stores: stores, 161 } 162 } 163 164 func (rrs *roundRobinStore) Get(ctx context.Context, addr storage.Address) (*storage.Chunk, error) { 165 return nil, errors.New("get not well defined on round robin store") 166 } 167 168 func (rrs *roundRobinStore) Put(ctx context.Context, chunk *storage.Chunk) { 169 i := atomic.AddUint32(&rrs.index, 1) 170 idx := int(i) % len(rrs.stores) 171 rrs.stores[idx].Put(ctx, chunk) 172 } 173 174 func (rrs *roundRobinStore) Close() { 175 for _, store := range rrs.stores { 176 store.Close() 177 } 178 } 179 180 func readAll(fileStore *storage.FileStore, hash []byte) (int64, error) { 181 r, _ := fileStore.Retrieve(context.TODO(), hash) 182 buf := make([]byte, 1024) 183 var n int 184 var total int64 185 var err error 186 for (total == 0 || n > 0) && err == nil { 187 n, err = r.ReadAt(buf, total) 188 total += int64(n) 189 } 190 if err != nil && err != io.EOF { 191 return total, err 192 } 193 return total, nil 194 } 195 196 func uploadFilesToNodes(sim *simulation.Simulation) ([]storage.Address, []string, error) { 197 nodes := sim.UpNodeIDs() 198 nodeCnt := len(nodes) 199 log.Debug(fmt.Sprintf("Uploading %d files to nodes", nodeCnt)) 200 // 201 rfiles := make([]string, nodeCnt) 202 // 203 rootAddrs := make([]storage.Address, nodeCnt) 204 205 var err error 206 // 207 for i, id := range nodes { 208 item, ok := sim.NodeItem(id, bucketKeyFileStore) 209 if !ok { 210 return nil, nil, fmt.Errorf("Error accessing localstore") 211 } 212 fileStore := item.(*storage.FileStore) 213 // 214 rfiles[i], err = generateRandomFile() 215 if err != nil { 216 return nil, nil, err 217 } 218 // 219 ctx := context.TODO() 220 rk, wait, err := fileStore.Store(ctx, strings.NewReader(rfiles[i]), int64(len(rfiles[i])), false) 221 log.Debug("Uploaded random string file to node") 222 if err != nil { 223 return nil, nil, err 224 } 225 err = wait(ctx) 226 if err != nil { 227 return nil, nil, err 228 } 229 rootAddrs[i] = rk 230 } 231 return rootAddrs, rfiles, nil 232 } 233 234 // 235 func generateRandomFile() (string, error) { 236 // 237 fileSize := rand.Intn(maxFileSize-minFileSize) + minFileSize 238 log.Debug(fmt.Sprintf("Generated file with filesize %d kB", fileSize)) 239 b := make([]byte, fileSize*1024) 240 _, err := crand.Read(b) 241 if err != nil { 242 log.Error("Error generating random file.", "err", err) 243 return "", err 244 } 245 return string(b), nil 246 } 247 248 // 249 func createTestLocalStorageForID(id discover.NodeID, addr *network.BzzAddr) (storage.ChunkStore, string, error) { 250 var datadir string 251 var err error 252 datadir, err = ioutil.TempDir("", fmt.Sprintf("syncer-test-%s", id.TerminalString())) 253 if err != nil { 254 return nil, "", err 255 } 256 var store storage.ChunkStore 257 params := storage.NewDefaultLocalStoreParams() 258 params.ChunkDbPath = datadir 259 params.BaseKey = addr.Over() 260 store, err = storage.NewTestLocalStoreForAddr(params) 261 if err != nil { 262 os.RemoveAll(datadir) 263 return nil, "", err 264 } 265 return store, datadir, nil 266 } 267