gopkg.in/dedis/onet.v2@v2.0.0-20181115163211-c8f3724038a7/service_test.go (about) 1 package onet 2 3 import ( 4 "bytes" 5 "errors" 6 "net/http" 7 "testing" 8 "time" 9 10 "sync" 11 12 "github.com/dedis/protobuf" 13 "github.com/stretchr/testify/require" 14 "gopkg.in/dedis/onet.v2/log" 15 "gopkg.in/dedis/onet.v2/network" 16 ) 17 18 const dummyServiceName = "dummyService" 19 const dummyService2Name = "dummyService2" 20 const ismServiceName = "ismService" 21 const backForthServiceName = "backForth" 22 const dummyProtocolName = "DummyProtocol2" 23 24 func init() { 25 network.RegisterMessage(SimpleMessageForth{}) 26 network.RegisterMessage(SimpleMessageBack{}) 27 network.RegisterMessage(SimpleRequest{}) 28 dummyMsgType = network.RegisterMessage(DummyMsg{}) 29 RegisterNewService(ismServiceName, newServiceMessages) 30 RegisterNewService(dummyService2Name, newDummyService2) 31 GlobalProtocolRegister(dummyProtocolName, newDummyProtocol2) 32 } 33 34 func TestServiceRegistration(t *testing.T) { 35 var name = "dummy" 36 RegisterNewService(name, func(c *Context) (Service, error) { 37 return &DummyService{}, nil 38 }) 39 40 names := ServiceFactory.RegisteredServiceNames() 41 var found bool 42 for _, n := range names { 43 if n == name { 44 found = true 45 } 46 } 47 if !found { 48 t.Fatal("Name not found !?") 49 } 50 ServiceFactory.Unregister(name) 51 names = ServiceFactory.RegisteredServiceNames() 52 for _, n := range names { 53 if n == name { 54 t.Fatal("Dummy should not be found!") 55 } 56 } 57 } 58 59 func TestServiceNew(t *testing.T) { 60 ds := &DummyService{ 61 link: make(chan bool, 1), 62 } 63 RegisterNewService(dummyServiceName, func(c *Context) (Service, error) { 64 ds.c = c 65 ds.link <- true 66 return ds, nil 67 }) 68 defer UnregisterService(dummyServiceName) 69 var local *LocalTest 70 servers := make(chan bool) 71 go func() { 72 local = NewLocalTest(tSuite) 73 local.GenServers(1) 74 servers <- true 75 }() 76 77 <-servers 78 waitOrFatal(ds.link, t) 79 local.CloseAll() 80 } 81 82 func TestServiceProcessRequest(t *testing.T) { 83 link := make(chan bool, 1) 84 _, err := RegisterNewService(dummyServiceName, func(c *Context) (Service, error) { 85 ds := &DummyService{ 86 link: link, 87 c: c, 88 } 89 return ds, nil 90 }) 91 log.ErrFatal(err) 92 defer UnregisterService(dummyServiceName) 93 94 local := NewTCPTest(tSuite) 95 hs := local.GenServers(2) 96 server := hs[0] 97 log.Lvl1("Host created and listening") 98 defer local.CloseAll() 99 // Send a request to the service 100 client := NewClient(tSuite, dummyServiceName) 101 log.Lvl1("Sending request to service...") 102 _, err = client.Send(server.ServerIdentity, "nil", []byte("a")) 103 log.Lvl2("Got reply") 104 require.Error(t, err) 105 // wait for the link 106 if <-link { 107 log.Fatal("was expecting false !") 108 } 109 } 110 111 // Test if a request that makes the service create a new protocol works 112 func TestServiceRequestNewProtocol(t *testing.T) { 113 ds := &DummyService{ 114 link: make(chan bool, 1), 115 } 116 RegisterNewService(dummyServiceName, func(c *Context) (Service, error) { 117 ds.c = c 118 return ds, nil 119 }) 120 121 defer UnregisterService(dummyServiceName) 122 local := NewTCPTest(tSuite) 123 hs := local.GenServers(2) 124 server := hs[0] 125 client := local.NewClient(dummyServiceName) 126 defer local.CloseAll() 127 // create the entityList and tree 128 el := NewRoster([]*network.ServerIdentity{server.ServerIdentity}) 129 tree := el.GenerateBinaryTree() 130 // give it to the service 131 ds.fakeTree = tree 132 133 // Send a request to the service 134 log.Lvl1("Sending request to service...") 135 log.ErrFatal(client.SendProtobuf(server.ServerIdentity, &DummyMsg{10}, nil)) 136 // wait for the link from the 137 waitOrFatalValue(ds.link, true, t) 138 139 // Now resend the value so we instantiate using the same treenode 140 log.Lvl1("Sending request again to service...") 141 err := client.SendProtobuf(server.ServerIdentity, &DummyMsg{10}, nil) 142 require.Error(t, err) 143 // this should fail 144 waitOrFatalValue(ds.link, false, t) 145 } 146 147 // test for calling the NewProtocol method on a remote Service 148 func TestServiceNewProtocol(t *testing.T) { 149 ds1 := &DummyService{ 150 link: make(chan bool), 151 Config: DummyConfig{ 152 Send: true, 153 }, 154 } 155 ds2 := &DummyService{ 156 link: make(chan bool), 157 } 158 var count int 159 countMutex := sync.Mutex{} 160 RegisterNewService(dummyServiceName, func(c *Context) (Service, error) { 161 countMutex.Lock() 162 defer countMutex.Unlock() 163 log.Lvl2("Creating service", count) 164 var localDs *DummyService 165 switch count { 166 case 2: 167 // the client does not need a Service 168 return &DummyService{link: make(chan bool)}, nil 169 case 1: // children 170 localDs = ds2 171 case 0: // root 172 localDs = ds1 173 } 174 localDs.c = c 175 176 count++ 177 return localDs, nil 178 }) 179 180 defer UnregisterService(dummyServiceName) 181 local := NewTCPTest(tSuite) 182 defer local.CloseAll() 183 hs := local.GenServers(3) 184 server1, server2 := hs[0], hs[1] 185 client := local.NewClient(dummyServiceName) 186 log.Lvl1("Host created and listening") 187 188 // create the entityList and tree 189 el := NewRoster([]*network.ServerIdentity{server1.ServerIdentity, server2.ServerIdentity}) 190 tree := el.GenerateBinaryTree() 191 // give it to the service 192 ds1.fakeTree = tree 193 194 // Send a request to the service 195 log.Lvl1("Sending request to service...") 196 log.ErrFatal(client.SendProtobuf(server1.ServerIdentity, &DummyMsg{10}, nil)) 197 log.Lvl1("Waiting for end") 198 // wait for the link from the protocol that Starts 199 waitOrFatalValue(ds1.link, true, t) 200 // now wait for the second link on the second HOST that the second service 201 // should have started (ds2) in ProcessRequest 202 waitOrFatalValue(ds2.link, true, t) 203 log.Lvl1("Done") 204 } 205 206 func TestServiceProcessor(t *testing.T) { 207 ds1 := &DummyService{ 208 link: make(chan bool), 209 } 210 ds2 := &DummyService{ 211 link: make(chan bool), 212 } 213 var count int 214 RegisterNewService(dummyServiceName, func(c *Context) (Service, error) { 215 var s *DummyService 216 if count == 0 { 217 s = ds1 218 } else { 219 s = ds2 220 } 221 s.c = c 222 c.RegisterProcessor(s, dummyMsgType) 223 return s, nil 224 }) 225 local := NewLocalTest(tSuite) 226 defer local.CloseAll() 227 hs := local.GenServers(2) 228 server1, server2 := hs[0], hs[1] 229 230 defer UnregisterService(dummyServiceName) 231 // create two servers 232 log.Lvl1("Host created and listening") 233 // create request 234 log.Lvl1("Sending request to service...") 235 sentLen, err := server2.Send(server1.ServerIdentity, &DummyMsg{10}) 236 require.Nil(t, err) 237 require.NotNil(t, sentLen) 238 239 // wait for the link from the Service on server 1 240 waitOrFatalValue(ds1.link, true, t) 241 } 242 243 func TestServiceBackForthProtocol(t *testing.T) { 244 local := NewTCPTest(tSuite) 245 defer local.CloseAll() 246 247 // register service 248 _, err := RegisterNewService(backForthServiceName, func(c *Context) (Service, error) { 249 return &simpleService{ 250 ctx: c, 251 newProto: make(chan bool, 10), 252 }, nil 253 }) 254 log.ErrFatal(err) 255 defer ServiceFactory.Unregister(backForthServiceName) 256 257 // create servers 258 servers, el, _ := local.GenTree(4, false) 259 260 // create client 261 client := local.NewClient(backForthServiceName) 262 263 // create request 264 r := &SimpleRequest{ 265 ServerIdentities: el, 266 Val: 10, 267 } 268 sr := &SimpleResponse{} 269 err = client.SendProtobuf(servers[0].ServerIdentity, r, sr) 270 log.ErrFatal(err) 271 require.Equal(t, sr.Val, 10) 272 } 273 274 func TestPanicNewProto(t *testing.T) { 275 local := NewTCPTest(tSuite) 276 defer local.CloseAll() 277 278 name := "panicSvc" 279 panicID, err := RegisterNewService(name, func(c *Context) (Service, error) { 280 return &simpleService{ 281 ctx: c, 282 panic: true, 283 newProto: make(chan bool, 1), 284 }, nil 285 }) 286 log.ErrFatal(err) 287 defer ServiceFactory.Unregister(name) 288 289 // create servers 290 servers, el, _ := local.GenTree(2, false) 291 services := local.GetServices(servers, panicID) 292 293 // create client 294 client := local.NewClient(name) 295 296 // create request 297 r := &SimpleRequest{ 298 ServerIdentities: el, 299 Val: 10, 300 } 301 sr := &SimpleResponse{} 302 err = client.SendProtobuf(servers[0].ServerIdentity, r, sr) 303 require.Nil(t, err) 304 client.Close() 305 <-services[1].(*simpleService).newProto 306 } 307 308 func TestServiceManager_Service(t *testing.T) { 309 local := NewLocalTest(tSuite) 310 defer local.CloseAll() 311 servers, _, _ := local.GenTree(2, true) 312 313 services := servers[0].serviceManager.availableServices() 314 require.NotEqual(t, 0, len(services), "no services available") 315 316 service := servers[0].serviceManager.service("testService") 317 require.NotNil(t, service, "Didn't find service testService") 318 } 319 320 func TestServiceMessages(t *testing.T) { 321 local := NewLocalTest(tSuite) 322 defer local.CloseAll() 323 servers, _, _ := local.GenTree(2, true) 324 325 service := servers[0].serviceManager.service(ismServiceName) 326 require.NotNil(t, service, "Didn't find service ISMService") 327 ism := service.(*ServiceMessages) 328 ism.SendRaw(servers[0].ServerIdentity, &SimpleResponse{}) 329 require.True(t, <-ism.GotResponse, "Didn't get response") 330 } 331 332 func TestServiceProtocolInstantiation(t *testing.T) { 333 local := NewLocalTest(tSuite) 334 defer local.CloseAll() 335 servers, _, tree := local.GenTree(2, true) 336 337 s1 := servers[0].serviceManager.service(dummyService2Name) 338 s2 := servers[1].serviceManager.service(dummyService2Name) 339 340 ds1 := s1.(*dummyService2) 341 ds2 := s2.(*dummyService2) 342 343 link := make(chan bool) 344 ds1.link = link 345 ds2.link = link 346 347 go ds1.launchProtoStart(tree, false, true) 348 waitOrFatal(link, t) 349 waitOrFatal(link, t) 350 waitOrFatal(link, t) 351 } 352 353 func TestServiceGenericConfig(t *testing.T) { 354 local := NewLocalTest(tSuite) 355 defer local.CloseAll() 356 servers, _, tree := local.GenTree(2, true) 357 358 s1 := servers[0].serviceManager.service(dummyService2Name) 359 s2 := servers[1].serviceManager.service(dummyService2Name) 360 361 ds1 := s1.(*dummyService2) 362 ds2 := s2.(*dummyService2) 363 364 link := make(chan bool) 365 ds1.link = link 366 ds2.link = link 367 368 // First launch without any config 369 go ds1.launchProto(tree, false) 370 // wait for the service's protocol creation 371 waitOrFatalValue(link, true, t) 372 // wait for the service 2 say there is no config 373 waitOrFatalValue(link, false, t) 374 // then laucnh with config 375 go ds1.launchProto(tree, true) 376 // wait for the service's protocol creation 377 waitOrFatalValue(link, true, t) 378 // wait for the service 2 say there is no config 379 waitOrFatalValue(link, true, t) 380 381 } 382 383 // BackForthProtocolForth & Back are messages that go down and up the tree. 384 // => BackForthProtocol protocol / message 385 type SimpleMessageForth struct { 386 Val int 387 } 388 389 type SimpleMessageBack struct { 390 Val int 391 } 392 393 type BackForthProtocol struct { 394 *TreeNodeInstance 395 Val int 396 counter int 397 forthChan chan struct { 398 *TreeNode 399 SimpleMessageForth 400 } 401 backChan chan struct { 402 *TreeNode 403 SimpleMessageBack 404 } 405 stop chan struct{} 406 handler func(val int) 407 } 408 409 func newBackForthProtocolRoot(tn *TreeNodeInstance, val int, handler func(int)) (ProtocolInstance, error) { 410 s, err := newBackForthProtocol(tn) 411 s.Val = val 412 s.handler = handler 413 return s, err 414 } 415 416 func newBackForthProtocol(tn *TreeNodeInstance) (*BackForthProtocol, error) { 417 s := &BackForthProtocol{ 418 TreeNodeInstance: tn, 419 stop: make(chan struct{}), 420 } 421 err := s.RegisterChannel(&s.forthChan) 422 if err != nil { 423 return nil, err 424 } 425 err = s.RegisterChannel(&s.backChan) 426 if err != nil { 427 return nil, err 428 } 429 go s.dispatch() 430 return s, nil 431 } 432 433 func (sp *BackForthProtocol) Start() error { 434 // send down to children 435 msg := &SimpleMessageForth{ 436 Val: sp.Val, 437 } 438 for _, ch := range sp.Children() { 439 if err := sp.SendTo(ch, msg); err != nil { 440 return err 441 } 442 } 443 return nil 444 } 445 446 func (sp *BackForthProtocol) Shutdown() error { 447 close(sp.stop) 448 return nil 449 } 450 451 func (sp *BackForthProtocol) dispatch() error { 452 for { 453 select { 454 // dispatch the first msg down 455 case m := <-sp.forthChan: 456 msg := &m.SimpleMessageForth 457 for _, ch := range sp.Children() { 458 sp.SendTo(ch, msg) 459 } 460 if sp.IsLeaf() { 461 if err := sp.SendTo(sp.Parent(), &SimpleMessageBack{msg.Val}); err != nil { 462 log.Error(err) 463 } 464 sp.Done() 465 return nil 466 } 467 // pass the message up 468 case m := <-sp.backChan: 469 msg := m.SimpleMessageBack 470 // call the handler if we are the root 471 sp.counter++ 472 if sp.counter == len(sp.Children()) { 473 if sp.IsRoot() { 474 sp.handler(msg.Val) 475 } else { 476 sp.SendTo(sp.Parent(), &msg) 477 } 478 sp.Done() 479 return nil 480 } 481 case <-sp.stop: 482 sp.Done() 483 return nil 484 } 485 } 486 } 487 488 // Client API request / response emulation 489 type SimpleRequest struct { 490 ServerIdentities *Roster 491 Val int 492 } 493 494 type SimpleResponse struct { 495 Val int 496 } 497 498 var SimpleResponseType = network.RegisterMessage(SimpleResponse{}) 499 500 type simpleService struct { 501 ctx *Context 502 panic bool 503 newProto chan bool 504 } 505 506 func (s *simpleService) ProcessClientRequest(req *http.Request, path string, buf []byte) ([]byte, *StreamingTunnel, error) { 507 msg := &SimpleRequest{} 508 err := protobuf.DecodeWithConstructors(buf, msg, network.DefaultConstructors(tSuite)) 509 if err != nil { 510 return nil, nil, err 511 } 512 tree := msg.ServerIdentities.GenerateBinaryTree() 513 tni := s.ctx.NewTreeNodeInstance(tree, tree.Root, backForthServiceName) 514 ret := make(chan int) 515 proto, err := newBackForthProtocolRoot(tni, msg.Val, func(n int) { 516 ret <- n 517 }) 518 if err != nil { 519 return nil, nil, err 520 } 521 if err = s.ctx.RegisterProtocolInstance(proto); err != nil { 522 return nil, nil, err 523 } 524 proto.Start() 525 if s.panic { 526 proto.(*BackForthProtocol).Done() 527 close(ret) 528 } 529 resp, err := protobuf.Encode(&SimpleResponse{<-ret}) 530 return resp, nil, err 531 } 532 533 func (s *simpleService) NewProtocol(tni *TreeNodeInstance, conf *GenericConfig) (ProtocolInstance, error) { 534 select { 535 case s.newProto <- true: 536 default: 537 } 538 if s.panic { 539 panic("this is a panic in NewProtocol") 540 } 541 pi, err := newBackForthProtocol(tni) 542 return pi, err 543 } 544 545 func (s *simpleService) Process(env *network.Envelope) { 546 return 547 } 548 549 type DummyProtocol struct { 550 *TreeNodeInstance 551 link chan bool 552 config DummyConfig 553 } 554 555 type DummyConfig struct { 556 A int 557 Send bool 558 } 559 560 type DummyMsg struct { 561 A int 562 } 563 564 var dummyMsgType network.MessageTypeID 565 566 func newDummyProtocol(tni *TreeNodeInstance, conf DummyConfig, link chan bool) *DummyProtocol { 567 return &DummyProtocol{tni, link, conf} 568 } 569 570 func (dm *DummyProtocol) Start() error { 571 dm.link <- true 572 if dm.config.Send { 573 // also send to the children if any 574 if !dm.IsLeaf() { 575 if err := dm.SendToChildren(&DummyMsg{}); err != nil { 576 log.Error(err) 577 } 578 } 579 } 580 dm.Done() 581 return nil 582 } 583 584 func (dm *DummyProtocol) ProcessProtocolMsg(msg *ProtocolMsg) { 585 dm.link <- true 586 dm.Done() 587 } 588 589 // legacy reasons 590 func (dm *DummyProtocol) Dispatch() error { 591 return nil 592 } 593 594 type DummyService struct { 595 c *Context 596 link chan bool 597 fakeTree *Tree 598 firstTni *TreeNodeInstance 599 Config DummyConfig 600 } 601 602 func (ds *DummyService) ProcessClientRequest(req *http.Request, path string, buf []byte) ([]byte, *StreamingTunnel, error) { 603 log.Lvl2("Got called with path", path, buf) 604 msg := &DummyMsg{} 605 err := protobuf.Decode(buf, msg) 606 if err != nil { 607 ds.link <- false 608 return nil, nil, errors.New("wrong message") 609 } 610 if ds.firstTni == nil { 611 ds.firstTni = ds.c.NewTreeNodeInstance(ds.fakeTree, ds.fakeTree.Root, dummyServiceName) 612 } 613 614 dp := newDummyProtocol(ds.firstTni, ds.Config, ds.link) 615 616 if err := ds.c.RegisterProtocolInstance(dp); err != nil { 617 ds.link <- false 618 return nil, nil, err 619 } 620 log.Lvl2("Starting protocol") 621 go func() { 622 log.ErrFatal(dp.Start()) 623 }() 624 return nil, nil, nil 625 } 626 627 func (ds *DummyService) NewProtocol(tn *TreeNodeInstance, conf *GenericConfig) (ProtocolInstance, error) { 628 dp := newDummyProtocol(tn, DummyConfig{}, ds.link) 629 return dp, nil 630 } 631 632 func (ds *DummyService) Process(env *network.Envelope) { 633 if !env.MsgType.Equal(dummyMsgType) { 634 ds.link <- false 635 return 636 } 637 dms := env.Msg.(*DummyMsg) 638 if dms.A != 10 { 639 ds.link <- false 640 return 641 } 642 ds.link <- true 643 } 644 645 type ServiceMessages struct { 646 *ServiceProcessor 647 GotResponse chan bool 648 } 649 650 func (i *ServiceMessages) SimpleResponse(env *network.Envelope) { 651 i.GotResponse <- true 652 } 653 654 func newServiceMessages(c *Context) (Service, error) { 655 s := &ServiceMessages{ 656 ServiceProcessor: NewServiceProcessor(c), 657 GotResponse: make(chan bool), 658 } 659 c.RegisterProcessorFunc(SimpleResponseType, s.SimpleResponse) 660 return s, nil 661 } 662 663 type dummyService2 struct { 664 *Context 665 link chan bool 666 } 667 668 func newDummyService2(c *Context) (Service, error) { 669 return &dummyService2{Context: c}, nil 670 } 671 672 func (ds *dummyService2) ProcessClientRequest(req *http.Request, path string, buf []byte) ([]byte, *StreamingTunnel, error) { 673 panic("should not be called") 674 } 675 676 var serviceConfig = []byte{0x01, 0x02, 0x03, 0x04} 677 678 func (ds *dummyService2) NewProtocol(tn *TreeNodeInstance, conf *GenericConfig) (ProtocolInstance, error) { 679 ds.link <- conf != nil && bytes.Equal(conf.Data, serviceConfig) 680 pi, err := newDummyProtocol2(tn) 681 pi.(*DummyProtocol2).finishEarly = true 682 return pi, err 683 } 684 685 func (ds *dummyService2) Process(env *network.Envelope) { 686 panic("should not be called") 687 } 688 689 func (ds *dummyService2) launchProto(t *Tree, config bool) { 690 ds.launchProtoStart(t, config, false) 691 } 692 693 func (ds *dummyService2) launchProtoStart(t *Tree, config, startNew bool) { 694 tni := ds.NewTreeNodeInstance(t, t.Root, dummyService2Name) 695 pi, err := newDummyProtocol2(tni) 696 pi.(*DummyProtocol2).startNewProtocol = startNew 697 err2 := ds.RegisterProtocolInstance(pi) 698 ds.link <- err == nil && err2 == nil 699 700 if config { 701 tni.SetConfig(&GenericConfig{serviceConfig}) 702 } 703 go func() { 704 log.ErrFatal(pi.Start()) 705 }() 706 } 707 708 type DummyProtocol2 struct { 709 *TreeNodeInstance 710 c chan WrapDummyMsg 711 startNewProtocol bool 712 finishEarly bool 713 } 714 715 type WrapDummyMsg struct { 716 *TreeNode 717 DummyMsg 718 } 719 720 func newDummyProtocol2(n *TreeNodeInstance) (ProtocolInstance, error) { 721 d := &DummyProtocol2{TreeNodeInstance: n} 722 d.c = make(chan WrapDummyMsg, 1) 723 d.RegisterChannel(d.c) 724 return d, nil 725 } 726 727 func (dp2 *DummyProtocol2) Start() error { 728 if dp2.startNewProtocol { 729 pi, err := dp2.CreateProtocol(dummyProtocolName, dp2.Tree()) 730 if err != nil { 731 log.Error(err) 732 return err 733 } 734 go pi.Start() 735 } 736 err := dp2.SendToChildren(&DummyMsg{20}) 737 dp2.Done() 738 return err 739 } 740 741 func (dp2 *DummyProtocol2) Dispatch() error { 742 if dp2.finishEarly { 743 dp2.Done() 744 } 745 return nil 746 } 747 748 func waitOrFatalValue(ch chan bool, v bool, t *testing.T) { 749 select { 750 case b := <-ch: 751 if v != b { 752 log.Fatal("Wrong value returned on channel") 753 } 754 case <-time.After(time.Second): 755 log.Fatal("Waited too long") 756 } 757 758 } 759 760 func waitOrFatal(ch chan bool, t *testing.T) { 761 select { 762 case _ = <-ch: 763 return 764 case <-time.After(time.Second): 765 log.Fatal("Waited too long") 766 } 767 }