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 }