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

     1  package onet
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  	"gopkg.in/dedis/onet.v2/log"
    10  	"gopkg.in/dedis/onet.v2/network"
    11  	"gopkg.in/satori/go.uuid.v1"
    12  )
    13  
    14  // A checkableError is a type that implements error and also lets
    15  // you find out, by reading on a channel, how many times it has been
    16  // formatted using Error().
    17  type checkableError struct {
    18  	ch  chan struct{}
    19  	msg string
    20  }
    21  
    22  func (ce *checkableError) Error() string {
    23  	ce.ch <- struct{}{}
    24  	return ce.msg
    25  }
    26  
    27  var dispFailErr = &checkableError{
    28  	ch:  make(chan struct{}, 10),
    29  	msg: "Dispatch failed",
    30  }
    31  
    32  type ProtocolOverlay struct {
    33  	*TreeNodeInstance
    34  	done         bool
    35  	failDispatch bool
    36  	failChan     chan bool
    37  }
    38  
    39  func (po *ProtocolOverlay) Start() error {
    40  	// no need to do anything
    41  	return nil
    42  }
    43  
    44  func (po *ProtocolOverlay) Dispatch() error {
    45  	if po.failDispatch {
    46  		return dispFailErr
    47  	}
    48  	return nil
    49  }
    50  
    51  func (po *ProtocolOverlay) Release() {
    52  	// call the Done function
    53  	po.Done()
    54  }
    55  
    56  func TestOverlayDispatchFailure(t *testing.T) {
    57  	// setup
    58  	failChan := make(chan bool, 1)
    59  	fn := func(n *TreeNodeInstance) (ProtocolInstance, error) {
    60  		ps := ProtocolOverlay{
    61  			TreeNodeInstance: n,
    62  			failDispatch:     true,
    63  			failChan:         failChan,
    64  		}
    65  		return &ps, nil
    66  	}
    67  	GlobalProtocolRegister("ProtocolOverlay", fn)
    68  	local := NewLocalTest(tSuite)
    69  	defer local.CloseAll()
    70  
    71  	// Redirect output so we can check for the failure
    72  	log.OutputToBuf()
    73  	defer log.OutputToOs()
    74  
    75  	h, _, tree := local.GenTree(1, true)
    76  	h1 := h[0]
    77  	pi, err := h1.CreateProtocol("ProtocolOverlay", tree)
    78  	if err != nil {
    79  		t.Fatal("error starting new node", err)
    80  	}
    81  
    82  	// wait for the error message to get formatted by overlay.go
    83  	<-dispFailErr.ch
    84  
    85  	// This test was apparently always a bit fragile, and commit 5931349
    86  	// seems to have made it worse. Adding this tiny sleep makes
    87  	// 2000 iterations pass where before I could see errors about 1 in 20 times.
    88  	time.Sleep(5 * time.Millisecond)
    89  
    90  	// when using `go test -v`, the error string goes into the stderr buffer
    91  	// but with `go test`, it goes into the stdout buffer, so we check both
    92  	assert.Contains(t, log.GetStdOut()+log.GetStdErr(), "Dispatch failed")
    93  	pi.(*ProtocolOverlay).Done()
    94  }
    95  
    96  func TestOverlayDone(t *testing.T) {
    97  	log.OutputToBuf()
    98  	defer log.OutputToOs()
    99  
   100  	// setup
   101  	fn := func(n *TreeNodeInstance) (ProtocolInstance, error) {
   102  		ps := ProtocolOverlay{
   103  			TreeNodeInstance: n,
   104  		}
   105  		return &ps, nil
   106  	}
   107  	GlobalProtocolRegister("ProtocolOverlay", fn)
   108  	local := NewLocalTest(tSuite)
   109  	defer local.CloseAll()
   110  	h, _, tree := local.GenTree(1, true)
   111  	h1 := h[0]
   112  	p, err := h1.CreateProtocol("ProtocolOverlay", tree)
   113  	if err != nil {
   114  		t.Fatal("error starting new node", err)
   115  	}
   116  	po := p.(*ProtocolOverlay)
   117  	// release the resources
   118  	var count int
   119  	po.OnDoneCallback(func() bool {
   120  		count++
   121  		if count >= 2 {
   122  			return true
   123  		}
   124  		return false
   125  	})
   126  	po.Release()
   127  	overlay := h1.overlay
   128  	if _, ok := overlay.TokenToNode(po.Token()); !ok {
   129  		t.Fatal("Node should exists after first call Done()")
   130  	}
   131  	po.Release()
   132  	if _, ok := overlay.TokenToNode(po.Token()); ok {
   133  		t.Fatal("Node should NOT exists after call Done()")
   134  	}
   135  }
   136  
   137  // Test when a peer receives a New Roster, it can create the trees that are
   138  // waiting on this specific entitiy list, to be constructed.
   139  func TestOverlayPendingTreeMarshal(t *testing.T) {
   140  	local := NewLocalTest(tSuite)
   141  	hosts, el, tree := local.GenTree(2, false)
   142  	defer local.CloseAll()
   143  	h1 := hosts[0]
   144  
   145  	// Add the marshalled version of the tree
   146  	local.addPendingTreeMarshal(h1, tree.MakeTreeMarshal())
   147  	if _, ok := h1.GetTree(tree.ID); ok {
   148  		t.Fatal("host 1 should not have the tree definition yet.")
   149  	}
   150  	// Now make it check
   151  	local.checkPendingTreeMarshal(h1, el)
   152  	if _, ok := h1.GetTree(tree.ID); !ok {
   153  		t.Fatal("Host 1 should have the tree definition now.")
   154  	}
   155  }
   156  
   157  // overlayProc is a Processor which handles the management packet of Overlay,
   158  // i.e. Roster & Tree management.
   159  // Each type of message will be sent trhough the appropriate channel
   160  type overlayProc struct {
   161  	sendRoster  chan *Roster
   162  	treeMarshal chan *TreeMarshal
   163  	requestTree chan *RequestTree
   164  }
   165  
   166  func newOverlayProc() *overlayProc {
   167  	return &overlayProc{
   168  		sendRoster:  make(chan *Roster, 1),
   169  		treeMarshal: make(chan *TreeMarshal, 1),
   170  		requestTree: make(chan *RequestTree, 1),
   171  	}
   172  }
   173  
   174  func (op *overlayProc) Process(env *network.Envelope) {
   175  	switch env.MsgType {
   176  	case SendRosterMsgID:
   177  		op.sendRoster <- env.Msg.(*Roster)
   178  	case TreeMarshalTypeID:
   179  		op.treeMarshal <- env.Msg.(*TreeMarshal)
   180  	case RequestTreeMsgID:
   181  		op.requestTree <- env.Msg.(*RequestTree)
   182  	}
   183  }
   184  
   185  func (op *overlayProc) Types() []network.MessageTypeID {
   186  	return []network.MessageTypeID{SendRosterMsgID, TreeMarshalTypeID}
   187  }
   188  
   189  // Test propagation of roster - both known and unknown
   190  func TestOverlayRosterPropagation(t *testing.T) {
   191  	local := NewLocalTest(tSuite)
   192  	hosts, el, _ := local.GenTree(2, false)
   193  	defer local.CloseAll()
   194  	h1 := hosts[0]
   195  	h2 := hosts[1]
   196  	proc := newOverlayProc()
   197  	h1.RegisterProcessor(proc, proc.Types()...)
   198  
   199  	// Check that h2 sends back an empty list if it is unknown
   200  	sentLen, err := h1.Send(h2.ServerIdentity, &RequestRoster{
   201  		RosterID: el.ID})
   202  	require.Nil(t, err, "Couldn't send message to h1")
   203  	require.NotZero(t, sentLen)
   204  
   205  	roster := <-proc.sendRoster
   206  	if !roster.ID.IsNil() {
   207  		t.Fatal("List should be empty")
   208  	}
   209  
   210  	// Now add the list to h2 and try again
   211  	h2.AddRoster(el)
   212  	sentLen, err = h1.Send(h2.ServerIdentity, &RequestRoster{RosterID: el.ID})
   213  	require.Nil(t, err, "Couldn't send message to h2")
   214  	require.NotZero(t, sentLen)
   215  
   216  	msg := <-proc.sendRoster
   217  	if !msg.ID.Equal(el.ID) {
   218  		t.Fatal("List should be equal to original list")
   219  	}
   220  
   221  	sentLen, err = h1.Send(h2.ServerIdentity, &RequestRoster{RosterID: el.ID})
   222  	require.Nil(t, err, "Couldn't send message to h2")
   223  	require.NotZero(t, sentLen)
   224  
   225  	// check if we receive the Roster then
   226  	ros := <-proc.sendRoster
   227  	packet := network.Envelope{
   228  		ServerIdentity: h2.ServerIdentity,
   229  		Msg:            ros,
   230  		MsgType:        SendRosterMsgID,
   231  	}
   232  	h1.overlay.Process(&packet)
   233  	list, ok := h1.Roster(el.ID)
   234  	assert.True(t, ok)
   235  	assert.Equal(t, list.ID, el.ID)
   236  }
   237  
   238  // Test propagation of tree - both known and unknown
   239  func TestOverlayTreePropagation(t *testing.T) {
   240  	local := NewLocalTest(tSuite)
   241  	hosts, el, tree := local.GenTree(2, false)
   242  	defer local.CloseAll()
   243  	h1 := hosts[0]
   244  	h2 := hosts[1]
   245  	// Suppose both hosts have the list available, but not the tree
   246  	h1.AddRoster(el)
   247  	h2.AddRoster(el)
   248  
   249  	proc := newOverlayProc()
   250  	h1.RegisterProcessor(proc, SendTreeMsgID)
   251  	//h2.RegisterProcessor(proc, proc.Types()...)
   252  
   253  	// Check that h2 sends back an empty tree if it is unknown
   254  	sentLen, err := h1.Send(h2.ServerIdentity, &RequestTree{TreeID: tree.ID})
   255  	require.Nil(t, err, "Couldn't send message to h2")
   256  	require.NotZero(t, sentLen)
   257  
   258  	msg := <-proc.treeMarshal
   259  	if !msg.RosterID.IsNil() {
   260  		t.Fatal("List should be empty")
   261  	}
   262  
   263  	// Now add the list to h2 and try again
   264  	h2.AddTree(tree)
   265  	sentLen, err = h1.Send(h2.ServerIdentity, &RequestTree{TreeID: tree.ID})
   266  	require.Nil(t, err)
   267  	require.NotZero(t, sentLen)
   268  
   269  	msg = <-proc.treeMarshal
   270  	assert.Equal(t, msg.TreeID, tree.ID)
   271  
   272  	sentLen, err = h1.Send(h2.ServerIdentity, &RequestTree{TreeID: tree.ID})
   273  	require.Nil(t, err)
   274  	require.NotZero(t, sentLen)
   275  
   276  	// check if we receive the tree then
   277  	var tm *TreeMarshal
   278  	tm = <-proc.treeMarshal
   279  	packet := network.Envelope{
   280  		ServerIdentity: h2.ServerIdentity,
   281  		Msg:            tm,
   282  		MsgType:        SendTreeMsgID,
   283  	}
   284  	h1.overlay.Process(&packet)
   285  
   286  	tree2, ok := h1.GetTree(tree.ID)
   287  	if !ok {
   288  		t.Fatal("List-id not found")
   289  	}
   290  	if !tree.Equal(tree2) {
   291  		t.Fatal("Trees do not match")
   292  	}
   293  }
   294  
   295  // Tests both list- and tree-propagation
   296  // basically h1 ask for a tree id
   297  // h2 respond with the tree
   298  // h1 ask for the entitylist (because it dont know)
   299  // h2 respond with the entitylist
   300  func TestOverlayRosterTreePropagation(t *testing.T) {
   301  	local := NewLocalTest(tSuite)
   302  	hosts, el, tree := local.GenTree(2, false)
   303  	defer local.CloseAll()
   304  	h1 := hosts[0]
   305  	h2 := hosts[1]
   306  
   307  	// h2 knows the entity list
   308  	h2.AddRoster(el)
   309  	// and the tree
   310  	h2.AddTree(tree)
   311  	// make the communcation happen
   312  	sentLen, err := h1.Send(h2.ServerIdentity, &RequestTree{TreeID: tree.ID})
   313  	require.Nil(t, err, "Could not send tree request to host2")
   314  	require.NotZero(t, sentLen)
   315  
   316  	proc := newOverlayProc()
   317  	h1.RegisterProcessor(proc, SendRosterMsgID)
   318  	h1.RegisterProcessor(proc, SendTreeMsgID)
   319  
   320  	// check if we have the tree
   321  	treeM := <-proc.treeMarshal
   322  
   323  	packet := network.Envelope{
   324  		ServerIdentity: h2.ServerIdentity,
   325  		Msg:            treeM,
   326  		MsgType:        SendTreeMsgID,
   327  	}
   328  	// give it to overlay
   329  	h1.overlay.Process(&packet)
   330  	// the tree should not be there because we don't have the Roster associated
   331  	// yet
   332  	if _, ok := h1.GetTree(tree.ID); ok {
   333  		t.Fatal("Tree should Not be there")
   334  	}
   335  	// check if we receive the Roster then
   336  	roster := <-proc.sendRoster
   337  
   338  	packet = network.Envelope{
   339  		ServerIdentity: h2.ServerIdentity,
   340  		Msg:            roster,
   341  		MsgType:        SendRosterMsgID,
   342  	}
   343  	h1.overlay.Process(&packet)
   344  
   345  	// check if we have the roster now  & the tree
   346  	if _, ok := h1.Roster(el.ID); !ok {
   347  		t.Fatal("Roster should be here")
   348  	}
   349  	if _, ok := h1.GetTree(tree.ID); !ok {
   350  		t.Fatal("Tree should be there")
   351  	}
   352  }
   353  
   354  func TestTokenId(t *testing.T) {
   355  	t1 := &Token{
   356  		RosterID: RosterID(uuid.NewV1()),
   357  		TreeID:   TreeID(uuid.NewV1()),
   358  		ProtoID:  ProtocolID(uuid.NewV1()),
   359  		RoundID:  RoundID(uuid.NewV1()),
   360  	}
   361  	id1 := t1.ID()
   362  	t2 := &Token{
   363  		RosterID: RosterID(uuid.NewV1()),
   364  		TreeID:   TreeID(uuid.NewV1()),
   365  		ProtoID:  ProtocolID(uuid.NewV1()),
   366  		RoundID:  RoundID(uuid.NewV1()),
   367  	}
   368  	id2 := t2.ID()
   369  	if id1.Equal(id2) {
   370  		t.Fatal("Both token are the same")
   371  	}
   372  	if !id1.Equal(t1.ID()) {
   373  		t.Fatal("Twice the Id of the same token should be equal")
   374  	}
   375  	t3 := t1.ChangeTreeNodeID(TreeNodeID(uuid.NewV1()))
   376  	if t1.TreeNodeID.Equal(t3.TreeNodeID) {
   377  		t.Fatal("OtherToken should modify copy")
   378  	}
   379  }