11package node
22
33import (
4- "github.com/pkg/errors "
5- "github.com/stretchr/testify/assert "
4+ "context "
5+ "fmt "
66 "sync"
77 "testing"
88 "time"
9+
10+ "github.com/pkg/errors"
11+ "github.com/stretchr/testify/assert"
12+ "github.com/stretchr/testify/require"
913)
1014
1115func TestNoPeerDiscovery_UpdatePeers (t * testing.T ) {
@@ -87,19 +91,132 @@ func TestPublicPeerDiscovery_UpdatePeers(t *testing.T) {
8791 assert .Contains (t , hosts , "6.7.8.9" )
8892}
8993
90- func TestPublicPeerDiscovery_ExcludePeers (t * testing.T ) {
91- createNodeFunc := func (host string ) (* Node , error ) {
92- return createTestNodeWithPeers (host , []string {"1.2.3.4" , "6.6.6.6" }), nil // 6.6.6.6 excluded
93- }
94- discovery := newPublicPeerDiscovery (createNodeFunc , []string {" 6.6.6.6" }, time .Hour )
94+ func TestPublicPeerDiscovery_FindNewPeers (t * testing.T ) {
95+ t .Run ("returns empty when no new peers found" , func (t * testing.T ) {
96+ createNodeFunc := func (host string ) (* Node , error ) {
97+ return createTestNodeWithPeers (host , []string {}), nil
98+ }
99+ discovery := newPublicPeerDiscovery (createNodeFunc , []string {}, time .Hour )
95100
96- discoveredPeers := discovery .FindNewPeers ([]* Node {
97- createTestNodeWithPeers ("1.2.3.4" , []string {"2.3.4.5" , "3.4.5.6" }), // 3.4.5.6 new peer
98- }, []string {"1.2.3.4" , "2.3.4.5" })
101+ discoveredPeers := discovery .FindNewPeers ([]* Node {
102+ createTestNodeWithPeers ("1.2.3.4" , []string {"2.3.4.5" }),
103+ }, []string {"1.2.3.4" , "2.3.4.5" })
99104
100- assert .Len (t , discoveredPeers , 1 )
101- hosts := getHosts (discoveredPeers )
102- assert .Contains (t , hosts , "3.4.5.6" )
105+ assert .Empty (t , discoveredPeers )
106+ })
107+
108+ t .Run ("discovers new peers from existing nodes" , func (t * testing.T ) {
109+ createNodeFunc := func (host string ) (* Node , error ) {
110+ return createTestNodeWithPeers (host , []string {}), nil
111+ }
112+ discovery := newPublicPeerDiscovery (createNodeFunc , []string {}, time .Hour )
113+
114+ discoveredPeers := discovery .FindNewPeers ([]* Node {
115+ createTestNodeWithPeers ("1.2.3.4" , []string {"2.3.4.5" , "3.4.5.6" }),
116+ }, []string {"1.2.3.4" })
117+
118+ assert .Len (t , discoveredPeers , 2 )
119+ hosts := getHosts (discoveredPeers )
120+ assert .Contains (t , hosts , "2.3.4.5" )
121+ assert .Contains (t , hosts , "3.4.5.6" )
122+ })
123+
124+ t .Run ("recursively discovers peers from new peers" , func (t * testing.T ) {
125+ createNodeFunc := func (host string ) (* Node , error ) {
126+ switch host {
127+ case "2.3.4.5" :
128+ return createTestNodeWithPeers (host , []string {"3.4.5.6" }), nil
129+ case "3.4.5.6" :
130+ return createTestNodeWithPeers (host , []string {"4.5.6.7" }), nil
131+ default :
132+ return createTestNodeWithPeers (host , []string {}), nil
133+ }
134+ }
135+ discovery := newPublicPeerDiscovery (createNodeFunc , []string {}, time .Hour )
136+
137+ discoveredPeers := discovery .FindNewPeers ([]* Node {
138+ createTestNodeWithPeers ("1.2.3.4" , []string {"2.3.4.5" }),
139+ }, []string {"1.2.3.4" })
140+
141+ assert .Len (t , discoveredPeers , 3 )
142+ hosts := getHosts (discoveredPeers )
143+ assert .Contains (t , hosts , "2.3.4.5" )
144+ assert .Contains (t , hosts , "3.4.5.6" )
145+ assert .Contains (t , hosts , "4.5.6.7" )
146+ })
147+
148+ t .Run ("excludes peers from excluded list" , func (t * testing.T ) {
149+ createNodeFunc := func (host string ) (* Node , error ) {
150+ return createTestNodeWithPeers (host , []string {}), nil
151+ }
152+ discovery := newPublicPeerDiscovery (createNodeFunc , []string {"3.4.5.6" }, time .Hour )
153+
154+ discoveredPeers := discovery .FindNewPeers ([]* Node {
155+ createTestNodeWithPeers ("1.2.3.4" , []string {"2.3.4.5" , "3.4.5.6" , "4.5.6.7" }),
156+ }, []string {"1.2.3.4" })
157+
158+ assert .Len (t , discoveredPeers , 2 )
159+ hosts := getHosts (discoveredPeers )
160+ assert .Contains (t , hosts , "2.3.4.5" )
161+ assert .Contains (t , hosts , "4.5.6.7" )
162+ assert .NotContains (t , hosts , "3.4.5.6" )
163+ })
164+
165+ t .Run ("handles node creation errors gracefully" , func (t * testing.T ) {
166+ createNodeFunc := func (host string ) (* Node , error ) {
167+ if host == "3.4.5.6" {
168+ return nil , errors .Errorf ("connection failed" )
169+ }
170+ return createTestNodeWithPeers (host , []string {}), nil
171+ }
172+ discovery := newPublicPeerDiscovery (createNodeFunc , []string {}, time .Hour )
173+
174+ discoveredPeers := discovery .FindNewPeers ([]* Node {
175+ createTestNodeWithPeers ("1.2.3.4" , []string {"2.3.4.5" , "3.4.5.6" , "4.5.6.7" }),
176+ }, []string {"1.2.3.4" })
177+
178+ assert .Len (t , discoveredPeers , 2 )
179+ hosts := getHosts (discoveredPeers )
180+ assert .Contains (t , hosts , "2.3.4.5" )
181+ assert .Contains (t , hosts , "4.5.6.7" )
182+ assert .NotContains (t , hosts , "3.4.5.6" )
183+ })
184+ }
185+
186+ func TestPublicPeerDiscovery_nodeWithManyPeers (t * testing.T ) {
187+
188+ ctx , cancel := context .WithTimeout (context .Background (), 3 * time .Second )
189+ defer cancel ()
190+ done := make (chan struct {})
191+
192+ go func () {
193+ // Generate many peers to test the limit
194+ numberOfPeers := 100
195+ manyPeers := make ([]string , numberOfPeers )
196+ for i := 0 ; i < numberOfPeers ; i ++ {
197+ manyPeers [i ] = fmt .Sprintf ("10.0.0.%d" , i )
198+ }
199+
200+ createNodeFunc := func (host string ) (* Node , error ) {
201+ return createTestNodeWithPeers (host , []string {}), nil
202+ }
203+ discovery := newPublicPeerDiscovery (createNodeFunc , []string {}, time .Hour )
204+
205+ discoveredPeers := discovery .FindNewPeers ([]* Node {
206+ createTestNodeWithPeers ("1.2.3.4" , manyPeers ),
207+ }, []string {"1.2.3.4" })
208+
209+ // Should not exceed maxNewPeersPerUpdate (50)
210+ require .LessOrEqual (t , len (discoveredPeers ), approxMaxNewPeers )
211+ close (done )
212+ }()
213+
214+ select {
215+ case <- done :
216+ // Test passed
217+ case <- ctx .Done ():
218+ t .Fatal ("Test timed out" )
219+ }
103220}
104221
105222func TestPublicPeerDiscovery_CleanupPeers (t * testing.T ) {
@@ -121,7 +238,7 @@ func TestPublicPeerDiscovery_CleanupPeers(t *testing.T) {
121238 assert .Contains (t , unhealthy , "3.4.5.6" )
122239
123240 time .Sleep (5 * time .Millisecond )
124- // clean up one
241+ // clean up
125242 unhealthy = discovery .CleanupPeers ([]* Node {createTestNode ("2.3.4.5" )}, []string {"2.3.4.5" , "3.4.5.6" })
126243 assert .Len (t , unhealthy , 1 )
127244 assert .Contains (t , unhealthy , "3.4.5.6" )
0 commit comments