github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/p2p/switch_test.go (about) 1 package p2p 2 3 import ( 4 "io/ioutil" 5 "os" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/davecgh/go-spew/spew" 11 12 cfg "github.com/bytom/bytom/config" 13 "github.com/bytom/bytom/crypto/ed25519/chainkd" 14 dbm "github.com/bytom/bytom/database/leveldb" 15 "github.com/bytom/bytom/errors" 16 conn "github.com/bytom/bytom/p2p/connection" 17 "github.com/bytom/bytom/p2p/security" 18 ) 19 20 var ( 21 testCfg *cfg.Config 22 ) 23 24 func init() { 25 testCfg = cfg.DefaultConfig() 26 } 27 28 /* 29 Each peer has one `MConnection` (multiplex connection) instance. 30 31 __multiplex__ *noun* a system or signal involving simultaneous transmission of 32 several messages along a single channel of communication. 33 34 Each `MConnection` handles message transmission on multiple abstract communication 35 `Channel`s. Each channel has a globally unique byte id. 36 The byte id and the relative priorities of each `Channel` are configured upon 37 initialization of the connection. 38 39 There are two methods for sending messages: 40 func (m MConnection) Send(chID byte, msgBytes []byte) bool {} 41 func (m MConnection) TrySend(chID byte, msgBytes []byte}) bool {} 42 43 `Send(chID, msgBytes)` is a blocking call that waits until `msg` is 44 successfully queued for the channel with the given id byte `chID`, or until the 45 request times out. The message `msg` is serialized using Go-Amino. 46 47 `TrySend(chID, msgBytes)` is a nonblocking call that returns false if the 48 channel's queue is full. 49 50 Inbound message bytes are handled with an onReceive callback function. 51 */ 52 type PeerMessage struct { 53 PeerID string 54 Bytes []byte 55 Counter int 56 } 57 58 type TestReactor struct { 59 BaseReactor 60 61 mtx sync.Mutex 62 channels []*conn.ChannelDescriptor 63 logMessages bool 64 msgsCounter int 65 msgsReceived map[byte][]PeerMessage 66 } 67 68 func NewTestReactor(channels []*conn.ChannelDescriptor, logMessages bool) *TestReactor { 69 tr := &TestReactor{ 70 channels: channels, 71 logMessages: logMessages, 72 msgsReceived: make(map[byte][]PeerMessage), 73 } 74 tr.BaseReactor = *NewBaseReactor("TestReactor", tr) 75 76 return tr 77 } 78 79 // GetChannels implements Reactor 80 func (tr *TestReactor) GetChannels() []*conn.ChannelDescriptor { 81 return tr.channels 82 } 83 84 // OnStart implements BaseService 85 func (tr *TestReactor) OnStart() error { 86 tr.BaseReactor.OnStart() 87 return nil 88 } 89 90 // OnStop implements BaseService 91 func (tr *TestReactor) OnStop() { 92 tr.BaseReactor.OnStop() 93 } 94 95 // AddPeer implements Reactor by sending our state to peer. 96 func (tr *TestReactor) AddPeer(peer *Peer) error { 97 return nil 98 } 99 100 // RemovePeer implements Reactor by removing peer from the pool. 101 func (tr *TestReactor) RemovePeer(peer *Peer, reason interface{}) { 102 } 103 104 // Receive implements Reactor by handling 4 types of messages (look below). 105 func (tr *TestReactor) Receive(chID byte, peer *Peer, msgBytes []byte) { 106 if tr.logMessages { 107 tr.mtx.Lock() 108 defer tr.mtx.Unlock() 109 tr.msgsReceived[chID] = append(tr.msgsReceived[chID], PeerMessage{peer.ID(), msgBytes, tr.msgsCounter}) 110 tr.msgsCounter++ 111 } 112 } 113 114 func initSwitchFunc(sw *Switch) *Switch { 115 // Make two reactors of two channels each 116 sw.AddReactor("foo", NewTestReactor([]*conn.ChannelDescriptor{ 117 {ID: byte(0x00), Priority: 10}, 118 {ID: byte(0x01), Priority: 10}, 119 }, true)) 120 sw.AddReactor("bar", NewTestReactor([]*conn.ChannelDescriptor{ 121 {ID: byte(0x02), Priority: 10}, 122 {ID: byte(0x03), Priority: 10}, 123 }, true)) 124 125 return sw 126 } 127 128 //Test connect self. 129 func TestFiltersOutItself(t *testing.T) { 130 t.Skip("due to fail on mac") 131 dirPath, err := ioutil.TempDir(".", "") 132 if err != nil { 133 t.Fatal(err) 134 } 135 defer os.RemoveAll(dirPath) 136 137 testDB := dbm.NewDB("testdb", "leveldb", dirPath) 138 cfg := *testCfg 139 cfg.DBPath = dirPath 140 cfg.P2P.ListenAddress = "127.0.1.1:0" 141 swPrivKey, _ := chainkd.NewXPrv(nil) 142 s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc) 143 s1.Start() 144 defer s1.Stop() 145 146 rmdirPath, err := ioutil.TempDir(".", "") 147 if err != nil { 148 t.Fatal(err) 149 } 150 defer os.RemoveAll(rmdirPath) 151 152 // simulate s1 having a public key and creating a remote peer with the same key 153 rpCfg := *testCfg 154 rpCfg.DBPath = rmdirPath 155 rp := &remotePeer{PrivKey: s1.nodePrivKey, Config: &rpCfg} 156 rp.Start() 157 defer rp.Stop() 158 if err = s1.DialPeerWithAddress(rp.addr); errors.Root(err) != ErrConnectSelf { 159 t.Fatal(err) 160 } 161 162 //S1 dialing itself ip address 163 addr := NewNetAddress(s1.listeners[0].(*DefaultListener).NetListener().Addr()) 164 165 if err := s1.DialPeerWithAddress(addr); errors.Root(err) != ErrConnectSelf { 166 t.Fatal(err) 167 } 168 } 169 170 func TestDialBannedPeer(t *testing.T) { 171 t.Skip("due to fail on mac") 172 dirPath, err := ioutil.TempDir(".", "") 173 if err != nil { 174 t.Fatal(err) 175 } 176 defer os.RemoveAll(dirPath) 177 178 testDB := dbm.NewDB("testdb", "leveldb", dirPath) 179 cfg := *testCfg 180 cfg.DBPath = dirPath 181 cfg.P2P.ListenAddress = "127.0.1.1:0" 182 swPrivKey, _ := chainkd.NewXPrv(nil) 183 s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc) 184 s1.Start() 185 defer s1.Stop() 186 187 rmdirPath, err := ioutil.TempDir(".", "") 188 if err != nil { 189 t.Fatal(err) 190 } 191 defer os.RemoveAll(rmdirPath) 192 193 rpCfg := *testCfg 194 rpCfg.DBPath = rmdirPath 195 prvKey, _ := chainkd.NewXPrv(nil) 196 rp := &remotePeer{PrivKey: prvKey, Config: &rpCfg} 197 rp.Start() 198 defer rp.Stop() 199 for { 200 if ok := s1.security.IsBanned(rp.addr.IP.String(), security.LevelMsgIllegal, "test"); ok { 201 break 202 } 203 } 204 if err := s1.DialPeerWithAddress(rp.addr); errors.Root(err) != security.ErrConnectBannedPeer { 205 t.Fatal(err) 206 } 207 } 208 209 func TestDuplicateOutBoundPeer(t *testing.T) { 210 t.Skip("due to fail on mac") 211 dirPath, err := ioutil.TempDir(".", "") 212 if err != nil { 213 t.Fatal(err) 214 } 215 defer os.RemoveAll(dirPath) 216 217 testDB := dbm.NewDB("testdb", "leveldb", dirPath) 218 cfg := *testCfg 219 cfg.DBPath = dirPath 220 cfg.P2P.ListenAddress = "127.0.1.1:0" 221 swPrivKey, _ := chainkd.NewXPrv(nil) 222 s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc) 223 s1.Start() 224 defer s1.Stop() 225 226 rmdirPath, err := ioutil.TempDir(".", "") 227 if err != nil { 228 t.Fatal(err) 229 } 230 defer os.RemoveAll(rmdirPath) 231 232 rpCfg := *testCfg 233 prvKey, _ := chainkd.NewXPrv(nil) 234 rp := &remotePeer{PrivKey: prvKey, Config: &rpCfg} 235 rp.Start() 236 defer rp.Stop() 237 238 if err = s1.DialPeerWithAddress(rp.addr); err != nil { 239 t.Fatal(err) 240 } 241 242 if err = s1.DialPeerWithAddress(rp.addr); errors.Root(err) != ErrDuplicatePeer { 243 t.Fatal(err) 244 } 245 } 246 247 func TestDuplicateInBoundPeer(t *testing.T) { 248 t.Skip("due to fail on mac") 249 dirPath, err := ioutil.TempDir(".", "") 250 if err != nil { 251 t.Fatal(err) 252 } 253 defer os.RemoveAll(dirPath) 254 255 testDB := dbm.NewDB("testdb", "leveldb", dirPath) 256 cfg := *testCfg 257 cfg.DBPath = dirPath 258 cfg.P2P.ListenAddress = "127.0.1.1:0" 259 swPrivKey, _ := chainkd.NewXPrv(nil) 260 s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc) 261 s1.Start() 262 defer s1.Stop() 263 264 inpCfg := *testCfg 265 inp := &inboundPeer{PrivKey: swPrivKey, config: &inpCfg} 266 addr := NewNetAddress(s1.listeners[0].(*DefaultListener).NetListener().Addr()) 267 if err != nil { 268 t.Fatal(err) 269 } 270 go inp.dial(addr) 271 272 inp1Cfg := *testCfg 273 inp1 := &inboundPeer{PrivKey: inp.PrivKey, config: &inp1Cfg} 274 go inp1.dial(addr) 275 276 time.Sleep(1 * time.Second) 277 if _, outbound, inbound, dialing := s1.NumPeers(); outbound+inbound+dialing != 1 { 278 t.Fatal("TestDuplicateInBoundPeer peer size error want 1, got:", outbound, inbound, dialing, spew.Sdump(s1.peers.lookup)) 279 } 280 } 281 282 func TestAddInboundPeer(t *testing.T) { 283 t.Skip("due to fail on mac") 284 dirPath, err := ioutil.TempDir(".", "") 285 if err != nil { 286 t.Fatal(err) 287 } 288 defer os.RemoveAll(dirPath) 289 290 testDB := dbm.NewDB("testdb", "leveldb", dirPath) 291 cfg := *testCfg 292 cfg.DBPath = dirPath 293 cfg.P2P.MaxNumPeers = 2 294 cfg.P2P.ListenAddress = "127.0.1.1:0" 295 swPrivKey, _ := chainkd.NewXPrv(nil) 296 s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc) 297 s1.Start() 298 defer s1.Stop() 299 300 inpCfg := *testCfg 301 inpPrivKey, _ := chainkd.NewXPrv(nil) 302 inp := &inboundPeer{PrivKey: inpPrivKey, config: &inpCfg} 303 addr := NewNetAddress(s1.listeners[0].(*DefaultListener).NetListener().Addr()) 304 if err != nil { 305 t.Fatal(err) 306 } 307 go inp.dial(addr) 308 309 rpCfg := *testCfg 310 rpPrivKey, _ := chainkd.NewXPrv(nil) 311 rp := &remotePeer{PrivKey: rpPrivKey, Config: &rpCfg} 312 rp.Start() 313 defer rp.Stop() 314 315 if err := s1.DialPeerWithAddress(rp.addr); err != nil { 316 t.Fatal(err) 317 } 318 319 inp2Cfg := *testCfg 320 inp2PrivKey, _ := chainkd.NewXPrv(nil) 321 inp2 := &inboundPeer{PrivKey: inp2PrivKey, config: &inp2Cfg} 322 323 go inp2.dial(addr) 324 325 time.Sleep(1 * time.Second) 326 if _, outbound, inbound, dialing := s1.NumPeers(); outbound+inbound+dialing != 2 { 327 t.Fatal("TestAddInboundPeer peer size error want 2 got:", spew.Sdump(s1.peers.lookup)) 328 } 329 } 330 331 func TestStopPeer(t *testing.T) { 332 t.Skip("due to fail on mac") 333 dirPath, err := ioutil.TempDir(".", "") 334 if err != nil { 335 t.Fatal(err) 336 } 337 defer os.RemoveAll(dirPath) 338 339 testDB := dbm.NewDB("testdb", "leveldb", dirPath) 340 cfg := *testCfg 341 cfg.DBPath = dirPath 342 cfg.P2P.MaxNumPeers = 2 343 cfg.P2P.ListenAddress = "127.0.1.1:0" 344 swPrivKey, _ := chainkd.NewXPrv(nil) 345 s1 := MakeSwitch(&cfg, testDB, swPrivKey, initSwitchFunc) 346 s1.Start() 347 defer s1.Stop() 348 349 inpCfg := *testCfg 350 inpPrivKey, _ := chainkd.NewXPrv(nil) 351 inp := &inboundPeer{PrivKey: inpPrivKey, config: &inpCfg} 352 addr := NewNetAddress(s1.listeners[0].(*DefaultListener).NetListener().Addr()) 353 if err != nil { 354 t.Fatal(err) 355 } 356 go inp.dial(addr) 357 358 rpCfg := *testCfg 359 rpPrivKey, _ := chainkd.NewXPrv(nil) 360 rp := &remotePeer{PrivKey: rpPrivKey, Config: &rpCfg} 361 rp.Start() 362 defer rp.Stop() 363 364 if err := s1.DialPeerWithAddress(rp.addr); err != nil { 365 t.Fatal(err) 366 } 367 time.Sleep(1 * time.Second) 368 if _, outbound, inbound, dialing := s1.NumPeers(); outbound+inbound+dialing != 2 { 369 t.Fatal("TestStopPeer peer size error want 2,got:", spew.Sdump(s1.peers.lookup)) 370 } 371 372 s1.StopPeerGracefully(s1.peers.list[0].Key) 373 if _, outbound, inbound, dialing := s1.NumPeers(); outbound+inbound+dialing != 1 { 374 t.Fatal("TestStopPeer peer size error,want 1,got:", spew.Sdump(s1.peers.lookup)) 375 } 376 377 s1.StopPeerForError(s1.peers.list[0], "stop for test") 378 if _, outbound, inbound, dialing := s1.NumPeers(); outbound+inbound+dialing != 0 { 379 t.Fatal("TestStopPeer peer size error,want 0, got:", spew.Sdump(s1.peers.lookup)) 380 } 381 }