github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/go-ethereum-master/swarm/network/stream/intervals_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package stream 18 19 import ( 20 "context" 21 crand "crypto/rand" 22 "encoding/binary" 23 "fmt" 24 "io" 25 "sync" 26 "testing" 27 "time" 28 29 "github.com/ethereum/go-ethereum/node" 30 "github.com/ethereum/go-ethereum/p2p/discover" 31 "github.com/ethereum/go-ethereum/p2p/simulations" 32 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 33 "github.com/ethereum/go-ethereum/rpc" 34 "github.com/ethereum/go-ethereum/swarm/network" 35 streamTesting "github.com/ethereum/go-ethereum/swarm/network/stream/testing" 36 "github.com/ethereum/go-ethereum/swarm/state" 37 "github.com/ethereum/go-ethereum/swarm/storage" 38 ) 39 40 var ( 41 externalStreamName = "externalStream" 42 externalStreamSessionAt uint64 = 50 43 externalStreamMaxKeys uint64 = 100 44 ) 45 46 func newIntervalsStreamerService(ctx *adapters.ServiceContext) (node.Service, error) { 47 id := ctx.Config.ID 48 addr := toAddr(id) 49 kad := network.NewKademlia(addr.Over(), network.NewKadParams()) 50 store := stores[id].(*storage.LocalStore) 51 db := storage.NewDBAPI(store) 52 delivery := NewDelivery(kad, db) 53 deliveries[id] = delivery 54 r := NewRegistry(addr, delivery, db, state.NewInmemoryStore(), &RegistryOptions{ 55 SkipCheck: defaultSkipCheck, 56 }) 57 58 r.RegisterClientFunc(externalStreamName, func(p *Peer, t string, live bool) (Client, error) { 59 return newTestExternalClient(db), nil 60 }) 61 r.RegisterServerFunc(externalStreamName, func(p *Peer, t string, live bool) (Server, error) { 62 return newTestExternalServer(t, externalStreamSessionAt, externalStreamMaxKeys, nil), nil 63 }) 64 65 go func() { 66 waitPeerErrC <- waitForPeers(r, 1*time.Second, peerCount(id)) 67 }() 68 return &TestExternalRegistry{r}, nil 69 } 70 71 func TestIntervals(t *testing.T) { 72 testIntervals(t, true, nil, false) 73 testIntervals(t, false, NewRange(9, 26), false) 74 testIntervals(t, true, NewRange(9, 26), false) 75 76 testIntervals(t, true, nil, true) 77 testIntervals(t, false, NewRange(9, 26), true) 78 testIntervals(t, true, NewRange(9, 26), true) 79 } 80 81 func testIntervals(t *testing.T, live bool, history *Range, skipCheck bool) { 82 nodes := 2 83 chunkCount := dataChunkCount 84 85 defer setDefaultSkipCheck(defaultSkipCheck) 86 defaultSkipCheck = skipCheck 87 88 toAddr = network.NewAddrFromNodeID 89 conf := &streamTesting.RunConfig{ 90 Adapter: *adapter, 91 NodeCount: nodes, 92 ConnLevel: 1, 93 ToAddr: toAddr, 94 Services: services, 95 DefaultService: "intervalsStreamer", 96 } 97 98 sim, teardown, err := streamTesting.NewSimulation(conf) 99 var rpcSubscriptionsWg sync.WaitGroup 100 defer func() { 101 rpcSubscriptionsWg.Wait() 102 teardown() 103 }() 104 if err != nil { 105 t.Fatal(err) 106 } 107 108 stores = make(map[discover.NodeID]storage.ChunkStore) 109 deliveries = make(map[discover.NodeID]*Delivery) 110 for i, id := range sim.IDs { 111 stores[id] = sim.Stores[i] 112 } 113 114 peerCount = func(id discover.NodeID) int { 115 return 1 116 } 117 118 fileStore := storage.NewFileStore(sim.Stores[0], storage.NewFileStoreParams()) 119 size := chunkCount * chunkSize 120 ctx := context.TODO() 121 _, wait, err := fileStore.Store(ctx, io.LimitReader(crand.Reader, int64(size)), int64(size), false) 122 if err != nil { 123 t.Fatal(err) 124 } 125 err = wait(ctx) 126 if err != nil { 127 t.Fatal(err) 128 } 129 130 errc := make(chan error, 1) 131 waitPeerErrC = make(chan error) 132 quitC := make(chan struct{}) 133 defer close(quitC) 134 135 action := func(ctx context.Context) error { 136 i := 0 137 for err := range waitPeerErrC { 138 if err != nil { 139 return fmt.Errorf("error waiting for peers: %s", err) 140 } 141 i++ 142 if i == nodes { 143 break 144 } 145 } 146 147 id := sim.IDs[1] 148 149 err := sim.CallClient(id, func(client *rpc.Client) error { 150 151 sid := sim.IDs[0] 152 153 doneC, err := streamTesting.WatchDisconnections(id, client, errc, quitC) 154 if err != nil { 155 return err 156 } 157 rpcSubscriptionsWg.Add(1) 158 go func() { 159 <-doneC 160 rpcSubscriptionsWg.Done() 161 }() 162 ctx, cancel := context.WithTimeout(ctx, 100*time.Second) 163 defer cancel() 164 165 err = client.CallContext(ctx, nil, "stream_subscribeStream", sid, NewStream(externalStreamName, "", live), history, Top) 166 if err != nil { 167 return err 168 } 169 170 liveErrC := make(chan error) 171 historyErrC := make(chan error) 172 173 go func() { 174 if !live { 175 close(liveErrC) 176 return 177 } 178 179 var err error 180 defer func() { 181 liveErrC <- err 182 }() 183 184 // live stream 185 liveHashesChan := make(chan []byte) 186 liveSubscription, err := client.Subscribe(ctx, "stream", liveHashesChan, "getHashes", sid, NewStream(externalStreamName, "", true)) 187 if err != nil { 188 return 189 } 190 defer liveSubscription.Unsubscribe() 191 192 i := externalStreamSessionAt 193 194 // we have subscribed, enable notifications 195 err = client.CallContext(ctx, nil, "stream_enableNotifications", sid, NewStream(externalStreamName, "", true)) 196 if err != nil { 197 return 198 } 199 200 for { 201 select { 202 case hash := <-liveHashesChan: 203 h := binary.BigEndian.Uint64(hash) 204 if h != i { 205 err = fmt.Errorf("expected live hash %d, got %d", i, h) 206 return 207 } 208 i++ 209 if i > externalStreamMaxKeys { 210 return 211 } 212 case err = <-liveSubscription.Err(): 213 return 214 case <-ctx.Done(): 215 return 216 } 217 } 218 }() 219 220 go func() { 221 if live && history == nil { 222 close(historyErrC) 223 return 224 } 225 226 var err error 227 defer func() { 228 historyErrC <- err 229 }() 230 231 // history stream 232 historyHashesChan := make(chan []byte) 233 historySubscription, err := client.Subscribe(ctx, "stream", historyHashesChan, "getHashes", sid, NewStream(externalStreamName, "", false)) 234 if err != nil { 235 return 236 } 237 defer historySubscription.Unsubscribe() 238 239 var i uint64 240 historyTo := externalStreamMaxKeys 241 if history != nil { 242 i = history.From 243 if history.To != 0 { 244 historyTo = history.To 245 } 246 } 247 248 // we have subscribed, enable notifications 249 err = client.CallContext(ctx, nil, "stream_enableNotifications", sid, NewStream(externalStreamName, "", false)) 250 if err != nil { 251 return 252 } 253 254 for { 255 select { 256 case hash := <-historyHashesChan: 257 h := binary.BigEndian.Uint64(hash) 258 if h != i { 259 err = fmt.Errorf("expected history hash %d, got %d", i, h) 260 return 261 } 262 i++ 263 if i > historyTo { 264 return 265 } 266 case err = <-historySubscription.Err(): 267 return 268 case <-ctx.Done(): 269 return 270 } 271 } 272 }() 273 274 if err := <-liveErrC; err != nil { 275 return err 276 } 277 if err := <-historyErrC; err != nil { 278 return err 279 } 280 281 return nil 282 }) 283 return err 284 } 285 check := func(ctx context.Context, id discover.NodeID) (bool, error) { 286 select { 287 case err := <-errc: 288 return false, err 289 case <-ctx.Done(): 290 return false, ctx.Err() 291 default: 292 } 293 return true, nil 294 } 295 296 conf.Step = &simulations.Step{ 297 Action: action, 298 Trigger: streamTesting.Trigger(10*time.Millisecond, quitC, sim.IDs[0]), 299 Expect: &simulations.Expectation{ 300 Nodes: sim.IDs[1:1], 301 Check: check, 302 }, 303 } 304 startedAt := time.Now() 305 timeout := 300 * time.Second 306 ctx, cancel := context.WithTimeout(context.Background(), timeout) 307 defer cancel() 308 result, err := sim.Run(ctx, conf) 309 finishedAt := time.Now() 310 if err != nil { 311 t.Fatalf("Setting up simulation failed: %v", err) 312 } 313 if result.Error != nil { 314 t.Fatalf("Simulation failed: %s", result.Error) 315 } 316 streamTesting.CheckResult(t, result, startedAt, finishedAt) 317 }