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  }