github.com/pvitto98/fabric@v2.1.1+incompatible/core/dispatcher/dispatcher_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package dispatcher_test
     8  
     9  import (
    10  	"fmt"
    11  	"time"
    12  
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  
    16  	"github.com/hyperledger/fabric/core/dispatcher"
    17  	"github.com/hyperledger/fabric/core/dispatcher/mock"
    18  
    19  	"github.com/golang/protobuf/proto"
    20  	"github.com/golang/protobuf/ptypes"
    21  	"github.com/golang/protobuf/ptypes/timestamp"
    22  )
    23  
    24  type TestReceiver struct{}
    25  
    26  func (tr TestReceiver) GoodFunc(ts *timestamp.Timestamp) (*timestamp.Timestamp, error) {
    27  	return ptypes.TimestampProto(time.Unix(0, 0))
    28  }
    29  
    30  func (tr TestReceiver) MissingFuncParameters() (*timestamp.Timestamp, error) {
    31  	return ptypes.TimestampProto(time.Unix(0, 0))
    32  }
    33  
    34  func (tr TestReceiver) NotProtoParameter(foo *string) (*timestamp.Timestamp, error) {
    35  	return ptypes.TimestampProto(time.Unix(0, 0))
    36  }
    37  
    38  func (tr TestReceiver) NotPointerParameter(foo string) (*timestamp.Timestamp, error) {
    39  	return ptypes.TimestampProto(time.Unix(0, 0))
    40  }
    41  
    42  func (tr TestReceiver) NoReturnValues(ts *timestamp.Timestamp) {
    43  	return
    44  }
    45  
    46  func (tr TestReceiver) NotProtoReturn(ts *timestamp.Timestamp) (string, error) {
    47  	return "", nil
    48  }
    49  
    50  func (tr TestReceiver) NotErrorReturn(ts *timestamp.Timestamp) (*timestamp.Timestamp, string) {
    51  	return nil, ""
    52  }
    53  
    54  func (tr TestReceiver) NilNilReturn(ts *timestamp.Timestamp) (*timestamp.Timestamp, error) {
    55  	return nil, nil
    56  }
    57  
    58  func (tr TestReceiver) ErrorReturned(ts *timestamp.Timestamp) (*timestamp.Timestamp, error) {
    59  	return nil, fmt.Errorf("fake-error")
    60  }
    61  
    62  var _ = Describe("Dispatcher", func() {
    63  	var (
    64  		d         *dispatcher.Dispatcher
    65  		fakeProto *mock.Protobuf
    66  	)
    67  
    68  	BeforeEach(func() {
    69  		fakeProto = &mock.Protobuf{}
    70  		fakeProto.MarshalStub = proto.Marshal
    71  		fakeProto.UnmarshalStub = proto.Unmarshal
    72  
    73  		d = &dispatcher.Dispatcher{
    74  			Protobuf: fakeProto,
    75  		}
    76  	})
    77  
    78  	Describe("Dispatch", func() {
    79  		var (
    80  			testReceiver TestReceiver
    81  			inputBytes   []byte
    82  		)
    83  
    84  		BeforeEach(func() {
    85  			var err error
    86  			inputBytes, err = proto.Marshal(ptypes.TimestampNow())
    87  			Expect(err).NotTo(HaveOccurred())
    88  		})
    89  
    90  		It("unmarshals, dispatches to the correct function, and marshals the result", func() {
    91  			outputBytes, err := d.Dispatch(inputBytes, "GoodFunc", testReceiver)
    92  			Expect(err).NotTo(HaveOccurred())
    93  			ts := &timestamp.Timestamp{}
    94  			err = proto.Unmarshal(outputBytes, ts)
    95  			Expect(err).NotTo(HaveOccurred())
    96  			gts, err := ptypes.Timestamp(ts)
    97  			Expect(err).NotTo(HaveOccurred())
    98  			Expect(gts).To(Equal(time.Unix(0, 0).UTC()))
    99  		})
   100  
   101  		Context("when the receiver does not have a method to dispatch to", func() {
   102  			It("returns an error", func() {
   103  				_, err := d.Dispatch(inputBytes, "MissingMethod", testReceiver)
   104  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.MissingMethod does not exist"))
   105  			})
   106  		})
   107  
   108  		Context("when the receiver does not return the right number of parameters", func() {
   109  			It("returns an error", func() {
   110  				_, err := d.Dispatch(inputBytes, "MissingFuncParameters", testReceiver)
   111  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.MissingFuncParameters has 0 parameters but expected 1"))
   112  			})
   113  		})
   114  
   115  		Context("when the receiver does not take a pointer", func() {
   116  			It("returns an error", func() {
   117  				_, err := d.Dispatch(inputBytes, "NotPointerParameter", testReceiver)
   118  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.NotPointerParameter does not accept a pointer as its argument"))
   119  			})
   120  		})
   121  
   122  		Context("when the receiver does not take a protobuf message", func() {
   123  			It("returns an error", func() {
   124  				_, err := d.Dispatch(inputBytes, "NotProtoParameter", testReceiver)
   125  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.NotProtoParameter does not accept a proto.Message as its argument, it is '*string'"))
   126  			})
   127  		})
   128  
   129  		Context("when the input bytes cannot be unmarshaled", func() {
   130  			It("wraps and returns the error", func() {
   131  				_, err := d.Dispatch([]byte("garbage"), "GoodFunc", testReceiver)
   132  				Expect(err).To(MatchError("could not decode input arg for dispatcher_test.TestReceiver.GoodFunc: proto: can't skip unknown wire type 7"))
   133  			})
   134  		})
   135  
   136  		Context("when the receiver does not return the right number of paramters", func() {
   137  			It("returns an error", func() {
   138  				_, err := d.Dispatch(inputBytes, "NoReturnValues", testReceiver)
   139  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.NoReturnValues returns 0 values but expected 2"))
   140  			})
   141  		})
   142  
   143  		Context("when the receiver does not return a proto message as the first return value", func() {
   144  			It("returns an error", func() {
   145  				_, err := d.Dispatch(inputBytes, "NotProtoReturn", testReceiver)
   146  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.NotProtoReturn does not return a an implementor of proto.Message as its first return value"))
   147  			})
   148  		})
   149  
   150  		Context("when the receiver does not return an error as its second return value", func() {
   151  			It("returns an error", func() {
   152  				_, err := d.Dispatch(inputBytes, "NotErrorReturn", testReceiver)
   153  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.NotErrorReturn does not return an error as its second return value"))
   154  			})
   155  		})
   156  
   157  		Context("when the receiver returns nil, nil", func() {
   158  			It("returns an error", func() {
   159  				_, err := d.Dispatch(inputBytes, "NilNilReturn", testReceiver)
   160  				Expect(err).To(MatchError("receiver dispatcher_test.TestReceiver.NilNilReturn returned (nil, nil) which is not allowed"))
   161  			})
   162  		})
   163  
   164  		Context("when the receiver returns an error", func() {
   165  			It("returns the error", func() {
   166  				_, err := d.Dispatch(inputBytes, "ErrorReturned", testReceiver)
   167  				Expect(err).To(MatchError("fake-error"))
   168  			})
   169  		})
   170  
   171  		Context("when the returned output cannot be marshaled", func() {
   172  			BeforeEach(func() {
   173  				fakeProto.MarshalReturns(nil, fmt.Errorf("fake-error"))
   174  			})
   175  
   176  			It("wraps and returns the error", func() {
   177  				_, err := d.Dispatch(inputBytes, "GoodFunc", testReceiver)
   178  				Expect(err).To(MatchError("failed to marshal result for dispatcher_test.TestReceiver.GoodFunc: fake-error"))
   179  			})
   180  		})
   181  	})
   182  })