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  })