github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/dispatcher/dispatcher_test.go (about)

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