github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/protocols/dag/dagstream/dagstreamleecher/leecher_test.go (about) 1 package dagstreamleecher 2 3 import ( 4 "math/rand" 5 "strconv" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/require" 10 11 "github.com/unicornultrafoundation/go-helios/hash" 12 "github.com/unicornultrafoundation/go-helios/native/idx" 13 14 "github.com/unicornultrafoundation/go-u2u/gossip/protocols/dag/dagstream" 15 ) 16 17 func TestLeecherNoDeadlocks(t *testing.T) { 18 for try := 0; try < 10; try++ { 19 testLeecherNoDeadlocks(t, 1+rand.Intn(500)) 20 } 21 } 22 23 type peerRequest struct { 24 peer string 25 request dagstream.Request 26 } 27 28 func testLeecherNoDeadlocks(t *testing.T, maxPeers int) { 29 requests := make(chan peerRequest, 1000) 30 config := LiteConfig() 31 config.RecheckInterval = time.Millisecond * 5 32 config.MinSessionRestart = 2 * time.Millisecond * 5 33 config.MaxSessionRestart = 5 * time.Millisecond * 5 34 config.BaseProgressWatchdog = 3 * time.Millisecond * 5 35 config.Session.RecheckInterval = time.Millisecond 36 epoch := idx.Epoch(1) 37 leecher := New(epoch, rand.Intn(2) == 0, config, Callbacks{ 38 IsProcessed: func(id hash.Event) bool { 39 return rand.Intn(2) == 0 40 }, 41 RequestChunk: func(peer string, r dagstream.Request) error { 42 requests <- peerRequest{peer, r} 43 return nil 44 }, 45 Suspend: func(peer string) bool { 46 return rand.Intn(10) == 0 47 }, 48 PeerEpoch: func(peer string) idx.Epoch { 49 return 1 + epoch/2 + idx.Epoch(rand.Intn(int(epoch*2))) 50 }, 51 }) 52 terminated := false 53 for i := 0; i < maxPeers*2; i++ { 54 peer := strconv.Itoa(rand.Intn(maxPeers)) 55 coin := rand.Intn(100) 56 if coin <= 50 { 57 err := leecher.RegisterPeer(peer) 58 if !terminated { 59 require.NoError(t, err) 60 } 61 } else if coin <= 60 { 62 err := leecher.UnregisterPeer(peer) 63 if !terminated { 64 require.NoError(t, err) 65 } 66 } else if coin <= 65 { 67 epoch++ 68 leecher.OnNewEpoch(epoch) 69 } else if coin <= 70 { 70 leecher.ForceSyncing() 71 } else { 72 time.Sleep(time.Millisecond) 73 } 74 select { 75 case req := <-requests: 76 if rand.Intn(10) != 0 { 77 err := leecher.NotifyChunkReceived(req.request.Session.ID, hash.FakeEvent(), rand.Intn(5) == 0) 78 if !terminated { 79 require.NoError(t, err) 80 } 81 } 82 default: 83 } 84 if !terminated && rand.Intn(maxPeers*2) == 0 { 85 terminated = true 86 leecher.Terminate() 87 } 88 } 89 if !terminated { 90 leecher.Stop() 91 } else { 92 leecher.Wg.Wait() 93 } 94 }