github.com/braveheart12/just@v0.8.7/testutils/testmessagebus/testmessagebus.go (about)

     1  /*
     2   *    Copyright 2019 Insolar Technologies
     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 testmessagebus
    18  
    19  import (
    20  	"context"
    21  	"encoding/gob"
    22  	"fmt"
    23  	"io"
    24  	"reflect"
    25  	"testing"
    26  
    27  	"github.com/pkg/errors"
    28  
    29  	"github.com/insolar/insolar/component"
    30  	"github.com/insolar/insolar/core"
    31  	"github.com/insolar/insolar/core/delegationtoken"
    32  	"github.com/insolar/insolar/core/message"
    33  	"github.com/insolar/insolar/instrumentation/inslogger"
    34  	"github.com/insolar/insolar/messagebus"
    35  	"github.com/insolar/insolar/platformpolicy"
    36  	"github.com/insolar/insolar/testutils"
    37  )
    38  
    39  type TapeRecord struct {
    40  	Message core.Message
    41  	Reply   core.Reply
    42  	Error   error
    43  }
    44  
    45  type TestMessageBus struct {
    46  	handlers     map[core.MessageType]core.MessageHandler
    47  	pf           message.ParcelFactory
    48  	PulseStorage core.PulseStorage
    49  	ReadingTape  []TapeRecord
    50  	WritingTape  []TapeRecord
    51  }
    52  
    53  func (mb *TestMessageBus) NewPlayer(ctx context.Context, reader io.Reader) (core.MessageBus, error) {
    54  	tape := make([]TapeRecord, 0)
    55  	enc := gob.NewDecoder(reader)
    56  	err := enc.Decode(&tape)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	res := *mb
    61  	res.ReadingTape = tape
    62  	return &res, nil
    63  }
    64  
    65  func (mb *TestMessageBus) WriteTape(ctx context.Context, writer io.Writer) error {
    66  	if mb.WritingTape == nil {
    67  		return errors.New("Not writing message bus")
    68  	}
    69  	enc := gob.NewEncoder(writer)
    70  	err := enc.Encode(mb.WritingTape)
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	return nil
    76  }
    77  
    78  func (mb *TestMessageBus) NewRecorder(ctx context.Context, currentPulse core.Pulse) (core.MessageBus, error) {
    79  	tape := make([]TapeRecord, 0)
    80  	res := *mb
    81  	res.WritingTape = tape
    82  	return &res, nil
    83  }
    84  
    85  func NewTestMessageBus(t *testing.T) *TestMessageBus {
    86  	cryptoServiceMock := testutils.NewCryptographyServiceMock(t)
    87  	cryptoServiceMock.SignFunc = func(p []byte) (r *core.Signature, r1 error) {
    88  		signature := core.SignatureFromBytes(nil)
    89  		return &signature, nil
    90  	}
    91  
    92  	delegationTokenFactory := delegationtoken.NewDelegationTokenFactory()
    93  
    94  	parcelFactory := messagebus.NewParcelFactory()
    95  
    96  	cm := &component.Manager{}
    97  	cm.Register(platformpolicy.NewPlatformCryptographyScheme())
    98  	cm.Inject(delegationTokenFactory, parcelFactory, cryptoServiceMock)
    99  
   100  	return &TestMessageBus{handlers: map[core.MessageType]core.MessageHandler{}, pf: parcelFactory}
   101  }
   102  
   103  func (mb *TestMessageBus) Register(p core.MessageType, handler core.MessageHandler) error {
   104  	_, ok := mb.handlers[p]
   105  	if ok {
   106  		return errors.New("handler for this type already exists")
   107  	}
   108  
   109  	mb.handlers[p] = handler
   110  	return nil
   111  }
   112  
   113  func (mb *TestMessageBus) ReRegister(p core.MessageType, handler core.MessageHandler) {
   114  	mb.handlers[p] = handler
   115  }
   116  
   117  func (mb *TestMessageBus) MustRegister(p core.MessageType, handler core.MessageHandler) {
   118  	err := mb.Register(p, handler)
   119  	if err != nil {
   120  		panic(err)
   121  	}
   122  }
   123  
   124  func (mb *TestMessageBus) Send(ctx context.Context, m core.Message, _ *core.MessageSendOptions) (core.Reply, error) {
   125  	if mb.ReadingTape != nil {
   126  		if len(mb.ReadingTape) == 0 {
   127  			return nil, errors.Errorf("No expected messages, got %+v", m)
   128  		}
   129  		head, tail := mb.ReadingTape[0], mb.ReadingTape[1:]
   130  		mb.ReadingTape = tail
   131  
   132  		inslogger.FromContext(ctx).Debugf("Reading message %+v off the tape", head.Message)
   133  
   134  		if !reflect.DeepEqual(head.Message, m) {
   135  			return nil, errors.Errorf("Message in the tape and sended arn't equal; got: %+v, expected: %+v", m, head.Message)
   136  		}
   137  		return head.Reply, head.Error
   138  	}
   139  
   140  	currentPulse, err := mb.PulseStorage.Current(ctx)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	parcel, err := mb.pf.Create(ctx, m, testutils.RandomRef(), nil, core.Pulse{PulseNumber: currentPulse.PulseNumber, Entropy: core.Entropy{}})
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	t := parcel.Message().Type()
   150  	handler, ok := mb.handlers[t]
   151  	if !ok {
   152  		return nil, errors.New(fmt.Sprint("no handler for message type:", t.String()))
   153  	}
   154  
   155  	ctx = parcel.Context(context.Background())
   156  
   157  	reply, err := handler(ctx, parcel)
   158  	if mb.WritingTape != nil {
   159  		// WARNING! The following commented line of code is cursed.
   160  		// It makes some test (e.g. TestNilResults) hang under the debugger, and we have no idea why.
   161  		// Don't uncomment unless you solved this mystery.
   162  		// inslogger.FromContext(ctx).Debugf("Writing message %+v on the tape", m)
   163  		mb.WritingTape = append(mb.WritingTape, TapeRecord{Message: m, Reply: reply, Error: err})
   164  	}
   165  
   166  	return reply, err
   167  }
   168  
   169  func (mb *TestMessageBus) OnPulse(context.Context, core.Pulse) error {
   170  	return nil
   171  }