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