@@ -2,13 +2,18 @@ package sync
22
33import (
44 "context"
5+ "fmt"
6+ "io"
57 "sync"
68 "testing"
79 "time"
810
911 "github.com/libp2p/go-libp2p/core/discovery"
1012 libp2p_peer "github.com/libp2p/go-libp2p/core/peer"
1113 "github.com/libp2p/go-libp2p/core/protocol"
14+ "github.com/rs/zerolog"
15+
16+ nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
1217)
1318
1419func TestProtocol_Match (t * testing.T ) {
@@ -48,6 +53,11 @@ func TestProtocol_advertiseLoop(t *testing.T) {
4853 disc : disc ,
4954 closeC : make (chan struct {}),
5055 ctx : context .Background (),
56+ config : Config {
57+ Network : "unitest" ,
58+ ShardID : 0 ,
59+ },
60+ logger : zerolog .New (io .Discard ),
5161 }
5262
5363 go p .advertiseLoop ()
@@ -67,6 +77,260 @@ func TestProtocol_advertiseLoop(t *testing.T) {
6777 }
6878}
6979
80+ func TestProtocol_StartupMode (t * testing.T ) {
81+ // Test that startup mode is enabled by default
82+ p := & Protocol {
83+ startupMode : true ,
84+ startupStartTime : time .Now (),
85+ }
86+
87+ if ! p .IsInStartupMode () {
88+ t .Error ("Expected startup mode to be enabled by default" )
89+ }
90+
91+ // Test exiting startup mode
92+ p .ExitStartupMode ()
93+ if p .IsInStartupMode () {
94+ t .Error ("Expected startup mode to be disabled after exit" )
95+ }
96+ }
97+
98+ func TestProtocol_Advertise (t * testing.T ) {
99+ tests := []struct {
100+ name string
101+ startupMode bool
102+ peersFound int
103+ expectedTiming string // "fast" or "normal"
104+ }{
105+ {
106+ name : "startup mode with peers found" ,
107+ startupMode : true ,
108+ peersFound : 5 ,
109+ expectedTiming : "fast" ,
110+ },
111+ {
112+ name : "startup mode no peers found" ,
113+ startupMode : true ,
114+ peersFound : 0 ,
115+ expectedTiming : "fast" ,
116+ },
117+ {
118+ name : "normal mode with peers found" ,
119+ startupMode : false ,
120+ peersFound : 3 ,
121+ expectedTiming : "normal" ,
122+ },
123+ {
124+ name : "normal mode no peers found" ,
125+ startupMode : false ,
126+ peersFound : 0 ,
127+ expectedTiming : "normal" ,
128+ },
129+ }
130+
131+ for _ , tt := range tests {
132+ t .Run (tt .name , func (t * testing.T ) {
133+ // Create mock discovery that returns specified number of peers
134+ mockDisc := & mockDiscovery {
135+ peersToReturn : tt .peersFound ,
136+ }
137+
138+ p := & Protocol {
139+ startupMode : tt .startupMode ,
140+ startupStartTime : time .Now (),
141+ disc : mockDisc ,
142+ ctx : context .Background (),
143+ logger : zerolog .New (io .Discard ),
144+ config : Config {
145+ Network : "unitest" ,
146+ ShardID : 0 ,
147+ },
148+ }
149+
150+ // Test startup mode timing constants
151+ if tt .startupMode {
152+ // Verify startup mode uses faster constants
153+ if BaseTimeoutStartup >= BaseTimeoutNormal {
154+ t .Error ("Startup timeout should be faster than normal timeout" )
155+ }
156+ if MaxTimeoutStartup >= MaxTimeoutNormal {
157+ t .Error ("Startup max timeout should be faster than normal max timeout" )
158+ }
159+ }
160+
161+ // Test peer discovery count tracking
162+ p .recentPeerDiscoveryCount = tt .peersFound
163+ if p .recentPeerDiscoveryCount != tt .peersFound {
164+ t .Errorf ("Expected peer count %d, got %d" , tt .peersFound , p .recentPeerDiscoveryCount )
165+ }
166+ })
167+ }
168+ }
169+
170+ func TestProtocol_AdvertiseLoop (t * testing.T ) {
171+ // Test that advertiseLoop respects startup mode timing
172+ mockDisc := & mockDiscovery {
173+ peersToReturn : 2 ,
174+ }
175+
176+ p := & Protocol {
177+ startupMode : true ,
178+ startupStartTime : time .Now (),
179+ disc : mockDisc ,
180+ ctx : context .Background (),
181+ closeC : make (chan struct {}),
182+ logger : zerolog .New (io .Discard ),
183+ config : Config {
184+ Network : "unitest" ,
185+ ShardID : 0 ,
186+ },
187+ }
188+
189+ // Test startup mode timing constants directly
190+ if ! p .IsInStartupMode () {
191+ t .Error ("Expected startup mode to be active" )
192+ }
193+
194+ // Test that startup mode uses faster constants
195+ if BaseTimeoutStartup >= BaseTimeoutNormal {
196+ t .Error ("Startup timeout should be faster than normal timeout" )
197+ }
198+ if MaxTimeoutStartup >= MaxTimeoutNormal {
199+ t .Error ("Startup max timeout should be faster than normal max timeout" )
200+ }
201+
202+ // Test exit from startup mode
203+ p .ExitStartupMode ()
204+ if p .IsInStartupMode () {
205+ t .Error ("Expected startup mode to be disabled after exit" )
206+ }
207+ }
208+
209+ func TestProtocol_ExitStartupMode (t * testing.T ) {
210+ p := & Protocol {
211+ startupMode : true ,
212+ startupStartTime : time .Now (),
213+ ctx : context .Background (),
214+ logger : zerolog .New (io .Discard ),
215+ }
216+
217+ // Test manual exit
218+ p .ExitStartupMode ()
219+ if p .IsInStartupMode () {
220+ t .Error ("Expected startup mode to be disabled after manual exit" )
221+ }
222+
223+ // Test automatic exit after timeout
224+ p .startupMode = true
225+ p .startupStartTime = time .Now ().Add (- StartupModeDuration - time .Second )
226+
227+ // Instead of calling advertise which requires complex setup,
228+ // test the timeout logic directly
229+ if time .Since (p .startupStartTime ) > StartupModeDuration {
230+ p .startupMode = false
231+ }
232+
233+ if p .IsInStartupMode () {
234+ t .Error ("Expected startup mode to be disabled after timeout" )
235+ }
236+ }
237+
238+ func TestProtocol_GetPeerDiscoveryLimit (t * testing.T ) {
239+ tests := []struct {
240+ network nodeconfig.NetworkType
241+ expected int
242+ }{
243+ {nodeconfig .Mainnet , DHTRequestLimitMainnet },
244+ {nodeconfig .Testnet , DHTRequestLimitTestnet },
245+ {nodeconfig .Pangaea , DHTRequestLimitPangaea },
246+ {nodeconfig .Partner , DHTRequestLimitPartner },
247+ {nodeconfig .Stressnet , DHTRequestLimitStressnet },
248+ {nodeconfig .Devnet , DHTRequestLimitDevnet },
249+ {nodeconfig .Localnet , DHTRequestLimitLocalnet },
250+ {"unknown" , DHTRequestLimitDevnet }, // Default fallback
251+ }
252+
253+ for _ , tt := range tests {
254+ t .Run (string (tt .network ), func (t * testing.T ) {
255+ p := & Protocol {
256+ config : Config {
257+ Network : tt .network ,
258+ },
259+ }
260+
261+ limit := p .getPeerDiscoveryLimit ()
262+ if limit != tt .expected {
263+ t .Errorf ("Expected peer discovery limit %d for network %s, got %d" ,
264+ tt .expected , tt .network , limit )
265+ }
266+ })
267+ }
268+ }
269+
270+ func TestProtocol_GetDHTRequestLimit (t * testing.T ) {
271+ tests := []struct {
272+ network nodeconfig.NetworkType
273+ expected int
274+ }{
275+ {nodeconfig .Mainnet , DHTRequestLimitMainnet },
276+ {nodeconfig .Testnet , DHTRequestLimitTestnet },
277+ {nodeconfig .Pangaea , DHTRequestLimitPangaea },
278+ {nodeconfig .Partner , DHTRequestLimitPartner },
279+ {nodeconfig .Stressnet , DHTRequestLimitStressnet },
280+ {nodeconfig .Devnet , DHTRequestLimitDevnet },
281+ {nodeconfig .Localnet , DHTRequestLimitLocalnet },
282+ {"unknown" , DHTRequestLimitDevnet }, // Default fallback
283+ }
284+
285+ for _ , tt := range tests {
286+ t .Run (string (tt .network ), func (t * testing.T ) {
287+ p := & Protocol {
288+ config : Config {
289+ Network : tt .network ,
290+ },
291+ }
292+
293+ limit := p .getDHTRequestLimit ()
294+ if limit != tt .expected {
295+ t .Errorf ("Expected DHT request limit %d for network %s, got %d" ,
296+ tt .expected , tt .network , limit )
297+ }
298+ })
299+ }
300+ }
301+
302+ func TestProtocol_GetTargetValidPeers (t * testing.T ) {
303+ tests := []struct {
304+ network nodeconfig.NetworkType
305+ expected int
306+ }{
307+ {nodeconfig .Mainnet , TargetValidPeersMainnet },
308+ {nodeconfig .Testnet , TargetValidPeersTestnet },
309+ {nodeconfig .Pangaea , TargetValidPeersPangaea },
310+ {nodeconfig .Partner , TargetValidPeersPartner },
311+ {nodeconfig .Stressnet , TargetValidPeersStressnet },
312+ {nodeconfig .Devnet , TargetValidPeersDevnet },
313+ {nodeconfig .Localnet , TargetValidPeersLocalnet },
314+ {"unknown" , TargetValidPeersDevnet }, // Default fallback
315+ }
316+
317+ for _ , tt := range tests {
318+ t .Run (string (tt .network ), func (t * testing.T ) {
319+ p := & Protocol {
320+ config : Config {
321+ Network : tt .network ,
322+ },
323+ }
324+
325+ limit := p .getTargetValidPeers ()
326+ if limit != tt .expected {
327+ t .Errorf ("Expected target valid peers %d for network %s, got %d" ,
328+ tt .expected , tt .network , limit )
329+ }
330+ })
331+ }
332+ }
333+
70334type testDiscovery struct {
71335 advCnt map [string ]int
72336 sleep time.Duration
@@ -104,9 +368,59 @@ func (disc *testDiscovery) Extract() map[string]int {
104368}
105369
106370func (disc * testDiscovery ) FindPeers (ctx context.Context , ns string , peerLimit int ) (<- chan libp2p_peer.AddrInfo , error ) {
107- return nil , nil
371+ peerChan := make (chan libp2p_peer.AddrInfo )
372+ go func () {
373+ defer close (peerChan )
374+ // Return some mock peers for testing
375+ for i := 0 ; i < 2 ; i ++ {
376+ peer := libp2p_peer.AddrInfo {
377+ ID : libp2p_peer .ID (fmt .Sprintf ("test-peer-%d" , i )),
378+ }
379+ peerChan <- peer
380+ }
381+ }()
382+ return peerChan , nil
108383}
109384
110385func (disc * testDiscovery ) GetRawDiscovery () discovery.Discovery {
111386 return nil
112387}
388+
389+ // Mock discovery for testing
390+ type mockDiscovery struct {
391+ peersToReturn int
392+ peersFound int
393+ }
394+
395+ func (md * mockDiscovery ) Start () error {
396+ return nil
397+ }
398+
399+ func (md * mockDiscovery ) Close () error {
400+ return nil
401+ }
402+
403+ func (md * mockDiscovery ) FindPeers (ctx context.Context , ns string , peerLimit int ) (<- chan libp2p_peer.AddrInfo , error ) {
404+ peerChan := make (chan libp2p_peer.AddrInfo , md .peersToReturn )
405+
406+ go func () {
407+ defer close (peerChan )
408+ for i := 0 ; i < md .peersToReturn ; i ++ {
409+ // Create a mock peer
410+ peer := libp2p_peer.AddrInfo {
411+ ID : libp2p_peer .ID (fmt .Sprintf ("peer%d" , i )),
412+ }
413+ peerChan <- peer
414+ }
415+ }()
416+
417+ return peerChan , nil
418+ }
419+
420+ func (md * mockDiscovery ) Advertise (ctx context.Context , ns string ) (time.Duration , error ) {
421+ return time .Minute , nil
422+ }
423+
424+ func (md * mockDiscovery ) GetRawDiscovery () discovery.Discovery {
425+ return nil
426+ }
0 commit comments