diff --git a/.golangci.yml b/.golangci.yml
index 1e52fc3d9..b6f06ac84 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -19,6 +19,7 @@ linters:
- govet
- ineffassign
- misspell
+ - testifylint
- typecheck
- unused
diff --git a/.mockery.yaml b/.mockery.yaml
new file mode 100644
index 000000000..1c9454373
--- /dev/null
+++ b/.mockery.yaml
@@ -0,0 +1,13 @@
+with-expecter: true
+exported: true
+filename: "{{.InterfaceName | lower}}_mock_test.go"
+mockname: "Mock{{.InterfaceName | firstUpper}}"
+unroll-variadic: false
+packages:
+ google.golang.org/grpc:
+ config:
+ dir: pkg/client
+ outpkg: client
+ interfaces:
+ ClientConnInterface:
+ ClientStream:
diff --git a/Makefile b/Makefile
index 24c00a595..96fe72f9a 100644
--- a/Makefile
+++ b/Makefile
@@ -13,6 +13,10 @@ scenario_dir := $(base_dir)/scenario
go_bin_dir := $(shell go env GOPATH)/bin
+mockery_version := 2.46.2
+kernel_name := $(shell uname -s)
+machine_hardware := $(shell uname -m)
+
export SOFTHSM2_CONF ?= $(base_dir)/softhsm2.conf
TMPDIR ?= /tmp
@@ -130,10 +134,18 @@ scan-java-osv-scanner:
go install github.com/google/osv-scanner/cmd/osv-scanner@latest
osv-scanner scan --lockfile='$(java_dir)/pom.xml'
+.PHONY: install-mockery
+install-mockery:
+ curl --fail --location \
+ 'https://github.com/vektra/mockery/releases/download/v$(mockery_version)/mockery_$(mockery_version)_$(kernel_name)_$(machine_hardware).tar.gz' \
+ | tar -C '$(go_bin_dir)' -xzf - mockery
+
+$(go_bin_dir)/mockery:
+ $(MAKE) install-mockery
+
.PHONY: generate
-generate:
- go install go.uber.org/mock/mockgen@latest
- go generate '$(go_dir)/...'
+generate: $(go_bin_dir)/mockery clean-generated
+ cd '$(base_dir)' && mockery
.PHONY: vendor-chaincode
vendor-chaincode:
diff --git a/go.mod b/go.mod
index e1dc34340..ae4125ec4 100644
--- a/go.mod
+++ b/go.mod
@@ -4,13 +4,13 @@ go 1.22.0
require (
github.com/cucumber/godog v0.14.1
- github.com/hyperledger/fabric-protos-go-apiv2 v0.3.3
+ github.com/google/go-cmp v0.6.0
+ github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4
github.com/miekg/pkcs11 v1.1.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
- go.uber.org/mock v0.4.0
- golang.org/x/crypto v0.27.0
- google.golang.org/grpc v1.67.0
+ golang.org/x/crypto v0.28.0
+ google.golang.org/grpc v1.67.1
google.golang.org/protobuf v1.34.2
)
@@ -23,9 +23,10 @@ require (
github.com/hashicorp/go-memdb v1.3.4 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/stretchr/objx v0.5.2 // indirect
golang.org/x/net v0.28.0 // indirect
- golang.org/x/sys v0.25.0 // indirect
- golang.org/x/text v0.18.0 // indirect
+ golang.org/x/sys v0.26.0 // indirect
+ golang.org/x/text v0.19.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index f89ff07ec..7182b770b 100644
--- a/go.sum
+++ b/go.sum
@@ -27,8 +27,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
-github.com/hyperledger/fabric-protos-go-apiv2 v0.3.3 h1:Xpd6fzG/KjAOHJsq7EQXY2l+qi/y8muxBaY7R6QWABk=
-github.com/hyperledger/fabric-protos-go-apiv2 v0.3.3/go.mod h1:2pq0ui6ZWA0cC8J+eCErgnMDCS1kPOEYVY+06ZAK0qE=
+github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4 h1:YJrd+gMaeY0/vsN0aS0QkEKTivGoUnSRIXxGJ7KI+Pc=
+github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4/go.mod h1:bau/6AJhvEcu9GKKYHlDXAxXKzYNfhP6xu2GXuxEcFk=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -46,26 +46,26 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
-go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
-golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
-golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
+golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
+golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
-golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
-golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
-golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
+golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
+golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
-google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
-google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
+google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
+google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/java/pom.xml b/java/pom.xml
index 4eb670dcb..c8bdf588d 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -40,7 +40,7 @@
8
1.78.1
${skipTests}
- 7.5.0
+ 7.6.0
@@ -48,29 +48,29 @@
io.cucumber
cucumber-bom
- 7.19.0
+ 7.20.0
pom
import
org.junit
junit-bom
- 5.11.0
+ 5.11.2
pom
import
io.grpc
grpc-bom
- 1.68.0
+ 1.67.1
pom
import
-
+
com.google.protobuf
protobuf-bom
- 3.25.5
+ 4.28.2
pom
import
@@ -97,7 +97,7 @@
org.mockito
mockito-core
- 5.13.0
+ 5.14.1
test
@@ -146,7 +146,7 @@
org.hyperledger.fabric
fabric-protos
- 0.3.3
+ 0.3.4
@@ -530,7 +530,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 3.2.5
+ 3.2.6
sign-artifacts
diff --git a/node/package.json b/node/package.json
index ca5f18cae..539890521 100644
--- a/node/package.json
+++ b/node/package.json
@@ -57,6 +57,6 @@
"ts-jest": "^29.2.4",
"typedoc": "^0.26.6",
"typescript": "~5.5.4",
- "typescript-eslint": "~8.5.0"
+ "typescript-eslint": "^8.7.0"
}
}
diff --git a/pkg/client/blockevents_test.go b/pkg/client/blockevents_test.go
index dd28af3af..2fd7f08d1 100644
--- a/pkg/client/blockevents_test.go
+++ b/pkg/client/blockevents_test.go
@@ -5,369 +5,17 @@ package client
import (
"context"
- "errors"
"testing"
- "github.com/hyperledger/fabric-gateway/pkg/internal/test"
"github.com/hyperledger/fabric-protos-go-apiv2/common"
- "github.com/hyperledger/fabric-protos-go-apiv2/msp"
- "github.com/hyperledger/fabric-protos-go-apiv2/orderer"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
- "google.golang.org/grpc"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/proto"
)
-func AssertValidBlockEventRequestHeader(t *testing.T, payload *common.Payload, expectedChannel string) {
- channelHeader := &common.ChannelHeader{}
- test.AssertUnmarshal(t, payload.GetHeader().GetChannelHeader(), channelHeader)
-
- require.Equal(t, expectedChannel, channelHeader.GetChannelId(), "channel name")
-
- signatureHeader := &common.SignatureHeader{}
- test.AssertUnmarshal(t, payload.GetHeader().GetSignatureHeader(), signatureHeader)
-
- expectedCreator := &msp.SerializedIdentity{
- Mspid: TestCredentials.Identity().MspID(),
- IdBytes: TestCredentials.Identity().Credentials(),
- }
- actualCreator := &msp.SerializedIdentity{}
- test.AssertUnmarshal(t, signatureHeader.GetCreator(), actualCreator)
- test.AssertProtoEqual(t, expectedCreator, actualCreator)
-}
-
func TestBlockEvents(t *testing.T) {
- t.Run("Returns connect error", func(t *testing.T) {
- expected := NewStatusError(t, codes.Aborted, "BLOCK_EVENTS_ERROR")
- mockClient := NewMockDeliverClient(gomock.NewController(t))
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(nil, expected)
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.BlockEvents(ctx)
-
- require.Equal(t, status.Code(expected), status.Code(err), "status code")
- require.ErrorIs(t, err, expected, "error type: %T", err)
- require.ErrorContains(t, err, expected.Error(), "message")
- })
-
- t.Run("Sends valid request with default start position", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.BlockEvents(ctx)
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_NextCommit{
- NextCommit: &orderer.SeekNextCommit{},
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with specified start block number", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.BlockEvents(ctx, WithStartBlock(418))
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 418,
- },
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Uses specified start block instead of unset checkpoint", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
-
- _, err := network.BlockEvents(ctx, WithStartBlock(418), WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 418,
- },
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Uses checkpoint block instead of specified start block", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
- checkpointer.CheckpointBlock(uint64(500))
-
- _, err := network.BlockEvents(ctx, WithStartBlock(418), WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 501,
- },
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Uses checkpoint block zero with set transaction ID instead of specified start block", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
- blockNumber := uint64(0)
- checkpointer.CheckpointTransaction(blockNumber, "transctionId")
-
- _, err := network.BlockEvents(ctx, WithStartBlock(418), WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: blockNumber,
- },
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Uses default start position with unset checkpoint and no start block", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
-
- _, err := network.BlockEvents(ctx, WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_NextCommit{
- NextCommit: &orderer.SeekNextCommit{},
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Closes event channel on receive error", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake"))
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.BlockEvents(ctx, WithStartBlock(418))
- require.NoError(t, err)
-
- actual, ok := <-receive
-
- require.False(t, ok, "Expected event listening to be cancelled, got %v", actual)
- })
-
t.Run("Receives events", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
-
- blocks := []*common.Block{
+ expected := []*common.Block{
{
Header: &common.BlockHeader{
Number: 1,
@@ -389,46 +37,32 @@ func TestBlockEvents(t *testing.T) {
},
},
}
- responseIndex := 0
- mockEvents.EXPECT().Recv().
- DoAndReturn(func() (*peer.DeliverResponse, error) {
- if responseIndex >= len(blocks) {
- return nil, errors.New("fake")
- }
- response := &peer.DeliverResponse{
- Type: &peer.DeliverResponse_Block{
- Block: blocks[responseIndex],
- },
- }
- responseIndex++
- return response, nil
- }).
- AnyTimes()
+
+ var responses []*peer.DeliverResponse
+ for _, block := range expected {
+ responses = append(responses, &peer.DeliverResponse{
+ Type: &peer.DeliverResponse_Block{
+ Block: block,
+ },
+ })
+ }
+
+ tester := NewBlockEventsTest(t)
+ tester.SetResponses(responses...)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.BlockEvents(ctx)
+ events, err := tester.Events(ctx)
require.NoError(t, err)
- for _, event := range blocks {
- actual := <-receive
- test.AssertProtoEqual(t, event, actual)
+ for _, event := range expected {
+ actual := <-events
+ AssertProtoEqual(t, event, actual)
}
})
t.Run("Closes event channel on non-block message", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
-
block := &common.Block{
Header: &common.BlockHeader{
Number: 1,
@@ -456,102 +90,25 @@ func TestBlockEvents(t *testing.T) {
},
},
}
- responseIndex := 0
- mockEvents.EXPECT().Recv().
- DoAndReturn(func() (*peer.DeliverResponse, error) {
- if responseIndex >= len(responses) {
- return nil, errors.New("fake")
- }
- response := responses[responseIndex]
- responseIndex++
- return response, nil
- }).
- AnyTimes()
+
+ tester := NewBlockEventsTest(t)
+ tester.SetResponses(responses...)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.BlockEvents(ctx)
+ events, err := tester.Events(ctx)
require.NoError(t, err)
- expected := []*common.Block{
+ // proto.Message must be used to match the type of events channel; otherwise nil comparisons will fail
+ expected := []proto.Message{
block,
nil,
nil,
}
for _, event := range expected {
- actual := <-receive
- test.AssertProtoEqual(t, event, actual)
+ actual := <-events
+ AssertProtoEqual(t, event, actual)
}
})
-
- t.Run("Uses specified gRPC call options", func(t *testing.T) {
- var actual []grpc.CallOption
- expected := grpc.WaitForReady(true)
-
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil).
- AnyTimes()
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- request, err := network.NewBlockEventsRequest()
- require.NoError(t, err, "NewBlockEventsRequest")
-
- _, err = request.Events(ctx, expected)
- require.NoError(t, err, "Events")
-
- require.Contains(t, actual, expected, "CallOptions")
- })
-
- t.Run("Sends request with TLS client certificate hash", func(t *testing.T) {
- expected := []byte("TLS_CLIENT_CERTIFICATE_HASH")
-
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient), WithTLSClientCertificateHash(expected))
- _, err := network.BlockEvents(ctx)
- require.NoError(t, err)
-
- channelHeader := &common.ChannelHeader{}
- test.AssertUnmarshal(t, payload.GetHeader().GetChannelHeader(), channelHeader)
-
- require.Equal(t, expected, channelHeader.GetTlsCertHash())
- })
}
diff --git a/pkg/client/blockeventscommon_test.go b/pkg/client/blockeventscommon_test.go
new file mode 100644
index 000000000..f03e67d32
--- /dev/null
+++ b/pkg/client/blockeventscommon_test.go
@@ -0,0 +1,423 @@
+// Copyright IBM Corp. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "context"
+ "errors"
+ "io"
+ "testing"
+
+ "github.com/hyperledger/fabric-protos-go-apiv2/common"
+ "github.com/hyperledger/fabric-protos-go-apiv2/orderer"
+ "github.com/hyperledger/fabric-protos-go-apiv2/peer"
+ "github.com/stretchr/testify/require"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/proto"
+)
+
+func TestCommonBlockEvents(t *testing.T) {
+ for eventType, newTester := range map[string]func(*testing.T) blockEventsTester{
+ "Block": func(t *testing.T) blockEventsTester {
+ return NewBlockEventsTest(t)
+ },
+ "FilteredBlock": func(t *testing.T) blockEventsTester {
+ return NewFilteredBlockEventsTest(t)
+ },
+ "BlockAndPrivateData": func(t *testing.T) blockEventsTester {
+ return NewBlockAndPrivateDataEventsTest(t)
+ },
+ } {
+ t.Run(eventType, func(t *testing.T) {
+ t.Run("Returns connect error", func(t *testing.T) {
+ expected := NewStatusError(t, codes.Aborted, "BLOCK_EVENTS_ERROR")
+
+ tester := newTester(t)
+ tester.SetConnectError(expected)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ _, err := tester.Events(ctx)
+
+ require.Equal(t, status.Code(expected), status.Code(err), "status code")
+ require.ErrorIs(t, err, expected, "error type: %T", err)
+ require.ErrorContains(t, err, expected.Error(), "message")
+ })
+ })
+
+ for testName, testCase := range map[string]struct {
+ options []BlockEventsOption
+ expected *orderer.SeekInfo
+ }{
+ "Sends valid request with default start position": {
+ options: nil,
+ expected: &orderer.SeekInfo{
+ Start: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_NextCommit{
+ NextCommit: &orderer.SeekNextCommit{},
+ },
+ },
+ Stop: seekLargestBlockNumber(),
+ },
+ },
+ "Sends valid request with specified start block number": {
+ options: []BlockEventsOption{
+ WithStartBlock(418),
+ },
+ expected: &orderer.SeekInfo{
+ Start: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 418,
+ },
+ },
+ },
+ Stop: seekLargestBlockNumber(),
+ },
+ },
+ "Uses specified start block instead of unset checkpoint": {
+ options: []BlockEventsOption{
+ WithStartBlock(418),
+ WithCheckpoint(new(InMemoryCheckpointer)),
+ },
+ expected: &orderer.SeekInfo{
+ Start: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 418,
+ },
+ },
+ },
+ Stop: seekLargestBlockNumber(),
+ },
+ },
+ "Uses checkpoint block instead of specified start block": {
+ options: func() []BlockEventsOption {
+ checkpointer := new(InMemoryCheckpointer)
+ checkpointer.CheckpointBlock(500)
+ return []BlockEventsOption{
+ WithStartBlock(418),
+ WithCheckpoint(checkpointer),
+ }
+ }(),
+ expected: &orderer.SeekInfo{
+ Start: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 501,
+ },
+ },
+ },
+ Stop: seekLargestBlockNumber(),
+ },
+ },
+ "Uses checkpoint block zero with set transaction ID instead of specified start block": {
+ options: func() []BlockEventsOption {
+ checkpointer := new(InMemoryCheckpointer)
+ checkpointer.CheckpointTransaction(0, "transctionId")
+ return []BlockEventsOption{
+ WithStartBlock(418),
+ WithCheckpoint(checkpointer),
+ }
+ }(),
+ expected: &orderer.SeekInfo{
+ Start: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 0,
+ },
+ },
+ },
+ Stop: seekLargestBlockNumber(),
+ },
+ },
+ "Uses default start position with unset checkpoint and no start block": {
+ options: []BlockEventsOption{
+ WithCheckpoint(new(InMemoryCheckpointer)),
+ },
+ expected: &orderer.SeekInfo{
+ Start: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_NextCommit{
+ NextCommit: &orderer.SeekNextCommit{},
+ },
+ },
+ Stop: seekLargestBlockNumber(),
+ },
+ },
+ } {
+ t.Run(testName, func(t *testing.T) {
+ networkName := "NETWORK"
+
+ tester := newTester(t)
+ tester.SetNetworkName(networkName)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ _, err := tester.Events(ctx, testCase.options...)
+ require.NoError(t, err)
+
+ payload := &common.Payload{}
+ AssertUnmarshal(t, (<-tester.Requests()).GetPayload(), payload)
+ AssertValidBlockEventRequestHeader(t, payload, networkName)
+ actual := &orderer.SeekInfo{}
+ AssertUnmarshal(t, payload.GetData(), actual)
+
+ AssertProtoEqual(t, testCase.expected, actual)
+ })
+ }
+
+ t.Run("Closes event channel on receive error", func(t *testing.T) {
+ tester := newTester(t)
+ tester.SetReceiveError(errors.New("fake"))
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ events, err := tester.Events(ctx, WithStartBlock(418))
+ require.NoError(t, err)
+
+ actual, ok := <-events
+
+ require.False(t, ok, "Expected event listening to be cancelled, got %v", actual)
+ })
+
+ t.Run("Uses specified gRPC call options", func(t *testing.T) {
+ expected := grpc.WaitForReady(true)
+
+ tester := newTester(t)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ _, err := tester.EventsWithCallOptions(ctx, expected)
+ require.NoError(t, err)
+
+ require.Contains(t, (<-tester.CallOptions()), expected, "CallOptions")
+ })
+
+ t.Run("Sends request with TLS client certificate hash", func(t *testing.T) {
+ expected := []byte("TLS_CLIENT_CERTIFICATE_HASH")
+
+ tester := newTester(t)
+ tester.SetGatewayOptions(WithTLSClientCertificateHash(expected))
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ _, err := tester.Events(ctx)
+ require.NoError(t, err)
+
+ payload := &common.Payload{}
+ AssertUnmarshal(t, (<-tester.Requests()).GetPayload(), payload)
+ channelHeader := &common.ChannelHeader{}
+ AssertUnmarshal(t, payload.GetHeader().GetChannelHeader(), channelHeader)
+
+ require.Equal(t, expected, channelHeader.GetTlsCertHash())
+ })
+ }
+}
+
+type blockEventsTester interface {
+ SetConnectError(error)
+ SetNetworkName(string)
+ SetGatewayOptions(...ConnectOption)
+ SetReceiveError(error)
+ SetResponses(...*peer.DeliverResponse)
+ Events(context.Context, ...BlockEventsOption) (<-chan proto.Message, error)
+ Requests() <-chan *common.Envelope
+ EventsWithCallOptions(context.Context, ...grpc.CallOption) (<-chan proto.Message, error)
+ CallOptions() <-chan []grpc.CallOption
+}
+
+type baseBlockEventsTest struct {
+ t *testing.T
+ connectError error
+ networkName string
+ gatewayOptions []ConnectOption
+ receiveError error
+ responses []*peer.DeliverResponse
+ requests chan *common.Envelope
+ callOptions chan []grpc.CallOption
+}
+
+type blockEventsTest struct {
+ baseBlockEventsTest
+}
+
+func (b *baseBlockEventsTest) SetConnectError(err error) {
+ b.connectError = err
+}
+
+func (b *baseBlockEventsTest) SetNetworkName(channel string) {
+ b.networkName = channel
+}
+
+func (b *baseBlockEventsTest) SetGatewayOptions(options ...ConnectOption) {
+ b.gatewayOptions = append(b.gatewayOptions, options...)
+}
+
+func (b *baseBlockEventsTest) SetReceiveError(err error) {
+ b.receiveError = err
+}
+
+func (b *baseBlockEventsTest) SetResponses(responses ...*peer.DeliverResponse) {
+ b.responses = append(b.responses, responses...)
+}
+
+func (b *baseBlockEventsTest) Requests() <-chan *common.Envelope {
+ return b.requests
+}
+
+func (b *baseBlockEventsTest) CallOptions() <-chan []grpc.CallOption {
+ return b.callOptions
+}
+
+func (b *baseBlockEventsTest) deliverOptions() []newStreamFunction {
+ var result []newStreamFunction
+ if b.connectError != nil {
+ result = append(result, WithNewStreamError(b.connectError))
+ } else {
+ mockStream := NewMockClientStream(b.t)
+ b.callOptions = make(chan []grpc.CallOption, 1)
+ result = append(result, CaptureNewStreamOptions(b.callOptions), WithNewStreamResult(mockStream))
+
+ b.requests = make(chan *common.Envelope, 1)
+ ExpectSendMsg(mockStream, CaptureSendMsg(b.requests))
+ mockStream.EXPECT().CloseSend().Maybe().Return(nil)
+
+ if b.receiveError != nil {
+ ExpectRecvMsg(mockStream).Return(b.receiveError)
+ } else if len(b.responses) > 0 {
+ ExpectRecvMsg(mockStream, WithRecvMsgs(b.responses...))
+ } else {
+ ExpectRecvMsg(mockStream).Maybe().Return(io.EOF)
+ }
+ }
+
+ return result
+}
+
+func (b *baseBlockEventsTest) newNetwork(connection grpc.ClientConnInterface) *Network {
+ options := []ConnectOption{
+ WithClientConnection(connection),
+ }
+ options = append(options, b.gatewayOptions...)
+ return AssertNewTestNetwork(b.t, b.networkName, options...)
+}
+
+func NewBlockEventsTest(t *testing.T) *blockEventsTest {
+ return &blockEventsTest{
+ baseBlockEventsTest{
+ t: t,
+ },
+ }
+}
+
+func (b *blockEventsTest) Events(ctx context.Context, options ...BlockEventsOption) (<-chan proto.Message, error) {
+ mockConnection := NewMockClientConnInterface(b.t)
+ ExpectDeliver(mockConnection, b.deliverOptions()...)
+
+ network := b.newNetwork(mockConnection)
+ events, err := network.BlockEvents(ctx, options...)
+
+ return asProtoMessageChannel(events), err
+}
+
+func (b *blockEventsTest) EventsWithCallOptions(ctx context.Context, options ...grpc.CallOption) (<-chan proto.Message, error) {
+ mockConnection := NewMockClientConnInterface(b.t)
+ ExpectDeliver(mockConnection, b.deliverOptions()...)
+
+ network := b.newNetwork(mockConnection)
+ request, err := network.NewBlockEventsRequest()
+ require.NoError(b.t, err, "NewBlockEventsRequest")
+
+ events, err := request.Events(ctx, options...)
+
+ return asProtoMessageChannel(events), err
+}
+
+type filteredBlockEventsTest struct {
+ baseBlockEventsTest
+}
+
+func NewFilteredBlockEventsTest(t *testing.T) *filteredBlockEventsTest {
+ return &filteredBlockEventsTest{
+ baseBlockEventsTest{
+ t: t,
+ },
+ }
+}
+
+func (b *filteredBlockEventsTest) Events(ctx context.Context, options ...BlockEventsOption) (<-chan proto.Message, error) {
+ mockConnection := NewMockClientConnInterface(b.t)
+ ExpectDeliverFiltered(mockConnection, b.deliverOptions()...)
+
+ network := b.newNetwork(mockConnection)
+ events, err := network.FilteredBlockEvents(ctx, options...)
+
+ return asProtoMessageChannel(events), err
+}
+
+func (b *filteredBlockEventsTest) EventsWithCallOptions(ctx context.Context, options ...grpc.CallOption) (<-chan proto.Message, error) {
+ mockConnection := NewMockClientConnInterface(b.t)
+ ExpectDeliverFiltered(mockConnection, b.deliverOptions()...)
+
+ network := b.newNetwork(mockConnection)
+ request, err := network.NewFilteredBlockEventsRequest()
+ require.NoError(b.t, err, "NewFilteredBlockEventsRequest")
+
+ events, err := request.Events(ctx, options...)
+
+ return asProtoMessageChannel(events), err
+}
+
+type blockAndPrivateDataEventsTest struct {
+ baseBlockEventsTest
+}
+
+func NewBlockAndPrivateDataEventsTest(t *testing.T) *blockAndPrivateDataEventsTest {
+ return &blockAndPrivateDataEventsTest{
+ baseBlockEventsTest{
+ t: t,
+ },
+ }
+}
+
+func (b *blockAndPrivateDataEventsTest) Events(ctx context.Context, options ...BlockEventsOption) (<-chan proto.Message, error) {
+ mockConnection := NewMockClientConnInterface(b.t)
+ ExpectDeliverWithPrivateData(mockConnection, b.deliverOptions()...)
+
+ network := b.newNetwork(mockConnection)
+ events, err := network.BlockAndPrivateDataEvents(ctx, options...)
+
+ return asProtoMessageChannel(events), err
+}
+
+func (b *blockAndPrivateDataEventsTest) EventsWithCallOptions(ctx context.Context, options ...grpc.CallOption) (<-chan proto.Message, error) {
+ mockConnection := NewMockClientConnInterface(b.t)
+ ExpectDeliverWithPrivateData(mockConnection, b.deliverOptions()...)
+
+ network := b.newNetwork(mockConnection)
+ request, err := network.NewBlockAndPrivateDataEventsRequest()
+ require.NoError(b.t, err, "NewBlockAndPrivateDataEventsRequest")
+
+ events, err := request.Events(ctx, options...)
+
+ return asProtoMessageChannel(events), err
+}
+
+func asProtoMessageChannel[T proto.Message](events <-chan T) <-chan proto.Message {
+ result := make(chan proto.Message)
+ go func() {
+ for event := range events {
+ result <- event
+ }
+ close(result)
+ }()
+ return result
+}
diff --git a/pkg/client/blockeventsfiltered_test.go b/pkg/client/blockeventsfiltered_test.go
index fe3014c10..aa8fbd51d 100644
--- a/pkg/client/blockeventsfiltered_test.go
+++ b/pkg/client/blockeventsfiltered_test.go
@@ -5,161 +5,17 @@ package client
import (
"context"
- "errors"
"testing"
- "github.com/hyperledger/fabric-gateway/pkg/internal/test"
"github.com/hyperledger/fabric-protos-go-apiv2/common"
- "github.com/hyperledger/fabric-protos-go-apiv2/orderer"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
- "google.golang.org/grpc"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/proto"
)
func TestFilteredBlockEvents(t *testing.T) {
- t.Run("Returns connect error", func(t *testing.T) {
- expected := NewStatusError(t, codes.Aborted, "BLOCK_EVENTS_ERROR")
- mockClient := NewMockDeliverClient(gomock.NewController(t))
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(nil, expected)
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.FilteredBlockEvents(ctx)
-
- require.Equal(t, status.Code(expected), status.Code(err), "status code")
- require.ErrorIs(t, err, expected, "error type: %T", err)
- require.ErrorContains(t, err, expected.Error(), "message")
- })
-
- t.Run("Sends valid request with default start position", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverFilteredClient(controller)
-
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.FilteredBlockEvents(ctx)
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_NextCommit{
- NextCommit: &orderer.SeekNextCommit{},
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with specified start block number", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverFilteredClient(controller)
-
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.FilteredBlockEvents(ctx, WithStartBlock(418))
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 418,
- },
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Closes event channel on receive error", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverFilteredClient(controller)
-
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake"))
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.FilteredBlockEvents(ctx, WithStartBlock(418))
- require.NoError(t, err)
-
- actual, ok := <-receive
-
- require.False(t, ok, "Expected event listening to be cancelled, got %v", actual)
- })
-
t.Run("Receives events", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverFilteredClient(controller)
-
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
-
- blocks := []*peer.FilteredBlock{
+ expected := []*peer.FilteredBlock{
{
ChannelId: "NETWORK",
Number: 1,
@@ -179,46 +35,32 @@ func TestFilteredBlockEvents(t *testing.T) {
},
},
}
- responseIndex := 0
- mockEvents.EXPECT().Recv().
- DoAndReturn(func() (*peer.DeliverResponse, error) {
- if responseIndex >= len(blocks) {
- return nil, errors.New("fake")
- }
- response := &peer.DeliverResponse{
- Type: &peer.DeliverResponse_FilteredBlock{
- FilteredBlock: blocks[responseIndex],
- },
- }
- responseIndex++
- return response, nil
- }).
- AnyTimes()
+
+ var responses []*peer.DeliverResponse
+ for _, block := range expected {
+ responses = append(responses, &peer.DeliverResponse{
+ Type: &peer.DeliverResponse_FilteredBlock{
+ FilteredBlock: block,
+ },
+ })
+ }
+
+ tester := NewFilteredBlockEventsTest(t)
+ tester.SetResponses(responses...)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.FilteredBlockEvents(ctx)
+ events, err := tester.Events(ctx)
require.NoError(t, err)
- for _, event := range blocks {
- actual := <-receive
- test.AssertProtoEqual(t, event, actual)
+ for _, event := range expected {
+ actual := <-events
+ AssertProtoEqual(t, event, actual)
}
})
t.Run("Closes event channel on non-block message", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverFilteredClient(controller)
-
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
-
block := &peer.FilteredBlock{
ChannelId: "NETWORK",
Number: 1,
@@ -245,102 +87,25 @@ func TestFilteredBlockEvents(t *testing.T) {
},
},
}
- responseIndex := 0
- mockEvents.EXPECT().Recv().
- DoAndReturn(func() (*peer.DeliverResponse, error) {
- if responseIndex >= len(responses) {
- return nil, errors.New("fake")
- }
- response := responses[responseIndex]
- responseIndex++
- return response, nil
- }).
- AnyTimes()
+
+ tester := NewFilteredBlockEventsTest(t)
+ tester.SetResponses(responses...)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.FilteredBlockEvents(ctx)
+ events, err := tester.Events(ctx)
require.NoError(t, err)
- expected := []*peer.FilteredBlock{
+ // proto.Message must be used to match the type of events channel; otherwise nil comparisons will fail
+ expected := []proto.Message{
block,
nil,
nil,
}
for _, event := range expected {
- actual := <-receive
- test.AssertProtoEqual(t, event, actual)
+ actual := <-events
+ AssertProtoEqual(t, event, actual)
}
})
-
- t.Run("Uses specified gRPC call options", func(t *testing.T) {
- var actual []grpc.CallOption
- expected := grpc.WaitForReady(true)
-
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil).
- AnyTimes()
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- request, err := network.NewFilteredBlockEventsRequest()
- require.NoError(t, err, "NewFilteredBlockEventsRequest")
-
- _, err = request.Events(ctx, expected)
- require.NoError(t, err, "Events")
-
- require.Contains(t, actual, expected, "CallOptions")
- })
-
- t.Run("Sends request with TLS client certificate hash", func(t *testing.T) {
- expected := []byte("TLS_CLIENT_CERTIFICATE_HASH")
-
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient), WithTLSClientCertificateHash(expected))
- _, err := network.FilteredBlockEvents(ctx)
- require.NoError(t, err)
-
- channelHeader := &common.ChannelHeader{}
- test.AssertUnmarshal(t, payload.GetHeader().GetChannelHeader(), channelHeader)
-
- require.Equal(t, expected, channelHeader.GetTlsCertHash())
- })
}
diff --git a/pkg/client/blockeventswithprivatedata_test.go b/pkg/client/blockeventswithprivatedata_test.go
index 34e9ce04e..c051569f4 100644
--- a/pkg/client/blockeventswithprivatedata_test.go
+++ b/pkg/client/blockeventswithprivatedata_test.go
@@ -5,162 +5,18 @@ package client
import (
"context"
- "errors"
"testing"
- "github.com/hyperledger/fabric-gateway/pkg/internal/test"
"github.com/hyperledger/fabric-protos-go-apiv2/common"
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
- "github.com/hyperledger/fabric-protos-go-apiv2/orderer"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
- "google.golang.org/grpc"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/proto"
)
func TestBlockAndPrivateDataEvents(t *testing.T) {
- t.Run("Returns connect error", func(t *testing.T) {
- expected := NewStatusError(t, codes.Aborted, "BLOCK_EVENTS_ERROR")
- mockClient := NewMockDeliverClient(gomock.NewController(t))
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(nil, expected)
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.BlockAndPrivateDataEvents(ctx)
-
- require.Equal(t, status.Code(expected), status.Code(err), "status code")
- require.ErrorIs(t, err, expected, "error type: %T", err)
- require.ErrorContains(t, err, expected.Error(), "message")
- })
-
- t.Run("Sends valid request with default start position", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverWithPrivateDataClient(controller)
-
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.BlockAndPrivateDataEvents(ctx)
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_NextCommit{
- NextCommit: &orderer.SeekNextCommit{},
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with specified start block number", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverWithPrivateDataClient(controller)
-
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- _, err := network.BlockAndPrivateDataEvents(ctx, WithStartBlock(418))
- require.NoError(t, err)
-
- AssertValidBlockEventRequestHeader(t, payload, network.Name())
- actual := &orderer.SeekInfo{}
- test.AssertUnmarshal(t, payload.GetData(), actual)
-
- expected := &orderer.SeekInfo{
- Start: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 418,
- },
- },
- },
- Stop: seekLargestBlockNumber(),
- }
-
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Closes event channel on receive error", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverWithPrivateDataClient(controller)
-
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake"))
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.BlockAndPrivateDataEvents(ctx, WithStartBlock(418))
- require.NoError(t, err)
-
- actual, ok := <-receive
-
- require.False(t, ok, "Expected event listening to be cancelled, got %v", actual)
- })
-
t.Run("Receives events", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverWithPrivateDataClient(controller)
-
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
-
- blocksAndPrivateData := []*peer.BlockAndPrivateData{
+ expected := []*peer.BlockAndPrivateData{
{
Block: &common.Block{
Header: &common.BlockHeader{
@@ -198,47 +54,33 @@ func TestBlockAndPrivateDataEvents(t *testing.T) {
},
},
}
- responseIndex := 0
- mockEvents.EXPECT().Recv().
- DoAndReturn(func() (*peer.DeliverResponse, error) {
- if responseIndex >= len(blocksAndPrivateData) {
- return nil, errors.New("fake")
- }
- response := &peer.DeliverResponse{
- Type: &peer.DeliverResponse_BlockAndPrivateData{
- BlockAndPrivateData: blocksAndPrivateData[responseIndex],
- },
- }
- responseIndex++
- return response, nil
- }).
- AnyTimes()
+
+ var responses []*peer.DeliverResponse
+ for _, block := range expected {
+ responses = append(responses, &peer.DeliverResponse{
+ Type: &peer.DeliverResponse_BlockAndPrivateData{
+ BlockAndPrivateData: block,
+ },
+ })
+ }
+
+ tester := NewBlockAndPrivateDataEventsTest(t)
+ tester.SetResponses(responses...)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.BlockAndPrivateDataEvents(ctx)
+ events, err := tester.Events(ctx)
require.NoError(t, err)
- for _, event := range blocksAndPrivateData {
- actual := <-receive
- test.AssertProtoEqual(t, event, actual)
+ for _, event := range expected {
+ actual := <-events
+ AssertProtoEqual(t, event, actual)
}
})
t.Run("Closes event channel on non-block message", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverWithPrivateDataClient(controller)
-
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil)
-
- blockAndPrivateData := &peer.BlockAndPrivateData{
+ block := &peer.BlockAndPrivateData{
Block: &common.Block{
Header: &common.BlockHeader{
Number: 1,
@@ -259,7 +101,7 @@ func TestBlockAndPrivateDataEvents(t *testing.T) {
responses := []*peer.DeliverResponse{
{
Type: &peer.DeliverResponse_BlockAndPrivateData{
- BlockAndPrivateData: blockAndPrivateData,
+ BlockAndPrivateData: block,
},
},
{
@@ -269,106 +111,29 @@ func TestBlockAndPrivateDataEvents(t *testing.T) {
},
{
Type: &peer.DeliverResponse_BlockAndPrivateData{
- BlockAndPrivateData: blockAndPrivateData,
+ BlockAndPrivateData: block,
},
},
}
- responseIndex := 0
- mockEvents.EXPECT().Recv().
- DoAndReturn(func() (*peer.DeliverResponse, error) {
- if responseIndex >= len(responses) {
- return nil, errors.New("fake")
- }
- response := responses[responseIndex]
- responseIndex++
- return response, nil
- }).
- AnyTimes()
+
+ tester := NewBlockAndPrivateDataEventsTest(t)
+ tester.SetResponses(responses...)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- receive, err := network.BlockAndPrivateDataEvents(ctx)
+ events, err := tester.Events(ctx)
require.NoError(t, err)
- expected := []*peer.BlockAndPrivateData{
- blockAndPrivateData,
+ // proto.Message must be used to match the type of events channel; otherwise nil comparisons will fail
+ expected := []proto.Message{
+ block,
nil,
nil,
}
for _, event := range expected {
- actual := <-receive
- test.AssertProtoEqual(t, event, actual)
+ actual := <-events
+ AssertProtoEqual(t, event, actual)
}
})
-
- t.Run("Uses specified gRPC call options", func(t *testing.T) {
- var actual []grpc.CallOption
- expected := grpc.WaitForReady(true)
-
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Return(nil).
- AnyTimes()
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient))
- request, err := network.NewBlockAndPrivateDataEventsRequest()
- require.NoError(t, err, "NewBlockAndPrivateDataEventsRequest")
-
- _, err = request.Events(ctx, expected)
- require.NoError(t, err, "Events")
-
- require.Contains(t, actual, expected, "CallOptions")
- })
-
- t.Run("Sends request with TLS client certificate hash", func(t *testing.T) {
- expected := []byte("TLS_CLIENT_CERTIFICATE_HASH")
-
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- payload := &common.Payload{}
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- test.AssertUnmarshal(t, in.GetPayload(), payload)
- }).
- Return(nil).
- Times(1)
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithDeliverClient(mockClient), WithTLSClientCertificateHash(expected))
- _, err := network.BlockAndPrivateDataEvents(ctx)
- require.NoError(t, err)
-
- channelHeader := &common.ChannelHeader{}
- test.AssertUnmarshal(t, payload.GetHeader().GetChannelHeader(), channelHeader)
-
- require.Equal(t, expected, channelHeader.GetTlsCertHash())
- })
}
diff --git a/pkg/client/chaincodeevents_test.go b/pkg/client/chaincodeevents_test.go
index 8c54d2d3a..f98b5291c 100644
--- a/pkg/client/chaincodeevents_test.go
+++ b/pkg/client/chaincodeevents_test.go
@@ -6,17 +6,17 @@ package client
import (
"context"
"errors"
+ "io"
"testing"
- "github.com/hyperledger/fabric-gateway/pkg/internal/test"
"github.com/hyperledger/fabric-protos-go-apiv2/gateway"
"github.com/hyperledger/fabric-protos-go-apiv2/orderer"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
+ "google.golang.org/protobuf/proto"
)
func TestChaincodeEvents(t *testing.T) {
@@ -42,14 +42,14 @@ func TestChaincodeEvents(t *testing.T) {
t.Run("Returns connect error", func(t *testing.T) {
expected := NewStatusError(t, codes.Aborted, "CHAINCODE_EVENTS_ERROR")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Return(nil, expected)
+
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectChaincodeEvents(mockConnection, WithNewStreamError(expected))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
+ network := AssertNewTestNetwork(t, "NETWORK", WithClientConnection(mockConnection))
_, err := network.ChaincodeEvents(ctx, "CHAINCODE")
require.Equal(t, status.Code(expected), status.Code(err), "status code")
@@ -57,396 +57,189 @@ func TestChaincodeEvents(t *testing.T) {
require.ErrorContains(t, err, expected.Error(), "message")
})
- t.Run("Sends valid request with default start position", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE")
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
-
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_NextCommit{
- NextCommit: &orderer.SeekNextCommit{},
+ for testName, testCase := range map[string]struct {
+ options []ChaincodeEventsOption
+ expected *gateway.ChaincodeEventsRequest
+ }{
+ "Sends valid request with default start position": {
+ options: nil,
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_NextCommit{
+ NextCommit: &orderer.SeekNextCommit{},
+ },
},
},
- }
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with specified start block number", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE", WithStartBlock(418))
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
-
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 418,
+ },
+ "Sends valid request with specified start block number": {
+ options: []ChaincodeEventsOption{
+ WithStartBlock(418),
+ },
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 418,
+ },
},
},
},
- }
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with specified start block number and fresh checkpointer", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
-
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE", WithStartBlock(418), WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
-
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 418,
+ },
+ "Sends valid request with specified start block number and fresh checkpointer": {
+ options: []ChaincodeEventsOption{
+ WithStartBlock(418),
+ WithCheckpoint(new(InMemoryCheckpointer)),
+ },
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 418,
+ },
},
},
},
- }
- test.AssertProtoEqual(t, expected, actual)
- })
- t.Run("Sends valid request with specified start block and checkpoint block", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
- checkpointer.CheckpointBlock(uint64(500))
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE", WithStartBlock(418), WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
-
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 501,
+ },
+ "Sends valid request with specified start block and checkpoint block": {
+ options: func() []ChaincodeEventsOption {
+ checkpointer := new(InMemoryCheckpointer)
+ checkpointer.CheckpointBlock(500)
+ return []ChaincodeEventsOption{
+ WithStartBlock(418),
+ WithCheckpoint(checkpointer),
+ }
+ }(),
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 501,
+ },
},
},
},
- }
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with specified start block and checkpoint transaction ID", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
- checkpointer.CheckpointTransaction(uint64(500), "txn1")
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE", WithStartBlock(418), WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
-
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 500,
+ },
+ "Sends valid request with specified start block and checkpoint transaction ID": {
+ options: func() []ChaincodeEventsOption {
+ checkpointer := new(InMemoryCheckpointer)
+ checkpointer.CheckpointTransaction(500, "txn1")
+ return []ChaincodeEventsOption{
+ WithStartBlock(418),
+ WithCheckpoint(checkpointer),
+ }
+ }(),
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 500,
+ },
},
},
+ AfterTransactionId: "txn1",
},
- AfterTransactionId: "txn1",
- }
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with no start block and fresh checkpointer", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE", WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_NextCommit{
- NextCommit: &orderer.SeekNextCommit{},
+ },
+ "Sends valid request with no start block and fresh checkpointer": {
+ options: []ChaincodeEventsOption{
+ WithCheckpoint(new(InMemoryCheckpointer)),
+ },
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_NextCommit{
+ NextCommit: &orderer.SeekNextCommit{},
+ },
},
},
- }
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with no start block and checkpoint transaction ID", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
- checkpointer.CheckpointTransaction(uint64(500), "txn1")
-
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE", WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: 500,
+ },
+ "Sends valid request with no start block and checkpoint transaction ID": {
+ options: func() []ChaincodeEventsOption {
+ checkpointer := new(InMemoryCheckpointer)
+ checkpointer.CheckpointTransaction(500, "txn1")
+ return []ChaincodeEventsOption{
+ WithCheckpoint(checkpointer),
+ }
+ }(),
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 500,
+ },
},
},
+ AfterTransactionId: "txn1",
},
- AfterTransactionId: "txn1",
- }
- test.AssertProtoEqual(t, expected, actual)
- })
-
- t.Run("Sends valid request with with start block and checkpoint chaincode event", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- var actual *gateway.ChaincodeEventsRequest
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- request := &gateway.ChaincodeEventsRequest{}
- test.AssertUnmarshal(t, in.GetRequest(), request)
- actual = request
- }).
- Return(mockEvents, nil).
- Times(1)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
-
- checkpointer := new(InMemoryCheckpointer)
- event := &ChaincodeEvent{
- BlockNumber: 1,
- ChaincodeName: "CHAINCODE",
- EventName: "EVENT_1",
- Payload: []byte("PAYLOAD_1"),
- TransactionID: "TRANSACTION_1",
- }
-
- checkpointer.CheckpointChaincodeEvent(event)
-
- _, err := network.ChaincodeEvents(ctx, "CHAINCODE", WithStartBlock(418), WithCheckpoint(checkpointer))
- require.NoError(t, err)
-
- creator, err := network.signingID.Creator()
- require.NoError(t, err)
- expected := &gateway.ChaincodeEventsRequest{
- ChannelId: "NETWORK",
- ChaincodeId: "CHAINCODE",
- Identity: creator,
- StartPosition: &orderer.SeekPosition{
- Type: &orderer.SeekPosition_Specified{
- Specified: &orderer.SeekSpecified{
- Number: event.BlockNumber,
+ },
+ "Sends valid request with with start block and checkpoint chaincode event": {
+ options: func() []ChaincodeEventsOption {
+ checkpointer := new(InMemoryCheckpointer)
+ event := &ChaincodeEvent{
+ BlockNumber: 1,
+ TransactionID: "TRANSACTION_1",
+ }
+ checkpointer.CheckpointChaincodeEvent(event)
+ return []ChaincodeEventsOption{
+ WithCheckpoint(checkpointer),
+ }
+ }(),
+ expected: &gateway.ChaincodeEventsRequest{
+ StartPosition: &orderer.SeekPosition{
+ Type: &orderer.SeekPosition_Specified{
+ Specified: &orderer.SeekSpecified{
+ Number: 1,
+ },
},
},
+ AfterTransactionId: "TRANSACTION_1",
},
- AfterTransactionId: event.TransactionID,
- }
- test.AssertProtoEqual(t, expected, actual)
- })
+ },
+ } {
+ t.Run(testName, func(t *testing.T) {
+ mockConnection := NewMockClientConnInterface(t)
+ mockStream := NewMockClientStream(t)
+ ExpectChaincodeEvents(mockConnection, WithNewStreamResult(mockStream))
+
+ messages := make(chan *gateway.SignedChaincodeEventsRequest, 1)
+ ExpectSendMsg(mockStream, CaptureSendMsg(messages))
+ mockStream.EXPECT().CloseSend().Return(nil)
+ ExpectRecvMsg(mockStream).Maybe().Return(io.EOF)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ network := AssertNewTestNetwork(t, "NETWORK", WithClientConnection(mockConnection))
+ _, err := network.ChaincodeEvents(ctx, "CHAINCODE", testCase.options...)
+ require.NoError(t, err)
+
+ creator, err := network.signingID.Creator()
+ require.NoError(t, err)
+
+ expected := &gateway.ChaincodeEventsRequest{
+ ChannelId: "NETWORK",
+ ChaincodeId: "CHAINCODE",
+ Identity: creator,
+ }
+ proto.Merge(expected, testCase.expected)
+ actual := &gateway.ChaincodeEventsRequest{}
+ AssertUnmarshal(t, (<-messages).Request, actual)
+ AssertProtoEqual(t, expected, actual)
+ })
+ }
t.Run("Closes event channel on receive error", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
+ mockConnection := NewMockClientConnInterface(t)
+ mockStream := NewMockClientStream(t)
+ ExpectChaincodeEvents(mockConnection, WithNewStreamResult(mockStream))
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
+ ExpectSendMsg(mockStream)
+ mockStream.EXPECT().CloseSend().Return(nil)
+ ExpectRecvMsg(mockStream).Maybe().Return(errors.New("fake"))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
+ network := AssertNewTestNetwork(t, "NETWORK", WithClientConnection(mockConnection))
+
receive, err := network.ChaincodeEvents(ctx, "CHAINCODE")
require.NoError(t, err)
@@ -456,13 +249,6 @@ func TestChaincodeEvents(t *testing.T) {
})
t.Run("Receives events", func(t *testing.T) {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil)
-
expected := []*ChaincodeEvent{
{
BlockNumber: 1,
@@ -487,26 +273,24 @@ func TestChaincodeEvents(t *testing.T) {
},
}
- responses := []*gateway.ChaincodeEventsResponse{
+ mockConnection := NewMockClientConnInterface(t)
+ mockStream := NewMockClientStream(t)
+ options := make(chan []grpc.CallOption, 1)
+ ExpectChaincodeEvents(mockConnection, CaptureNewStreamOptions(options), WithNewStreamResult(mockStream))
+
+ messages := make(chan *gateway.SignedChaincodeEventsRequest, 1)
+ ExpectSendMsg(mockStream, CaptureSendMsg(messages))
+ mockStream.EXPECT().CloseSend().Return(nil)
+ ExpectRecvMsg(mockStream, WithRecvMsgs(
newChaincodeEventsResponse(expected[0:2]),
newChaincodeEventsResponse(expected[2:]),
- }
- responseIndex := 0
- mockEvents.EXPECT().Recv().
- DoAndReturn(func() (*gateway.ChaincodeEventsResponse, error) {
- if responseIndex >= len(responses) {
- return nil, errors.New("fake")
- }
- response := responses[responseIndex]
- responseIndex++
- return response, nil
- }).
- AnyTimes()
+ ))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
+ network := AssertNewTestNetwork(t, "NETWORK", WithClientConnection(mockConnection))
+
receive, err := network.ChaincodeEvents(ctx, "CHAINCODE")
require.NoError(t, err)
@@ -517,34 +301,29 @@ func TestChaincodeEvents(t *testing.T) {
})
t.Run("Uses specified gRPC call options", func(t *testing.T) {
- var actual []grpc.CallOption
expected := grpc.WaitForReady(true)
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
-
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, _ *gateway.SignedChaincodeEventsRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(mockEvents, nil).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ mockStream := NewMockClientStream(t)
+ options := make(chan []grpc.CallOption, 1)
+ ExpectChaincodeEvents(mockConnection, CaptureNewStreamOptions(options), WithNewStreamResult(mockStream))
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
+ messages := make(chan *gateway.SignedChaincodeEventsRequest, 1)
+ ExpectSendMsg(mockStream, CaptureSendMsg(messages))
+ mockStream.EXPECT().CloseSend().Return(nil)
+ ExpectRecvMsg(mockStream).Maybe().Return(io.EOF)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- network := AssertNewTestNetwork(t, "NETWORK", WithGatewayClient(mockClient))
+ network := AssertNewTestNetwork(t, "NETWORK", WithClientConnection(mockConnection))
+
request, err := network.NewChaincodeEventsRequest("CHAINCODE")
require.NoError(t, err, "NewChaincodeEventsRequest")
_, err = request.Events(ctx, expected)
require.NoError(t, err, "Events")
- require.Contains(t, actual, expected, "CallOptions")
+ require.Contains(t, <-options, expected, "CallOptions")
})
}
diff --git a/pkg/client/evaluate_test.go b/pkg/client/evaluate_test.go
index c034ae9a3..2894c1fa7 100644
--- a/pkg/client/evaluate_test.go
+++ b/pkg/client/evaluate_test.go
@@ -6,43 +6,22 @@ package client
import (
"context"
"testing"
- "time"
- "github.com/hyperledger/fabric-gateway/pkg/internal/test"
"github.com/hyperledger/fabric-protos-go-apiv2/gateway"
- "github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
- "google.golang.org/protobuf/runtime/protoiface"
)
-func NewStatusError(t *testing.T, code codes.Code, message string, details ...protoiface.MessageV1) error {
- s, err := status.New(code, message).WithDetails(details...)
- require.NoError(t, err)
-
- return s.Err()
-}
-
func TestEvaluateTransaction(t *testing.T) {
- newEvaluateResponse := func(value []byte) *gateway.EvaluateResponse {
- return &gateway.EvaluateResponse{
- Result: &peer.Response{
- Payload: []byte(value),
- },
- }
- }
-
t.Run("Returns evaluate error", func(t *testing.T) {
expected := NewStatusError(t, codes.Aborted, "EVALUATE_ERROR")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Return(nil, expected)
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEvaluate(mockConnection, WithInvokeError(expected))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, err := contract.EvaluateTransaction("transaction")
require.ErrorIs(t, err, expected, "error type: %T", err)
@@ -66,11 +45,10 @@ func TestEvaluateTransaction(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
expected := []byte("TRANSACTION_RESULT")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Return(newEvaluateResponse(expected), nil)
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEvaluate(mockConnection, WithEvaluateResponse(expected))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
actual, err := testCase.run(t, contract)
require.NoError(t, err)
@@ -78,231 +56,196 @@ func TestEvaluateTransaction(t *testing.T) {
require.EqualValues(t, expected, actual)
})
}
+
t.Run("Includes channel name in proposal", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalChannelheader(t, in.ProposedTransaction).ChannelId
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
+ expected := "CHANNEL_NAME"
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ network := AssertNewTestNetwork(t, expected, WithClientConnection(mockConnection))
+
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := network.GetContract("chaincode")
_, err := contract.EvaluateTransaction("transaction")
require.NoError(t, err)
- expected := contract.channelName
+ actual := AssertUnmarshalChannelheader(t, (<-requests).ProposedTransaction).ChannelId
require.Equal(t, expected, actual)
})
t.Run("Includes chaincode name in proposal", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.ChaincodeId.Name
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
+ expected := "CHAINCODE_NAME"
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := AssertNewTestContract(t, expected, WithClientConnection(mockConnection))
_, err := contract.EvaluateTransaction("transaction")
require.NoError(t, err)
- expected := contract.chaincodeName
+ actual := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.ChaincodeId.Name
require.Equal(t, expected, actual)
})
t.Run("Includes transaction name in proposal for default smart contract", func(t *testing.T) {
- var args [][]byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- args = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.Input.Args
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
+ expected := "TRANSACTION_NAME"
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
- expected := "TRANSACTION_NAME"
_, err := contract.EvaluateTransaction(expected)
require.NoError(t, err)
+ args := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.Input.Args
actual := string(args[0])
require.Equal(t, expected, actual, "got Args: %s", args)
})
t.Run("Includes transaction name in proposal for named smart contract", func(t *testing.T) {
- var args [][]byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- args = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.Input.Args
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
-
- contract := AssertNewTestContractWithName(t, "chaincode", "CONTRACT_NAME", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := AssertNewTestContractWithName(t, "chaincode", "CONTRACT_NAME", WithClientConnection(mockConnection))
_, err := contract.EvaluateTransaction("TRANSACTION_NAME")
require.NoError(t, err)
+ args := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.Input.Args
actual := string(args[0])
expected := "CONTRACT_NAME:TRANSACTION_NAME"
require.Equal(t, expected, actual, "got Args: %s", args)
})
t.Run("Includes arguments in proposal", func(t *testing.T) {
- var args [][]byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- args = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.Input.Args
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
+ expected := []string{"one", "two", "three"}
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
- expected := []string{"one", "two", "three"}
_, err := contract.EvaluateTransaction("transaction", expected...)
require.NoError(t, err)
+ args := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.Input.Args
actual := bytesAsStrings(args[1:])
require.EqualValues(t, expected, actual, "got Args: %s", args)
})
t.Run("Includes channel name in proposed transaction", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = in.ChannelId
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
+ expected := "CHANNEL_NAME"
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ network := AssertNewTestNetwork(t, expected, WithClientConnection(mockConnection))
+ contract := network.GetContract("chaincode")
+
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
_, err := contract.EvaluateTransaction("transaction")
require.NoError(t, err)
- expected := contract.channelName
- require.Equal(t, expected, actual)
+ actual := (<-requests).ChannelId
+ require.Equal(t, contract.channelName, actual)
})
t.Run("Includes transaction ID in proposed transaction", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalChannelheader(t, in.ProposedTransaction).TxId
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
_, err = proposal.Evaluate()
require.NoError(t, err, "Evaluate")
+ actual := AssertUnmarshalChannelheader(t, (<-requests).ProposedTransaction).TxId
require.Equal(t, proposal.TransactionID(), actual)
})
t.Run("Includes transaction ID in evaluate request", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = in.TransactionId
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
_, err = proposal.Evaluate()
require.NoError(t, err, "Evaluate")
+ actual := (<-requests).TransactionId
require.Equal(t, proposal.TransactionID(), actual)
})
t.Run("Uses sign", func(t *testing.T) {
- var actual []byte
expected := []byte("MY_SIGNATURE")
+
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+
sign := func(digest []byte) ([]byte, error) {
return expected, nil
}
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = in.ProposedTransaction.Signature
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithSign(sign))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithSign(sign))
_, err := contract.EvaluateTransaction("transaction")
require.NoError(t, err)
+ actual := (<-requests).ProposedTransaction.Signature
require.EqualValues(t, expected, actual)
})
t.Run("Uses hash", func(t *testing.T) {
- var actual []byte
expected := []byte("MY_DIGEST")
+
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEvaluate(mockConnection, WithEvaluateResponse(nil))
+
+ digests := make(chan []byte, 1)
sign := func(digest []byte) ([]byte, error) {
- actual = digest
- return expected, nil
+ digests <- digest
+ return digest, nil
}
hash := func(message []byte) []byte {
return expected
}
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Return(newEvaluateResponse(nil), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithSign(sign), WithHash(hash))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithSign(sign), WithHash(hash))
_, err := contract.EvaluateTransaction("transaction")
require.NoError(t, err)
+ actual := <-digests
require.EqualValues(t, expected, actual)
})
t.Run("Sends private data with evaluate", func(t *testing.T) {
- var actualOrgs []string
expectedOrgs := []string{"MY_ORG"}
- var actualPrice []byte
expectedPrice := []byte("3000")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actualOrgs = in.TargetOrganizations
- transient := test.AssertUnmarshalProposalPayload(t, in.ProposedTransaction).TransientMap
- actualPrice = transient["price"]
- }).
- Return(newEvaluateResponse(nil), nil)
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
privateData := map[string][]byte{
"price": []byte("3000"),
}
-
_, err := contract.Evaluate("transaction", WithTransient(privateData), WithEndorsingOrganizations("MY_ORG"))
require.NoError(t, err)
+ request := <-requests
+ actualOrgs := request.TargetOrganizations
require.EqualValues(t, expectedOrgs, actualOrgs)
+
+ transient := AssertUnmarshalProposalPayload(t, request.ProposedTransaction).TransientMap
+ actualPrice := transient["price"]
require.EqualValues(t, expectedPrice, actualPrice)
})
@@ -326,37 +269,20 @@ func TestEvaluateTransaction(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- DoAndReturn(func(ctx context.Context, _ *gateway.EvaluateRequest, _ ...grpc.CallOption) (*gateway.EvaluateResponse, error) {
- err := ctx.Err()
- if err != nil {
- return nil, err
- }
- return newEvaluateResponse(nil), nil
- })
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEvaluate(mockConnection, WithInvokeContextErr())
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, err := testCase.run(t, ctx, contract)
-
require.ErrorIs(t, err, context.Canceled)
})
}
t.Run("Uses default context", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- DoAndReturn(func(ctx context.Context, _ *gateway.EvaluateRequest, _ ...grpc.CallOption) (*gateway.EvaluateResponse, error) {
- select {
- case <-time.After(1 * time.Second):
- return newEvaluateResponse(nil), nil
- case <-ctx.Done(): // Zero timeout context should cancel immediately, selecting this case
- return nil, ctx.Err()
- }
- })
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithEvaluateTimeout(0))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEvaluate(mockConnection, WithInvokeContextErr(), WithEvaluateResponse(nil))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithEvaluateTimeout(0))
_, err := contract.Evaluate("transaction")
@@ -382,22 +308,17 @@ func TestEvaluateTransaction(t *testing.T) {
},
} {
t.Run(testName, func(t *testing.T) {
- var actual []grpc.CallOption
expected := grpc.WaitForReady(true)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, _ *gateway.EvaluateRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(newEvaluateResponse(nil), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ options := make(chan []grpc.CallOption, 1)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEvaluate(mockConnection, CaptureInvokeOptions(options), WithEvaluateResponse(nil))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, err := testCase.run(t, contract, []grpc.CallOption{expected})
require.NoError(t, err, "Evaluate")
+ actual := <-options
require.Contains(t, actual, expected, "CallOptions")
})
}
diff --git a/pkg/client/gateway_test.go b/pkg/client/gateway_test.go
index 540ad28e8..04e727b2a 100644
--- a/pkg/client/gateway_test.go
+++ b/pkg/client/gateway_test.go
@@ -8,32 +8,10 @@ import (
"testing"
"github.com/hyperledger/fabric-gateway/pkg/identity"
- "github.com/hyperledger/fabric-protos-go-apiv2/gateway"
- "github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
"google.golang.org/grpc"
)
-//go:generate mockgen -destination ./gateway_mock_test.go -package ${GOPACKAGE} github.com/hyperledger/fabric-protos-go-apiv2/gateway GatewayClient,Gateway_ChaincodeEventsClient
-//go:generate mockgen -destination ./deliver_mock_test.go -package ${GOPACKAGE} github.com/hyperledger/fabric-protos-go-apiv2/peer DeliverClient,Deliver_DeliverClient,Deliver_DeliverFilteredClient,Deliver_DeliverWithPrivateDataClient
-
-// WithGatewayClient uses the supplied client for the Gateway. Allows a stub implementation to be used for testing.
-func WithGatewayClient(client gateway.GatewayClient) ConnectOption {
- return func(gateway *Gateway) error {
- gateway.client.grpcGatewayClient = client
- return nil
- }
-}
-
-// WithDeliverClient uses the supplied client for the Deliver service. Allows a stub implementation to be used for testing.
-func WithDeliverClient(client peer.DeliverClient) ConnectOption {
- return func(gateway *Gateway) error {
- gateway.client.grpcDeliverClient = client
- return nil
- }
-}
-
// WithIdentity uses the supplied identity for the Gateway.
func WithIdentity(id identity.Identity) ConnectOption {
return func(gateway *Gateway) error {
@@ -45,8 +23,7 @@ func WithIdentity(id identity.Identity) ConnectOption {
func AssertNewTestGateway(t *testing.T, options ...ConnectOption) *Gateway {
defaultOptions := []ConnectOption{
WithSign(TestCredentials.sign),
- WithGatewayClient(NewMockGatewayClient(gomock.NewController(t))),
- WithDeliverClient(NewMockDeliverClient(gomock.NewController(t))),
+ WithClientConnection(NewMockClientConnInterface(t)),
}
options = append(defaultOptions, options...)
gateway, err := Connect(TestCredentials.Identity(), options...)
@@ -94,8 +71,7 @@ func TestGateway(t *testing.T) {
t.Run("GetNetwork returns correctly named Network", func(t *testing.T) {
networkName := "network"
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- gateway := AssertNewTestGateway(t, WithGatewayClient(mockClient))
+ gateway := AssertNewTestGateway(t)
network := gateway.GetNetwork(networkName)
@@ -104,8 +80,7 @@ func TestGateway(t *testing.T) {
})
t.Run("Identity returns connecting identity", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- gateway := AssertNewTestGateway(t, WithIdentity(id), WithGatewayClient(mockClient))
+ gateway := AssertNewTestGateway(t, WithIdentity(id))
result := gateway.Identity()
diff --git a/pkg/client/identity_test.go b/pkg/client/identity_test.go
index 586dd15a3..f56f34191 100644
--- a/pkg/client/identity_test.go
+++ b/pkg/client/identity_test.go
@@ -4,7 +4,6 @@
package client
import (
- "context"
"testing"
"github.com/hyperledger/fabric-gateway/pkg/identity"
@@ -13,8 +12,6 @@ import (
"github.com/hyperledger/fabric-protos-go-apiv2/msp"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
- "google.golang.org/grpc"
"google.golang.org/protobuf/proto"
)
@@ -36,51 +33,33 @@ func TestIdentity(t *testing.T) {
require.NoError(t, err)
t.Run("Evaluate uses client identity for proposals", func(t *testing.T) {
- var actual []byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- evaluateResponse := &gateway.EvaluateResponse{
- Result: &peer.Response{
- Payload: nil,
- },
- }
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalSignatureHeader(t, in.ProposedTransaction).Creator
- }).
- Return(evaluateResponse, nil).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil))
- contract := AssertNewTestContract(t, "contract", WithGatewayClient(mockClient), WithIdentity(id))
+ contract := AssertNewTestContract(t, "contract", WithClientConnection(mockConnection), WithIdentity(id))
_, err := contract.EvaluateTransaction("transaction")
require.NoError(t, err)
+ actual := AssertUnmarshalSignatureHeader(t, (<-requests).ProposedTransaction).Creator
require.EqualValues(t, creator, actual)
})
t.Run("Submit uses client identity for proposals", func(t *testing.T) {
- var actual []byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
endorseResponse := AssertNewEndorseResponse(t, "result", "channel")
- statusResponse := &gateway.CommitStatusResponse{
- Result: peer.TxValidationCode_VALID,
- }
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalSignatureHeader(t, in.ProposedTransaction).Creator
- }).
- Return(endorseResponse, nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(statusResponse, nil)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(endorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
- contract := AssertNewTestContract(t, "contract", WithGatewayClient(mockClient), WithIdentity(id))
+ contract := AssertNewTestContract(t, "contract", WithClientConnection(mockConnection), WithIdentity(id))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := AssertUnmarshalSignatureHeader(t, (<-requests).ProposedTransaction).Creator
require.EqualValues(t, creator, actual)
})
}
diff --git a/pkg/client/network_test.go b/pkg/client/network_test.go
index 676463443..9c30d6efa 100644
--- a/pkg/client/network_test.go
+++ b/pkg/client/network_test.go
@@ -7,7 +7,6 @@ import (
"testing"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
)
func AssertNewTestNetwork(t *testing.T, networkName string, options ...ConnectOption) *Network {
@@ -18,8 +17,7 @@ func AssertNewTestNetwork(t *testing.T, networkName string, options ...ConnectOp
func TestNetwork(t *testing.T) {
t.Run("GetContract returns correctly named Contract", func(t *testing.T) {
chaincodeName := "chaincode"
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- network := AssertNewTestNetwork(t, "network", WithGatewayClient(mockClient))
+ network := AssertNewTestNetwork(t, "network")
contract := network.GetContract(chaincodeName)
@@ -31,8 +29,7 @@ func TestNetwork(t *testing.T) {
t.Run("GetContractWithName returns correctly named Contract", func(t *testing.T) {
chaincodeName := "chaincode"
contractName := "contract"
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- network := AssertNewTestNetwork(t, "network", WithGatewayClient(mockClient))
+ network := AssertNewTestNetwork(t, "network")
contract := network.GetContractWithName(chaincodeName, contractName)
diff --git a/pkg/client/offlinesign_test.go b/pkg/client/offlinesign_test.go
index 323649f0f..535d051fe 100644
--- a/pkg/client/offlinesign_test.go
+++ b/pkg/client/offlinesign_test.go
@@ -5,573 +5,551 @@ package client
import (
"context"
- "errors"
+ "io"
"testing"
"github.com/hyperledger/fabric-protos-go-apiv2/common"
"github.com/hyperledger/fabric-protos-go-apiv2/gateway"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
- "google.golang.org/grpc"
)
func TestOfflineSign(t *testing.T) {
- var signature []byte
-
- newGatewayWithNoSign := func(t *testing.T, options ...ConnectOption) *Gateway {
- defaultOptions := []ConnectOption{
- WithDeliverClient(NewMockDeliverClient(gomock.NewController(t))),
- }
- options = append(defaultOptions, options...)
- gateway, err := Connect(TestCredentials.Identity(), options...)
- require.NoError(t, err)
-
- return gateway
- }
-
- newMockDeliverEvents := func(controller *gomock.Controller) *MockDeliver_DeliverClient {
- mockEvents := NewMockDeliver_DeliverClient(controller)
-
- mockEvents.EXPECT().Send(gomock.Any()).
- Do(func(in *common.Envelope) {
- signature = in.GetSignature()
- }).
- Return(nil).
- AnyTimes()
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
-
- return mockEvents
- }
-
- type Invocation struct {
- Invoke func() error
- }
-
- type Signable struct {
- Invocations map[string]Invocation
- OfflineSign func([]byte) *Signable
- State interface{}
- Recreate func() *Signable
- }
-
- var newSignableFromProposal func(t *testing.T, gateway *Gateway, proposal *Proposal) *Signable
- newSignableFromProposal = func(t *testing.T, gateway *Gateway, proposal *Proposal) *Signable {
- return &Signable{
- Invocations: map[string]Invocation{
- "Evaluate": {
- Invoke: func() error {
- _, err := proposal.Evaluate()
- return err
- },
+ for testName, testCase := range map[string]struct {
+ New func(*signingTest)
+ Sign func(*signingTest, []byte)
+ Invocations map[string](func(*signingTest) ([]byte, error))
+ Recreate func(*signingTest)
+ State func(*signingTest) any
+ }{
+ "Proposal": {
+ New: func(s *signingTest) {
+ s.NewProposal()
+ },
+ Sign: func(s *signingTest, signature []byte) {
+ s.SignProposal(signature)
+ },
+ Invocations: map[string](func(*signingTest) ([]byte, error)){
+ "Evaluate": func(s *signingTest) ([]byte, error) {
+ return s.Evaluate()
},
- "Endorse": {
- Invoke: func() error {
- _, err := proposal.Endorse()
- return err
- },
+ "Endorse": func(s *signingTest) ([]byte, error) {
+ return s.Endorse()
},
},
- OfflineSign: func(signature []byte) *Signable {
- bytes, err := proposal.Bytes()
- require.NoError(t, err, "Bytes")
-
- result, err := gateway.NewSignedProposal(bytes, signature)
- require.NoError(t, err, "NewSignedProposal")
-
- return newSignableFromProposal(t, gateway, result)
+ Recreate: func(s *signingTest) {
+ s.RecreateProposal()
},
- State: struct {
- Digest []byte
- TransactionID string
- EndorsingOrgs []string
- }{
- Digest: proposal.Digest(),
- TransactionID: proposal.TransactionID(),
- EndorsingOrgs: proposal.proposedTransaction.GetEndorsingOrganizations(),
+ State: func(s *signingTest) any {
+ return struct {
+ Digest []byte
+ TransactionID string
+ EndorsingOrgs []string
+ }{
+ Digest: s.proposal.Digest(),
+ TransactionID: s.proposal.TransactionID(),
+ EndorsingOrgs: s.proposal.proposedTransaction.GetEndorsingOrganizations(),
+ }
},
- Recreate: func() *Signable {
- signedBytes, err := proposal.Bytes()
- require.NoError(t, err, "NewSignedProposal")
-
- newProposal, err := gateway.NewProposal(signedBytes)
- require.NoError(t, err, "NewProposal")
-
- return newSignableFromProposal(t, gateway, newProposal)
+ },
+ "Transaction": {
+ New: func(s *signingTest) {
+ s.NewTransaction()
},
- }
- }
-
- var newSignableFromTransaction func(t *testing.T, gateway *Gateway, transaction *Transaction) *Signable
- newSignableFromTransaction = func(t *testing.T, gateway *Gateway, transaction *Transaction) *Signable {
- return &Signable{
- Invocations: map[string]Invocation{
- "Submit": {
- Invoke: func() error {
- _, err := transaction.Submit()
- return err
- },
+ Sign: func(s *signingTest, signature []byte) {
+ s.SignTransaction(signature)
+ },
+ Invocations: map[string](func(*signingTest) ([]byte, error)){
+ "Submit": func(s *signingTest) ([]byte, error) {
+ return s.Submit()
},
},
- OfflineSign: func(signature []byte) *Signable {
- bytes, err := transaction.Bytes()
- require.NoError(t, err, "Bytes")
-
- result, err := gateway.NewSignedTransaction(bytes, signature)
- require.NoError(t, err, "NewSignedTransaction")
-
- return newSignableFromTransaction(t, gateway, result)
+ Recreate: func(s *signingTest) {
+ s.RecreateTransaction()
},
- State: struct {
- Digest []byte
- TransactionID string
- }{
- Digest: transaction.Digest(),
- TransactionID: transaction.TransactionID(),
+ State: func(s *signingTest) any {
+ return struct {
+ Digest []byte
+ TransactionID string
+ Result []byte
+ }{
+ Digest: s.transaction.Digest(),
+ TransactionID: s.transaction.TransactionID(),
+ Result: s.transaction.Result(),
+ }
},
- Recreate: func() *Signable {
- signedBytes, err := transaction.Bytes()
- require.NoError(t, err, "NewSignedTransactionBytes")
-
- newTransaction, err := gateway.NewTransaction(signedBytes)
- require.NoError(t, err, "NewTransaction")
-
- return newSignableFromTransaction(t, gateway, newTransaction)
+ },
+ "Commit": {
+ New: func(s *signingTest) {
+ s.NewCommit()
},
- }
- }
-
- var newSignableFromCommit func(t *testing.T, gateway *Gateway, commit *Commit) *Signable
- newSignableFromCommit = func(t *testing.T, gateway *Gateway, commit *Commit) *Signable {
- return &Signable{
- Invocations: map[string]Invocation{
- "Status": {
- Invoke: func() error {
- _, err := commit.Status()
- return err
- },
+ Sign: func(s *signingTest, signature []byte) {
+ s.SignCommit(signature)
+ },
+ Invocations: map[string](func(*signingTest) ([]byte, error)){
+ "Status": func(s *signingTest) ([]byte, error) {
+ return s.CommitStatus()
},
},
- OfflineSign: func(signature []byte) *Signable {
- bytes, err := commit.Bytes()
- require.NoError(t, err, "Bytes")
-
- result, err := gateway.NewSignedCommit(bytes, signature)
- require.NoError(t, err, "NewSignedCommit")
-
- return newSignableFromCommit(t, gateway, result)
+ Recreate: func(s *signingTest) {
+ s.RecreateCommit()
},
- State: struct {
- Digest []byte
- TransactionID string
- }{
- Digest: commit.Digest(),
- TransactionID: commit.TransactionID(),
+ State: func(s *signingTest) any {
+ return struct {
+ Digest []byte
+ TransactionID string
+ }{
+ Digest: s.transaction.Digest(),
+ TransactionID: s.transaction.TransactionID(),
+ }
},
- Recreate: func() *Signable {
- signedBytes, err := commit.Bytes()
- require.NoError(t, err, "NewSignedCommitBytes")
-
- newCommit, err := gateway.NewCommit(signedBytes)
- require.NoError(t, err, "NewCommit")
-
- return newSignableFromCommit(t, gateway, newCommit)
+ },
+ "ChaincodeEvents": {
+ New: func(s *signingTest) {
+ s.NewChaincodeEvents()
},
- }
- }
-
- var newSignableFromChaincodeEventsRequest func(t *testing.T, gateway *Gateway, request *ChaincodeEventsRequest) *Signable
- newSignableFromChaincodeEventsRequest = func(t *testing.T, gateway *Gateway, request *ChaincodeEventsRequest) *Signable {
- return &Signable{
- Invocations: map[string]Invocation{
- "Events": {
- Invoke: func() error {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- _, err := request.Events(ctx)
- return err
- },
+ Sign: func(s *signingTest, signature []byte) {
+ s.SignChaincodeEvents(signature)
+ },
+ Invocations: map[string](func(*signingTest) ([]byte, error)){
+ "Events": func(s *signingTest) ([]byte, error) {
+ return s.ChaincodeEvents()
},
},
- OfflineSign: func(signature []byte) *Signable {
- bytes, err := request.Bytes()
- require.NoError(t, err, "Bytes")
-
- result, err := gateway.NewSignedChaincodeEventsRequest(bytes, signature)
- require.NoError(t, err, "NewSignedChaincodeEventsRequest")
-
- return newSignableFromChaincodeEventsRequest(t, gateway, result)
+ Recreate: func(s *signingTest) {
+ s.RecreateChaincodeEvents()
},
- State: struct {
- Digest []byte
- }{
- Digest: request.Digest(),
+ State: func(s *signingTest) any {
+ return struct {
+ Digest []byte
+ }{
+ Digest: s.chaincodeEvents.Digest(),
+ }
},
- Recreate: func() *Signable {
- signedBytes, err := request.Bytes()
- require.NoError(t, err, "NewSignedChaincodeEventsRequestBytes")
-
- newChaincodeRequest, err := gateway.NewChaincodeEventsRequest(signedBytes)
- require.NoError(t, err, "newChaincodeRequest")
-
- return newSignableFromChaincodeEventsRequest(t, gateway, newChaincodeRequest)
+ },
+ "BlockEvents": {
+ New: func(s *signingTest) {
+ s.NewBlockEvents()
},
- }
- }
-
- var newSignableFromBlockEventsRequest func(t *testing.T, gateway *Gateway, request *BlockEventsRequest) *Signable
- newSignableFromBlockEventsRequest = func(t *testing.T, gateway *Gateway, request *BlockEventsRequest) *Signable {
- return &Signable{
- Invocations: map[string]Invocation{
- "Events": {
- Invoke: func() error {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- _, err := request.Events(ctx)
- return err
- },
+ Sign: func(s *signingTest, signature []byte) {
+ s.SignBlockEvents(signature)
+ },
+ Invocations: map[string](func(*signingTest) ([]byte, error)){
+ "Events": func(s *signingTest) ([]byte, error) {
+ return s.BlockEvents()
},
},
- OfflineSign: func(signature []byte) *Signable {
- bytes, err := request.Bytes()
- require.NoError(t, err, "Bytes")
-
- result, err := gateway.NewSignedBlockEventsRequest(bytes, signature)
- require.NoError(t, err, "NewSignedBlockEventsRequest")
-
- return newSignableFromBlockEventsRequest(t, gateway, result)
+ Recreate: func(s *signingTest) {
+ s.RecreateBlockEvents()
},
- State: struct {
- Digest []byte
- }{
- Digest: request.Digest(),
+ State: func(s *signingTest) any {
+ return struct {
+ Digest []byte
+ }{
+ Digest: s.blockEvents.Digest(),
+ }
},
- Recreate: func() *Signable {
- signedBytes, err1 := request.Bytes()
- require.NoError(t, err1, "NewSignedBlockEventsRequestBytes")
-
- newBlockRequest, err2 := gateway.NewBlockEventsRequest(signedBytes)
- require.NoError(t, err2, "newBlockRequest")
-
- return newSignableFromBlockEventsRequest(t, gateway, newBlockRequest)
+ },
+ "FilteredBlockEvents": {
+ New: func(s *signingTest) {
+ s.NewFilteredBlockEvents()
},
- }
- }
-
- var newSignableFromFilteredBlockEventsRequest func(t *testing.T, gateway *Gateway, request *FilteredBlockEventsRequest) *Signable
- newSignableFromFilteredBlockEventsRequest = func(t *testing.T, gateway *Gateway, request *FilteredBlockEventsRequest) *Signable {
- return &Signable{
- Invocations: map[string]Invocation{
- "Events": {
- Invoke: func() error {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- _, err := request.Events(ctx)
- return err
- },
+ Sign: func(s *signingTest, signature []byte) {
+ s.SignFilteredBlockEvents(signature)
+ },
+ Invocations: map[string](func(*signingTest) ([]byte, error)){
+ "Events": func(s *signingTest) ([]byte, error) {
+ return s.FilteredBlockEvents()
},
},
- OfflineSign: func(signature []byte) *Signable {
- bytes, err := request.Bytes()
- require.NoError(t, err, "Bytes")
-
- result, err := gateway.NewSignedFilteredBlockEventsRequest(bytes, signature)
- require.NoError(t, err, "NewSignedFilteredBlockEventsRequest")
-
- return newSignableFromFilteredBlockEventsRequest(t, gateway, result)
+ Recreate: func(s *signingTest) {
+ s.RecreateFilteredBlockEvents()
},
- State: struct {
- Digest []byte
- }{
- Digest: request.Digest(),
+ State: func(s *signingTest) any {
+ return struct {
+ Digest []byte
+ }{
+ Digest: s.filteredBlockEvents.Digest(),
+ }
},
- Recreate: func() *Signable {
- signedBytes, err := request.Bytes()
- require.NoError(t, err, "NewSignedFilteredBlockEventsRequestBytes")
-
- newFilteredBlockRequest, err := gateway.NewFilteredBlockEventsRequest(signedBytes)
- require.NoError(t, err, "newRequest")
-
- return newSignableFromFilteredBlockEventsRequest(t, gateway, newFilteredBlockRequest)
+ },
+ "BlockAndPrivateDataEvents": {
+ New: func(s *signingTest) {
+ s.NewBlockAndPrivateDataEvents()
},
- }
- }
-
- var newSignableFromBlockAndPrivateDataEventsRequest func(t *testing.T, gateway *Gateway, request *BlockAndPrivateDataEventsRequest) *Signable
- newSignableFromBlockAndPrivateDataEventsRequest = func(t *testing.T, gateway *Gateway, request *BlockAndPrivateDataEventsRequest) *Signable {
- return &Signable{
- Invocations: map[string]Invocation{
- "Events": {
- Invoke: func() error {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- _, err := request.Events(ctx)
- return err
- },
+ Sign: func(s *signingTest, signature []byte) {
+ s.SignBlockAndPrivateDataEvents(signature)
+ },
+ Invocations: map[string](func(*signingTest) ([]byte, error)){
+ "Events": func(s *signingTest) ([]byte, error) {
+ return s.BlockAndPrivateDataEvents()
},
},
- OfflineSign: func(signature []byte) *Signable {
- bytes, err := request.Bytes()
- require.NoError(t, err, "Bytes")
-
- result, err := gateway.NewSignedBlockAndPrivateDataEventsRequest(bytes, signature)
- require.NoError(t, err, "NewSignedBlockEventsRequest")
-
- return newSignableFromBlockAndPrivateDataEventsRequest(t, gateway, result)
+ Recreate: func(s *signingTest) {
+ s.RecreateBlockAndPrivateDataEvents()
},
- State: struct {
- Digest []byte
- }{
- Digest: request.Digest(),
+ State: func(s *signingTest) any {
+ return struct {
+ Digest []byte
+ }{
+ Digest: s.blockAndPrivateDataEvents.Digest(),
+ }
},
- Recreate: func() *Signable {
- signedBytes, err1 := request.Bytes()
- require.NoError(t, err1, "NewSignedBlockAndPrivateDataEventsRequestBytes")
+ },
+ } {
+ t.Run(testName, func(t *testing.T) {
+ for invocationName, invoke := range testCase.Invocations {
+ t.Run(invocationName, func(t *testing.T) {
+ t.Run("Returns error with no signer and no explicit signing", func(t *testing.T) {
+ s := NewSigningTest(t)
+ testCase.New(s)
+ _, err := invoke(s)
+ require.Error(t, err)
+ })
- newBlockAndPrivateDataRequest, err2 := gateway.NewBlockAndPrivateDataEventsRequest(signedBytes)
- require.NoError(t, err2, "newBlockAndPrivateDataRequest")
+ t.Run("Uses off-line signature", func(t *testing.T) {
+ expected := []byte("SIGNATURE")
+ s := NewSigningTest(t)
- return newSignableFromBlockAndPrivateDataEventsRequest(t, gateway, newBlockAndPrivateDataRequest)
- },
- }
+ testCase.New(s)
+ testCase.Sign(s, expected)
+ actual, err := invoke(s)
+ require.NoError(t, err)
+
+ require.Equal(t, expected, actual)
+ })
+
+ t.Run("retains signature", func(t *testing.T) {
+ expected := []byte("SIGNATURE")
+ s := NewSigningTest(t)
+
+ testCase.New(s)
+ testCase.Sign(s, expected)
+
+ testCase.Recreate(s)
+ actual, err := invoke(s)
+ require.NoError(t, err)
+
+ require.Equal(t, expected, actual)
+ })
+ })
+ }
+
+ t.Run("Retains state after signing", func(t *testing.T) {
+ s := NewSigningTest(t)
+
+ testCase.New(s)
+ expected := testCase.State(s)
+
+ testCase.Sign(s, []byte("SIGNATURE"))
+ actual := testCase.State(s)
+
+ require.Equal(t, expected, actual)
+ })
+ })
}
+}
- for testName, testCase := range map[string]struct {
- Create func(*testing.T) *Signable
- }{
- "Proposal": {
- Create: func(t *testing.T) *Signable {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- signature = in.GetProposedTransaction().GetSignature()
- }).
- Return(&gateway.EvaluateResponse{
- Result: &peer.Response{
- Payload: nil,
- },
- }, nil).
- AnyTimes()
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- signature = in.GetProposedTransaction().GetSignature()
- }).
- Return(AssertNewEndorseResponse(t, "result", "network"), nil).
- AnyTimes()
-
- gateway := newGatewayWithNoSign(t, WithGatewayClient(mockClient))
- contract := gateway.GetNetwork("NETWORK").GetContract("CHAINCODE")
-
- proposal, err := contract.NewProposal("transaction")
- require.NoError(t, err)
-
- return newSignableFromProposal(t, gateway, proposal)
- },
- },
- "Transaction": {
- Create: func(t *testing.T) *Signable {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "result", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SubmitRequest, _ ...grpc.CallOption) {
- signature = in.GetPreparedTransaction().GetSignature()
- }).
- Return(nil, nil).
- AnyTimes()
+type signingTest struct {
+ t *testing.T
+ mockConnection *MockClientConnInterface
+ gateway *Gateway
+ proposal *Proposal
+ transaction *Transaction
+ commit *Commit
+ chaincodeEvents *ChaincodeEventsRequest
+ blockEvents *BlockEventsRequest
+ filteredBlockEvents *FilteredBlockEventsRequest
+ blockAndPrivateDataEvents *BlockAndPrivateDataEventsRequest
+}
- gateway := newGatewayWithNoSign(t, WithGatewayClient(mockClient))
- contract := gateway.GetNetwork("NETWORK").GetContract("CHAINCODE")
+func NewSigningTest(t *testing.T) *signingTest {
+ mockConnection := NewMockClientConnInterface(t)
+ gateway, err := Connect(TestCredentials.Identity(), WithClientConnection(mockConnection))
+ require.NoError(t, err, "Connect")
- unsignedProposal, err := contract.NewProposal("transaction")
- require.NoError(t, err)
+ return &signingTest{
+ t: t,
+ mockConnection: mockConnection,
+ gateway: gateway,
+ }
+}
- proposalBytes, err := unsignedProposal.Bytes()
- require.NoError(t, err)
+func (s *signingTest) NewProposal() {
+ result, err := s.gateway.GetNetwork("channel").GetContract("chaincode").NewProposal("transaction")
+ require.NoError(s.t, err, "NewProposal")
+ s.proposal = result
+}
- signedProposal, err := gateway.NewSignedProposal(proposalBytes, []byte("SIGNATURE"))
- require.NoError(t, err)
+func (s *signingTest) SignProposal(signature []byte) {
+ bytes := s.getBytes(s.proposal)
+ result, err := s.gateway.NewSignedProposal(bytes, signature)
+ require.NoError(s.t, err, "NewSignedProposal")
+ s.proposal = result
+}
- transaction, err := signedProposal.Endorse()
- require.NoError(t, err)
+func (s *signingTest) getBytes(serializable interface {
+ Bytes() ([]byte, error)
+}) []byte {
+ bytes, err := serializable.Bytes()
+ require.NoError(s.t, err, "Bytes")
+ return bytes
+}
- return newSignableFromTransaction(t, gateway, transaction)
- },
- },
- "Commit": {
- Create: func(t *testing.T) *Signable {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "result", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil).
- AnyTimes()
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedCommitStatusRequest, _ ...grpc.CallOption) {
- signature = in.GetSignature()
- }).
- Return(&gateway.CommitStatusResponse{
- Result: peer.TxValidationCode_VALID,
- }, nil).
- AnyTimes()
+func (s *signingTest) RecreateProposal() {
+ bytes := s.getBytes(s.proposal)
+ result, err := s.gateway.NewProposal(bytes)
+ require.NoError(s.t, err, "NewProposal")
+ s.proposal = result
+}
- gateway := newGatewayWithNoSign(t, WithGatewayClient(mockClient))
- contract := gateway.GetNetwork("NETWORK").GetContract("CHAINCODE")
+func (s *signingTest) Evaluate() ([]byte, error) {
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(s.mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(nil)).Maybe()
- unsignedProposal, err := contract.NewProposal("transaction")
- require.NoError(t, err)
+ _, err := s.proposal.Evaluate()
+ if err != nil {
+ return nil, err
+ }
- proposalBytes, err := unsignedProposal.Bytes()
- require.NoError(t, err)
+ return (<-requests).GetProposedTransaction().GetSignature(), nil
+}
- signedProposal, err := gateway.NewSignedProposal(proposalBytes, []byte("SIGNATURE"))
- require.NoError(t, err)
+func (s *signingTest) endorse() (*Transaction, []byte, error) {
+ requests := make(chan *gateway.EndorseRequest, 1)
+ response := AssertNewEndorseResponse(s.t, "TRANSACTION_RESULT", "network")
+ ExpectEndorse(s.mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(response)).Maybe()
- unsignedTransaction, err := signedProposal.Endorse()
- require.NoError(t, err)
+ transaction, err := s.proposal.Endorse()
+ if err != nil {
+ return nil, nil, err
+ }
- transactionBytes, err := unsignedTransaction.Bytes()
- require.NoError(t, err)
+ return transaction, (<-requests).ProposedTransaction.GetSignature(), nil
+}
- signedTransaction, err := gateway.NewSignedTransaction(transactionBytes, []byte("SIGNATURE"))
- require.NoError(t, err)
+func (s *signingTest) Endorse() ([]byte, error) {
+ _, signature, err := s.endorse()
+ return signature, err
+}
- commit, err := signedTransaction.Submit()
- require.NoError(t, err)
+func (s *signingTest) NewTransaction() {
+ s.NewProposal()
+ s.SignProposal([]byte("SIGNATURE"))
+ transaction, _, err := s.endorse()
+ require.NoError(s.t, err, "Endorse")
- return newSignableFromCommit(t, gateway, commit)
- },
- },
- "Chaincode events": {
- Create: func(t *testing.T) *Signable {
- controller := gomock.NewController(t)
- mockClient := NewMockGatewayClient(controller)
- mockEvents := NewMockGateway_ChaincodeEventsClient(controller)
+ s.transaction = transaction
+}
- mockClient.EXPECT().ChaincodeEvents(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedChaincodeEventsRequest, _ ...grpc.CallOption) {
- signature = in.GetSignature()
- }).
- Return(mockEvents, nil).
- AnyTimes()
+func (s *signingTest) SignTransaction(signature []byte) {
+ bytes := s.getBytes(s.transaction)
+ result, err := s.gateway.NewSignedTransaction(bytes, signature)
+ require.NoError(s.t, err, "NewSignedTransaction")
- mockEvents.EXPECT().Recv().
- Return(nil, errors.New("fake")).
- AnyTimes()
+ s.transaction = result
+}
- gateway := newGatewayWithNoSign(t, WithGatewayClient(mockClient))
- network := gateway.GetNetwork("NETWORK")
+func (s *signingTest) RecreateTransaction() {
+ bytes := s.getBytes(s.transaction)
+ result, err := s.gateway.NewTransaction(bytes)
+ require.NoError(s.t, err, "NewTransaction")
- request, err := network.NewChaincodeEventsRequest("CHAINCODE")
- require.NoError(t, err)
+ s.transaction = result
+}
- return newSignableFromChaincodeEventsRequest(t, gateway, request)
- },
- },
- "Block events": {
- Create: func(t *testing.T) *Signable {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := newMockDeliverEvents(controller)
+func (s *signingTest) submit() (*Commit, []byte, error) {
+ requests := make(chan *gateway.SubmitRequest, 1)
+ ExpectSubmit(s.mockConnection, CaptureInvokeRequest(requests)).Maybe()
- mockClient.EXPECT().Deliver(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil).
- AnyTimes()
+ commit, err := s.transaction.Submit()
+ if err != nil {
+ return nil, nil, err
+ }
- gateway := newGatewayWithNoSign(t, WithGatewayClient(NewMockGatewayClient(controller)), WithDeliverClient(mockClient))
- network := gateway.GetNetwork("NETWORK")
+ return commit, (<-requests).GetPreparedTransaction().GetSignature(), nil
+}
- request, err := network.NewBlockEventsRequest()
- require.NoError(t, err)
+func (s *signingTest) Submit() ([]byte, error) {
+ _, signature, err := s.submit()
+ return signature, err
+}
- return newSignableFromBlockEventsRequest(t, gateway, request)
- },
- },
- "Filtered block events": {
- Create: func(t *testing.T) *Signable {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := newMockDeliverEvents(controller)
+func (s *signingTest) NewCommit() {
+ s.NewTransaction()
+ s.SignTransaction([]byte("SIGNATURE"))
+ commit, _, err := s.submit()
+ require.NoError(s.t, err, "Submit")
- mockClient.EXPECT().DeliverFiltered(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil).
- AnyTimes()
+ s.commit = commit
+}
- gateway := newGatewayWithNoSign(t, WithGatewayClient(NewMockGatewayClient(controller)), WithDeliverClient(mockClient))
- network := gateway.GetNetwork("NETWORK")
+func (s *signingTest) SignCommit(signature []byte) {
+ bytes := s.getBytes(s.commit)
+ result, err := s.gateway.NewSignedCommit(bytes, signature)
+ require.NoError(s.t, err, "NewSignedCommit")
- request, err := network.NewFilteredBlockEventsRequest()
- require.NoError(t, err)
+ s.commit = result
+}
- return newSignableFromFilteredBlockEventsRequest(t, gateway, request)
- },
- },
- "Block and private data events": {
- Create: func(t *testing.T) *Signable {
- controller := gomock.NewController(t)
- mockClient := NewMockDeliverClient(controller)
- mockEvents := newMockDeliverEvents(controller)
+func (s *signingTest) RecreateCommit() {
+ bytes := s.getBytes(s.commit)
+ result, err := s.gateway.NewCommit(bytes)
+ require.NoError(s.t, err, "NewCommit")
+ s.commit = result
+}
- mockClient.EXPECT().DeliverWithPrivateData(gomock.Any(), gomock.Any()).
- Return(mockEvents, nil).
- AnyTimes()
+func (s *signingTest) CommitStatus() ([]byte, error) {
+ requests := make(chan *gateway.SignedCommitStatusRequest, 1)
+ ExpectCommitStatus(s.mockConnection, CaptureInvokeRequest(requests), WithCommitStatusResponse(peer.TxValidationCode_VALID, 1)).Maybe()
- gateway := newGatewayWithNoSign(t, WithGatewayClient(NewMockGatewayClient(controller)), WithDeliverClient(mockClient))
- network := gateway.GetNetwork("NETWORK")
+ _, err := s.commit.Status()
+ if err != nil {
+ return nil, err
+ }
- request, err := network.NewBlockAndPrivateDataEventsRequest()
- require.NoError(t, err)
+ return (<-requests).GetSignature(), nil
+}
- return newSignableFromBlockAndPrivateDataEventsRequest(t, gateway, request)
- },
- },
- } {
- t.Run(testName, func(t *testing.T) {
- unsigned := testCase.Create(t)
+func (s *signingTest) NewChaincodeEvents() {
+ result, err := s.gateway.GetNetwork("channel").NewChaincodeEventsRequest("chaincode")
+ require.NoError(s.t, err, "NewChaincodeEventsRequest")
+ s.chaincodeEvents = result
+}
- for invocationName, invocation := range unsigned.Invocations {
- t.Run(invocationName, func(t *testing.T) {
- t.Run("Returns error with no signer and no explicit signing", func(t *testing.T) {
- err := invocation.Invoke()
- require.Error(t, err)
- })
+func (s *signingTest) SignChaincodeEvents(signature []byte) {
+ bytes := s.getBytes(s.chaincodeEvents)
+ result, err := s.gateway.NewSignedChaincodeEventsRequest(bytes, signature)
+ require.NoError(s.t, err, "NewSignedChaincodeEventsRequest")
+ s.chaincodeEvents = result
+}
- t.Run("Uses off-line signature", func(t *testing.T) {
- signature = nil
- expected := []byte("SIGNATURE")
+func (s *signingTest) RecreateChaincodeEvents() {
+ bytes := s.getBytes(s.chaincodeEvents)
+ result, err := s.gateway.NewChaincodeEventsRequest(bytes)
+ require.NoError(s.t, err, "NewChaincodeEventsRequest")
+ s.chaincodeEvents = result
+}
- signed := unsigned.OfflineSign(expected)
- err := signed.Invocations[invocationName].Invoke()
- require.NoError(t, err)
+func (s *signingTest) ChaincodeEvents() ([]byte, error) {
+ mockStream := NewMockClientStream(s.t)
+ ExpectChaincodeEvents(s.mockConnection, WithNewStreamResult(mockStream)).Maybe()
- require.EqualValues(t, expected, signature)
- })
+ messages := make(chan *gateway.SignedChaincodeEventsRequest, 1)
+ ExpectSendMsg(mockStream, CaptureSendMsg(messages)).Maybe()
+ mockStream.EXPECT().CloseSend().Return(nil).Maybe()
+ ExpectRecvMsg(mockStream).Return(io.EOF).Maybe()
- t.Run("retains signature", func(t *testing.T) {
- signature = nil
- expected := []byte("SIGNATURE")
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
- signed := unsigned.OfflineSign(expected)
- recreated := signed.Recreate()
- err := recreated.Invocations[invocationName].Invoke()
- require.NoError(t, err)
+ _, err := s.chaincodeEvents.Events(ctx)
+ if err != nil {
+ return nil, err
+ }
- require.EqualValues(t, expected, signature)
+ return (<-messages).GetSignature(), nil
+}
- })
- })
- }
+func (s *signingTest) NewBlockEvents() {
+ result, err := s.gateway.GetNetwork("channel").NewBlockEventsRequest()
+ require.NoError(s.t, err, "NewBlockEventsRequest")
+ s.blockEvents = result
+}
- t.Run("Retains state after signing", func(t *testing.T) {
- signed := unsigned.OfflineSign([]byte("SIGNATURE"))
- require.EqualValues(t, unsigned.State, signed.State)
- })
- })
+func (s *signingTest) SignBlockEvents(signature []byte) {
+ bytes := s.getBytes(s.blockEvents)
+ result, err := s.gateway.NewSignedBlockEventsRequest(bytes, signature)
+ require.NoError(s.t, err, "NewSignedBlockEventsRequest")
+ s.blockEvents = result
+}
+
+func (s *signingTest) RecreateBlockEvents() {
+ bytes := s.getBytes(s.blockEvents)
+ result, err := s.gateway.NewBlockEventsRequest(bytes)
+ require.NoError(s.t, err, "NewBlockEventsRequest")
+ s.blockEvents = result
+}
+
+func (s *signingTest) BlockEvents() ([]byte, error) {
+ return s.deliverEvents(func(ctx context.Context) error {
+ _, err := s.blockEvents.Events(ctx)
+ return err
+ })
+}
+
+func (s *signingTest) deliverEvents(invoke func(context.Context) error) ([]byte, error) {
+ mockStream := NewMockClientStream(s.t)
+ ExpectDeliver(s.mockConnection, WithNewStreamResult(mockStream)).Maybe()
+ ExpectDeliverFiltered(s.mockConnection, WithNewStreamResult(mockStream)).Maybe()
+ ExpectDeliverWithPrivateData(s.mockConnection, WithNewStreamResult(mockStream)).Maybe()
+
+ messages := make(chan *common.Envelope, 1)
+ ExpectSendMsg(mockStream, CaptureSendMsg(messages)).Maybe()
+ mockStream.EXPECT().CloseSend().Return(nil).Maybe()
+ ExpectRecvMsg(mockStream).Return(io.EOF).Maybe()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ err := invoke(ctx)
+ if err != nil {
+ return nil, err
}
+
+ return (<-messages).GetSignature(), nil
+}
+
+func (s *signingTest) NewFilteredBlockEvents() {
+ result, err := s.gateway.GetNetwork("channel").NewFilteredBlockEventsRequest()
+ require.NoError(s.t, err, "NewFilteredBlockEventsRequest")
+ s.filteredBlockEvents = result
+}
+
+func (s *signingTest) SignFilteredBlockEvents(signature []byte) {
+ bytes := s.getBytes(s.filteredBlockEvents)
+ result, err := s.gateway.NewSignedFilteredBlockEventsRequest(bytes, signature)
+ require.NoError(s.t, err, "NewSignedFilteredBlockEventsRequest")
+ s.filteredBlockEvents = result
+}
+
+func (s *signingTest) RecreateFilteredBlockEvents() {
+ bytes := s.getBytes(s.filteredBlockEvents)
+ result, err := s.gateway.NewFilteredBlockEventsRequest(bytes)
+ require.NoError(s.t, err, "NewFilteredBlockEventsRequest")
+ s.filteredBlockEvents = result
+}
+
+func (s *signingTest) FilteredBlockEvents() ([]byte, error) {
+ return s.deliverEvents(func(ctx context.Context) error {
+ _, err := s.filteredBlockEvents.Events(ctx)
+ return err
+ })
+}
+
+func (s *signingTest) NewBlockAndPrivateDataEvents() {
+ result, err := s.gateway.GetNetwork("channel").NewBlockAndPrivateDataEventsRequest()
+ require.NoError(s.t, err, "NewBlockAndPrivateDataEventsRequest")
+ s.blockAndPrivateDataEvents = result
+}
+
+func (s *signingTest) SignBlockAndPrivateDataEvents(signature []byte) {
+ bytes := s.getBytes(s.blockAndPrivateDataEvents)
+ result, err := s.gateway.NewSignedBlockAndPrivateDataEventsRequest(bytes, signature)
+ require.NoError(s.t, err, "NewSignedBlockAndPrivateDataEventsRequest")
+ s.blockAndPrivateDataEvents = result
+}
+
+func (s *signingTest) RecreateBlockAndPrivateDataEvents() {
+ bytes := s.getBytes(s.blockAndPrivateDataEvents)
+ result, err := s.gateway.NewBlockAndPrivateDataEventsRequest(bytes)
+ require.NoError(s.t, err, "NewBlockAndPrivateDataEventsRequest")
+ s.blockAndPrivateDataEvents = result
+}
+
+func (s *signingTest) BlockAndPrivateDataEvents() ([]byte, error) {
+ return s.deliverEvents(func(ctx context.Context) error {
+ _, err := s.blockAndPrivateDataEvents.Events(ctx)
+ return err
+ })
}
diff --git a/pkg/client/protobuf_test.go b/pkg/client/protobuf_test.go
new file mode 100644
index 000000000..dc02d536e
--- /dev/null
+++ b/pkg/client/protobuf_test.go
@@ -0,0 +1,422 @@
+// Copyright IBM Corp. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "strings"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/hyperledger/fabric-protos-go-apiv2/common"
+ "github.com/hyperledger/fabric-protos-go-apiv2/gateway"
+ "github.com/hyperledger/fabric-protos-go-apiv2/msp"
+ "github.com/hyperledger/fabric-protos-go-apiv2/peer"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/runtime/protoiface"
+ "google.golang.org/protobuf/testing/protocmp"
+)
+
+// AssertProtoEqual ensures an expected protobuf message matches an actual message
+func AssertProtoEqual(t *testing.T, expected protoreflect.ProtoMessage, actual protoreflect.ProtoMessage) {
+ if diff := cmp.Diff(expected, actual, protocmp.Transform()); diff != "" {
+ require.FailNow(t, fmt.Sprintf(
+ "Not equal:\nexpected: %s\nactual : %s\n\nDiff:\n- Expected\n+ Actual\n\n%s",
+ formatProto(expected),
+ formatProto(actual),
+ diff,
+ ))
+ }
+}
+
+func formatProto(message proto.Message) string {
+ if message == nil {
+ return fmt.Sprintf("%T", message)
+ }
+
+ marshal := prototext.MarshalOptions{
+ Multiline: true,
+ Indent: "\t",
+ AllowPartial: true,
+ }
+ formatted := strings.TrimSpace(marshal.Format(message))
+ return fmt.Sprintf("%s{\n%s\n}", protoMessageType(message), indent(formatted))
+}
+
+func protoMessageType(message proto.Message) string {
+ return string(message.ProtoReflect().Descriptor().Name())
+}
+
+func indent(text string) string {
+ return "\t" + strings.ReplaceAll(text, "\n", "\n\t")
+}
+
+// AssertUnmarshal ensures that a protobuf is umarshaled without error
+func AssertUnmarshal(t *testing.T, b []byte, m protoreflect.ProtoMessage) {
+ err := proto.Unmarshal(b, m)
+ require.NoError(t, err)
+}
+
+// AssertUnmarshalProposalPayload ensures that a ChaincodeProposalPayload protobuf is umarshalled without error
+func AssertUnmarshalProposalPayload(t *testing.T, proposedTransaction *peer.SignedProposal) *peer.ChaincodeProposalPayload {
+ proposal := &peer.Proposal{}
+ AssertUnmarshal(t, proposedTransaction.ProposalBytes, proposal)
+
+ payload := &peer.ChaincodeProposalPayload{}
+ AssertUnmarshal(t, proposal.Payload, payload)
+
+ return payload
+}
+
+// AssertUnmarshalInvocationSpec ensures that a ChaincodeInvocationSpec protobuf is umarshalled without error
+func AssertUnmarshalInvocationSpec(t *testing.T, proposedTransaction *peer.SignedProposal) *peer.ChaincodeInvocationSpec {
+ proposal := &peer.Proposal{}
+ AssertUnmarshal(t, proposedTransaction.ProposalBytes, proposal)
+
+ payload := &peer.ChaincodeProposalPayload{}
+ AssertUnmarshal(t, proposal.Payload, payload)
+
+ input := &peer.ChaincodeInvocationSpec{}
+ AssertUnmarshal(t, payload.Input, input)
+
+ return input
+}
+
+// AssertUnmarshalChannelheader ensures that a ChannelHeader protobuf is umarshalled without error
+func AssertUnmarshalChannelheader(t *testing.T, proposedTransaction *peer.SignedProposal) *common.ChannelHeader {
+ header := AssertUnmarshalHeader(t, proposedTransaction)
+
+ channelHeader := &common.ChannelHeader{}
+ AssertUnmarshal(t, header.ChannelHeader, channelHeader)
+
+ return channelHeader
+}
+
+// AssertUnmarshalHeader ensures that a Header protobuf is umarshalled without error
+func AssertUnmarshalHeader(t *testing.T, proposedTransaction *peer.SignedProposal) *common.Header {
+ proposal := &peer.Proposal{}
+ AssertUnmarshal(t, proposedTransaction.ProposalBytes, proposal)
+
+ header := &common.Header{}
+ AssertUnmarshal(t, proposal.Header, header)
+
+ return header
+}
+
+// AssertUnmarshalSignatureHeader ensures that a SignatureHeader protobuf is umarshalled without error
+func AssertUnmarshalSignatureHeader(t *testing.T, proposedTransaction *peer.SignedProposal) *common.SignatureHeader {
+ header := AssertUnmarshalHeader(t, proposedTransaction)
+
+ signatureHeader := &common.SignatureHeader{}
+ AssertUnmarshal(t, header.SignatureHeader, signatureHeader)
+
+ return signatureHeader
+}
+
+type invokeFunction func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error
+
+func ExpectEvaluate(mockConnection *MockClientConnInterface, options ...invokeFunction) *MockClientConnInterface_Invoke_Call {
+ invokeCall := mockConnection.EXPECT().
+ Invoke(mock.Anything, "/gateway.Gateway/Evaluate", mock.Anything, mock.Anything, mock.Anything)
+ fakeInvoke(invokeCall, options...)
+ return invokeCall
+}
+
+func fakeInvoke(mock *MockClientConnInterface_Invoke_Call, options ...invokeFunction) {
+ mock.RunAndReturn(func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ for _, option := range options {
+ if err := option(ctx, method, args, reply, opts...); err != nil {
+ return err
+ }
+ }
+
+ return nil
+ })
+}
+
+func WithEvaluateResponse(value []byte) invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ proto.Merge(reply.(proto.Message), &gateway.EvaluateResponse{
+ Result: &peer.Response{
+ Payload: value,
+ },
+ })
+ return nil
+ }
+}
+
+// WithInvokeContextErr causes the invoke to return any error associated with the invocation context; otherwise it has
+// no effect.
+func WithInvokeContextErr() invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ return ctx.Err()
+ }
+}
+
+func WithInvokeError(err error) invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ return err
+ }
+}
+
+func CaptureInvokeRequest[T proto.Message](requests chan<- T) invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ TrySend(requests, args.(T))
+ return nil
+ }
+}
+
+func CaptureInvokeOptions(callOptions chan<- []grpc.CallOption) invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ TrySend(callOptions, opts)
+ return nil
+ }
+}
+
+func CaptureInvokeContext(contexts chan<- context.Context) invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ TrySend(contexts, ctx)
+ return nil
+ }
+}
+
+func TrySend[T any](channel chan<- T, value T) bool {
+ select {
+ case channel <- value:
+ return true
+ default:
+ return false
+ }
+}
+
+func NewStatusError(t *testing.T, code codes.Code, message string, details ...protoiface.MessageV1) error {
+ s, err := status.New(code, message).WithDetails(details...)
+ require.NoError(t, err)
+
+ return s.Err()
+}
+
+func ExpectEndorse(mockConnection *MockClientConnInterface, options ...invokeFunction) *MockClientConnInterface_Invoke_Call {
+ invokeCall := mockConnection.EXPECT().
+ Invoke(mock.Anything, "/gateway.Gateway/Endorse", mock.Anything, mock.Anything, mock.Anything)
+ fakeInvoke(invokeCall, options...)
+ return invokeCall
+}
+
+func ExpectSubmit(mockConnection *MockClientConnInterface, options ...invokeFunction) *MockClientConnInterface_Invoke_Call {
+ invokeCall := mockConnection.EXPECT().
+ Invoke(mock.Anything, "/gateway.Gateway/Submit", mock.Anything, mock.Anything, mock.Anything)
+ fakeInvoke(invokeCall, options...)
+ return invokeCall
+}
+
+func ExpectCommitStatus(mockConnection *MockClientConnInterface, options ...invokeFunction) *MockClientConnInterface_Invoke_Call {
+ invokeCall := mockConnection.EXPECT().
+ Invoke(mock.Anything, "/gateway.Gateway/CommitStatus", mock.Anything, mock.Anything, mock.Anything)
+ fakeInvoke(invokeCall, options...)
+ return invokeCall
+}
+
+func WithEndorseResponse(response *gateway.EndorseResponse) invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ proto.Merge(reply.(proto.Message), response)
+ return nil
+ }
+}
+
+func WithCommitStatusResponse(status peer.TxValidationCode, blockNumber uint64) invokeFunction {
+ return func(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error {
+ proto.Merge(reply.(proto.Message), &gateway.CommitStatusResponse{
+ Result: status,
+ BlockNumber: blockNumber,
+ })
+ return nil
+ }
+}
+
+type newStreamFunction func(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error)
+
+func ExpectChaincodeEvents(mockConnection *MockClientConnInterface, options ...newStreamFunction) *MockClientConnInterface_NewStream_Call {
+ newStreamCall := mockConnection.EXPECT().
+ NewStream(mock.Anything, mock.Anything, "/gateway.Gateway/ChaincodeEvents", mock.Anything)
+ fakeNewStream(newStreamCall, options...)
+ return newStreamCall
+}
+
+func ExpectDeliver(mockConnection *MockClientConnInterface, options ...newStreamFunction) *MockClientConnInterface_NewStream_Call {
+ newStreamCall := mockConnection.EXPECT().
+ NewStream(mock.Anything, mock.Anything, "/protos.Deliver/Deliver", mock.Anything)
+ fakeNewStream(newStreamCall, options...)
+ return newStreamCall
+}
+
+func ExpectDeliverFiltered(mockConnection *MockClientConnInterface, options ...newStreamFunction) *MockClientConnInterface_NewStream_Call {
+ newStreamCall := mockConnection.EXPECT().
+ NewStream(mock.Anything, mock.Anything, "/protos.Deliver/DeliverFiltered", mock.Anything)
+ fakeNewStream(newStreamCall, options...)
+ return newStreamCall
+}
+
+func ExpectDeliverWithPrivateData(mockConnection *MockClientConnInterface, options ...newStreamFunction) *MockClientConnInterface_NewStream_Call {
+ newStreamCall := mockConnection.EXPECT().
+ NewStream(mock.Anything, mock.Anything, "/protos.Deliver/DeliverWithPrivateData", mock.Anything)
+ fakeNewStream(newStreamCall, options...)
+ return newStreamCall
+}
+
+func fakeNewStream(mock *MockClientConnInterface_NewStream_Call, options ...newStreamFunction) {
+ mock.RunAndReturn(func(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ for _, option := range options {
+ if stream, err := option(ctx, desc, method, opts...); stream != nil || err != nil {
+ return stream, err
+ }
+ }
+
+ return nil, nil
+ })
+}
+
+func WithNewStreamResult(stream grpc.ClientStream) newStreamFunction {
+ return func(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ return stream, nil
+ }
+}
+
+func WithNewStreamError(err error) newStreamFunction {
+ return func(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ return nil, err
+ }
+}
+
+func CaptureNewStreamOptions(callOptions chan<- []grpc.CallOption) newStreamFunction {
+ return func(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ TrySend(callOptions, opts)
+ return nil, nil
+ }
+}
+
+type sendMsgFunction func(message any) error
+
+func ExpectSendMsg(mockStream *MockClientStream, options ...sendMsgFunction) *MockClientStream_SendMsg_Call {
+ result := mockStream.EXPECT().SendMsg(mock.Anything)
+ result.RunAndReturn(func(message any) error {
+ for _, option := range options {
+ if err := option(message); err != nil {
+ return err
+ }
+ }
+
+ return nil
+ })
+ return result
+}
+
+func CaptureSendMsg[T proto.Message](messages chan<- T) sendMsgFunction {
+ return func(message any) error {
+ TrySend(messages, message.(T))
+ return nil
+ }
+}
+
+type recvMsgFunction func(message any) error
+
+func ExpectRecvMsg(mockStream *MockClientStream, options ...recvMsgFunction) *MockClientStream_RecvMsg_Call {
+ result := mockStream.EXPECT().RecvMsg(mock.Anything)
+
+ if len(options) > 0 {
+ result.RunAndReturn(func(message any) error {
+ for _, option := range options {
+ if err := option(message); err != nil {
+ return err
+ }
+ }
+
+ return nil
+ })
+ }
+
+ return result
+}
+
+func WithRecvMsgs[T proto.Message](responses ...T) recvMsgFunction {
+ responseChannel := make(chan proto.Message, len(responses))
+ for _, response := range responses {
+ responseChannel <- response
+ }
+ close(responseChannel)
+
+ return func(message any) error {
+ response, ok := <-responseChannel
+ if !ok {
+ return io.EOF
+ }
+
+ proto.Merge(message.(proto.Message), response)
+ return nil
+ }
+}
+
+func AssertMarshal(t *testing.T, message protoreflect.ProtoMessage, msgAndArgs ...any) []byte {
+ bytes, err := proto.Marshal(message)
+ require.NoError(t, err, msgAndArgs...)
+ return bytes
+}
+
+func AssertNewEndorseResponse(t *testing.T, result string, channelName string) *gateway.EndorseResponse {
+ return &gateway.EndorseResponse{
+ PreparedTransaction: &common.Envelope{
+ Payload: AssertMarshal(t, &common.Payload{
+ Header: &common.Header{
+ ChannelHeader: AssertMarshal(t, &common.ChannelHeader{
+ ChannelId: channelName,
+ }),
+ },
+ Data: AssertMarshal(t, &peer.Transaction{
+ Actions: []*peer.TransactionAction{
+ {
+ Payload: AssertMarshal(t, &peer.ChaincodeActionPayload{
+ Action: &peer.ChaincodeEndorsedAction{
+ ProposalResponsePayload: AssertMarshal(t, &peer.ProposalResponsePayload{
+ Extension: AssertMarshal(t, &peer.ChaincodeAction{
+ Response: &peer.Response{
+ Payload: []byte(result),
+ },
+ }),
+ }),
+ },
+ }),
+ },
+ },
+ }),
+ }),
+ },
+ }
+}
+
+func AssertValidBlockEventRequestHeader(t *testing.T, payload *common.Payload, expectedChannel string) {
+ channelHeader := &common.ChannelHeader{}
+ AssertUnmarshal(t, payload.GetHeader().GetChannelHeader(), channelHeader)
+
+ require.Equal(t, expectedChannel, channelHeader.GetChannelId(), "channel name")
+
+ signatureHeader := &common.SignatureHeader{}
+ AssertUnmarshal(t, payload.GetHeader().GetSignatureHeader(), signatureHeader)
+
+ expectedCreator := &msp.SerializedIdentity{
+ Mspid: TestCredentials.Identity().MspID(),
+ IdBytes: TestCredentials.Identity().Credentials(),
+ }
+ actualCreator := &msp.SerializedIdentity{}
+ AssertUnmarshal(t, signatureHeader.GetCreator(), actualCreator)
+ AssertProtoEqual(t, expectedCreator, actualCreator)
+}
diff --git a/pkg/client/sign_test.go b/pkg/client/sign_test.go
index d9cd96f37..1c567254b 100644
--- a/pkg/client/sign_test.go
+++ b/pkg/client/sign_test.go
@@ -4,110 +4,81 @@
package client
import (
- "context"
"testing"
"github.com/hyperledger/fabric-protos-go-apiv2/gateway"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
- "google.golang.org/grpc"
)
func TestSign(t *testing.T) {
- evaluateResponse := &gateway.EvaluateResponse{
- Result: &peer.Response{
- Payload: nil,
- },
- }
-
- statusResponse := &gateway.CommitStatusResponse{
- Result: peer.TxValidationCode_VALID,
- }
+ endorseResponse := AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network")
t.Run("Evaluate signs proposal using client signing implementation", func(t *testing.T) {
expected := []byte("SIGNATURE")
+
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EvaluateRequest, 1)
+ ExpectEvaluate(mockConnection, CaptureInvokeRequest(requests), WithEvaluateResponse(expected))
+
sign := func(digest []byte) ([]byte, error) {
return expected, nil
}
- var actual []byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EvaluateRequest, _ ...grpc.CallOption) {
- actual = in.ProposedTransaction.Signature
- }).
- Return(evaluateResponse, nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "contract", WithGatewayClient(mockClient), WithSign(sign))
+ contract := AssertNewTestContract(t, "contract", WithClientConnection(mockConnection), WithSign(sign))
_, err := contract.EvaluateTransaction("transaction")
require.NoError(t, err)
+ actual := (<-requests).ProposedTransaction.Signature
require.EqualValues(t, expected, actual)
})
t.Run("Submit signs proposal using client signing implementation", func(t *testing.T) {
expected := []byte("SIGNATURE")
+
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(endorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
sign := func(digest []byte) ([]byte, error) {
return expected, nil
}
- var actual []byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = in.ProposedTransaction.Signature
- }).
- Return(AssertNewEndorseResponse(t, "result", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(statusResponse, nil)
-
- contract := AssertNewTestContract(t, "contract", WithGatewayClient(mockClient), WithSign(sign))
+ contract := AssertNewTestContract(t, "contract", WithClientConnection(mockConnection), WithSign(sign))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := (<-requests).ProposedTransaction.Signature
require.EqualValues(t, expected, actual)
})
t.Run("Submit signs transaction using client signing implementation", func(t *testing.T) {
expected := []byte("SIGNATURE")
+
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(endorseResponse))
+ requests := make(chan *gateway.SubmitRequest, 1)
+ ExpectSubmit(mockConnection, CaptureInvokeRequest(requests))
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
sign := func(digest []byte) ([]byte, error) {
return expected, nil
}
- var actual []byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "result", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SubmitRequest, _ ...grpc.CallOption) {
- actual = in.PreparedTransaction.Signature
- }).
- Return(nil, nil).
- Times(1)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(statusResponse, nil)
-
- contract := AssertNewTestContract(t, "contract", WithGatewayClient(mockClient), WithSign(sign))
+ contract := AssertNewTestContract(t, "contract", WithClientConnection(mockConnection), WithSign(sign))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := (<-requests).PreparedTransaction.Signature
require.EqualValues(t, expected, actual)
})
t.Run("Default error implementation is used if no signing implementation supplied", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Evaluate(gomock.Any(), gomock.Any()).
- Return(evaluateResponse, nil).
- AnyTimes()
-
- mockDeliver := NewMockDeliverClient(gomock.NewController(t))
+ mockConnection := NewMockClientConnInterface(t)
- gateway, err := Connect(TestCredentials.Identity(), WithGatewayClient(mockClient), WithDeliverClient(mockDeliver))
+ gateway, err := Connect(TestCredentials.Identity(), WithClientConnection(mockConnection))
require.NoError(t, err)
contract := gateway.GetNetwork("network").GetContract("chaincode")
diff --git a/pkg/client/submit_test.go b/pkg/client/submit_test.go
index c63a3bdbb..6fea403d9 100644
--- a/pkg/client/submit_test.go
+++ b/pkg/client/submit_test.go
@@ -6,73 +6,47 @@ package client
import (
"context"
"testing"
- "time"
- "github.com/hyperledger/fabric-gateway/pkg/internal/test"
- "github.com/hyperledger/fabric-protos-go-apiv2/common"
"github.com/hyperledger/fabric-protos-go-apiv2/gateway"
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
- "google.golang.org/protobuf/proto"
- "google.golang.org/protobuf/reflect/protoreflect"
)
-func AssertMarshal(t *testing.T, message protoreflect.ProtoMessage, msgAndArgs ...interface{}) []byte {
- bytes, err := proto.Marshal(message)
- require.NoError(t, err, msgAndArgs...)
- return bytes
+func ReceiveAll[T any](channel <-chan T) []T {
+ var results []T
+
+ for {
+ if value, ok := TryReceive(channel); !ok {
+ return results
+ } else {
+ results = append(results, value)
+ }
+ }
}
-func AssertNewEndorseResponse(t *testing.T, result string, channelName string) *gateway.EndorseResponse {
- return &gateway.EndorseResponse{
- PreparedTransaction: &common.Envelope{
- Payload: AssertMarshal(t, &common.Payload{
- Header: &common.Header{
- ChannelHeader: AssertMarshal(t, &common.ChannelHeader{
- ChannelId: channelName,
- }),
- },
- Data: AssertMarshal(t, &peer.Transaction{
- Actions: []*peer.TransactionAction{
- {
- Payload: AssertMarshal(t, &peer.ChaincodeActionPayload{
- Action: &peer.ChaincodeEndorsedAction{
- ProposalResponsePayload: AssertMarshal(t, &peer.ProposalResponsePayload{
- Extension: AssertMarshal(t, &peer.ChaincodeAction{
- Response: &peer.Response{
- Payload: []byte(result),
- },
- }),
- }),
- },
- }),
- },
- },
- }),
- }),
- },
+func TryReceive[T any](channel <-chan T) (T, bool) {
+ var result T
+ select {
+ case result = <-channel:
+ return result, true
+ default:
+ return result, false
}
}
func TestSubmitTransaction(t *testing.T) {
- newCommitStatusResponse := func(status peer.TxValidationCode, blockNumber uint64) *gateway.CommitStatusResponse {
- return &gateway.CommitStatusResponse{
- Result: status,
- BlockNumber: blockNumber,
- }
- }
+ defaultEndorseResponse := AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network")
t.Run("Returns endorse error", func(t *testing.T) {
expected := NewStatusError(t, codes.Aborted, "ENDORSE_ERROR")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(nil, expected)
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithInvokeError(expected))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
@@ -87,13 +61,12 @@ func TestSubmitTransaction(t *testing.T) {
t.Run("Returns submit error", func(t *testing.T) {
expected := NewStatusError(t, codes.Aborted, "SUBMIT_ERROR")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, expected)
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection, WithInvokeError(expected))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
transaction, err := proposal.Endorse()
@@ -110,15 +83,13 @@ func TestSubmitTransaction(t *testing.T) {
t.Run("Returns commit status error", func(t *testing.T) {
expected := NewStatusError(t, codes.Aborted, "COMMIT_ERROR")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(nil, expected)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithInvokeError(expected))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
transaction, err := proposal.Endorse()
@@ -136,7 +107,7 @@ func TestSubmitTransaction(t *testing.T) {
})
for name, testCase := range map[string]struct {
- run func(t *testing.T, contract *Contract) ([]byte, error)
+ run func(*testing.T, *Contract) ([]byte, error)
}{
"SubmitTransaction returns result for committed transaction": {
run: func(t *testing.T, contract *Contract) ([]byte, error) {
@@ -151,15 +122,13 @@ func TestSubmitTransaction(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
expected := []byte("TRANSACTION_RESULT")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
actual, err := testCase.run(t, contract)
require.NoError(t, err)
@@ -169,7 +138,7 @@ func TestSubmitTransaction(t *testing.T) {
}
for testName, testCase := range map[string]struct {
- run func(t *testing.T, contract *Contract) ([]byte, error)
+ run func(*testing.T, *Contract) ([]byte, error)
}{
"SubmitTransaction returns commit error for invalid commit status": {
run: func(t *testing.T, contract *Contract) ([]byte, error) {
@@ -183,15 +152,12 @@ func TestSubmitTransaction(t *testing.T) {
},
} {
t.Run(testName, func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, err := testCase.run(t, contract)
var actual *CommitError
@@ -202,388 +168,309 @@ func TestSubmitTransaction(t *testing.T) {
}
t.Run("Includes channel name in proposal", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalChannelheader(t, in.ProposedTransaction).ChannelId
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := AssertUnmarshalChannelheader(t, (<-requests).ProposedTransaction).ChannelId
expected := contract.channelName
require.Equal(t, expected, actual)
})
t.Run("Includes chaincode name in proposal", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.ChaincodeId.Name
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.ChaincodeId.Name
expected := contract.chaincodeName
require.Equal(t, expected, actual)
})
t.Run("Includes transaction name in proposal for default contract", func(t *testing.T) {
- var args [][]byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- args = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.Input.Args
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
-
expected := "TRANSACTION_NAME"
+
+ mockConnection := NewMockClientConnInterface(t)
+
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
+
_, err := contract.SubmitTransaction(expected)
require.NoError(t, err)
+ args := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.Input.Args
actual := string(args[0])
require.Equal(t, expected, actual)
})
t.Run("Includes transaction name in proposal for named contract", func(t *testing.T) {
- var args [][]byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- args = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.Input.Args
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContractWithName(t, "chaincode", "CONTRACT_NAME", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContractWithName(t, "chaincode", "CONTRACT_NAME", WithClientConnection(mockConnection))
_, err := contract.SubmitTransaction("TRANSACTION_NAME")
require.NoError(t, err)
+ args := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.Input.Args
actual := string(args[0])
expected := "CONTRACT_NAME:TRANSACTION_NAME"
require.Equal(t, expected, actual)
})
t.Run("Includes arguments in proposal", func(t *testing.T) {
- var args [][]byte
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- args = test.AssertUnmarshalInvocationSpec(t, in.ProposedTransaction).ChaincodeSpec.Input.Args
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
expected := []string{"one", "two", "three"}
_, err := contract.SubmitTransaction("transaction", expected...)
require.NoError(t, err)
+ args := AssertUnmarshalInvocationSpec(t, (<-requests).ProposedTransaction).ChaincodeSpec.Input.Args
actual := bytesAsStrings(args[1:])
require.EqualValues(t, expected, actual)
})
- t.Run("Includes channel name in proposed transaction", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = in.ChannelId
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ t.Run("Includes channel name in endorse request", func(t *testing.T) {
+ expected := "CHANNEL_NAME"
+
+ mockConnection := NewMockClientConnInterface(t)
+ network := AssertNewTestNetwork(t, expected, WithClientConnection(mockConnection))
+
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := network.GetContract("chaincode")
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
- expected := contract.channelName
+ actual := (<-requests).ChannelId
require.Equal(t, expected, actual)
})
- t.Run("Includes transaction ID in proposed transaction", func(t *testing.T) {
- var actual string
-
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = test.AssertUnmarshalChannelheader(t, in.ProposedTransaction).TxId
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
+ t.Run("Includes transaction ID in proposal", func(t *testing.T) {
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
_, err = proposal.Endorse()
require.NoError(t, err, "Endorse")
+ actual := AssertUnmarshalChannelheader(t, (<-requests).ProposedTransaction).TxId
require.Equal(t, proposal.TransactionID(), actual)
})
t.Run("Includes transaction ID in endorse request", func(t *testing.T) {
- var actual string
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = in.TransactionId
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
_, err = proposal.Endorse()
require.NoError(t, err, "Endorse")
+ actual := (<-requests).TransactionId
require.Equal(t, proposal.TransactionID(), actual)
})
t.Run("Includes channel name in commit status request", func(t *testing.T) {
- var actual string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedCommitStatusRequest, _ ...grpc.CallOption) {
- request := &gateway.CommitStatusRequest{}
- test.AssertUnmarshal(t, in.Request, request)
- actual = request.ChannelId
- }).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ expected := "CHANNEL_NAME"
+
+ mockConnection := NewMockClientConnInterface(t)
+ network := AssertNewTestNetwork(t, expected, WithClientConnection(mockConnection))
+ endorseResponse := AssertNewEndorseResponse(t, "TRANSACTION_RESULT", expected)
+ ExpectEndorse(mockConnection, WithEndorseResponse(endorseResponse))
+ ExpectSubmit(mockConnection)
+ requests := make(chan *gateway.SignedCommitStatusRequest, 1)
+ ExpectCommitStatus(mockConnection, CaptureInvokeRequest(requests), WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := network.GetContract("chaincode")
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
- expected := contract.channelName
+ request := &gateway.CommitStatusRequest{}
+ AssertUnmarshal(t, (<-requests).Request, request)
+ actual := request.ChannelId
require.Equal(t, expected, actual)
})
t.Run("Includes transaction ID in commit status request", func(t *testing.T) {
- var actual string
- var expected string
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- expected = test.AssertUnmarshalChannelheader(t, in.ProposedTransaction).TxId
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedCommitStatusRequest, _ ...grpc.CallOption) {
- request := &gateway.CommitStatusRequest{}
- test.AssertUnmarshal(t, in.Request, request)
- actual = request.TransactionId
- }).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ endorseRequests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(endorseRequests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ commitStatusRequests := make(chan *gateway.SignedCommitStatusRequest, 1)
+ ExpectCommitStatus(mockConnection, CaptureInvokeRequest(commitStatusRequests), WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ expected := AssertUnmarshalChannelheader(t, (<-endorseRequests).ProposedTransaction).TxId
+ request := &gateway.CommitStatusRequest{}
+ AssertUnmarshal(t, (<-commitStatusRequests).Request, request)
+ actual := request.TransactionId
require.Equal(t, expected, actual)
})
t.Run("Uses signer for endorse", func(t *testing.T) {
- var actual []byte
expected := []byte("MY_SIGNATURE")
+
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
sign := func(digest []byte) ([]byte, error) {
return expected, nil
}
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actual = in.ProposedTransaction.Signature
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithSign(sign))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithSign(sign))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := (<-requests).ProposedTransaction.Signature
require.EqualValues(t, expected, actual)
})
t.Run("Uses signer for submit", func(t *testing.T) {
- var actual []byte
expected := []byte("MY_SIGNATURE")
+
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ requests := make(chan *gateway.SubmitRequest, 1)
+ ExpectSubmit(mockConnection, CaptureInvokeRequest(requests))
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
sign := func(digest []byte) ([]byte, error) {
return expected, nil
}
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SubmitRequest, _ ...grpc.CallOption) {
- actual = in.PreparedTransaction.Signature
- }).
- Return(nil, nil).
- Times(1)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithSign(sign))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithSign(sign))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := (<-requests).PreparedTransaction.Signature
require.EqualValues(t, expected, actual)
})
t.Run("Sends private data with submit", func(t *testing.T) {
- var actualOrgs []string
- expectedOrgs := []string{"MY_ORG"}
- var actualPrice []byte
+ expectedOrg := "MY_ORG"
expectedPrice := []byte("3000")
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.EndorseRequest, _ ...grpc.CallOption) {
- actualOrgs = in.EndorsingOrganizations
- transient := test.AssertUnmarshalProposalPayload(t, in.ProposedTransaction).TransientMap
- actualPrice = transient["price"]
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+
+ mockConnection := NewMockClientConnInterface(t)
+ requests := make(chan *gateway.EndorseRequest, 1)
+ ExpectEndorse(mockConnection, CaptureInvokeRequest(requests), WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
privateData := map[string][]byte{
- "price": []byte("3000"),
+ "price": expectedPrice,
}
-
- _, err := contract.Submit("transaction", WithTransient(privateData), WithEndorsingOrganizations("MY_ORG"))
+ _, err := contract.Submit("transaction", WithTransient(privateData), WithEndorsingOrganizations(expectedOrg))
require.NoError(t, err)
- require.EqualValues(t, expectedOrgs, actualOrgs)
- require.EqualValues(t, expectedPrice, actualPrice)
+ request := <-requests
+ require.ElementsMatch(t, []string{expectedOrg}, request.EndorsingOrganizations)
+
+ transient := AssertUnmarshalProposalPayload(t, request.ProposedTransaction).TransientMap
+ require.EqualValues(t, expectedPrice, transient["price"])
})
t.Run("Uses signer for commit status", func(t *testing.T) {
- var actual []byte
expected := []byte("MY_SIGNATURE")
+
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ requests := make(chan *gateway.SignedCommitStatusRequest, 1)
+ ExpectCommitStatus(mockConnection, CaptureInvokeRequest(requests), WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
+
sign := func(digest []byte) ([]byte, error) {
return expected, nil
}
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, in *gateway.SignedCommitStatusRequest, _ ...grpc.CallOption) {
- actual = in.Signature
- }).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithSign(sign))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithSign(sign))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
+ actual := (<-requests).Signature
require.EqualValues(t, expected, actual)
})
t.Run("Uses hash", func(t *testing.T) {
- var actual [][]byte
+ digests := make(chan []byte, 3)
digest := []byte("MY_DIGEST")
sign := func(digest []byte) ([]byte, error) {
- actual = append(actual, digest)
+ digests <- digest
return digest, nil
}
hash := func(message []byte) []byte {
return digest
}
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithSign(sign), WithHash(hash))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithSign(sign), WithHash(hash))
_, err := contract.SubmitTransaction("transaction")
require.NoError(t, err)
expected := [][]byte{digest, digest, digest}
+ actual := ReceiveAll(digests)
require.EqualValues(t, expected, actual)
})
t.Run("Commit returns transaction status", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, 1), nil)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, 1))
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, commit, err := contract.SubmitAsync("transaction")
require.NoError(t, err)
@@ -595,15 +482,12 @@ func TestSubmitTransaction(t *testing.T) {
})
t.Run("Commit returns successful for successful transaction", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_VALID, 1))
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, commit, err := contract.SubmitAsync("transaction")
require.NoError(t, err, "submit")
@@ -615,15 +499,12 @@ func TestSubmitTransaction(t *testing.T) {
})
t.Run("Commit returns unsuccessful for failed transaction", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, 1), nil)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, 1))
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, commit, err := contract.SubmitAsync("transaction")
require.NoError(t, err, "submit")
@@ -636,15 +517,13 @@ func TestSubmitTransaction(t *testing.T) {
t.Run("Commit returns block number", func(t *testing.T) {
expectedBlockNumber := uint64(101)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, expectedBlockNumber), nil)
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithCommitStatusResponse(peer.TxValidationCode_MVCC_READ_CONFLICT, expectedBlockNumber))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
_, commit, err := contract.SubmitAsync("transaction")
require.NoError(t, err, "submit")
@@ -656,24 +535,10 @@ func TestSubmitTransaction(t *testing.T) {
})
t.Run("Uses default context for endorse", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- DoAndReturn(func(ctx context.Context, _ *gateway.EndorseRequest, _ ...grpc.CallOption) (*gateway.EndorseResponse, error) {
- select {
- case <-time.After(1 * time.Second):
- return AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil
- case <-ctx.Done(): // Zero timeout context should cancel immediately, selecting this case
- return nil, ctx.Err()
- }
- })
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil).
- AnyTimes()
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- AnyTimes()
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithEndorseTimeout(0))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithInvokeContextErr(), WithEndorseResponse(defaultEndorseResponse))
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithEndorseTimeout(0))
_, err := contract.Submit("transaction")
@@ -681,23 +546,11 @@ func TestSubmitTransaction(t *testing.T) {
})
t.Run("Uses default context for submit", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- DoAndReturn(func(ctx context.Context, _ *gateway.SubmitRequest, _ ...grpc.CallOption) (*gateway.SubmitResponse, error) {
- select {
- case <-time.After(1 * time.Second):
- return nil, nil
- case <-ctx.Done(): // Zero timeout context should cancel immediately, selecting this case
- return nil, ctx.Err()
- }
- })
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- AnyTimes()
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithSubmitTimeout(0))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection, WithInvokeContextErr())
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithSubmitTimeout(0))
_, err := contract.Submit("transaction")
@@ -724,61 +577,41 @@ func TestSubmitTransaction(t *testing.T) {
},
} {
t.Run(name, func(t *testing.T) {
- var endorseCtxErr error
- var submitCtxErr error
- var commitStatusCtxErr error
+ endorseContexts := make(chan context.Context, 1)
+ submitContexts := make(chan context.Context, 1)
+ commitStatusContexts := make(chan context.Context, 1)
ctx, cancel := context.WithCancel(context.Background())
cancel()
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Do(func(ctx context.Context, _ *gateway.EndorseRequest, _ ...grpc.CallOption) {
- endorseCtxErr = ctx.Err()
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Do(func(ctx context.Context, _ *gateway.SubmitRequest, _ ...grpc.CallOption) {
- submitCtxErr = ctx.Err()
- }).
- Return(nil, nil).
- Times(1)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Do(func(ctx context.Context, _ *gateway.SignedCommitStatusRequest, _ ...grpc.CallOption) {
- commitStatusCtxErr = ctx.Err()
- }).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- Times(1)
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection,
+ CaptureInvokeContext(endorseContexts),
+ WithEndorseResponse(defaultEndorseResponse),
+ )
+ ExpectSubmit(mockConnection, CaptureInvokeContext(submitContexts))
+ ExpectCommitStatus(mockConnection,
+ CaptureInvokeContext(commitStatusContexts),
+ WithCommitStatusResponse(peer.TxValidationCode_VALID, 1),
+ )
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
testCase.run(t, ctx, contract)
- require.ErrorIs(t, endorseCtxErr, context.Canceled, "endorse context")
- require.ErrorIs(t, submitCtxErr, context.Canceled, "submit context")
- require.ErrorIs(t, commitStatusCtxErr, context.Canceled, "commit status context")
+ require.ErrorIs(t, (<-endorseContexts).Err(), context.Canceled, "endorse context")
+ require.ErrorIs(t, (<-submitContexts).Err(), context.Canceled, "submit context")
+ require.ErrorIs(t, (<-commitStatusContexts).Err(), context.Canceled, "commit status context")
})
}
t.Run("Uses default context for commit status", func(t *testing.T) {
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- DoAndReturn(func(ctx context.Context, _ *gateway.SignedCommitStatusRequest, _ ...grpc.CallOption) (*gateway.CommitStatusResponse, error) {
- select {
- case <-time.After(1 * time.Second):
- return nil, nil
- case <-ctx.Done(): // Zero timeout context should cancel immediately, selecting this case
- return nil, ctx.Err()
- }
- })
-
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient), WithCommitStatusTimeout(0))
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection, WithInvokeContextErr())
+
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection), WithCommitStatusTimeout(0))
_, err := contract.Submit("transaction")
@@ -786,18 +619,16 @@ func TestSubmitTransaction(t *testing.T) {
})
t.Run("Endorse uses specified gRPC call options", func(t *testing.T) {
- var actual []grpc.CallOption
+ callOptions := make(chan []grpc.CallOption, 1)
expected := grpc.WaitForReady(true)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, _ *gateway.EndorseRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection,
+ CaptureInvokeOptions(callOptions),
+ WithEndorseResponse(defaultEndorseResponse),
+ )
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
@@ -805,22 +636,20 @@ func TestSubmitTransaction(t *testing.T) {
_, err = proposal.Endorse(expected)
require.NoError(t, err, "Endorse")
- require.Contains(t, actual, expected, "CallOptions")
+ require.Contains(t, <-callOptions, expected, "CallOptions")
})
t.Run("Endorse uses specified gRPC call options with specified context", func(t *testing.T) {
- var actual []grpc.CallOption
+ callOptions := make(chan []grpc.CallOption, 1)
expected := grpc.WaitForReady(true)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, _ *gateway.EndorseRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection,
+ CaptureInvokeOptions(callOptions),
+ WithEndorseResponse(defaultEndorseResponse),
+ )
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
@@ -831,24 +660,18 @@ func TestSubmitTransaction(t *testing.T) {
_, err = proposal.EndorseWithContext(ctx, expected)
require.NoError(t, err, "Endorse")
- require.Contains(t, actual, expected, "CallOptions")
+ require.Contains(t, <-callOptions, expected, "CallOptions")
})
t.Run("Submit uses specified gRPC call options", func(t *testing.T) {
- var actual []grpc.CallOption
+ callOptions := make(chan []grpc.CallOption, 1)
expected := grpc.WaitForReady(true)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, _ *gateway.SubmitRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(nil, nil).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection, CaptureInvokeOptions(callOptions))
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
@@ -859,24 +682,18 @@ func TestSubmitTransaction(t *testing.T) {
_, err = transaction.Submit(expected)
require.NoError(t, err, "Submit")
- require.Contains(t, actual, expected, "CallOptions")
+ require.Contains(t, <-callOptions, expected, "CallOptions")
})
t.Run("Submit uses specified gRPC call options with specified context", func(t *testing.T) {
- var actual []grpc.CallOption
+ callOptions := make(chan []grpc.CallOption, 1)
expected := grpc.WaitForReady(true)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any()).
- Do(func(_ context.Context, _ *gateway.SubmitRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Return(nil, nil).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection, CaptureInvokeOptions(callOptions))
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
@@ -890,26 +707,22 @@ func TestSubmitTransaction(t *testing.T) {
_, err = transaction.SubmitWithContext(ctx, expected)
require.NoError(t, err, "Submit")
- require.Contains(t, actual, expected, "CallOptions")
+ require.Contains(t, <-callOptions, expected, "CallOptions")
})
t.Run("CommisStatus uses specified gRPC call options", func(t *testing.T) {
- var actual []grpc.CallOption
+ callOptions := make(chan []grpc.CallOption, 1)
expected := grpc.WaitForReady(true)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- Do(func(ctx context.Context, _ *gateway.SignedCommitStatusRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection,
+ CaptureInvokeOptions(callOptions),
+ WithCommitStatusResponse(peer.TxValidationCode_VALID, 1),
+ )
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
@@ -923,26 +736,22 @@ func TestSubmitTransaction(t *testing.T) {
_, err = commit.Status(expected)
require.NoError(t, err, "Status")
- require.Contains(t, actual, expected, "CallOptions")
+ require.Contains(t, <-callOptions, expected, "CallOptions")
})
t.Run("CommisStatus uses specified gRPC call options with specified context", func(t *testing.T) {
- var actual []grpc.CallOption
+ callOptions := make(chan []grpc.CallOption, 1)
expected := grpc.WaitForReady(true)
- mockClient := NewMockGatewayClient(gomock.NewController(t))
- mockClient.EXPECT().Endorse(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(AssertNewEndorseResponse(t, "TRANSACTION_RESULT", "network"), nil)
- mockClient.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(nil, nil)
- mockClient.EXPECT().CommitStatus(gomock.Any(), gomock.Any(), gomock.Any()).
- Return(newCommitStatusResponse(peer.TxValidationCode_VALID, 1), nil).
- Do(func(ctx context.Context, _ *gateway.SignedCommitStatusRequest, opts ...grpc.CallOption) {
- actual = opts
- }).
- Times(1)
+ mockConnection := NewMockClientConnInterface(t)
+ ExpectEndorse(mockConnection, WithEndorseResponse(defaultEndorseResponse))
+ ExpectSubmit(mockConnection)
+ ExpectCommitStatus(mockConnection,
+ CaptureInvokeOptions(callOptions),
+ WithCommitStatusResponse(peer.TxValidationCode_VALID, 1),
+ )
- contract := AssertNewTestContract(t, "chaincode", WithGatewayClient(mockClient))
+ contract := AssertNewTestContract(t, "chaincode", WithClientConnection(mockConnection))
proposal, err := contract.NewProposal("transaction")
require.NoError(t, err, "NewProposal")
@@ -959,6 +768,6 @@ func TestSubmitTransaction(t *testing.T) {
_, err = commit.StatusWithContext(ctx, expected)
require.NoError(t, err, "Status")
- require.Contains(t, actual, expected, "CallOptions")
+ require.Contains(t, <-callOptions, expected, "CallOptions")
})
}
diff --git a/pkg/internal/test/credentials.go b/pkg/internal/test/credentials.go
index 5813af844..252ec6f48 100644
--- a/pkg/internal/test/credentials.go
+++ b/pkg/internal/test/credentials.go
@@ -9,7 +9,6 @@ import (
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
- "crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
@@ -27,19 +26,6 @@ func NewEd25519KeyPair() (ed25519.PublicKey, ed25519.PrivateKey, error) {
return ed25519.GenerateKey(rand.Reader)
}
-func publicKey(priv crypto.PrivateKey) crypto.PublicKey {
- switch k := priv.(type) {
- case *rsa.PrivateKey:
- return &k.PublicKey
- case *ecdsa.PrivateKey:
- return &k.PublicKey
- case ed25519.PrivateKey:
- return k.Public().(ed25519.PublicKey)
- default:
- return nil
- }
-}
-
// NewCertificate generates a new certificate from a private key for testing
func NewCertificate(privateKey crypto.PrivateKey) (*x509.Certificate, error) {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
@@ -66,7 +52,8 @@ func NewCertificate(privateKey crypto.PrivateKey) (*x509.Certificate, error) {
DNSNames: []string{"test.example.org"},
}
- certificateBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(privateKey), privateKey)
+ publicKey := privateKey.(crypto.Signer).Public()
+ certificateBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey, privateKey)
if err != nil {
return nil, fmt.Errorf("failed to generate certificate: %w", err)
}
diff --git a/pkg/internal/test/transaction.go b/pkg/internal/test/transaction.go
deleted file mode 100644
index 965f97784..000000000
--- a/pkg/internal/test/transaction.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright IBM Corp. All Rights Reserved.
-// SPDX-License-Identifier: Apache-2.0
-
-package test
-
-import (
- "testing"
-
- "github.com/hyperledger/fabric-protos-go-apiv2/common"
- "github.com/hyperledger/fabric-protos-go-apiv2/peer"
- "github.com/stretchr/testify/require"
- "google.golang.org/protobuf/proto"
- "google.golang.org/protobuf/reflect/protoreflect"
-)
-
-// AssertProtoEqual ensures an expected protobuf message matches an actual message
-func AssertProtoEqual(t *testing.T, expected protoreflect.ProtoMessage, actual protoreflect.ProtoMessage) {
- require.True(t, proto.Equal(expected, actual), "Expected %v, got %v", expected, actual)
-}
-
-// AssertUnmarshal ensures that a protobuf is umarshaled without error
-func AssertUnmarshal(t *testing.T, b []byte, m protoreflect.ProtoMessage) {
- err := proto.Unmarshal(b, m)
- require.NoError(t, err)
-}
-
-// AssertUnmarshalProposalPayload ensures that a ChaincodeProposalPayload protobuf is umarshalled without error
-func AssertUnmarshalProposalPayload(t *testing.T, proposedTransaction *peer.SignedProposal) *peer.ChaincodeProposalPayload {
- proposal := &peer.Proposal{}
- AssertUnmarshal(t, proposedTransaction.ProposalBytes, proposal)
-
- payload := &peer.ChaincodeProposalPayload{}
- AssertUnmarshal(t, proposal.Payload, payload)
-
- return payload
-}
-
-// AssertUnmarshalInvocationSpec ensures that a ChaincodeInvocationSpec protobuf is umarshalled without error
-func AssertUnmarshalInvocationSpec(t *testing.T, proposedTransaction *peer.SignedProposal) *peer.ChaincodeInvocationSpec {
- proposal := &peer.Proposal{}
- AssertUnmarshal(t, proposedTransaction.ProposalBytes, proposal)
-
- payload := &peer.ChaincodeProposalPayload{}
- AssertUnmarshal(t, proposal.Payload, payload)
-
- input := &peer.ChaincodeInvocationSpec{}
- AssertUnmarshal(t, payload.Input, input)
-
- return input
-}
-
-// AssertUnmarshalChannelheader ensures that a ChannelHeader protobuf is umarshalled without error
-func AssertUnmarshalChannelheader(t *testing.T, proposedTransaction *peer.SignedProposal) *common.ChannelHeader {
- header := AssertUnmarshalHeader(t, proposedTransaction)
-
- channelHeader := &common.ChannelHeader{}
- AssertUnmarshal(t, header.ChannelHeader, channelHeader)
-
- return channelHeader
-}
-
-// AssertUnmarshalHeader ensures that a Header protobuf is umarshalled without error
-func AssertUnmarshalHeader(t *testing.T, proposedTransaction *peer.SignedProposal) *common.Header {
- proposal := &peer.Proposal{}
- AssertUnmarshal(t, proposedTransaction.ProposalBytes, proposal)
-
- header := &common.Header{}
- AssertUnmarshal(t, proposal.Header, header)
-
- return header
-}
-
-// AssertUnmarshalSignatureHeader ensures that a SignatureHeader protobuf is umarshalled without error
-func AssertUnmarshalSignatureHeader(t *testing.T, proposedTransaction *peer.SignedProposal) *common.SignatureHeader {
- header := AssertUnmarshalHeader(t, proposedTransaction)
-
- signatureHeader := &common.SignatureHeader{}
- AssertUnmarshal(t, header.SignatureHeader, signatureHeader)
-
- return signatureHeader
-}
diff --git a/scenario/go/scenario_test.go b/scenario/go/scenario_test.go
index dfc5bacbc..7f98b3234 100644
--- a/scenario/go/scenario_test.go
+++ b/scenario/go/scenario_test.go
@@ -320,7 +320,7 @@ func theResponseShouldBeJSONMatching(arg *godog.DocString) error {
}
func jsonEqual(a, b []byte) (bool, error) {
- var j, j2 interface{}
+ var j, j2 any
if err := json.Unmarshal(a, &j); err != nil {
return false, err
}