github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/broadcast/broadcast_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package broadcast_test 8 9 import ( 10 "context" 11 "fmt" 12 "io" 13 14 "github.com/golang/protobuf/proto" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 18 cb "github.com/hyperledger/fabric-protos-go/common" 19 ab "github.com/hyperledger/fabric-protos-go/orderer" 20 "github.com/hyperledger/fabric/orderer/common/broadcast" 21 "github.com/hyperledger/fabric/orderer/common/broadcast/mock" 22 "github.com/hyperledger/fabric/orderer/common/msgprocessor" 23 ) 24 25 var _ = Describe("Broadcast", func() { 26 var ( 27 fakeSupportRegistrar *mock.ChannelSupportRegistrar 28 handler *broadcast.Handler 29 fakeValidateHistogram *mock.MetricsHistogram 30 fakeEnqueueHistogram *mock.MetricsHistogram 31 fakeProcessedCounter *mock.MetricsCounter 32 ) 33 34 BeforeEach(func() { 35 fakeSupportRegistrar = &mock.ChannelSupportRegistrar{} 36 37 fakeValidateHistogram = &mock.MetricsHistogram{} 38 fakeValidateHistogram.WithReturns(fakeValidateHistogram) 39 40 fakeEnqueueHistogram = &mock.MetricsHistogram{} 41 fakeEnqueueHistogram.WithReturns(fakeEnqueueHistogram) 42 43 fakeProcessedCounter = &mock.MetricsCounter{} 44 fakeProcessedCounter.WithReturns(fakeProcessedCounter) 45 46 handler = &broadcast.Handler{ 47 SupportRegistrar: fakeSupportRegistrar, 48 Metrics: &broadcast.Metrics{ 49 ValidateDuration: fakeValidateHistogram, 50 EnqueueDuration: fakeEnqueueHistogram, 51 ProcessedCount: fakeProcessedCounter, 52 }, 53 } 54 }) 55 56 Describe("Handle", func() { 57 var ( 58 fakeABServer *mock.ABServer 59 fakeSupport *mock.ChannelSupport 60 fakeMsg *cb.Envelope 61 ) 62 63 BeforeEach(func() { 64 fakeMsg = &cb.Envelope{} 65 66 fakeABServer = &mock.ABServer{} 67 fakeABServer.ContextReturns(context.TODO()) 68 fakeABServer.RecvReturns(fakeMsg, nil) 69 fakeABServer.RecvReturnsOnCall(1, nil, io.EOF) 70 71 fakeSupport = &mock.ChannelSupport{} 72 fakeSupport.ProcessNormalMsgReturns(5, nil) 73 74 fakeSupportRegistrar.BroadcastChannelSupportReturns(&cb.ChannelHeader{ 75 Type: 3, 76 ChannelId: "fake-channel", 77 }, false, fakeSupport, nil) 78 }) 79 80 It("enqueues the message to the consenter", func() { 81 err := handler.Handle(fakeABServer) 82 Expect(err).NotTo(HaveOccurred()) 83 84 Expect(fakeABServer.RecvCallCount()).To(Equal(2)) 85 Expect(fakeSupportRegistrar.BroadcastChannelSupportCallCount()).To(Equal(1)) 86 Expect(fakeSupportRegistrar.BroadcastChannelSupportArgsForCall(0)).To(Equal(fakeMsg)) 87 88 Expect(fakeSupport.ProcessNormalMsgCallCount()).To(Equal(1)) 89 Expect(fakeSupport.ProcessNormalMsgArgsForCall(0)).To(Equal(fakeMsg)) 90 91 Expect(fakeSupport.WaitReadyCallCount()).To(Equal(1)) 92 93 Expect(fakeSupport.OrderCallCount()).To(Equal(1)) 94 orderedMsg, seq := fakeSupport.OrderArgsForCall(0) 95 Expect(orderedMsg).To(Equal(fakeMsg)) 96 Expect(seq).To(Equal(uint64(5))) 97 98 Expect(fakeValidateHistogram.WithCallCount()).To(Equal(1)) 99 Expect(fakeValidateHistogram.WithArgsForCall(0)).To(Equal([]string{ 100 "status", "SUCCESS", 101 "channel", "fake-channel", 102 "type", "ENDORSER_TRANSACTION", 103 })) 104 Expect(fakeValidateHistogram.ObserveCallCount()).To(Equal(1)) 105 Expect(fakeValidateHistogram.ObserveArgsForCall(0)).To(BeNumerically(">", 0)) 106 Expect(fakeValidateHistogram.ObserveArgsForCall(0)).To(BeNumerically("<", 1)) 107 108 Expect(fakeEnqueueHistogram.WithCallCount()).To(Equal(1)) 109 Expect(fakeEnqueueHistogram.WithArgsForCall(0)).To(Equal([]string{ 110 "status", "SUCCESS", 111 "channel", "fake-channel", 112 "type", "ENDORSER_TRANSACTION", 113 })) 114 Expect(fakeEnqueueHistogram.ObserveCallCount()).To(Equal(1)) 115 Expect(fakeEnqueueHistogram.ObserveArgsForCall(0)).To(BeNumerically(">", 0)) 116 Expect(fakeEnqueueHistogram.ObserveArgsForCall(0)).To(BeNumerically("<", 1)) 117 118 Expect(fakeProcessedCounter.WithCallCount()).To(Equal(1)) 119 Expect(fakeProcessedCounter.WithArgsForCall(0)).To(Equal([]string{ 120 "status", "SUCCESS", 121 "channel", "fake-channel", 122 "type", "ENDORSER_TRANSACTION", 123 })) 124 Expect(fakeProcessedCounter.AddCallCount()).To(Equal(1)) 125 Expect(fakeProcessedCounter.AddArgsForCall(0)).To(Equal(float64(1))) 126 127 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 128 Expect(proto.Equal(fakeABServer.SendArgsForCall(0), &ab.BroadcastResponse{Status: cb.Status_SUCCESS})).To(BeTrue()) 129 }) 130 131 Context("when the channel support cannot be retrieved", func() { 132 BeforeEach(func() { 133 fakeSupportRegistrar.BroadcastChannelSupportReturns(&cb.ChannelHeader{ 134 Type: 2, 135 ChannelId: "fake-channel", 136 }, false, nil, fmt.Errorf("support-error")) 137 }) 138 139 It("returns the error to the client with a bad status", func() { 140 err := handler.Handle(fakeABServer) 141 Expect(err).NotTo(HaveOccurred()) 142 143 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 144 Expect(proto.Equal( 145 fakeABServer.SendArgsForCall(0), 146 &ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST, Info: "support-error"}), 147 ).To(BeTrue()) 148 }) 149 150 Context("when the channel header is not validly decoded", func() { 151 BeforeEach(func() { 152 fakeSupportRegistrar.BroadcastChannelSupportReturns(nil, false, nil, fmt.Errorf("support-error")) 153 }) 154 155 It("does not crash", func() { 156 err := handler.Handle(fakeABServer) 157 Expect(err).NotTo(HaveOccurred()) 158 159 Expect(fakeValidateHistogram.WithCallCount()).To(Equal(1)) 160 Expect(fakeValidateHistogram.WithArgsForCall(0)).To(Equal([]string{ 161 "status", "BAD_REQUEST", 162 "channel", "unknown", 163 "type", "unknown", 164 })) 165 Expect(fakeEnqueueHistogram.WithCallCount()).To(Equal(0)) 166 Expect(fakeProcessedCounter.WithCallCount()).To(Equal(1)) 167 }) 168 }) 169 170 }) 171 172 Context("when the receive from the client fails", func() { 173 BeforeEach(func() { 174 fakeABServer.RecvReturns(nil, fmt.Errorf("recv-error")) 175 }) 176 177 It("returns the error", func() { 178 err := handler.Handle(fakeABServer) 179 Expect(err).To(MatchError("recv-error")) 180 }) 181 }) 182 183 Context("when the consenter is not ready for the request", func() { 184 BeforeEach(func() { 185 fakeSupport.WaitReadyReturns(fmt.Errorf("not-ready")) 186 }) 187 188 It("returns the error to the client with a service unavailable status", func() { 189 err := handler.Handle(fakeABServer) 190 Expect(err).NotTo(HaveOccurred()) 191 192 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 193 Expect(proto.Equal( 194 fakeABServer.SendArgsForCall(0), 195 &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: "not-ready"}), 196 ).To(BeTrue()) 197 }) 198 }) 199 200 Context("when the send to the client fails", func() { 201 BeforeEach(func() { 202 fakeABServer.SendReturns(fmt.Errorf("send-error")) 203 }) 204 205 It("returns the error", func() { 206 err := handler.Handle(fakeABServer) 207 Expect(err).To(MatchError("send-error")) 208 }) 209 }) 210 211 Context("when the consenter cannot enqueue the message", func() { 212 BeforeEach(func() { 213 fakeSupport.OrderReturns(fmt.Errorf("consenter-error")) 214 }) 215 216 It("returns the error", func() { 217 err := handler.Handle(fakeABServer) 218 Expect(err).NotTo(HaveOccurred()) 219 220 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 221 Expect(proto.Equal( 222 fakeABServer.SendArgsForCall(0), 223 &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: "consenter-error"}), 224 ).To(BeTrue()) 225 }) 226 }) 227 228 Context("when the message processor returns an error", func() { 229 BeforeEach(func() { 230 fakeSupport.ProcessNormalMsgReturns(0, fmt.Errorf("normal-messsage-processing-error")) 231 }) 232 233 It("returns the error and an error status", func() { 234 err := handler.Handle(fakeABServer) 235 Expect(err).NotTo(HaveOccurred()) 236 237 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 238 Expect(proto.Equal( 239 fakeABServer.SendArgsForCall(0), 240 &ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST, Info: "normal-messsage-processing-error"}, 241 )).To(BeTrue()) 242 }) 243 244 Context("when the error cause is msgprocessor.ErrChannelDoesNotExist", func() { 245 BeforeEach(func() { 246 fakeSupport.ProcessNormalMsgReturns(0, msgprocessor.ErrChannelDoesNotExist) 247 }) 248 249 It("returns the error and a not found status", func() { 250 err := handler.Handle(fakeABServer) 251 Expect(err).NotTo(HaveOccurred()) 252 253 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 254 Expect(proto.Equal( 255 fakeABServer.SendArgsForCall(0), 256 &ab.BroadcastResponse{Status: cb.Status_NOT_FOUND, Info: msgprocessor.ErrChannelDoesNotExist.Error()}, 257 )).To(BeTrue()) 258 }) 259 }) 260 261 Context("when the error cause is msgprocessor.ErrPermissionDenied", func() { 262 BeforeEach(func() { 263 fakeSupport.ProcessNormalMsgReturns(0, msgprocessor.ErrPermissionDenied) 264 }) 265 266 It("returns the error and a not found status", func() { 267 err := handler.Handle(fakeABServer) 268 Expect(err).NotTo(HaveOccurred()) 269 270 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 271 Expect(proto.Equal( 272 fakeABServer.SendArgsForCall(0), 273 &ab.BroadcastResponse{Status: cb.Status_FORBIDDEN, Info: msgprocessor.ErrPermissionDenied.Error()}, 274 )).To(BeTrue()) 275 }) 276 }) 277 }) 278 279 Context("when the message is a config message", func() { 280 var ( 281 fakeConfig *cb.Envelope 282 ) 283 284 BeforeEach(func() { 285 fakeConfig = &cb.Envelope{} 286 287 fakeSupportRegistrar.BroadcastChannelSupportReturns(&cb.ChannelHeader{ 288 Type: 1, 289 ChannelId: "fake-channel", 290 }, true, fakeSupport, nil) 291 292 fakeSupport.ProcessConfigUpdateMsgReturns(fakeConfig, 3, nil) 293 }) 294 295 It("enqueues the message as a config message to the consenter", func() { 296 err := handler.Handle(fakeABServer) 297 Expect(err).NotTo(HaveOccurred()) 298 299 Expect(fakeSupport.ProcessNormalMsgCallCount()).To(Equal(0)) 300 Expect(fakeSupport.ProcessConfigUpdateMsgCallCount()).To(Equal(1)) 301 Expect(fakeSupport.ProcessConfigUpdateMsgArgsForCall(0)).To(Equal(fakeMsg)) 302 303 Expect(fakeSupport.WaitReadyCallCount()).To(Equal(1)) 304 305 Expect(fakeSupport.OrderCallCount()).To(Equal(0)) 306 Expect(fakeSupport.ConfigureCallCount()).To(Equal(1)) 307 configMsg, seq := fakeSupport.ConfigureArgsForCall(0) 308 Expect(configMsg).To(Equal(fakeConfig)) 309 Expect(seq).To(Equal(uint64(3))) 310 311 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 312 Expect(proto.Equal(fakeABServer.SendArgsForCall(0), &ab.BroadcastResponse{Status: cb.Status_SUCCESS})).To(BeTrue()) 313 }) 314 315 Context("when the consenter is not ready for the request", func() { 316 BeforeEach(func() { 317 fakeSupport.WaitReadyReturns(fmt.Errorf("not-ready")) 318 }) 319 320 It("returns the error to the client with a service unavailable status", func() { 321 err := handler.Handle(fakeABServer) 322 Expect(err).NotTo(HaveOccurred()) 323 324 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 325 Expect(proto.Equal( 326 fakeABServer.SendArgsForCall(0), 327 &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: "not-ready"}), 328 ).To(BeTrue()) 329 }) 330 }) 331 332 Context("when the consenter cannot enqueue the message", func() { 333 BeforeEach(func() { 334 fakeSupport.ConfigureReturns(fmt.Errorf("consenter-error")) 335 }) 336 337 It("returns the error", func() { 338 err := handler.Handle(fakeABServer) 339 Expect(err).NotTo(HaveOccurred()) 340 341 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 342 Expect(proto.Equal( 343 fakeABServer.SendArgsForCall(0), 344 &ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE, Info: "consenter-error"}), 345 ).To(BeTrue()) 346 }) 347 }) 348 349 Context("when the processing of the config update fails", func() { 350 BeforeEach(func() { 351 fakeSupport.ProcessConfigUpdateMsgReturns(nil, 0, fmt.Errorf("config-processing-error")) 352 }) 353 354 It("returns the error with a bad_status", func() { 355 err := handler.Handle(fakeABServer) 356 Expect(err).NotTo(HaveOccurred()) 357 358 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 359 Expect(proto.Equal( 360 fakeABServer.SendArgsForCall(0), 361 &ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST, Info: "config-processing-error"}, 362 )).To(BeTrue()) 363 }) 364 365 Context("when the error cause is msgprocessor.ErrChannelDoesNotExist", func() { 366 BeforeEach(func() { 367 fakeSupport.ProcessConfigUpdateMsgReturns(nil, 0, msgprocessor.ErrChannelDoesNotExist) 368 }) 369 370 It("returns the error and a not found status", func() { 371 err := handler.Handle(fakeABServer) 372 Expect(err).NotTo(HaveOccurred()) 373 374 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 375 Expect(proto.Equal( 376 fakeABServer.SendArgsForCall(0), 377 &ab.BroadcastResponse{Status: cb.Status_NOT_FOUND, Info: msgprocessor.ErrChannelDoesNotExist.Error()}, 378 )).To(BeTrue()) 379 }) 380 }) 381 382 Context("when the error cause is msgprocessor.ErrPermissionDenied", func() { 383 BeforeEach(func() { 384 fakeSupport.ProcessConfigUpdateMsgReturns(nil, 0, msgprocessor.ErrPermissionDenied) 385 }) 386 387 It("returns the error and a not found status", func() { 388 err := handler.Handle(fakeABServer) 389 Expect(err).NotTo(HaveOccurred()) 390 391 Expect(fakeABServer.SendCallCount()).To(Equal(1)) 392 Expect(proto.Equal( 393 fakeABServer.SendArgsForCall(0), 394 &ab.BroadcastResponse{Status: cb.Status_FORBIDDEN, Info: msgprocessor.ErrPermissionDenied.Error()}, 395 )).To(BeTrue()) 396 }) 397 }) 398 }) 399 }) 400 }) 401 })