@@ -2,13 +2,18 @@ package sync
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
6
+ "io"
5
7
"sync"
6
8
"testing"
7
9
"time"
8
10
9
11
"github.com/libp2p/go-libp2p/core/discovery"
10
12
libp2p_peer "github.com/libp2p/go-libp2p/core/peer"
11
13
"github.com/libp2p/go-libp2p/core/protocol"
14
+ "github.com/rs/zerolog"
15
+
16
+ nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
12
17
)
13
18
14
19
func TestProtocol_Match (t * testing.T ) {
@@ -48,6 +53,11 @@ func TestProtocol_advertiseLoop(t *testing.T) {
48
53
disc : disc ,
49
54
closeC : make (chan struct {}),
50
55
ctx : context .Background (),
56
+ config : Config {
57
+ Network : "unitest" ,
58
+ ShardID : 0 ,
59
+ },
60
+ logger : zerolog .New (io .Discard ),
51
61
}
52
62
53
63
go p .advertiseLoop ()
@@ -67,6 +77,260 @@ func TestProtocol_advertiseLoop(t *testing.T) {
67
77
}
68
78
}
69
79
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
+
70
334
type testDiscovery struct {
71
335
advCnt map [string ]int
72
336
sleep time.Duration
@@ -104,9 +368,59 @@ func (disc *testDiscovery) Extract() map[string]int {
104
368
}
105
369
106
370
func (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
108
383
}
109
384
110
385
func (disc * testDiscovery ) GetRawDiscovery () discovery.Discovery {
111
386
return nil
112
387
}
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