@@ -2,18 +2,224 @@ package eth
22
33import (
44 "crypto/rand"
5+ "errors"
56 "math/big"
67 "testing"
78 "time"
89
910 "github.com/ethereum/go-ethereum/common"
1011 "github.com/ethereum/go-ethereum/eth/protocols/eth"
12+ "github.com/ethereum/go-ethereum/eth/protocols/snap"
1113 "github.com/ethereum/go-ethereum/eth/protocols/wit"
1214 "github.com/ethereum/go-ethereum/log"
1315 "github.com/ethereum/go-ethereum/p2p"
1416 "github.com/ethereum/go-ethereum/p2p/enode"
1517)
1618
19+ func TestPeerSetExtensions (t * testing.T ) {
20+ t .Run ("snap" , func (t * testing.T ) {
21+ caps := []p2p.Cap {{Name : eth .ProtocolName , Version : eth .ETH69 }, {Name : snap .ProtocolName , Version : snap .SNAP1 }}
22+ testPeerSetExtension (t , caps , false , errSnapWithoutEth , newPeerSetSnapPeer , (* peerSet ).registerSnapExtension , (* peerSet ).waitSnapExtension )
23+ })
24+ t .Run ("wit" , func (t * testing.T ) {
25+ caps := []p2p.Cap {{Name : eth .ProtocolName , Version : eth .ETH69 }, {Name : wit .ProtocolName , Version : wit .WIT2 }}
26+ testPeerSetExtension (t , caps , true , errWitWithoutEth , newPeerSetWitPeer , (* peerSet ).registerWitExtension , (* peerSet ).waitWitExtension )
27+ })
28+ }
29+
30+ func TestPeerSetRevision (t * testing.T ) {
31+ ps := newPeerSet ()
32+ peer := newPeerSetEthPeer (t , enode.ID {1 }, nil )
33+
34+ if err := ps .unregisterPeer (peer .ID ()); ! errors .Is (err , errPeerNotRegistered ) {
35+ t .Fatalf ("unexpected unregister error: %v" , err )
36+ }
37+ if revision := ps .currentRevision (); revision != 0 {
38+ t .Fatalf ("failed unregister changed revision to %d" , revision )
39+ }
40+ if err := ps .registerPeer (peer , nil , nil ); err != nil {
41+ t .Fatal (err )
42+ }
43+ if err := ps .registerPeer (peer , nil , nil ); ! errors .Is (err , errPeerAlreadyRegistered ) {
44+ t .Fatalf ("unexpected duplicate registration error: %v" , err )
45+ }
46+ if revision := ps .currentRevision (); revision != 1 {
47+ t .Fatalf ("registration changed revision to %d" , revision )
48+ }
49+ if err := ps .unregisterPeer (peer .ID ()); err != nil {
50+ t .Fatal (err )
51+ }
52+ if revision := ps .currentRevision (); revision != 2 {
53+ t .Fatalf ("unregister changed revision to %d" , revision )
54+ }
55+ ps .close ()
56+ if err := ps .registerPeer (peer , nil , nil ); ! errors .Is (err , errPeerSetClosed ) {
57+ t .Fatalf ("unexpected closed set error: %v" , err )
58+ }
59+ if revision := ps .currentRevision (); revision != 2 {
60+ t .Fatalf ("failed registration changed revision to %d" , revision )
61+ }
62+ }
63+
64+ type extensionResult [T comparable ] struct {
65+ peer T
66+ err error
67+ }
68+
69+ func testPeerSetExtension [T comparable ](
70+ t * testing.T ,
71+ caps []p2p.Cap ,
72+ witness bool ,
73+ incompatibleError error ,
74+ newExtension func (* testing.T , enode.ID , []p2p.Cap ) T ,
75+ register func (* peerSet , T ) error ,
76+ wait func (* peerSet , * eth.Peer ) (T , error ),
77+ ) {
78+ t .Helper ()
79+
80+ t .Run ("extension first" , func (t * testing.T ) {
81+ ps := newPeerSet ()
82+ defer ps .close ()
83+
84+ id := enode.ID {1 }
85+ main := newPeerSetEthPeer (t , id , caps )
86+ ext := newExtension (t , id , caps )
87+ if err := register (ps , ext ); err != nil {
88+ t .Fatal (err )
89+ }
90+ if err := register (ps , ext ); ! errors .Is (err , errPeerAlreadyRegistered ) {
91+ t .Fatalf ("unexpected duplicate registration error: %v" , err )
92+ }
93+ got , err := wait (ps , main )
94+ if err != nil || got != ext {
95+ t .Fatalf ("extension mismatch: got %v, want %v, err %v" , got , ext , err )
96+ }
97+ })
98+
99+ t .Run ("main first" , func (t * testing.T ) {
100+ ps := newPeerSet ()
101+ defer ps .close ()
102+
103+ id := enode.ID {2 }
104+ main := newPeerSetEthPeer (t , id , caps )
105+ ext := newExtension (t , id , caps )
106+ result := make (chan extensionResult [T ], 1 )
107+ go func () {
108+ peer , err := wait (ps , main )
109+ result <- extensionResult [T ]{peer , err }
110+ }()
111+ waitForPeerSetWaiter (t , ps , id .String (), witness )
112+ if err := register (ps , ext ); err != nil {
113+ t .Fatal (err )
114+ }
115+ if got := <- result ; got .err != nil || got .peer != ext {
116+ t .Fatalf ("extension mismatch: got %v, want %v, err %v" , got .peer , ext , got .err )
117+ }
118+ })
119+
120+ t .Run ("closed" , func (t * testing.T ) {
121+ ps := newPeerSet ()
122+ id := enode.ID {3 }
123+ main := newPeerSetEthPeer (t , id , caps )
124+ result := make (chan extensionResult [T ], 1 )
125+ go func () {
126+ peer , err := wait (ps , main )
127+ result <- extensionResult [T ]{peer , err }
128+ }()
129+ waitForPeerSetWaiter (t , ps , id .String (), witness )
130+ ps .close ()
131+ if got := <- result ; ! errors .Is (got .err , errPeerSetClosed ) {
132+ t .Fatalf ("unexpected close error: %v" , got .err )
133+ }
134+ })
135+
136+ t .Run ("registered" , func (t * testing.T ) {
137+ ps := newPeerSet ()
138+ defer ps .close ()
139+
140+ id := enode.ID {4 }
141+ main := newPeerSetEthPeer (t , id , caps )
142+ ext := newExtension (t , id , caps )
143+ if err := ps .registerPeer (main , nil , nil ); err != nil {
144+ t .Fatal (err )
145+ }
146+ if err := register (ps , ext ); ! errors .Is (err , errPeerAlreadyRegistered ) {
147+ t .Fatalf ("unexpected extension registration error: %v" , err )
148+ }
149+ if _ , err := wait (ps , main ); ! errors .Is (err , errPeerAlreadyRegistered ) {
150+ t .Fatalf ("unexpected extension wait error: %v" , err )
151+ }
152+ })
153+
154+ t .Run ("incompatible" , func (t * testing.T ) {
155+ ps := newPeerSet ()
156+ defer ps .close ()
157+
158+ id := enode.ID {5 }
159+ ext := newExtension (t , id , caps [1 :])
160+ if err := register (ps , ext ); ! errors .Is (err , incompatibleError ) {
161+ t .Fatalf ("unexpected extension registration error: %v" , err )
162+ }
163+ main := newPeerSetEthPeer (t , id , caps [:1 ])
164+ var zero T
165+ if got , err := wait (ps , main ); err != nil || got != zero {
166+ t .Fatalf ("unexpected extension: got %v, err %v" , got , err )
167+ }
168+ })
169+ }
170+
171+ func newPeerSetEthPeer (t * testing.T , id enode.ID , caps []p2p.Cap ) * eth.Peer {
172+ t .Helper ()
173+ peer , rw := newPeerSetProtocolPeer (t , id , caps )
174+ result := eth .NewPeer (eth .ETH69 , peer , rw , nil )
175+ t .Cleanup (result .Close )
176+ return result
177+ }
178+
179+ func newPeerSetSnapPeer (t * testing.T , id enode.ID , caps []p2p.Cap ) * snap.Peer {
180+ t .Helper ()
181+ peer , rw := newPeerSetProtocolPeer (t , id , caps )
182+ return snap .NewPeer (snap .SNAP1 , peer , rw )
183+ }
184+
185+ func newPeerSetWitPeer (t * testing.T , id enode.ID , caps []p2p.Cap ) * wit.Peer {
186+ t .Helper ()
187+ peer , rw := newPeerSetProtocolPeer (t , id , caps )
188+ result := wit .NewPeer (wit .WIT2 , peer , rw , log .New ())
189+ t .Cleanup (result .Close )
190+ return result
191+ }
192+
193+ func newPeerSetProtocolPeer (t * testing.T , id enode.ID , caps []p2p.Cap ) (* p2p.Peer , p2p.MsgReadWriter ) {
194+ t .Helper ()
195+ app , net := p2p .MsgPipe ()
196+ t .Cleanup (func () {
197+ app .Close ()
198+ net .Close ()
199+ })
200+ return p2p .NewPeer (id , "test" , caps ), net
201+ }
202+
203+ func waitForPeerSetWaiter (t * testing.T , ps * peerSet , id string , witness bool ) {
204+ t .Helper ()
205+ deadline := time .Now ().Add (time .Second )
206+ for time .Now ().Before (deadline ) {
207+ ps .lock .RLock ()
208+ _ , snapReady := ps .snapWait [id ]
209+ _ , witReady := ps .witWait [id ]
210+ ps .lock .RUnlock ()
211+ ready := snapReady
212+ if witness {
213+ ready = witReady
214+ }
215+ if ready {
216+ return
217+ }
218+ time .Sleep (time .Millisecond )
219+ }
220+ t .Fatal ("extension waiter was not registered" )
221+ }
222+
17223func TestPeerSetForgetTransactions (t * testing.T ) {
18224 t .Parallel ()
19225
0 commit comments