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 }