gopkg.in/dedis/onet.v2@v2.0.0-20181115163211-c8f3724038a7/treenode_test.go (about) 1 package onet 2 3 import ( 4 "sync" 5 "testing" 6 "time" 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 ) 13 14 func init() { 15 GlobalProtocolRegister(spawnName, newSpawnProto) 16 GlobalProtocolRegister(pingPongProtoName, newPingPongProto) 17 } 18 19 func TestTreeNodeCreateProtocol(t *testing.T) { 20 local := NewLocalTest(tSuite) 21 defer local.CloseAll() 22 23 hosts, _, tree := local.GenTree(1, true) 24 pi, err := hosts[0].overlay.CreateProtocol(spawnName, tree, NilServiceID) 25 log.ErrFatal(err) 26 p := pi.(*spawnProto) 27 p.spawn = true 28 go p.Start() 29 30 // wait once for the protocol just created 31 <-spawnCh 32 // wait once more for the protocol created inside the first one 33 <-spawnCh 34 35 pi.(*spawnProto).Done() 36 } 37 38 func TestTreeNodeRxTx(t *testing.T) { 39 local := NewTCPTest(tSuite) 40 testTreeNodeRxTx(t, local) 41 local.CloseAll() 42 43 local = NewLocalTest(tSuite) 44 testTreeNodeRxTx(t, local) 45 local.CloseAll() 46 } 47 48 func testTreeNodeRxTx(t *testing.T, local *LocalTest) { 49 _, _, tree := local.GenTree(2, true) 50 pi, err := local.StartProtocol(pingPongProtoName, tree) 51 require.Nil(t, err) 52 protocol := pi.(*pingPongProto) 53 54 <-protocol.done 55 require.NotZero(t, protocol.TreeNodeInstance.Rx()) 56 require.NotZero(t, protocol.TreeNodeInstance.Tx()) 57 } 58 59 func TestHandlerReturn(t *testing.T) { 60 local := NewLocalTest(tSuite) 61 defer local.CloseAll() 62 63 hosts, _, tree := local.GenTree(1, true) 64 pi, err := hosts[0].overlay.CreateProtocol(spawnName, tree, NilServiceID) 65 log.ErrFatal(err) 66 p := pi.(*spawnProto) 67 assert.NotNil(t, p.RegisterHandler(p.HandlerError1)) 68 assert.Nil(t, p.RegisterHandler(p.HandlerError2)) 69 assert.NotNil(t, p.RegisterHandler(p.HandlerError3)) 70 p.Done() 71 } 72 73 type dummyMsg struct{} 74 75 type configProcessor struct { 76 configCount int 77 expected int 78 done chan<- bool 79 sync.Mutex 80 } 81 82 func (p *configProcessor) Process(env *network.Envelope) { 83 p.Lock() 84 if env.MsgType == ConfigMsgID { 85 p.configCount++ 86 if p.configCount == p.expected { 87 p.done <- true 88 } 89 } 90 p.Unlock() 91 } 92 93 func TestConfigPropagation(t *testing.T) { 94 local := NewLocalTest(tSuite) 95 defer local.CloseAll() 96 const treeSize = 3 97 var serviceConfig = []byte{0x01, 0x02, 0x03, 0x04} 98 hosts, _, tree := local.GenTree(treeSize, true) 99 pi, err := hosts[0].overlay.CreateProtocol(spawnName, tree, NilServiceID) 100 log.ErrFatal(err) 101 102 done := make(chan bool) 103 pr := &configProcessor{expected: treeSize - 1, done: done} 104 105 for _, host := range hosts { 106 host.RegisterProcessor(pr, 107 ProtocolMsgID, 108 RequestTreeMsgID, 109 SendTreeMsgID, 110 RequestRosterMsgID, 111 SendRosterMsgID, 112 ConfigMsgID) 113 } 114 115 network.RegisterMessage(dummyMsg{}) 116 rootInstance, _ := local.NewTreeNodeInstance(tree.Root, spawnName) 117 require.Zero(t, rootInstance.Tx()) 118 require.Zero(t, rootInstance.Rx()) 119 120 err = rootInstance.SetConfig(&GenericConfig{serviceConfig}) 121 assert.Nil(t, err) 122 err = rootInstance.SetConfig(&GenericConfig{serviceConfig}) 123 assert.NotNil(t, err) 124 125 err = rootInstance.SendToChildren(&dummyMsg{}) 126 assert.NotZero(t, rootInstance.Tx()) 127 log.ErrFatal(err) 128 // wait until the processor has processed the expected number of config messages 129 select { 130 case <-done: 131 case <-time.After(time.Second): 132 t.Fatal("Didn't receive response in time") 133 } 134 pi.(*spawnProto).Done() 135 } 136 137 func TestTreeNodeInstance_RegisterChannel(t *testing.T) { 138 local := NewLocalTest(tSuite) 139 defer local.CloseAll() 140 141 _, _, tree := local.GenTree(3, true) 142 ri, err := local.NewTreeNodeInstance(tree.Root, spawnName) 143 log.ErrFatal(err) 144 145 var c chan spawnMsg 146 log.ErrFatal(ri.RegisterChannel(&c)) 147 148 m := &ProtocolMsg{ 149 MsgType: network.RegisterMessage(&spawn{}), 150 From: &Token{ 151 TreeNodeID: ri.treeNode.ID, 152 }, 153 Msg: &spawn{I: 10}, 154 } 155 msg := []*ProtocolMsg{} 156 for i := 0; i < 101; i++ { 157 msg = append(msg, m) 158 } 159 require.NotNil(t, ri.dispatchChannel(msg)) 160 log.ErrFatal(ri.RegisterChannelLength(&c, 200)) 161 log.ErrFatal(ri.dispatchChannel(msg)) 162 } 163 164 // spawnCh is used to dispatch information from a spawnProto to the test 165 var spawnCh = make(chan bool) 166 167 const spawnName = "Spawn" 168 169 // spawnProto is a simple protocol which just spawn another protocol when 170 // started 171 type spawnProto struct { 172 *TreeNodeInstance 173 spawn bool 174 } 175 176 func newSpawnProto(tn *TreeNodeInstance) (ProtocolInstance, error) { 177 sp := &spawnProto{ 178 TreeNodeInstance: tn, 179 } 180 return sp, nil 181 } 182 183 func (s *spawnProto) Start() error { 184 defer s.Done() 185 r := s.Roster() 186 tree := r.GenerateBinaryTree() 187 spawnCh <- true 188 if !s.spawn { 189 return nil 190 } 191 proto, err := s.CreateProtocol(spawnName, tree) 192 log.ErrFatal(err) 193 go proto.Start() 194 return nil 195 } 196 197 type spawn struct { 198 I int 199 } 200 201 type spawnMsg struct { 202 *TreeNode 203 M spawn 204 } 205 206 // Invalid handler 207 func (s *spawnProto) HandlerError1(msg spawnMsg) {} 208 209 // Valid handler 210 func (s *spawnProto) HandlerError2(msg spawnMsg) error { 211 s.Done() 212 return nil 213 } 214 215 // Invalid handler 216 func (s *spawnProto) HandlerError3(msg spawnMsg) (int, error) { 217 return 0, nil 218 } 219 220 // Simple protocol to have messages transmit between nodes 221 const pingPongProtoName = "PingPongProtoTest" 222 223 type PingPongMsg struct{} 224 225 type pingPongProto struct { 226 *TreeNodeInstance 227 done chan bool 228 pingPongChan chan struct { 229 *TreeNode 230 PingPongMsg 231 } 232 } 233 234 func newPingPongProto(tn *TreeNodeInstance) (ProtocolInstance, error) { 235 cp := &pingPongProto{ 236 TreeNodeInstance: tn, 237 done: make(chan bool, len(tn.List())), 238 } 239 err := cp.RegisterChannelsLength(len(tn.Tree().List()), &cp.pingPongChan) 240 return cp, err 241 } 242 243 func (cp *pingPongProto) Dispatch() error { 244 defer cp.Done() 245 246 select { 247 case <-cp.pingPongChan: 248 if !cp.IsRoot() { 249 cp.SendToParent(&PingPongMsg{}) 250 } 251 } 252 253 cp.done <- true 254 return nil 255 } 256 257 func (cp *pingPongProto) Start() error { 258 // only called by the root 259 err := cp.SendToChildren(&PingPongMsg{}) 260 if err != nil { 261 return err 262 } 263 264 return nil 265 }