github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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 "testing" 22 "time" 23 24 "github.com/hyperledger/fabric/orderer/common/filter" 25 cb "github.com/hyperledger/fabric/protos/common" 26 ab "github.com/hyperledger/fabric/protos/orderer" 27 "github.com/hyperledger/fabric/protos/utils" 28 29 logging "github.com/op/go-logging" 30 "github.com/stretchr/testify/assert" 31 "google.golang.org/grpc" 32 ) 33 34 func init() { 35 logging.SetLevel(logging.DEBUG, "") 36 } 37 38 var systemChain = "systemChain" 39 40 type mockB struct { 41 grpc.ServerStream 42 recvChan chan *cb.Envelope 43 sendChan chan *ab.BroadcastResponse 44 } 45 46 func newMockB() *mockB { 47 return &mockB{ 48 recvChan: make(chan *cb.Envelope), 49 sendChan: make(chan *ab.BroadcastResponse), 50 } 51 } 52 53 func (m *mockB) Send(br *ab.BroadcastResponse) error { 54 m.sendChan <- br 55 return nil 56 } 57 58 func (m *mockB) Recv() (*cb.Envelope, error) { 59 msg, ok := <-m.recvChan 60 if !ok { 61 return msg, fmt.Errorf("Channel closed") 62 } 63 return msg, nil 64 } 65 66 type mockSupportManager struct { 67 chains map[string]*mockSupport 68 ProcessVal *cb.Envelope 69 } 70 71 func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) { 72 chain, ok := mm.chains[chainID] 73 return chain, ok 74 } 75 76 func (mm *mockSupportManager) Process(configTx *cb.Envelope) (*cb.Envelope, error) { 77 if mm.ProcessVal == nil { 78 return nil, fmt.Errorf("Nil result implies error") 79 } 80 return mm.ProcessVal, nil 81 } 82 83 type mockSupport struct { 84 filters *filter.RuleSet 85 rejectEnqueue bool 86 } 87 88 func (ms *mockSupport) Filters() *filter.RuleSet { 89 return ms.filters 90 } 91 92 // Enqueue sends a message for ordering 93 func (ms *mockSupport) Enqueue(env *cb.Envelope) bool { 94 return !ms.rejectEnqueue 95 } 96 97 func makeConfigMessage(chainID string) *cb.Envelope { 98 payload := &cb.Payload{ 99 Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{}), 100 Header: &cb.Header{ 101 ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ 102 ChannelId: chainID, 103 Type: int32(cb.HeaderType_CONFIG_UPDATE), 104 }), 105 }, 106 } 107 return &cb.Envelope{ 108 Payload: utils.MarshalOrPanic(payload), 109 } 110 } 111 112 func makeMessage(chainID string, data []byte) *cb.Envelope { 113 payload := &cb.Payload{ 114 Data: data, 115 Header: &cb.Header{ 116 ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ 117 ChannelId: chainID, 118 }), 119 }, 120 } 121 return &cb.Envelope{ 122 Payload: utils.MarshalOrPanic(payload), 123 } 124 } 125 126 func getMockSupportManager() (*mockSupportManager, *mockSupport) { 127 filters := filter.NewRuleSet([]filter.Rule{ 128 filter.EmptyRejectRule, 129 filter.AcceptRule, 130 }) 131 mm := &mockSupportManager{ 132 chains: make(map[string]*mockSupport), 133 } 134 mSysChain := &mockSupport{ 135 filters: filters, 136 } 137 mm.chains[string(systemChain)] = mSysChain 138 return mm, mSysChain 139 } 140 141 func TestEnqueueFailure(t *testing.T) { 142 mm, mSysChain := getMockSupportManager() 143 bh := NewHandlerImpl(mm) 144 m := newMockB() 145 defer close(m.recvChan) 146 done := make(chan struct{}) 147 go func() { 148 bh.Handle(m) 149 close(done) 150 }() 151 152 for i := 0; i < 2; i++ { 153 m.recvChan <- makeMessage(systemChain, []byte("Some bytes")) 154 reply := <-m.sendChan 155 if reply.Status != cb.Status_SUCCESS { 156 t.Fatalf("Should have successfully queued the message") 157 } 158 } 159 160 mSysChain.rejectEnqueue = true 161 m.recvChan <- makeMessage(systemChain, []byte("Some bytes")) 162 reply := <-m.sendChan 163 if reply.Status != cb.Status_SERVICE_UNAVAILABLE { 164 t.Fatalf("Should not have successfully queued the message") 165 } 166 167 select { 168 case <-done: 169 case <-time.After(time.Second): 170 t.Fatalf("Should have terminated the stream") 171 } 172 } 173 174 func TestEmptyEnvelope(t *testing.T) { 175 mm, _ := getMockSupportManager() 176 bh := NewHandlerImpl(mm) 177 m := newMockB() 178 defer close(m.recvChan) 179 done := make(chan struct{}) 180 go func() { 181 bh.Handle(m) 182 close(done) 183 }() 184 185 m.recvChan <- &cb.Envelope{} 186 reply := <-m.sendChan 187 if reply.Status != cb.Status_BAD_REQUEST { 188 t.Fatalf("Should have rejected the null message") 189 } 190 191 select { 192 case <-done: 193 case <-time.After(time.Second): 194 t.Fatalf("Should have terminated the stream") 195 } 196 } 197 198 func TestBadChannelId(t *testing.T) { 199 mm, _ := getMockSupportManager() 200 bh := NewHandlerImpl(mm) 201 m := newMockB() 202 defer close(m.recvChan) 203 done := make(chan struct{}) 204 go func() { 205 bh.Handle(m) 206 close(done) 207 }() 208 209 m.recvChan <- makeMessage("Wrong chain", []byte("Some bytes")) 210 reply := <-m.sendChan 211 if reply.Status != cb.Status_NOT_FOUND { 212 t.Fatalf("Should have rejected message to a chain which does not exist") 213 } 214 215 select { 216 case <-done: 217 case <-time.After(time.Second): 218 t.Fatalf("Should have terminated the stream") 219 } 220 } 221 222 func TestGoodConfigUpdate(t *testing.T) { 223 mm, _ := getMockSupportManager() 224 mm.ProcessVal = &cb.Envelope{Payload: utils.MarshalOrPanic(&cb.Payload{Header: &cb.Header{ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ChannelId: systemChain})}})} 225 bh := NewHandlerImpl(mm) 226 m := newMockB() 227 defer close(m.recvChan) 228 go bh.Handle(m) 229 newChannelId := "New Chain" 230 231 m.recvChan <- makeConfigMessage(newChannelId) 232 reply := <-m.sendChan 233 assert.Equal(t, cb.Status_SUCCESS, reply.Status, "Should have allowed a good CONFIG_UPDATE") 234 } 235 236 func TestBadConfigUpdate(t *testing.T) { 237 mm, _ := getMockSupportManager() 238 bh := NewHandlerImpl(mm) 239 m := newMockB() 240 defer close(m.recvChan) 241 go bh.Handle(m) 242 243 m.recvChan <- makeConfigMessage(systemChain) 244 reply := <-m.sendChan 245 assert.NotEqual(t, cb.Status_SUCCESS, reply.Status, "Should have rejected CONFIG_UPDATE") 246 }