github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/stream/syncer_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 //</624342676371673088> 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 "fmt" 34 "io" 35 "io/ioutil" 36 "math" 37 "os" 38 "sync" 39 "testing" 40 "time" 41 42 "github.com/ethereum/go-ethereum/common" 43 "github.com/ethereum/go-ethereum/node" 44 "github.com/ethereum/go-ethereum/p2p" 45 "github.com/ethereum/go-ethereum/p2p/discover" 46 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 47 "github.com/ethereum/go-ethereum/swarm/log" 48 "github.com/ethereum/go-ethereum/swarm/network" 49 "github.com/ethereum/go-ethereum/swarm/network/simulation" 50 "github.com/ethereum/go-ethereum/swarm/state" 51 "github.com/ethereum/go-ethereum/swarm/storage" 52 mockdb "github.com/ethereum/go-ethereum/swarm/storage/mock/db" 53 ) 54 55 const dataChunkCount = 200 56 57 func TestSyncerSimulation(t *testing.T) { 58 testSyncBetweenNodes(t, 2, 1, dataChunkCount, true, 1) 59 testSyncBetweenNodes(t, 4, 1, dataChunkCount, true, 1) 60 testSyncBetweenNodes(t, 8, 1, dataChunkCount, true, 1) 61 testSyncBetweenNodes(t, 16, 1, dataChunkCount, true, 1) 62 } 63 64 func createMockStore(globalStore *mockdb.GlobalStore, id discover.NodeID, addr *network.BzzAddr) (lstore storage.ChunkStore, datadir string, err error) { 65 address := common.BytesToAddress(id.Bytes()) 66 mockStore := globalStore.NewNodeStore(address) 67 params := storage.NewDefaultLocalStoreParams() 68 69 datadir, err = ioutil.TempDir("", "localMockStore-"+id.TerminalString()) 70 if err != nil { 71 return nil, "", err 72 } 73 params.Init(datadir) 74 params.BaseKey = addr.Over() 75 lstore, err = storage.NewLocalStore(params, mockStore) 76 return lstore, datadir, nil 77 } 78 79 func testSyncBetweenNodes(t *testing.T, nodes, conns, chunkCount int, skipCheck bool, po uint8) { 80 sim := simulation.New(map[string]simulation.ServiceFunc{ 81 "streamer": func(ctx *adapters.ServiceContext, bucket *sync.Map) (s node.Service, cleanup func(), err error) { 82 var store storage.ChunkStore 83 var globalStore *mockdb.GlobalStore 84 var gDir, datadir string 85 86 id := ctx.Config.ID 87 addr := network.NewAddrFromNodeID(id) 88 // 89 addr.OAddr[0] = byte(0) 90 91 if *useMockStore { 92 gDir, globalStore, err = createGlobalStore() 93 if err != nil { 94 return nil, nil, fmt.Errorf("Something went wrong; using mockStore enabled but globalStore is nil") 95 } 96 store, datadir, err = createMockStore(globalStore, id, addr) 97 } else { 98 store, datadir, err = createTestLocalStorageForID(id, addr) 99 } 100 if err != nil { 101 return nil, nil, err 102 } 103 bucket.Store(bucketKeyStore, store) 104 cleanup = func() { 105 store.Close() 106 os.RemoveAll(datadir) 107 if *useMockStore { 108 err := globalStore.Close() 109 if err != nil { 110 log.Error("Error closing global store! %v", "err", err) 111 } 112 os.RemoveAll(gDir) 113 } 114 } 115 localStore := store.(*storage.LocalStore) 116 db := storage.NewDBAPI(localStore) 117 bucket.Store(bucketKeyDB, db) 118 kad := network.NewKademlia(addr.Over(), network.NewKadParams()) 119 delivery := NewDelivery(kad, db) 120 bucket.Store(bucketKeyDelivery, delivery) 121 122 r := NewRegistry(addr, delivery, db, state.NewInmemoryStore(), &RegistryOptions{ 123 SkipCheck: skipCheck, 124 }) 125 126 fileStore := storage.NewFileStore(storage.NewNetStore(localStore, nil), storage.NewFileStoreParams()) 127 bucket.Store(bucketKeyFileStore, fileStore) 128 129 return r, cleanup, nil 130 131 }, 132 }) 133 defer sim.Close() 134 135 // 136 timeout := 30 * time.Second 137 ctx, cancel := context.WithTimeout(context.Background(), timeout) 138 // 139 defer cancel() 140 141 _, err := sim.AddNodesAndConnectChain(nodes) 142 if err != nil { 143 t.Fatal(err) 144 } 145 result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error { 146 nodeIDs := sim.UpNodeIDs() 147 148 nodeIndex := make(map[discover.NodeID]int) 149 for i, id := range nodeIDs { 150 nodeIndex[id] = i 151 } 152 153 disconnections := sim.PeerEvents( 154 context.Background(), 155 sim.NodeIDs(), 156 simulation.NewPeerEventsFilter().Type(p2p.PeerEventTypeDrop), 157 ) 158 159 go func() { 160 for d := range disconnections { 161 if d.Error != nil { 162 log.Error("peer drop", "node", d.NodeID, "peer", d.Event.Peer) 163 t.Fatal(d.Error) 164 } 165 } 166 }() 167 168 // 169 for j := 0; j < nodes-1; j++ { 170 id := nodeIDs[j] 171 client, err := sim.Net.GetNode(id).Client() 172 if err != nil { 173 t.Fatal(err) 174 } 175 sid := nodeIDs[j+1] 176 client.CallContext(ctx, nil, "stream_subscribeStream", sid, NewStream("SYNC", FormatSyncBinKey(1), false), NewRange(0, 0), Top) 177 if err != nil { 178 return err 179 } 180 if j > 0 || nodes == 2 { 181 item, ok := sim.NodeItem(nodeIDs[j], bucketKeyFileStore) 182 if !ok { 183 return fmt.Errorf("No filestore") 184 } 185 fileStore := item.(*storage.FileStore) 186 size := chunkCount * chunkSize 187 _, wait, err := fileStore.Store(ctx, io.LimitReader(crand.Reader, int64(size)), int64(size), false) 188 if err != nil { 189 t.Fatal(err.Error()) 190 } 191 wait(ctx) 192 } 193 } 194 // 195 if _, err := sim.WaitTillHealthy(ctx, 2); err != nil { 196 return err 197 } 198 199 // 200 hashes := make([][]storage.Address, nodes) 201 totalHashes := 0 202 hashCounts := make([]int, nodes) 203 for i := nodes - 1; i >= 0; i-- { 204 if i < nodes-1 { 205 hashCounts[i] = hashCounts[i+1] 206 } 207 item, ok := sim.NodeItem(nodeIDs[i], bucketKeyDB) 208 if !ok { 209 return fmt.Errorf("No DB") 210 } 211 db := item.(*storage.DBAPI) 212 db.Iterator(0, math.MaxUint64, po, func(addr storage.Address, index uint64) bool { 213 hashes[i] = append(hashes[i], addr) 214 totalHashes++ 215 hashCounts[i]++ 216 return true 217 }) 218 } 219 var total, found int 220 for _, node := range nodeIDs { 221 i := nodeIndex[node] 222 223 for j := i; j < nodes; j++ { 224 total += len(hashes[j]) 225 for _, key := range hashes[j] { 226 item, ok := sim.NodeItem(nodeIDs[j], bucketKeyDB) 227 if !ok { 228 return fmt.Errorf("No DB") 229 } 230 db := item.(*storage.DBAPI) 231 chunk, err := db.Get(ctx, key) 232 if err == storage.ErrFetching { 233 <-chunk.ReqC 234 } else if err != nil { 235 continue 236 } 237 // 238 // 239 found++ 240 } 241 } 242 log.Debug("sync check", "node", node, "index", i, "bin", po, "found", found, "total", total) 243 } 244 if total == found && total > 0 { 245 return nil 246 } 247 return fmt.Errorf("Total not equallying found: total is %d", total) 248 }) 249 250 if result.Error != nil { 251 t.Fatal(result.Error) 252 } 253 } 254