gopkg.in/dedis/onet.v2@v2.0.0-20181115163211-c8f3724038a7/protocol_test.go (about)

     1  package onet
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  	"gopkg.in/dedis/onet.v2/log"
    11  	"gopkg.in/dedis/onet.v2/network"
    12  	"gopkg.in/satori/go.uuid.v1"
    13  )
    14  
    15  var testProto = "test"
    16  
    17  func init() {
    18  	network.RegisterMessage(SimpleMessage{})
    19  }
    20  
    21  // ProtocolTest is the most simple protocol to be implemented, ignoring
    22  // everything it receives.
    23  type ProtocolTest struct {
    24  	*TreeNodeInstance
    25  	StartMsg chan string
    26  	DispMsg  chan string
    27  }
    28  
    29  // NewProtocolTest is used to create a new protocolTest-instance
    30  func NewProtocolTest(n *TreeNodeInstance) (ProtocolInstance, error) {
    31  	return &ProtocolTest{
    32  		TreeNodeInstance: n,
    33  		StartMsg:         make(chan string, 1),
    34  		DispMsg:          make(chan string),
    35  	}, nil
    36  }
    37  
    38  // Dispatch is used to send the messages further - here everything is
    39  // copied to /dev/null
    40  func (p *ProtocolTest) Dispatch() error {
    41  	log.Lvl2("ProtocolTest.Dispatch()")
    42  	p.DispMsg <- "Dispatch"
    43  	p.Done()
    44  	return nil
    45  }
    46  
    47  func (p *ProtocolTest) Start() error {
    48  	log.Lvl2("ProtocolTest.Start()")
    49  	p.StartMsg <- "Start"
    50  	p.Done()
    51  	return nil
    52  }
    53  
    54  type SimpleProtocol struct {
    55  	// chan to get back to testing
    56  	Chan  chan bool
    57  	Error error
    58  	*TreeNodeInstance
    59  }
    60  
    61  // Sends a simple message to its first children
    62  func (p *SimpleProtocol) Start() error {
    63  	err := p.SendTo(p.Children()[0], &SimpleMessage{10})
    64  	if err != nil {
    65  		return err
    66  	}
    67  	p.Chan <- true
    68  	return nil
    69  }
    70  
    71  // Dispatch analyses the message and does nothing else
    72  func (p *SimpleProtocol) ReceiveMessage(msg MsgSimpleMessage) error {
    73  	if msg.I != 10 {
    74  		return errors.New("Not the value expected")
    75  	}
    76  	p.Chan <- true
    77  	p.Done()
    78  	return nil
    79  }
    80  
    81  // ReturnError sends a message to the parent, and if it's the parent
    82  // receiving the message, it triggers the channel
    83  func (p *SimpleProtocol) ReturnError(msg MsgSimpleMessage) error {
    84  	if msg.I == 10 {
    85  		p.SendToParent(&SimpleMessage{9})
    86  	} else {
    87  		p.Chan <- true
    88  	}
    89  	p.Done()
    90  	return p.Error
    91  }
    92  
    93  type SimpleMessage struct {
    94  	I int
    95  }
    96  
    97  type MsgSimpleMessage struct {
    98  	*TreeNode
    99  	SimpleMessage
   100  }
   101  
   102  // Test simple protocol-implementation
   103  // - registration
   104  func TestProtocolRegistration(t *testing.T) {
   105  	testProtoName := "testProto"
   106  	testProtoID, err := GlobalProtocolRegister(testProtoName, NewProtocolTest)
   107  	log.ErrFatal(err)
   108  	_, err = GlobalProtocolRegister(testProtoName, NewProtocolTest)
   109  	require.NotNil(t, err)
   110  	if !protocols.ProtocolExists(testProtoID) {
   111  		t.Fatal("Test should exist now")
   112  	}
   113  	if !ProtocolNameToID(testProtoName).Equal(testProtoID) {
   114  		t.Fatal("Not correct translation from string to ID")
   115  	}
   116  	require.Equal(t, "", protocols.ProtocolIDToName(ProtocolID(uuid.Nil)))
   117  	if protocols.ProtocolIDToName(testProtoID) != testProtoName {
   118  		t.Fatal("Not correct translation from ID to String")
   119  	}
   120  }
   121  
   122  // This makes h2 the leader, so it creates a tree and entity list
   123  // and start a protocol. H1 should receive that message and request the entity
   124  // list and the treelist and then instantiate the protocol.
   125  func TestProtocolAutomaticInstantiation(t *testing.T) {
   126  	var simpleProto = "simpleAI"
   127  
   128  	// setup
   129  	chanH1 := make(chan bool)
   130  	chanH2 := make(chan bool)
   131  	chans := []chan bool{chanH1, chanH2}
   132  	id := 0
   133  	// custom creation function so we know the step due to the channels
   134  	fn := func(n *TreeNodeInstance) (ProtocolInstance, error) {
   135  		ps := SimpleProtocol{
   136  			TreeNodeInstance: n,
   137  			Chan:             chans[id],
   138  		}
   139  		log.ErrFatal(ps.RegisterHandler(ps.ReceiveMessage))
   140  		id++
   141  		return &ps, nil
   142  	}
   143  
   144  	_, err := GlobalProtocolRegister(simpleProto, fn)
   145  	require.Nil(t, err)
   146  	local := NewLocalTest(tSuite)
   147  	defer local.CloseAll()
   148  	h, _, tree := local.GenTree(2, true)
   149  	h1 := h[0]
   150  	var pi ProtocolInstance
   151  	started := make(chan bool)
   152  	// start the protocol
   153  	go func() {
   154  		var err error
   155  		pi, err = h1.StartProtocol(simpleProto, tree)
   156  		if err != nil {
   157  			t.Fatal(fmt.Sprintf("Could not start protocol %v", err))
   158  		}
   159  		started <- true
   160  	}()
   161  
   162  	// we are supposed to receive something from host1 from Start()
   163  	<-chanH1
   164  
   165  	// Then we are supposed to receive from h2 after he got the tree and the
   166  	// entity list from h1
   167  	<-chanH2
   168  	<-started
   169  	pi.(*SimpleProtocol).Done()
   170  }
   171  
   172  func TestProtocolError(t *testing.T) {
   173  	var simpleProto = "simplePE"
   174  	done := make(chan bool)
   175  	// The simplePE-protocol sends a message from the root to its
   176  	// children, which sends a message back and returns an error.
   177  	// When the root receives the message back, the second message
   178  	// is sent through the 'done'-channel. Like this we're sure that
   179  	// the children-message-handler had the time to return an error.
   180  	var protocolError error
   181  	fn := func(n *TreeNodeInstance) (ProtocolInstance, error) {
   182  		ps := SimpleProtocol{
   183  			TreeNodeInstance: n,
   184  			Chan:             done,
   185  		}
   186  		ps.Error = protocolError
   187  		log.ErrFatal(ps.RegisterHandler(ps.ReturnError))
   188  		return &ps, nil
   189  	}
   190  
   191  	_, err := GlobalProtocolRegister(simpleProto, fn)
   192  	require.Nil(t, err)
   193  	local := NewLocalTest(tSuite)
   194  	h, _, tree := local.GenTree(2, true)
   195  	h1 := h[0]
   196  
   197  	oldlvl := log.DebugVisible()
   198  	// The error won't show if the DebugVisible is < 1
   199  	if oldlvl < 1 {
   200  		log.SetDebugVisible(1)
   201  	}
   202  	// Redirecting stderr, so we can catch the error
   203  	log.OutputToBuf()
   204  	defer func() {
   205  		log.OutputToOs()
   206  		log.SetDebugVisible(oldlvl)
   207  	}()
   208  	// Empty it of previous messages before running our test.
   209  	_ = log.GetStdErr()
   210  
   211  	// start the protocol
   212  	go func() {
   213  		_, err := h1.StartProtocol(simpleProto, tree)
   214  		if err != nil {
   215  			t.Fatal(fmt.Sprintf("Could not start protocol %v", err))
   216  		}
   217  	}()
   218  	// Start is finished
   219  	<-done
   220  	// Return message is received
   221  	<-done
   222  	assert.Equal(t, "", log.GetStdErr(), "This should yield no error")
   223  
   224  	protocolError = errors.New("Protocol Error")
   225  	// start the protocol
   226  	go func() {
   227  		_, err := h1.StartProtocol(simpleProto, tree)
   228  		if err != nil {
   229  			t.Fatal(fmt.Sprintf("Could not start protocol %v", err))
   230  		}
   231  	}()
   232  	// Start is finished
   233  	<-done
   234  	// Return message is received
   235  	<-done
   236  	local.CloseAll()
   237  
   238  	str := log.GetStdErr()
   239  	assert.NotEqual(t, "", str, "No error output")
   240  
   241  }
   242  
   243  func TestGlobalProtocolRegisterTooLate(t *testing.T) {
   244  	var simpleProto = "simplePE"
   245  	done := make(chan bool)
   246  	fn := func(n *TreeNodeInstance) (ProtocolInstance, error) {
   247  		ps := SimpleProtocol{
   248  			TreeNodeInstance: n,
   249  			Chan:             done,
   250  		}
   251  		log.ErrFatal(ps.RegisterHandler(ps.ReturnError))
   252  		return &ps, nil
   253  	}
   254  
   255  	local := NewLocalTest(tSuite)
   256  	defer local.CloseAll()
   257  	local.GenTree(2, true)
   258  	fnShouldPanic := func() {
   259  		GlobalProtocolRegister(simpleProto, fn)
   260  	}
   261  	assert.Panics(t, fnShouldPanic)
   262  }
   263  
   264  func TestMessageProxyFactory(t *testing.T) {
   265  	defer eraseAllMessageProxy()
   266  	RegisterMessageProxy(NewTestMessageProxyChan)
   267  	assert.True(t, len(messageProxyFactory.factories) == 1)
   268  }
   269  
   270  func TestMessageProxyStore(t *testing.T) {
   271  	defer eraseAllMessageProxy()
   272  	local := NewLocalTest(tSuite)
   273  	defer local.CloseAll()
   274  
   275  	RegisterMessageProxy(NewTestMessageProxy)
   276  	_, err := GlobalProtocolRegister(testProtoIOName, newTestProtocolInstance)
   277  	require.Nil(t, err)
   278  	h, _, tree := local.GenTree(2, true)
   279  
   280  	go func() {
   281  		// first time to wrap
   282  		res := <-chanProtoIOFeedback
   283  		require.Equal(t, "", res)
   284  		// second time to unwrap
   285  		res = <-chanProtoIOFeedback
   286  		require.Equal(t, "", res)
   287  
   288  	}()
   289  	pi, err := h[0].StartProtocol(testProtoIOName, tree)
   290  	require.Nil(t, err)
   291  
   292  	res := <-chanTestProtoInstance
   293  	assert.True(t, res)
   294  	pi.(*TestProtocolInstance).Done()
   295  }
   296  
   297  // MessageProxy part
   298  var chanProtoIOCreation = make(chan bool)
   299  var chanProtoIOFeedback = make(chan string)
   300  
   301  const testProtoIOName = "TestIO"
   302  
   303  type OuterPacket struct {
   304  	Info  *OverlayMsg
   305  	Inner *SimpleMessage
   306  }
   307  
   308  var OuterPacketType = network.RegisterMessage(OuterPacket{})
   309  
   310  type TestMessageProxy struct{}
   311  
   312  func NewTestMessageProxyChan() MessageProxy {
   313  	chanProtoIOCreation <- true
   314  	return &TestMessageProxy{}
   315  }
   316  
   317  func NewTestMessageProxy() MessageProxy {
   318  	return &TestMessageProxy{}
   319  }
   320  
   321  func eraseAllMessageProxy() {
   322  	messageProxyFactory.factories = nil
   323  }
   324  
   325  func (t *TestMessageProxy) Wrap(msg interface{}, info *OverlayMsg) (interface{}, error) {
   326  	outer := &OuterPacket{}
   327  	inner, ok := msg.(*SimpleMessage)
   328  	if !ok {
   329  		chanProtoIOFeedback <- "wrong message type in wrap"
   330  	}
   331  	outer.Inner = inner
   332  	outer.Info = info
   333  	chanProtoIOFeedback <- ""
   334  	return outer, nil
   335  }
   336  
   337  func (t *TestMessageProxy) Unwrap(msg interface{}) (interface{}, *OverlayMsg, error) {
   338  	if msg == nil {
   339  		chanProtoIOFeedback <- "message nil!"
   340  		return nil, nil, errors.New("message nil")
   341  	}
   342  
   343  	real, ok := msg.(*OuterPacket)
   344  	if !ok {
   345  		chanProtoIOFeedback <- "wrong type of message in unwrap"
   346  		return nil, nil, errors.New("wrong message")
   347  	}
   348  	chanProtoIOFeedback <- ""
   349  	return real.Inner, real.Info, nil
   350  }
   351  
   352  func (t *TestMessageProxy) PacketType() network.MessageTypeID {
   353  	return OuterPacketType
   354  }
   355  
   356  func (t *TestMessageProxy) Name() string {
   357  	return testProtoIOName
   358  }
   359  
   360  var chanTestProtoInstance = make(chan bool)
   361  
   362  // ProtocolInstance part
   363  type TestProtocolInstance struct {
   364  	*TreeNodeInstance
   365  }
   366  
   367  func newTestProtocolInstance(n *TreeNodeInstance) (ProtocolInstance, error) {
   368  	pi := &TestProtocolInstance{n}
   369  	n.RegisterHandler(pi.handleSimpleMessage)
   370  	return pi, nil
   371  }
   372  
   373  func (t *TestProtocolInstance) Start() error {
   374  	t.SendTo(t.Root(), &SimpleMessage{12})
   375  	return nil
   376  }
   377  
   378  type SimpleMessageHandler struct {
   379  	*TreeNode
   380  	SimpleMessage
   381  }
   382  
   383  func (t TestProtocolInstance) handleSimpleMessage(h SimpleMessageHandler) error {
   384  	chanTestProtoInstance <- h.SimpleMessage.I == 12
   385  	return nil
   386  }