github.com/s7techlab/cckit@v0.10.5/testing/mocked_peer.go (about)

     1  package testing
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  
     8  	"github.com/golang/protobuf/ptypes/timestamp"
     9  	"github.com/hyperledger/fabric-chaincode-go/shim"
    10  	"github.com/hyperledger/fabric-protos-go/common"
    11  	"github.com/hyperledger/fabric-protos-go/peer"
    12  	"github.com/hyperledger/fabric/msp"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  type (
    17  	MockedPeer struct {
    18  		// channel name -> chaincode name
    19  		ChannelCC ChannelsMockStubs
    20  		m         sync.Mutex
    21  	}
    22  
    23  	ChannelMockStubs map[string]*MockStub
    24  
    25  	ChannelsMockStubs map[string]ChannelMockStubs
    26  
    27  	EventSubscription struct {
    28  		events chan *peer.ChaincodeEvent
    29  		errors chan error
    30  		closer sync.Once
    31  	}
    32  )
    33  
    34  // NewPeer implements Peer interface
    35  func NewPeer() *MockedPeer {
    36  	return &MockedPeer{
    37  		ChannelCC: make(ChannelsMockStubs),
    38  	}
    39  }
    40  
    41  func (mp *MockedPeer) WithChannel(channel string, mockStubs ...*MockStub) *MockedPeer {
    42  	if _, ok := mp.ChannelCC[channel]; !ok {
    43  		mp.ChannelCC[channel] = make(ChannelMockStubs)
    44  	}
    45  
    46  	for _, ms := range mockStubs {
    47  		mp.ChannelCC[channel][ms.Name] = ms
    48  		for chName, chnl := range mp.ChannelCC {
    49  			for ccName, cc := range chnl {
    50  
    51  				// add visibility of added cc to all other cc
    52  				cc.MockPeerChaincode(ms.Name+`/`+channel, ms)
    53  
    54  				// add visibility of other cc to added cc
    55  				ms.MockPeerChaincode(ccName+`/`+chName, cc)
    56  			}
    57  		}
    58  	}
    59  
    60  	return mp
    61  }
    62  
    63  func (mp *MockedPeer) CurrentIdentity() msp.SigningIdentity {
    64  	return nil
    65  }
    66  
    67  func (mp *MockedPeer) Invoke(
    68  	ctx context.Context,
    69  	channel string,
    70  	chaincode string,
    71  	args [][]byte,
    72  	identity msp.SigningIdentity,
    73  	transArgs map[string][]byte,
    74  	txWaiterType string) (res *peer.Response, chaincodeTx string, err error) {
    75  
    76  	mp.m.Lock()
    77  	defer mp.m.Unlock()
    78  	mockStub, err := mp.Chaincode(channel, chaincode)
    79  	if err != nil {
    80  		return nil, ``, err
    81  	}
    82  
    83  	response := mockStub.From(identity).WithTransient(transArgs).InvokeBytes(args...)
    84  	if response.Status == shim.ERROR {
    85  		err = errors.New(response.Message)
    86  	}
    87  
    88  	return &response, mockStub.TxID, err
    89  }
    90  
    91  func (mp *MockedPeer) Query(
    92  	ctx context.Context,
    93  	channel string,
    94  	chaincode string,
    95  	args [][]byte,
    96  	identity msp.SigningIdentity,
    97  	transArgs map[string][]byte) (*peer.Response, error) {
    98  
    99  	mp.m.Lock()
   100  	defer mp.m.Unlock()
   101  	mockStub, err := mp.Chaincode(channel, chaincode)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	response := mockStub.From(identity).WithTransient(transArgs).QueryBytes(args...)
   107  	if response.Status == shim.ERROR {
   108  		err = errors.New(response.Message)
   109  	}
   110  
   111  	return &response, err
   112  
   113  }
   114  
   115  func (mp *MockedPeer) Chaincode(channel string, chaincode string) (*MockStub, error) {
   116  	ms, exists := mp.ChannelCC[channel][chaincode]
   117  	if !exists {
   118  		return nil, fmt.Errorf(`%s: channell=%s, chaincode=%s`, ErrChaincodeNotExists, channel, chaincode)
   119  	}
   120  
   121  	return ms, nil
   122  }
   123  
   124  func (mp *MockedPeer) Events(
   125  	ctx context.Context,
   126  	channel string,
   127  	chaincode string,
   128  	identity msp.SigningIdentity,
   129  	blockRange ...int64,
   130  ) (events chan interface {
   131  	Event() *peer.ChaincodeEvent
   132  	Block() uint64
   133  	TxTimestamp() *timestamp.Timestamp
   134  }, closer func() error, err error) {
   135  	mockStub, err := mp.Chaincode(channel, chaincode)
   136  	if err != nil {
   137  		return nil, nil, err
   138  	}
   139  
   140  	var (
   141  		eventsRaw chan *peer.ChaincodeEvent
   142  	)
   143  	// from oldest block to current channel height
   144  	if len(blockRange) > 0 && blockRange[0] == 0 {
   145  		// create copy of mockStub events chan
   146  		eventsRaw, closer = mockStub.EventSubscription(0)
   147  
   148  		// In real HLF peer stream not closed
   149  		//// close events channel if its empty, because we receive events until current channel height
   150  		//go func() {
   151  		//	ticker := time.NewTicker(5 * time.Millisecond)
   152  		//	for {
   153  		//		<-ticker.C
   154  		//		if len(events) == 0 {
   155  		//			closer()
   156  		//			ticker.Stop()
   157  		//			return
   158  		//		}
   159  		//	}
   160  		//}()
   161  	} else {
   162  		eventsRaw, closer = mockStub.EventSubscription()
   163  	}
   164  
   165  	go func() {
   166  		<-ctx.Done()
   167  		_ = closer()
   168  	}()
   169  
   170  	eventsExtended := make(chan interface {
   171  		Event() *peer.ChaincodeEvent
   172  		Block() uint64
   173  		TxTimestamp() *timestamp.Timestamp
   174  	})
   175  	go func() {
   176  		for e := range eventsRaw {
   177  			eventsExtended <- &ChaincodeEvent{
   178  				event: e,
   179  
   180  				// todo: store information about block and timestamp in MockStub
   181  				block:       55,
   182  				txTimestamp: nil,
   183  			}
   184  		}
   185  		close(eventsExtended)
   186  	}()
   187  
   188  	return eventsExtended, closer, nil
   189  }
   190  
   191  func (m *MockedPeer) Blocks(
   192  	ctx context.Context,
   193  	channelName string,
   194  	identity msp.SigningIdentity,
   195  	blockRange ...int64,
   196  ) (blockChan <-chan *common.Block, closer func() error, err error) {
   197  	panic("not implemented")
   198  }
   199  
   200  func (es *EventSubscription) Events() chan *peer.ChaincodeEvent {
   201  	return es.events
   202  }
   203  
   204  func (es *EventSubscription) Errors() chan error {
   205  	return es.errors
   206  }
   207  
   208  func (es *EventSubscription) Close() error {
   209  	es.closer.Do(func() {
   210  		close(es.events)
   211  		close(es.errors)
   212  	})
   213  	return nil
   214  }