go.dedis.ch/onet/v4@v4.0.0-pre1/network/router_test.go (about) 1 package network 2 3 import ( 4 "sync" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/require" 9 "go.dedis.ch/onet/v4/log" 10 "golang.org/x/xerrors" 11 ) 12 13 func NewTestRouterTCP(port int) (*Router, error) { 14 h, err := NewTestTCPHost(port) 15 if err != nil { 16 return nil, xerrors.Errorf("tcp host: %v", err) 17 } 18 h.sid.Address = h.TCPListener.Address() 19 r := NewRouter(h.sid, h) 20 r.UnauthOk = true 21 return r, nil 22 } 23 24 func NewTestRouterLocal(port int) (*Router, error) { 25 h, err := NewTestLocalHost(port) 26 if err != nil { 27 return nil, xerrors.Errorf("local host: %v", err) 28 } 29 id := NewTestServerIdentity(h.addr) 30 return NewRouter(id, h), nil 31 } 32 33 type routerFactory func(port int) (*Router, error) 34 35 // Test if router fits the interface such as calling Run(), then Stop(), 36 // should return 37 func TestRouterTCP(t *testing.T) { 38 testRouter(t, NewTestRouterTCP) 39 } 40 func TestRouterLocal(t *testing.T) { 41 testRouter(t, NewTestRouterLocal) 42 } 43 44 func testRouter(t *testing.T, fac routerFactory) { 45 h, err := fac(2004) 46 if err != nil { 47 t.Fatal(err) 48 } 49 var stop = make(chan bool) 50 go func() { 51 stop <- true 52 h.Start() 53 stop <- true 54 }() 55 <-stop 56 // Time needed so the listener is up. Equivalent to "connecting ourself" as 57 // we had before. 58 time.Sleep(250 * time.Millisecond) 59 h.Stop() 60 select { 61 case <-stop: 62 return 63 case <-time.After(500 * time.Millisecond): 64 t.Fatal("TcpHost should have returned from Run() by now") 65 } 66 } 67 68 // Test connection of multiple Hosts and sending messages back and forth 69 // also tests for the counterIO interface that it works well 70 func TestRouterErrorHandling(t *testing.T) { 71 h1, err1 := NewTestRouterTCP(2109) 72 h2, err2 := NewTestRouterTCP(2110) 73 if err1 != nil || err2 != nil { 74 t.Fatal("Could not setup hosts") 75 } 76 77 go h1.Start() 78 go h2.Start() 79 80 defer func() { 81 h1.Stop() 82 }() 83 84 // tests the setting error handler 85 require.NotNil(t, h1.connectionErrorHandlers) 86 if len(h1.connectionErrorHandlers) != 0 { 87 t.Error("errorHandlers should start empty") 88 } 89 errHandlerCalled := make(chan bool, 1) 90 errHandler := func(remote *ServerIdentity) { 91 errHandlerCalled <- true 92 } 93 h1.AddErrorHandler(errHandler) 94 if len(h1.connectionErrorHandlers) != 1 { 95 t.Error("errorHandlers should now hold one function") 96 } 97 98 //register handlers 99 proc := &simpleMessageProc{t, make(chan SimpleMessage)} 100 h1.RegisterProcessor(proc, SimpleMessageType) 101 h2.RegisterProcessor(proc, SimpleMessageType) 102 103 msgSimple := &SimpleMessage{3} 104 sentLen, err := h1.Send(h2.ServerIdentity, msgSimple) 105 require.Nil(t, err) 106 require.NotZero(t, sentLen) 107 decoded := <-proc.relay 108 require.Equal(t, int64(3), decoded.I) 109 sentLen, err = h2.Send(h1.ServerIdentity, msgSimple) 110 require.Nil(t, err) 111 require.NotZero(t, sentLen) 112 decoded = <-proc.relay 113 114 //stop node 2 115 h2.Stop() 116 117 // test if the error handler was called 118 select { 119 case <-errHandlerCalled: 120 // all good 121 case <-time.After(250 * time.Millisecond): 122 t.Error("Error handler should have been called after a disconnection") 123 } 124 } 125 126 func TestRouterSendToSelf(t *testing.T) { 127 r, err := NewTestRouterTCP(0) 128 require.Nil(t, err) 129 130 go r.Start() 131 132 defer func() { 133 r.Stop() 134 }() 135 136 // Need the "1" because sending message through channel in the same 137 // goroutine, will deadlock otherwise 138 proc := &simpleMessageProc{t, make(chan SimpleMessage, 1)} 139 r.RegisterProcessor(proc, SimpleMessageType) 140 141 simpleMsg := &SimpleMessage{3} 142 sentLen, err := r.Send(r.ServerIdentity, simpleMsg) 143 require.Nil(t, err) 144 require.NotZero(t, sentLen) 145 decoded := <-proc.relay 146 require.Equal(t, int64(3), decoded.I) 147 148 // Ensure no connections were open (since sending to ourself) 149 r.Lock() 150 require.Equal(t, 0, len(r.connections)) 151 r.Unlock() 152 } 153 154 func testRouterRemoveConnection(t *testing.T) { 155 r1, err := NewTestRouterTCP(2008) 156 require.Nil(t, err) 157 r2, err := NewTestRouterTCP(2009) 158 require.Nil(t, err) 159 160 defer r1.Stop() 161 162 go r1.Start() 163 go r2.Start() 164 165 sentLen, err := r1.Send(r2.ServerIdentity, nil) 166 require.NotNil(t, err) 167 require.Zero(t, sentLen) 168 169 r1.Lock() 170 require.Equal(t, 1, len(r1.connections[r2.ServerIdentity.ID])) 171 r1.Unlock() 172 173 require.Nil(t, r2.Stop()) 174 175 r1.Lock() 176 require.Equal(t, 0, len(r1.connections[r2.ServerIdentity.ID])) 177 r1.Unlock() 178 } 179 180 // Test the automatic connection upon request 181 func TestRouterAutoConnectionTCP(t *testing.T) { 182 testRouterAutoConnection(t, NewTestRouterTCP) 183 } 184 func TestRouterAutoConnectionLocal(t *testing.T) { 185 testRouterAutoConnection(t, NewTestRouterLocal) 186 } 187 188 func testRouterAutoConnection(t *testing.T, fac routerFactory) { 189 h1, err := fac(2007) 190 if err != nil { 191 t.Fatal(err) 192 } 193 _, err = h1.Send(&ServerIdentity{Address: NewLocalAddress("127.1.2.3:2890")}, &SimpleMessage{12}) 194 require.NotNil(t, err, "Should not be able to send") 195 196 h2, err := fac(2008) 197 if err != nil { 198 t.Fatal(err) 199 } 200 201 _, err = h1.Send(h2.ServerIdentity, nil) 202 require.NotNil(t, err) 203 204 go h2.Start() 205 for !h2.Listening() { 206 time.Sleep(10 * time.Millisecond) 207 } 208 209 clean := func() { 210 require.Nil(t, h1.Stop()) 211 require.Nil(t, h2.Stop()) 212 } 213 defer clean() 214 215 proc := newSimpleMessageProc(t) 216 h2.RegisterProcessor(proc, SimpleMessageType) 217 h1.RegisterProcessor(proc, SimpleMessageType) 218 219 sentLen, err := h1.Send(h2.ServerIdentity, &SimpleMessage{12}) 220 require.Nil(t, err) 221 require.NotZero(t, sentLen) 222 223 // Receive the message 224 msg := <-proc.relay 225 if msg.I != 12 { 226 t.Fatal("Simple message got distorted") 227 } 228 229 h12 := h1.connection(h2.ServerIdentity.ID) 230 h21 := h2.connection(h1.ServerIdentity.ID) 231 require.NotNil(t, h12) 232 require.NotNil(t, h21) 233 require.Nil(t, h21.Close()) 234 time.Sleep(100 * time.Millisecond) 235 236 sentLen, err = h1.Send(h2.ServerIdentity, &SimpleMessage{12}) 237 require.Nil(t, err) 238 require.NotZero(t, sentLen) 239 <-proc.relay 240 241 if err := h2.Stop(); err != nil { 242 t.Fatal("Should be able to stop h2") 243 } 244 _, err = h1.Send(h2.ServerIdentity, &SimpleMessage{12}) 245 if err == nil { 246 // This should not happen, but it can due to a race in 247 // the kernel between closing and writing to the 248 // existing h1->h2 TCP connections. It would be nice 249 // to fix this to make the tests more deterministic, 250 // but for now we'll just give up and log it. 251 t.Log("h1 let us send still") 252 } 253 } 254 255 // Test connection of multiple Hosts and sending messages back and forth 256 // also tests for the counterIO interface that it works well 257 func TestRouterMessaging(t *testing.T) { 258 h1, err1 := NewTestRouterTCP(2009) 259 h2, err2 := NewTestRouterTCP(2010) 260 if err1 != nil || err2 != nil { 261 t.Fatal("Could not setup hosts") 262 } 263 264 go h1.Start() 265 go h2.Start() 266 267 defer func() { 268 h1.Stop() 269 h2.Stop() 270 time.Sleep(250 * time.Millisecond) 271 }() 272 273 proc := &simpleMessageProc{t, make(chan SimpleMessage)} 274 h1.RegisterProcessor(proc, SimpleMessageType) 275 h2.RegisterProcessor(proc, SimpleMessageType) 276 277 msgSimple := &SimpleMessage{3} 278 sentLen, err := h1.Send(h2.ServerIdentity, msgSimple) 279 require.Nil(t, err) 280 require.NotZero(t, sentLen) 281 282 decoded := <-proc.relay 283 require.Equal(t, int64(3), decoded.I) 284 285 // make sure the connection is registered in host1 (because it's launched in 286 // a go routine). Since we try to avoid random timeout, let's send a msg 287 // from host2 -> host1. 288 sentLen, err = h2.Send(h1.ServerIdentity, msgSimple) 289 require.Nil(t, err) 290 require.NotZero(t, sentLen) 291 292 decoded = <-proc.relay 293 require.Equal(t, int64(3), decoded.I) 294 295 written := h1.Tx() 296 read := h2.Rx() 297 if written == 0 || read == 0 || written != read { 298 log.Errorf("Tx = %d, Rx = %d", written, read) 299 log.Errorf("h1.Tx() %d vs h2.Rx() %d", h1.Tx(), h2.Rx()) 300 log.Errorf("Something is wrong with Host.CounterIO") 301 } 302 } 303 304 func TestRouterLotsOfConnTCP(t *testing.T) { 305 testRouterLotsOfConn(t, NewTestRouterTCP, 5) 306 } 307 308 func TestRouterLotsOfConnLocal(t *testing.T) { 309 testRouterLotsOfConn(t, NewTestRouterLocal, 5) 310 } 311 312 // nSquareProc will send back all packet sent and stop when it has received 313 // enough, it releases the waitgroup. 314 type nSquareProc struct { 315 t *testing.T 316 r *Router 317 expected int 318 wg *sync.WaitGroup 319 firstRound map[Address]bool 320 secondRound map[Address]bool 321 sync.Mutex 322 } 323 324 func newNSquareProc(t *testing.T, r *Router, expect int, wg *sync.WaitGroup) *nSquareProc { 325 return &nSquareProc{t, r, expect, wg, make(map[Address]bool), make(map[Address]bool), sync.Mutex{}} 326 } 327 328 func (p *nSquareProc) Process(env *Envelope) { 329 p.Lock() 330 defer p.Unlock() 331 remote := env.ServerIdentity.Address 332 ok := p.firstRound[remote] 333 if ok { 334 // second round 335 if ok := p.secondRound[remote]; ok { 336 p.t.Fatal("Already received second round") 337 } 338 p.secondRound[remote] = true 339 340 if len(p.secondRound) == p.expected { 341 // release 342 p.wg.Done() 343 } 344 return 345 } 346 347 p.firstRound[remote] = true 348 if _, err := p.r.Send(env.ServerIdentity, &SimpleMessage{3}); err != nil { 349 p.t.Fatal("Could not send to first round dest.") 350 } 351 352 } 353 354 // Makes a big mesh where every host send and receive to every other hosts 355 func testRouterLotsOfConn(t *testing.T, fac routerFactory, nbrRouter int) { 356 // create all the routers 357 routers := make([]*Router, nbrRouter) 358 // to wait for the creation of all hosts 359 var wg1 sync.WaitGroup 360 wg1.Add(nbrRouter) 361 var wg2 sync.WaitGroup 362 wg2.Add(nbrRouter) 363 for i := 0; i < nbrRouter; i++ { 364 go func(j int) { 365 r, err := fac(2000 + j) 366 if err != nil { 367 t.Fatal(err) 368 } 369 go r.Start() 370 for !r.Listening() { 371 time.Sleep(10 * time.Millisecond) 372 } 373 374 routers[j] = r 375 // expect nbrRouter - 1 messages 376 proc := newNSquareProc(t, r, nbrRouter-1, &wg2) 377 r.RegisterProcessor(proc, SimpleMessageType) 378 wg1.Done() 379 }(i) 380 } 381 wg1.Wait() 382 383 for i := 0; i < nbrRouter; i++ { 384 go func(j int) { 385 r := routers[j] 386 for k := 0; k < nbrRouter; k++ { 387 if k == j { 388 // don't send to yourself 389 continue 390 } 391 // send to everyone else 392 if _, err := r.Send(routers[k].ServerIdentity, &SimpleMessage{3}); err != nil { 393 t.Fatal(err) 394 } 395 } 396 }(i) 397 } 398 wg2.Wait() 399 for i := 0; i < nbrRouter; i++ { 400 r := routers[i] 401 if err := r.Stop(); err != nil { 402 t.Fatal(err) 403 } 404 405 } 406 } 407 408 // Test sending data back and forth using the sendProtocolMsg 409 func TestRouterSendMsgDuplexTCP(t *testing.T) { 410 testRouterSendMsgDuplex(t, NewTestRouterTCP) 411 } 412 413 func TestRouterSendMsgDuplexLocal(t *testing.T) { 414 testRouterSendMsgDuplex(t, NewTestRouterLocal) 415 } 416 func testRouterSendMsgDuplex(t *testing.T, fac routerFactory) { 417 h1, err1 := fac(2011) 418 h2, err2 := fac(2012) 419 if err1 != nil { 420 t.Fatal("Could not setup hosts: ", err1) 421 } 422 if err2 != nil { 423 t.Fatal("Could not setup hosts: ", err2) 424 } 425 go h1.Start() 426 go h2.Start() 427 428 defer func() { 429 h1.Stop() 430 h2.Stop() 431 time.Sleep(250 * time.Millisecond) 432 }() 433 434 proc := &simpleMessageProc{t, make(chan SimpleMessage)} 435 h1.RegisterProcessor(proc, SimpleMessageType) 436 h2.RegisterProcessor(proc, SimpleMessageType) 437 438 msgSimple := &SimpleMessage{5} 439 sentLen, err := h1.Send(h2.ServerIdentity, msgSimple) 440 require.Nil(t, err, "Couldn't send message from h1 to h2") 441 require.NotZero(t, sentLen) 442 443 msg := <-proc.relay 444 log.Lvl2("Received msg h1 -> h2", msg) 445 446 sentLen, err = h2.Send(h1.ServerIdentity, msgSimple) 447 require.Nil(t, err, "Couldn't send message from h2 to h1") 448 require.NotZero(t, sentLen) 449 450 msg = <-proc.relay 451 log.Lvl2("Received msg h2 -> h1", msg) 452 } 453 454 func TestRouterExchange(t *testing.T) { 455 log.OutputToBuf() 456 defer log.OutputToOs() 457 router1, err := NewTestRouterTCP(7878) 458 router2, err2 := NewTestRouterTCP(8787) 459 if err != nil || err2 != nil { 460 t.Fatal("Could not setup host", err, err2) 461 } 462 463 done := make(chan bool) 464 go func() { 465 done <- true 466 router1.Start() 467 done <- true 468 }() 469 <-done 470 // try correctly 471 c, err := NewTCPConn(router1.ServerIdentity.Address, tSuite) 472 if err != nil { 473 t.Fatal("Couldn't connect to host1:", err) 474 } 475 sentLen, err := c.Send(router2.ServerIdentity) 476 require.Nil(t, err, "Wrong negotiation") 477 require.NotZero(t, sentLen) 478 479 // triggers the dispatching conditional branch error router.go: 480 // `log.Lvl3("Error dispatching:", err)` 481 sentLen, err = router2.Send(router1.ServerIdentity, &SimpleMessage{12}) 482 require.Nil(t, err, "Could not send") 483 require.NotZero(t, sentLen) 484 c.Close() 485 486 // try messing with the connections here 487 c, err = NewTCPConn(router1.ServerIdentity.Address, tSuite) 488 if err != nil { 489 t.Fatal("Couldn't connect to host1:", err) 490 } 491 // closing before sending 492 c.Close() 493 _, err = c.Send(router2.ServerIdentity) 494 require.NotNil(t, err, "negotiation should have aborted") 495 496 // stop everything 497 log.Lvl4("Closing connections") 498 if err := router2.Stop(); err != nil { 499 t.Fatal("Couldn't close host", err) 500 } 501 if err := router1.Stop(); err != nil { 502 t.Fatal("Couldn't close host", err) 503 } 504 <-done 505 } 506 507 func TestRouterRxTx(t *testing.T) { 508 router1, err := NewTestRouterTCP(0) 509 log.ErrFatal(err) 510 router2, err := NewTestRouterTCP(0) 511 log.ErrFatal(err) 512 go router1.Start() 513 go router2.Start() 514 515 addr := NewAddress(router1.address.ConnType(), "127.0.0.1:"+router1.address.Port()) 516 si1 := NewServerIdentity(Suite.Point(tSuite).Null(), addr) 517 518 sentLen, err := router2.Send(si1, si1) 519 require.Nil(t, err) 520 require.NotZero(t, sentLen) 521 522 // Wait for the message to be sent and received 523 waitTimeout(time.Second, 10, func() bool { 524 return router1.Rx() > 0 && router1.Rx() == router2.Tx() 525 }) 526 rx := router1.Rx() 527 require.Equal(t, 1, len(router1.connections)) 528 router1.Lock() 529 var si2 ServerIdentityID 530 for si2 = range router1.connections { 531 log.Lvl3("Connection:", si2) 532 } 533 router1.Unlock() 534 router2.Stop() 535 waitTimeout(time.Second, 10, func() bool { 536 router1.Lock() 537 defer router1.Unlock() 538 return len(router1.connections[si2]) == 0 539 }) 540 require.Equal(t, rx, router1.Rx()) 541 require.Equal(t, uint64(1), router1.MsgRx()) 542 require.Equal(t, uint64(0), router1.MsgTx()) 543 require.Equal(t, uint64(1), router2.MsgTx()) 544 require.Equal(t, uint64(0), router2.MsgRx()) 545 defer router1.Stop() 546 } 547 548 func waitTimeout(timeout time.Duration, repeat int, 549 f func() bool) { 550 success := make(chan bool) 551 go func() { 552 for !f() { 553 time.Sleep(timeout / time.Duration(repeat)) 554 } 555 success <- true 556 }() 557 select { 558 case <-success: 559 case <-time.After(timeout): 560 log.Fatal("Timeout" + log.Stack()) 561 } 562 563 } 564 565 type testConn struct{} 566 567 func (c *testConn) Receive() (*Envelope, error) { 568 return nil, ErrUnknown 569 } 570 571 func (c *testConn) Close() error { 572 return nil 573 } 574 575 func (c *testConn) Local() Address { 576 return "" 577 } 578 579 func (c *testConn) Remote() Address { 580 return "" 581 } 582 583 func (c *testConn) Rx() uint64 { 584 return 0 585 } 586 587 func (c *testConn) Tx() uint64 { 588 return 0 589 } 590 591 func (c *testConn) Send(msg Message) (uint64, error) { 592 return 0, nil 593 } 594 595 func (c *testConn) Type() ConnType { 596 return "testConn" 597 } 598 599 // This test insures that an unknown error cannot end up as an infinite loop 600 // when handling a connection 601 func TestRouterHandleUnknownError(t *testing.T) { 602 router, err := NewTestRouterTCP(0) 603 require.NoError(t, err) 604 605 router.wg.Add(1) 606 // The test will leak 1 goroutine if the connection is not dropped 607 go router.handleConn(router.ServerIdentity, &testConn{}) 608 }