testing

package
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 9, 2024 License: Apache-2.0 Imports: 28 Imported by: 0

README

Test Driven Hyperledger Fabric Golang chaincode development

How to fast and continuously check smart contract logic : blockchain transactions, fired events and chaincode permissioning

Testing stage is a critical requirement for software quality assurance, doesn't matter is this
web application or a smart contract. Tests must be fast enough to run on every commit to repository. CCKit, programming toolkit for developing and testing Hyperledger Fabric Golang chaincodes, enhances the development experience with extended version of MockStub for chaincode testing.

Steps in chaincode development process

A smart contract defines the different states of a business object and governs the processes that move the object between these different states. Smart contracts allows architects and smart contract developers to define the business processes and structure of data that are shared across different organizations collaborating in a blockchain network.

The job of a smart contract developer is to take an existing business process and express it as a smart contract in a programming language. Steps of chaincode development:

  • Define chaincode model - schema for state entries, input payload and events
  • Define chaincode interface
  • Implement chaincode instantiate method
  • Implement chaincode methods with business logic
  • Create tests

Test driven development (TDD) or Behavioral Driven Development, possibly, single way to develop smart contracts.

Chaincode (smart contract) testing

Tests must ensure that chaincode works as expected:

  • particular input payload leads to particular business object state change
  • particular (invalid) input payload leads to validation or other errors
  • particular object state allow subset of state transitions (state machine)

Any software testing (chaincode or web application for example) may either be a manual or an automated process. Manual software testing is led by a team or individual who will manually operate a software product and ensure it behaves as expected. In case of chaincode tests you can manually invoke chaincode via peer cli tools.

Automated software testing is the practice of instrumenting input and output correctness checks for individual units of code. During automated testing, code are executed in a test environment with simulated input.

Running chaincode

Deploying chaincode to blockchain network isn't the quickest thing in the world, there's a lot of time that can be saved with testing. Also, more importantly, since blockchain is immutable and supposed to be secure because the code is on the network, we rather not leave flaws in our code.

During chaincode development and deploying to live network we can divide testing to multiple stage - fast stage, when testing only smart contract logic, and more complicated stage, when we do integration testing with live blockchain network, multiple peers, deployed on-chain code (smart contracts) and off-chain application, that uses SDK to connect with blockchain network peers.

Chaincode DEV mode

Deploying a Hyperledger Fabric blockchain network, chaincode installing and initializing, is quite complicated to set up and a long procedure. Time to re-install / upgrade the code of a smart contract can be reduced by using chaincode dev mode. Normally chaincodes are started and maintained by peer. In “dev” mode, chaincode is built and started by the user. This mode is useful during chaincode development phase for rapid code/build/run/debug cycle turnaround. However, the process of updating the code will still be slow.

MockStub - mocked chaincode stub

Mocking is a unit testing phenomenon which helps to test objects in isolation by replacing dependent objects with complex behavior with test objects with pre-defined/simulated behavior. These test objects are called as Mock objects.

The shim package contains a MockStub implementation that wraps calls to a chaincode, simulating its behavior in the HLF peer environment. MockStub does not need to start multiple docker containers with peer, world state database, chaincodes and allows to get test results almost immediately. MockStub essentially replaces the SDK and peer environment and allows to test chaincode without actually starting your blockchain network. It implements almost every function the actual stub does, but in memory.

mockstub

MockStub from https://github.com/hyperledger/fabric/ repository includes implementation for most of shim.ChaincodeStubInterface function, but until current version of Hyperledger Fabric (1.4), the MockStub has not implemented some of the important methods such as GetCreator or method for work with private state range, for example. Since chaincode would use GetCreator method to get transaction creator certificate for access control, it's critical to be able to stub this method in order to completely unit-test chaincode.

CCKit MockStub

CCKit testing package contains:

  • MockStub with implemented GetTransient and others methods and event subscription feature
  • Test identity creation helpers
  • Chaincode response expect helpers

Example: Commercial Paper chaincode

Scenario

Official hyperledger fabric documentation contain detailed chaincode example - Commercial Paper smart contract that defines the valid states for commercial paper, and the transaction logic that transition a paper from one state to another. We will test commercial paper extended chaincode example based on CCKit with protobuf state, described in this article.

We can represent the lifecycle of a commercial paper using a state transition diagram: commercial papers transition between issued, trading and redeemed states by means of the issue, buy and redeem transactions.

state

Requirements

To produce tests first we need to define requirements to tested application. Let’s start by listing our requirements for commercial paper chaincode:

  • It should allow the issuer to issue commercial paper
  • It should allow the participant to buy commercial paper
  • It should allow the owner to redeem commercial paper

Chaincode interface functions described in file chaincode.go, so we can see all possible operations (transactions) with chaincode data:

    Query("list", queryCPapers).

    // Get method has 2 params - commercial paper primary key components
    Query("get", queryCPaper, defparam.Proto(&schema.CommercialPaperId{})).
    Query("getByExternalId", queryCPaperGetByExternalId, param.String("externalId")).

    // txn methods
    Invoke("issue", invokeCPaperIssue, defparam.Proto(&schema.IssueCommercialPaper{})).
    Invoke("buy", invokeCPaperBuy, defparam.Proto(&schema.BuyCommercialPaper{})).
    Invoke("redeem", invokeCPaperRedeem, defparam.Proto(&schema.RedeemCommercialPaper{})).
    Invoke("delete", invokeCPaperDelete, defparam.Proto(&schema.CommercialPaperId{}))

Getting started

Before you begin, be sure to get CCKit:

git clone git@github.com:hyperledger-labs/cckit.git

This will fetch and install the CCKit package with examples. After that we need to install the dependencies using command:

go mod vendor

Creating test suite

Testing in Go

Go has a built-in testing command called go test and a package testing which gives a minimal but complete testing experience. In our example we use Ginkgo - BDD-style Go testing framework, built on Go’s testing package, and allows to write readable tests in an efficient manner. It is best paired with the Gomega matcher library, but is designed to be matcher-agnostic.

As with popular BDD frameworks in other languages, Ginkgo allows you to group tests in Describe and Context container blocks. Ginkgo provides the It and Specify blocks which can hold your assertions. It also comes with handy structural utilities such as BeforeSuite, AfterSuite, etc that allows you to separate test configuration from test creation, and improve code reuse.

Ginkgo also comes with support for writing asynchronous tests. This makes testing code that use channels with chaincode events as easy as testing synchronous code.

Test package

To write a new test suite, create a file whose name ends _test.go that contains the TestXxx functions, in our case will be cpaper_extended/chaincode_test.go

Using separate package with tests cpaper_extended_test instead of cpaper_extended allows us to respect the encapsulation of the chaincode package: your tests will need to import chaincode and access it from the outside. You cannot fiddle around with the internals, instead you focus on the exposed chaincode interface.

Import matchers and helpers

To get started, we need to import the matcher functionality from the Ginkgo testing package so we can use different comparison mechanisms like comparing response objects or status codes.

We import the ginkgo and gomega packages with the . namespace, so that we can use functions from these packages without the package prefix. This allows us to use Describe instead of ginkgo.Describe, and Equal instead of gomega.Equal.

Bootstrap

The call to RegisterFailHandler registers a handler, the Fail function from the Ginkgo package. This creates the coupling between Ginkgo and Gomega.

Test suite bootstrap example:

package main

import (
	"fmt"
	"testing"
	"github.com/hyperledger-labs/cckit/examples/insurance/app"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	testcc "github.com/hyperledger-labs/cckit/testing"
	expectcc "github.com/hyperledger-labs/cckit/testing/expect"
)

func TestCommercialPaper(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Commercial paper suite")
}

var _ = Describe(`Commercial paper`, func() {
	

}
Test structure

This particular test specification can be written using Ginkgo as follows:

var _ = Describe(`CommercialPaper`, func() {
	
            Describe("Commercial Paper lifecycle", func() {
            
                It("Allow issuer to issue new commercial paper", func() { ... }
                
                It("Allow issuer to get commercial paper by composite primary key", func() { ... }
                
                It("Allow issuer to get commercial paper by unique key", func() { ... }
                
                It("Allow issuer to get a list of commercial papers", func() { ... }
                
                It("Allow buyer to buy commercial paper", func() { ... }
                
                It("Allow buyer to redeem commercial paper", func() { ... }
                
                It("Allow issuer to delete commercial paper", func() { ... }
            }
}
Implementing tests

Now we go in depth to see how to create test functions specifically for chaincode development using MockStub features.

Creating chaincode instance

Tests suite usually starts with creating a new instance of chaincode, or we can also instantiate a new chaincode instance before every test spec. This depends on how and what we want to test. In this example we instantiate a global commercial paper chaincode that can be used in multiple test specs.

	paperChaincode := testcc.NewMockStub(
		// chaincode name
		`commercial_paper`,
		// chaincode implementation, supports Chaincode interface with Init and Invoke methods
		cpaper_extended.NewCC(),
	)
Test chaincode Init method

All chaincode invocation (via SDK to blockchain peer or to MockStub) resulted as peer.Response structure:

type Response struct {
	// A status code that should follow the HTTP status codes.
	Status int32 
	// A message associated with the response code.
	Message string 
	// A payload that can be used to include metadata with this response.
	Payload              []byte   
}

During tests we can check Response attribute:

  • Status (error or success)
  • Message string (contains error description)
  • Payload contents (marshaled JSON or Protobuf)

Testing package contains multiple helpers / wrappers on ginkgo expect functions.

Most frequently used helpers are:

  • ResponseOk (response peer.Response) expects that peer response contains ok status code(200). Optionally you can pass either a string or an OmegaMatcher any available matcher provided by Gomega, to check, for example, if the error contains a specific substring.
  • ResponseError (response peer.Response) expects that peer response contains error status code (500). Optionally you can pass either a string, an error or an OmegaMatcher as for ResponseOk
  • PayloadIs(response peer.Response, target **interface{}) expects that peer response contains ok status code (200) and converts response to target type using CCKit convert package

For example we can simply test that Init method (invoked when the chaincode is initialised) returns successful status code:

BeforeSuite(func() {
    // Init chaincode with admin identity

    adminIdentity, err := testcc.IdentityFromFile(MspName, `testdata/admin.pem`, ioutil.ReadFile)
    Expect(err).NotTo(HaveOccurred())

    expectcc.ResponseOk(
        paperChaincode.
            From(adminIdentity).
            Init())
})

Test the Issue method

We expect that invocation of issue chaincode method will result in:

  • response with Ok status
  • event IssueCommercialPaper is fired

In the test we can invoke issue method via MockStub, check response status and check chaincode event. Chaincode events can be receive from chaincodeEventsChannel. The BeEquivalentTo method of the expect functionality comes in handy to compare the event payload.

It("Allow issuer to issue new commercial paper", func(done Done) {
    //input payload for chaincode method
    issueTransactionData := &schema.IssueCommercialPaper{
        Issuer:       IssuerName,
        PaperNumber:  "0001",
        IssueDate:    ptypes.TimestampNow(),
        MaturityDate: testcc.MustProtoTimestamp(time.Now().AddDate(0, 2, 0)),
        FaceValue:    100000,
        ExternalId:   "EXT0001",
    }

    // we expect tha `issue` method invocation with particular input payload returns response with 200 code
    // &schema.IssueCommercialPaper wil automatically converts to bytes via proto.Marshall function
    expectcc.ResponseOk(
        paperChaincode.Invoke(`issue`, issueTransactionData))

    // Validate event has been emitted with the transaction data
    Expect(<-paperChaincode.ChaincodeEventsChannel).To(BeEquivalentTo(&peer.ChaincodeEvent{
        EventName: `IssueCommercialPaper`,
        Payload:   testcc.MustProtoMarshal(issueTransactionData),
    }))

    // Clear events channel after a test case that emits an event
    paperChaincode.ClearEvents()
    close(done)
}, 0.1)

This test will block until a response is received over the channel paperChaincode.ChaincodeEventsChannel (chaincode event). A deadlock or timeout is a common failure mode for tests like this. A common pattern in such situations is to add a select statement at the bottom of the function and include a <-time.After(X) channel to specify a timeout. Ginkgo has this pattern built in. The body functions in all non-container blocks (It , BeforeEache etc ) can take an optional done Done argument.

Done is a chan interface{}. When Ginkgo detects that the done Done argument has been requested it runs the body function as a goroutine, wrapping it with the necessary logic to apply a timeout assertion. You must either close the done channel, or send something (anything) to it to tell Ginkgo that your test has ended. If your test doesn’t end after a timeout period, Ginkgo will fail the test and move on the next one.

The default timeout is 1 second. You can modify this timeout by passing a float64 (in seconds) after the body function. In this example we set the timeout to 0.1 second.

Test the Get method

We expect that invocation of get chaincode method will result in:

  • response with Ok status
  • response payload is marshaled *schema.CommercialPaper with certain attributes values

PayloadIs allows to check response status and converts to *schema.CommercialPaper, then Expect helps to check equality of received data with expected values:

It("Allow issuer to get commercial paper by composite primary key", func() {
    queryResponse := paperChaincode.Query("get", &schema.CommercialPaperId{
        Issuer:      IssuerName,
        PaperNumber: "0001",
    })

    // we expect that returned []byte payload can be unmarshalled to *schema.CommercialPaper entity
    paper := expectcc.PayloadIs(queryResponse, &schema.CommercialPaper{}).(*schema.CommercialPaper)

    Expect(paper.Issuer).To(Equal(IssuerName))
    Expect(paper.Owner).To(Equal(IssuerName))
    Expect(paper.State).To(Equal(schema.CommercialPaper_ISSUED))
    Expect(paper.PaperNumber).To(Equal("0001"))
    Expect(paper.FaceValue).To(BeNumerically("==", 100000))
})
Test chaincode permissioning

Each user can have different permissions to work with chaincode methods. All permissioning is based on user certificates and Membership Service Provider Identifiers, which means that permissions always correspond to an X.509 certificate.

The simple car contains logic to control who can invoke carRegister method. Test use From MockStub method to set certificate and MSP id of invoker


	It("Disallow non authority to add information about car", func() {
			//invoke chaincode method from non authority actor
			expectcc.ResponseError(
				cc.From(actors[`someone`]).Invoke(`carRegister`, cars.Payloads[0]),
				ContainSubstring(owner.ErrOwnerOnly.Error())) // expect "only owner" error
		})

	It("Allow authority to add information about car", func() {
			//invoke chaincode method from authority actor
			expectcc.ResponseOk(cc.From(actors[`authority`]).Invoke(`carRegister`, cars.Payloads[0]))
    })

Debugging operations with chaincode

During test execution you may need to debug operations in chaincode method handler. CCKit supports Hyperledger Fabric Chaincode Logger and its options, so you can use CORE_CHAINCODE_LOGGING_LEVEL environment variable. CCKit chaincode state wrapper outputs debug severity level messages, for example:

## CORE_CHAINCODE_LOGGING_LEVEL=debug go test
Running Suite: Commercial Paper Suite
=====================================
Random Seed: 1559680577
Will run 7 of 7 specs

2019-06-04 ... [commercial_paper] Debug -> DEBU 001 router handler:  init
2019-06-04 ... [commercial_paper] Debugf -> DEBU 002 state KEY: [OWNER]
2019-06-04 ... [commercial_paper] Debugf -> DEBU 003 state check EXISTENCE OWNER
2019-06-04 ... [commercial_paper] Debugf -> DEBU 007 state PUT with string key: OWNER
2019-06-04 ... [commercial_paper] Debug -> DEBU 008 router handler:  issue
2019-06-04 ... [commercial_paper] Debugf -> DEBU 009 state KEY: [_idx CommercialPaper ExternalId EXT0001]
2019-06-04 ... [commercial_paper] Debugf -> DEBU 00a state check EXISTENCE _idxCommercialPaperExternalIdEXT0001
2019-06-04 ... [commercial_paper] Debugf -> DEBU 00b state KEY: [_idx CommercialPaper ExternalId EXT0001]
2019-06-04 ... [commercial_paper] Debugf -> DEBU 00c state PUT with string key: _idxCommercialPaperExternalIdEXT0001

It shows there are several operations with chaincode state performed while chaincode execution:

  • checked existence entry with OWNER key while handling init chaincode method
  • putted state entry with OWNER key
  • putted state entry with [_idx CommercialPaper ExternalId EXT0001] while handling issue chaincode method (no uniq index for Commercial entry entity) ...

Running test

To run the test suite you have to simply run the command in the repository where the test suite is located:

go test

if you have any failures in test you can use -ginkgo.failFast option to disable running additional tests after any test fails.

Conclusion

Chaincode MockStub is really useful as it allows a developer to test his chaincode without starting the network every time. This reduces development time as he can use a test driven development (TDD) approach where he doesn’t need to start the network (this takes +- 40-80 seconds depending on the specs of the computer).

Documentation

Index

Constants

View Source
const EventChannelBufferSize = 100

Variables

View Source
var (
	ErrPeerInvoke                   = errors.New(`invoke failed`)
	ErrPeerQuery                    = errors.New(`query failed`)
	ChaincodeSimulationErrorReponse = &peer.Response{
		Status: shim.ERROR, Message: `chaincode simulation produced error response`}
)
View Source
var (
	// ErrChaincodeNotExists occurs when attempting to invoke a nonexostent external chaincode
	ErrChaincodeNotExists = errors.New(`chaincode not exists`)
	// ErrUnknownFromArgsType occurs when attempting to set unknown args in From func
	ErrUnknownFromArgsType = errors.New(`unknown args type to cckit.MockStub.From func`)
	// ErrKeyAlreadyExistsInTransientMap occurs when attempting to set existing key in transient map
	ErrKeyAlreadyExistsInTransientMap = errors.New(`key already exists in transient map`)
)

Functions

func CreatorFromSigningIdentity

func CreatorFromSigningIdentity(creator msp.SigningIdentity) (mspID string, certPEM []byte, err error)

func IdentityFromFile

func IdentityFromFile(mspID string, file string, readFile ReadFile) (*identity.CertIdentity, error)

IdentityFromFile returns Identity struct containing mspId and certificate

func MustConvertFromBytes

func MustConvertFromBytes(bb []byte, target interface{}, fromBytesConverter serialize.FromBytesConverter) interface{}

func MustIdentityFromPem

func MustIdentityFromPem(mspID string, certPEM []byte) *identity.CertIdentity

func MustJSONMarshal

func MustJSONMarshal(val interface{}) []byte

func MustProtoMarshal

func MustProtoMarshal(pb proto.Message) []byte

MustProtoMarshal marshals proto.Message, panics if error

func MustProtoTimestamp

func MustProtoTimestamp(t time.Time) *timestamp.Timestamp

MustProtoTimestamp creates proto.Timestamp, panics if error

func MustProtoUnmarshal

func MustProtoUnmarshal(bb []byte, pm proto.Message) proto.Message

MustProtoUnmarshal unmarshals proto.Message, panics if error

func MustTime

func MustTime(s string) *timestamp.Timestamp

MustTime returns Timestamp for date string or panic

func PanicIfError

func PanicIfError(err error)

PanicIfError

func TransformCreator

func TransformCreator(txCreator ...interface{}) (mspID string, certPEM []byte, err error)

TransformCreator transforms arbitrary tx creator (pmsp.SerializedIdentity etc) to mspID string, certPEM []byte,

Types

type ChaincodeEvent

type ChaincodeEvent struct {
	// contains filtered or unexported fields
}

func (*ChaincodeEvent) Block

func (eb *ChaincodeEvent) Block() uint64

func (*ChaincodeEvent) Event

func (eb *ChaincodeEvent) Event() *peer.ChaincodeEvent

func (*ChaincodeEvent) TxTimestamp

func (eb *ChaincodeEvent) TxTimestamp() *timestamp.Timestamp

type ChannelMockStubs

type ChannelMockStubs map[string]*MockStub

type ChannelsMockStubs

type ChannelsMockStubs map[string]ChannelMockStubs

type CreatorTransformer

type CreatorTransformer func(...interface{}) (mspID string, certPEM []byte, err error)

type EventSubscription

type EventSubscription struct {
	// contains filtered or unexported fields
}

func (*EventSubscription) Close

func (es *EventSubscription) Close() error

func (*EventSubscription) Errors

func (es *EventSubscription) Errors() chan error

func (*EventSubscription) Events

func (es *EventSubscription) Events() chan *peer.ChaincodeEvent

type Identities

type Identities map[string]identity.Identity

func IdentitiesFromFiles

func IdentitiesFromFiles(mspID string, files map[string]string, readFile ReadFile) (Identities, error)

IdentitiesFromFiles returns map of CertIdentity, loaded from PEM files

func IdentitiesFromPem

func IdentitiesFromPem(mspID string, certPEMs map[string][]byte) (ids Identities, err error)

IdentitiesFromPem returns CertIdentity (MSP ID and X.509 cert) converted PEM content

func MustIdentitiesFromFiles

func MustIdentitiesFromFiles(mspID string, files map[string]string, readFile ReadFile) Identities

MustIdentitiesFromFiles

type IdentitySample

type IdentitySample interface {
	SigningIdentity() msp.SigningIdentity
}

type InvokeMutator

type InvokeMutator func(
	sdk sdk.SDK,
	ctx context.Context,
	channel string,
	chaincode string,
	args [][]byte,
	identity msp.SigningIdentity,
	transArgs map[string][]byte,
	txWaiterType string) (res *peer.Response, chaincodeTx string, err error)

type MockStateRangeQueryPagedIterator

type MockStateRangeQueryPagedIterator struct {
	Closed  bool
	Stub    *MockStub
	Keys    *list.List
	Current *list.Element
	// contains filtered or unexported fields
}

MockStateRangeQueryPagedIterator represents paged version of shimtest.MockStateRangeQueryIterator

func NewMockStatesRangeQueryPagedIterator

func NewMockStatesRangeQueryPagedIterator(stub *MockStub, startKey string, endKey string, pageSize int32, bookmark string) *MockStateRangeQueryPagedIterator

NewMockStatesRangeQueryPagedIterator creates iterator starting from bookmark and limited by pageSize

func (*MockStateRangeQueryPagedIterator) Close

func (*MockStateRangeQueryPagedIterator) HasNext

func (iter *MockStateRangeQueryPagedIterator) HasNext() bool

func (*MockStateRangeQueryPagedIterator) Len

func (*MockStateRangeQueryPagedIterator) Next

func (*MockStateRangeQueryPagedIterator) NextBookmark

func (iter *MockStateRangeQueryPagedIterator) NextBookmark() string

type MockStub

type MockStub struct {
	shimtest.MockStub

	StateBuffer []*StateItem // buffer for state changes during transaction
	Serializer  serialize.Serializer

	TxResult peer.Response // last tx result

	ClearCreatorAfterInvoke bool

	Invokables map[string]*MockStub // invokable this version of MockStub

	LastTxID       string
	ChaincodeEvent *peer.ChaincodeEvent // event in last tx

	PrivateKeys map[string]*list.List
	// contains filtered or unexported fields
}

MockStub replacement of shim.MockStub with creator mocking facilities

func NewMockStub

func NewMockStub(name string, cc shim.Chaincode) *MockStub

NewMockStub creates chaincode imitation

func (*MockStub) AddTransient

func (stub *MockStub) AddTransient(transient map[string][]byte) *MockStub

AddTransient adds key-value pairs to transient map

func (*MockStub) ClearEvents

func (stub *MockStub) ClearEvents()

ClearEvents clears chaincode events channel

func (*MockStub) DelPrivateData

func (stub *MockStub) DelPrivateData(collection string, key string) error

DelPrivateData mocked

func (*MockStub) DelState

func (stub *MockStub) DelState(key string) error

func (*MockStub) DumpStateBuffer

func (stub *MockStub) DumpStateBuffer()

func (*MockStub) EventSubscription

func (stub *MockStub) EventSubscription(from ...int64) (events chan *peer.ChaincodeEvent, closer func() error)

EventSubscription for new or all events

func (*MockStub) EventsList

func (stub *MockStub) EventsList() []*peer.ChaincodeEvent

func (*MockStub) From

func (stub *MockStub) From(txCreator ...interface{}) *MockStub

From mock tx creator

func (*MockStub) GetArgs

func (stub *MockStub) GetArgs() [][]byte

GetArgs mocked args

func (*MockStub) GetCreator

func (stub *MockStub) GetCreator() ([]byte, error)

GetCreator mocked

func (*MockStub) GetFunctionAndParameters

func (stub *MockStub) GetFunctionAndParameters() (function string, params []string)

GetFunctionAndParameters mocked

func (*MockStub) GetPrivateDataByPartialCompositeKey

func (stub *MockStub) GetPrivateDataByPartialCompositeKey(collection, objectType string, attributes []string) (shim.StateQueryIteratorInterface, error)

GetPrivateDataByPartialCompositeKey mocked

func (*MockStub) GetStateByPartialCompositeKeyWithPagination

func (stub *MockStub) GetStateByPartialCompositeKeyWithPagination(objectType string, keys []string,
	pageSize int32, bookmark string) (shim.StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)

GetStateByPartialCompositeKeyWithPagination mocked

func (*MockStub) GetStateByRangeWithPagination

func (stub *MockStub) GetStateByRangeWithPagination(startKey, endKey string, pageSize int32,
	bookmark string) (shim.StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)

GetStateByRangeWithPagination mocked

func (*MockStub) GetStringArgs

func (stub *MockStub) GetStringArgs() []string

GetStringArgs get mocked args as strings

func (*MockStub) GetTransient

func (stub *MockStub) GetTransient() (map[string][]byte, error)

func (*MockStub) Init

func (stub *MockStub) Init(iargs ...interface{}) peer.Response

Init func of chaincode - sugared version with autogenerated tx uuid

func (*MockStub) InitBytes

func (stub *MockStub) InitBytes(args ...[]byte) peer.Response

InitBytes init func with ...[]byte args

func (*MockStub) Invoke

func (stub *MockStub) Invoke(funcName string, iargs ...interface{}) peer.Response

Invoke sugared invoke function with autogenerated tx uuid

func (*MockStub) InvokeBytes

func (stub *MockStub) InvokeBytes(args ...[]byte) peer.Response

InvokeBytes mock invoke with autogenerated tx uuid

func (*MockStub) InvokeChaincode

func (stub *MockStub) InvokeChaincode(chaincodeName string, args [][]byte, channel string) peer.Response

InvokeChaincode using another MockStub

func (*MockStub) MockCreator

func (stub *MockStub) MockCreator(mspID string, certPEM []byte)

MockCreator of tx

func (*MockStub) MockInit

func (stub *MockStub) MockInit(uuid string, args [][]byte) peer.Response

MockInit mocked init function

func (*MockStub) MockInvoke

func (stub *MockStub) MockInvoke(uuid string, args [][]byte) peer.Response

MockInvoke

func (*MockStub) MockPeerChaincode

func (stub *MockStub) MockPeerChaincode(invokableChaincodeName string, otherStub *MockStub)

MockPeerChaincode link to another MockStub

func (*MockStub) MockQuery

func (stub *MockStub) MockQuery(uuid string, args [][]byte) peer.Response

MockQuery

func (*MockStub) MockTransactionEnd

func (stub *MockStub) MockTransactionEnd(uuid string)

func (*MockStub) MockTransactionStart

func (stub *MockStub) MockTransactionStart(uuid string)

func (*MockStub) MockedPeerChaincodes

func (stub *MockStub) MockedPeerChaincodes() []string

MockedPeerChaincodes returns names of mocked chaincodes, available for invoke from current stub

func (*MockStub) PutPrivateData

func (stub *MockStub) PutPrivateData(collection string, key string, value []byte) error

PutPrivateData mocked

func (*MockStub) PutState

func (stub *MockStub) PutState(key string, value []byte) error

PutState wrapped functions puts state items in queue and dumps to state after invocation

func (*MockStub) Query

func (stub *MockStub) Query(funcName string, iargs ...interface{}) peer.Response

func (*MockStub) QueryBytes

func (stub *MockStub) QueryBytes(args ...[]byte) peer.Response

QueryBytes mock query with autogenerated tx uuid

func (*MockStub) RegisterCreatorTransformer

func (stub *MockStub) RegisterCreatorTransformer(creatorTransformer CreatorTransformer) *MockStub

RegisterCreatorTransformer that transforms creator data to MSP_ID and X.509 certificate

func (*MockStub) SetArgs

func (stub *MockStub) SetArgs(args [][]byte)

SetArgs set mocked args

func (*MockStub) SetEvent

func (stub *MockStub) SetEvent(name string, payload []byte) error

SetEvent sets chaincode event

func (*MockStub) WithChannel

func (stub *MockStub) WithChannel(channelID string) *MockStub

WithChannel sets channel id

func (*MockStub) WithTransient

func (stub *MockStub) WithTransient(transient map[string][]byte) *MockStub

WithTransient sets transient map

type MockedPeer

type MockedPeer struct {
	// channel name -> chaincode name
	ChannelCC ChannelsMockStubs
	// contains filtered or unexported fields
}

func NewPeer

func NewPeer() *MockedPeer

NewPeer implements Peer interface

func (*MockedPeer) Blocks

func (m *MockedPeer) Blocks(
	ctx context.Context,
	channelName string,
	identity msp.SigningIdentity,
	blockRange ...int64,
) (blockChan <-chan *common.Block, closer func() error, err error)

func (*MockedPeer) Chaincode

func (mp *MockedPeer) Chaincode(channel string, chaincode string) (*MockStub, error)

func (*MockedPeer) CurrentIdentity

func (mp *MockedPeer) CurrentIdentity() msp.SigningIdentity

func (*MockedPeer) Events

func (mp *MockedPeer) Events(
	ctx context.Context,
	channel string,
	chaincode string,
	identity msp.SigningIdentity,
	blockRange ...int64,
) (events chan interface {
	Event() *peer.ChaincodeEvent
	Block() uint64
	TxTimestamp() *timestamp.Timestamp
}, closer func() error, err error)

func (*MockedPeer) Invoke

func (mp *MockedPeer) Invoke(
	ctx context.Context,
	channel string,
	chaincode string,
	args [][]byte,
	identity msp.SigningIdentity,
	transArgs map[string][]byte,
	txWaiterType string) (res *peer.Response, chaincodeTx string, err error)

func (*MockedPeer) Query

func (mp *MockedPeer) Query(
	ctx context.Context,
	channel string,
	chaincode string,
	args [][]byte,
	identity msp.SigningIdentity,
	transArgs map[string][]byte) (*peer.Response, error)

func (*MockedPeer) WithChannel

func (mp *MockedPeer) WithChannel(channel string, mockStubs ...*MockStub) *MockedPeer

type MockedPeerDecorator

type MockedPeerDecorator struct {
	SDK sdk.SDK

	InvokeMutator InvokeMutator
	QueryMutator  QueryMutator
}

func NewPeerDecorator

func NewPeerDecorator(sdk sdk.SDK) *MockedPeerDecorator

func (*MockedPeerDecorator) CurrentIdentity

func (mpd *MockedPeerDecorator) CurrentIdentity() msp.SigningIdentity

func (*MockedPeerDecorator) Events

func (mpd *MockedPeerDecorator) Events(
	ctx context.Context,
	channel string,
	chaincode string,
	identity msp.SigningIdentity,
	blockRange ...int64,
) (events chan interface {
	Event() *peer.ChaincodeEvent
	Block() uint64
	TxTimestamp() *timestamp.Timestamp
}, closer func() error, err error)

func (*MockedPeerDecorator) FailChaincode

func (mpd *MockedPeerDecorator) FailChaincode(chaincodes ...string)

func (*MockedPeerDecorator) FailInvoke

func (mpd *MockedPeerDecorator) FailInvoke(chaincodes ...string)

func (*MockedPeerDecorator) FailQuery

func (mpd *MockedPeerDecorator) FailQuery(chaincodes ...string)

func (*MockedPeerDecorator) Invoke

func (mpd *MockedPeerDecorator) Invoke(
	ctx context.Context,
	channel string,
	chaincode string,
	args [][]byte,
	identity msp.SigningIdentity,
	transArgs map[string][]byte,
	txWaiterType string) (res *peer.Response, chaincodeTx string, err error)

func (*MockedPeerDecorator) Query

func (mpd *MockedPeerDecorator) Query(
	ctx context.Context,
	channel string,
	chaincode string,
	args [][]byte,
	identity msp.SigningIdentity,
	transArgs map[string][]byte) (*peer.Response, error)

type PrivateMockStateRangeQueryIterator

type PrivateMockStateRangeQueryIterator struct {
	Closed     bool
	Stub       *MockStub
	StartKey   string
	EndKey     string
	Current    *list.Element
	Collection string
}

func NewPrivateMockStateRangeQueryIterator

func NewPrivateMockStateRangeQueryIterator(stub *MockStub, collection string, startKey string, endKey string) *PrivateMockStateRangeQueryIterator

func (*PrivateMockStateRangeQueryIterator) Close

Close closes the range query iterator. This should be called when done reading from the iterator to free up resources.

func (*PrivateMockStateRangeQueryIterator) HasNext

func (iter *PrivateMockStateRangeQueryIterator) HasNext() bool

HasNext returns true if the range query iterator contains additional keys and values.

func (*PrivateMockStateRangeQueryIterator) Next

Next returns the next key and value in the range query iterator.

type QueryMutator

type QueryMutator func(
	sdk sdk.SDK,
	ctx context.Context,
	channel string,
	chaincode string,
	args [][]byte,
	identity msp.SigningIdentity,
	transArgs map[string][]byte) (*peer.Response, error)

type ReadFile

type ReadFile func(string) ([]byte, error)

type StateItem

type StateItem struct {
	Key    string
	Value  []byte
	Delete bool
}

type TxHandler

type TxHandler struct {
	MockStub *MockStub

	Logger  *zap.Logger
	Context router.Context
	// contains filtered or unexported fields
}

func NewTxHandler

func NewTxHandler(name string, serializer ...*serialize.GenericSerializer) (*TxHandler, router.Context)

func (*TxHandler) Expect

func (p *TxHandler) Expect(res interface{}, err error) *expect.TxRes

Expect returns assertion helper

func (*TxHandler) From

func (p *TxHandler) From(creator ...interface{}) *TxHandler

func (*TxHandler) Init

func (p *TxHandler) Init(txHdl func(ctx router.Context) (interface{}, error)) *TxResult

func (*TxHandler) Invoke

func (p *TxHandler) Invoke(invoke func(ctx router.Context) (interface{}, error)) *TxResult

Invoke emulates chaincode invocation and returns transaction result

func (*TxHandler) SetTxResult

func (p *TxHandler) SetTxResult(err error)

SetTxResult can be used for set txResult error during Tx

func (*TxHandler) Tx

func (p *TxHandler) Tx(tx func())

Tx emulates chaincode invocation

func (*TxHandler) TxEvent

func (p *TxHandler) TxEvent() *peer.ChaincodeEvent

TxEvent returns last tx event

func (*TxHandler) TxFunc

func (p *TxHandler) TxFunc(tx func()) func()

TxFunc returns tx closure, can be used directly as ginkgo func

func (*TxHandler) TxTimestamp

func (p *TxHandler) TxTimestamp() *timestamp.Timestamp

TxTimestamp returns last tx timestamp

type TxResult

type TxResult struct {
	Result interface{}
	Err    error
	Event  *peer.ChaincodeEvent
}

func (*TxResult) Expect

func (r *TxResult) Expect() *expect.TxRes

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL