github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/broadcast/broadcast_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package broadcast 18 19 import ( 20 "fmt" 21 "io" 22 "testing" 23 "time" 24 25 "github.com/hyperledger/fabric/orderer/common/filter" 26 cb "github.com/hyperledger/fabric/protos/common" 27 ab "github.com/hyperledger/fabric/protos/orderer" 28 "github.com/hyperledger/fabric/protos/utils" 29 30 logging "github.com/op/go-logging" 31 "github.com/stretchr/testify/assert" 32 "google.golang.org/grpc" 33 ) 34 35 func init() { 36 logging.SetLevel(logging.DEBUG, "") 37 } 38 39 var systemChain = "systemChain" 40 41 type mockB struct { 42 grpc.ServerStream 43 recvChan chan *cb.Envelope 44 sendChan chan *ab.BroadcastResponse 45 } 46 47 func newMockB() *mockB { 48 return &mockB{ 49 recvChan: make(chan *cb.Envelope), 50 sendChan: make(chan *ab.BroadcastResponse), 51 } 52 } 53 54 func (m *mockB) Send(br *ab.BroadcastResponse) error { 55 m.sendChan <- br 56 return nil 57 } 58 59 func (m *mockB) Recv() (*cb.Envelope, error) { 60 msg, ok := <-m.recvChan 61 if !ok { 62 return msg, io.EOF 63 } 64 return msg, nil 65 } 66 67 type erroneousRecvMockB struct { 68 grpc.ServerStream 69 } 70 71 func (m *erroneousRecvMockB) Send(br *ab.BroadcastResponse) error { 72 return nil 73 } 74 75 func (m *erroneousRecvMockB) Recv() (*cb.Envelope, error) { 76 // The point here is to simulate an error other than EOF. 77 // We don't bother to create a new custom error type. 78 return nil, io.ErrUnexpectedEOF 79 } 80 81 type erroneousSendMockB struct { 82 grpc.ServerStream 83 recvVal *cb.Envelope 84 } 85 86 func (m *erroneousSendMockB) Send(br *ab.BroadcastResponse) error { 87 // The point here is to simulate an error other than EOF. 88 // We don't bother to create a new custom error type. 89 return io.ErrUnexpectedEOF 90 } 91 92 func (m *erroneousSendMockB) Recv() (*cb.Envelope, error) { 93 return m.recvVal, nil 94 } 95 96 var RejectRule = filter.Rule(rejectRule{}) 97 98 type rejectRule struct{} 99 100 func (r rejectRule) Apply(message *cb.Envelope) (filter.Action, filter.Committer) { 101 return filter.Reject, nil 102 } 103 104 type mockSupportManager struct { 105 chains map[string]*mockSupport 106 ProcessVal *cb.Envelope 107 } 108 109 func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) { 110 chain, ok := mm.chains[chainID] 111 return chain, ok 112 } 113 114 func (mm *mockSupportManager) Process(configTx *cb.Envelope) (*cb.Envelope, error) { 115 if mm.ProcessVal == nil { 116 return nil, fmt.Errorf("Nil result implies error") 117 } 118 return mm.ProcessVal, nil 119 } 120 121 type mockSupport struct { 122 filters *filter.RuleSet 123 rejectEnqueue bool 124 } 125 126 func (ms *mockSupport) Filters() *filter.RuleSet { 127 return ms.filters 128 } 129 130 // Enqueue sends a message for ordering 131 func (ms *mockSupport) Enqueue(env *cb.Envelope) bool { 132 return !ms.rejectEnqueue 133 } 134 135 func makeConfigMessage(chainID string) *cb.Envelope { 136 payload := &cb.Payload{ 137 Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{}), 138 Header: &cb.Header{ 139 ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ 140 ChannelId: chainID, 141 Type: int32(cb.HeaderType_CONFIG_UPDATE), 142 }), 143 }, 144 } 145 return &cb.Envelope{ 146 Payload: utils.MarshalOrPanic(payload), 147 } 148 } 149 150 func makeMessage(chainID string, data []byte) *cb.Envelope { 151 payload := &cb.Payload{ 152 Data: data, 153 Header: &cb.Header{ 154 ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ 155 ChannelId: chainID, 156 }), 157 }, 158 } 159 return &cb.Envelope{ 160 Payload: utils.MarshalOrPanic(payload), 161 } 162 } 163 164 func getMockSupportManager() (*mockSupportManager, *mockSupport) { 165 filters := filter.NewRuleSet([]filter.Rule{ 166 filter.EmptyRejectRule, 167 filter.AcceptRule, 168 }) 169 mm := &mockSupportManager{ 170 chains: make(map[string]*mockSupport), 171 } 172 mSysChain := &mockSupport{ 173 filters: filters, 174 } 175 mm.chains[string(systemChain)] = mSysChain 176 return mm, mSysChain 177 } 178 179 func TestEnqueueFailure(t *testing.T) { 180 mm, mSysChain := getMockSupportManager() 181 bh := NewHandlerImpl(mm) 182 m := newMockB() 183 defer close(m.recvChan) 184 done := make(chan struct{}) 185 go func() { 186 bh.Handle(m) 187 close(done) 188 }() 189 190 for i := 0; i < 2; i++ { 191 m.recvChan <- makeMessage(systemChain, []byte("Some bytes")) 192 reply := <-m.sendChan 193 if reply.Status != cb.Status_SUCCESS { 194 t.Fatalf("Should have successfully queued the message") 195 } 196 } 197 198 mSysChain.rejectEnqueue = true 199 m.recvChan <- makeMessage(systemChain, []byte("Some bytes")) 200 reply := <-m.sendChan 201 if reply.Status != cb.Status_SERVICE_UNAVAILABLE { 202 t.Fatalf("Should not have successfully queued the message") 203 } 204 205 select { 206 case <-done: 207 case <-time.After(time.Second): 208 t.Fatalf("Should have terminated the stream") 209 } 210 } 211 212 func TestEmptyEnvelope(t *testing.T) { 213 mm, _ := getMockSupportManager() 214 bh := NewHandlerImpl(mm) 215 m := newMockB() 216 defer close(m.recvChan) 217 done := make(chan struct{}) 218 go func() { 219 bh.Handle(m) 220 close(done) 221 }() 222 223 m.recvChan <- &cb.Envelope{} 224 reply := <-m.sendChan 225 if reply.Status != cb.Status_BAD_REQUEST { 226 t.Fatalf("Should have rejected the null message") 227 } 228 229 select { 230 case <-done: 231 case <-time.After(time.Second): 232 t.Fatalf("Should have terminated the stream") 233 } 234 } 235 236 func TestBadChannelId(t *testing.T) { 237 mm, _ := getMockSupportManager() 238 bh := NewHandlerImpl(mm) 239 m := newMockB() 240 defer close(m.recvChan) 241 done := make(chan struct{}) 242 go func() { 243 bh.Handle(m) 244 close(done) 245 }() 246 247 m.recvChan <- makeMessage("Wrong chain", []byte("Some bytes")) 248 reply := <-m.sendChan 249 if reply.Status != cb.Status_NOT_FOUND { 250 t.Fatalf("Should have rejected message to a chain which does not exist") 251 } 252 253 select { 254 case <-done: 255 case <-time.After(time.Second): 256 t.Fatalf("Should have terminated the stream") 257 } 258 } 259 260 func TestGoodConfigUpdate(t *testing.T) { 261 mm, _ := getMockSupportManager() 262 mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})} 263 bh := NewHandlerImpl(mm) 264 m := newMockB() 265 defer close(m.recvChan) 266 go bh.Handle(m) 267 newChannelId := "New Chain" 268 269 m.recvChan <- makeConfigMessage(newChannelId) 270 reply := <-m.sendChan 271 assert.Equal(t, cb.Status_SUCCESS, reply.Status, "Should have allowed a good CONFIG_UPDATE") 272 } 273 274 func TestBadConfigUpdate(t *testing.T) { 275 mm, _ := getMockSupportManager() 276 bh := NewHandlerImpl(mm) 277 m := newMockB() 278 defer close(m.recvChan) 279 go bh.Handle(m) 280 281 m.recvChan <- makeConfigMessage(systemChain) 282 reply := <-m.sendChan 283 assert.NotEqual(t, cb.Status_SUCCESS, reply.Status, "Should have rejected CONFIG_UPDATE") 284 } 285 286 func TestGracefulShutdown(t *testing.T) { 287 bh := NewHandlerImpl(nil) 288 m := newMockB() 289 close(m.recvChan) 290 assert.NoError(t, bh.Handle(m), "Should exit normally upon EOF") 291 } 292 293 func TestRejected(t *testing.T) { 294 filters := filter.NewRuleSet([]filter.Rule{RejectRule}) 295 mm := &mockSupportManager{ 296 chains: map[string]*mockSupport{string(systemChain): {filters: filters}}, 297 } 298 mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})} 299 bh := NewHandlerImpl(mm) 300 m := newMockB() 301 defer close(m.recvChan) 302 go bh.Handle(m) 303 304 newChannelId := "New Chain" 305 306 m.recvChan <- makeConfigMessage(newChannelId) 307 reply := <-m.sendChan 308 assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected CONFIG_UPDATE") 309 } 310 311 func TestBadStreamRecv(t *testing.T) { 312 bh := NewHandlerImpl(nil) 313 assert.Error(t, bh.Handle(&erroneousRecvMockB{}), "Should catch unexpected stream error") 314 } 315 316 func TestBadStreamSend(t *testing.T) { 317 mm, _ := getMockSupportManager() 318 mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})} 319 bh := NewHandlerImpl(mm) 320 m := &erroneousSendMockB{recvVal: makeConfigMessage("New Chain")} 321 assert.Error(t, bh.Handle(m), "Should catch unexpected stream error") 322 } 323 324 func TestMalformedEnvelope(t *testing.T) { 325 mm, _ := getMockSupportManager() 326 bh := NewHandlerImpl(mm) 327 m := newMockB() 328 defer close(m.recvChan) 329 go bh.Handle(m) 330 331 m.recvChan <- &cb.Envelope{Payload: []byte("foo")} 332 reply := <-m.sendChan 333 assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected the malformed message") 334 } 335 336 func TestMissingHeader(t *testing.T) { 337 mm, _ := getMockSupportManager() 338 bh := NewHandlerImpl(mm) 339 m := newMockB() 340 defer close(m.recvChan) 341 go bh.Handle(m) 342 343 m.recvChan <- &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{})} 344 reply := <-m.sendChan 345 assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected the payload without header") 346 } 347 348 func TestBadChannelHeader(t *testing.T) { 349 mm, _ := getMockSupportManager() 350 bh := NewHandlerImpl(mm) 351 m := newMockB() 352 defer close(m.recvChan) 353 go bh.Handle(m) 354 355 m.recvChan <- &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: []byte("foo")}})} 356 reply := <-m.sendChan 357 assert.Equal(t, cb.Status_BAD_REQUEST, reply.Status, "Should have rejected bad header") 358 } 359 360 func TestBadPayloadAfterProcessing(t *testing.T) { 361 mm, _ := getMockSupportManager() 362 mm.ProcessVal = &cb.Envelope{Payload: []byte("foo")} 363 bh := NewHandlerImpl(mm) 364 m := newMockB() 365 defer close(m.recvChan) 366 go bh.Handle(m) 367 368 m.recvChan <- makeConfigMessage("New Chain") 369 reply := <-m.sendChan 370 assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error") 371 } 372 373 func TestNilHeaderAfterProcessing(t *testing.T) { 374 mm, _ := getMockSupportManager() 375 mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{})} 376 bh := NewHandlerImpl(mm) 377 m := newMockB() 378 defer close(m.recvChan) 379 go bh.Handle(m) 380 381 m.recvChan <- makeConfigMessage("New Chain") 382 reply := <-m.sendChan 383 assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error") 384 } 385 386 func TestBadChannelHeaderAfterProcessing(t *testing.T) { 387 mm, _ := getMockSupportManager() 388 mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: []byte("foo")}})} 389 bh := NewHandlerImpl(mm) 390 m := newMockB() 391 defer close(m.recvChan) 392 go bh.Handle(m) 393 394 m.recvChan <- makeConfigMessage("New Chain") 395 reply := <-m.sendChan 396 assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error") 397 } 398 399 func TestEmptyChannelIDAfterProcessing(t *testing.T) { 400 mm, _ := getMockSupportManager() 401 mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{})}})} 402 bh := NewHandlerImpl(mm) 403 m := newMockB() 404 defer close(m.recvChan) 405 go bh.Handle(m) 406 407 m.recvChan <- makeConfigMessage("New Chain") 408 reply := <-m.sendChan 409 assert.Equal(t, cb.Status_INTERNAL_SERVER_ERROR, reply.Status, "Should respond with internal server error") 410 }