Channel Client: MVCC Read Conflict Test
@@ -8,9 +8,12 @@ package channel
import (
"strings"
+ "sync"
"testing"
"time"
+ "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/multi"
+
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -114,6 +117,69 @@ func TestChannelClient(t *testing.T) {
//test if CCEvents for chaincode events are in sync when new channel client are created
// for each transaction
testMultipleClientChaincodeEventLoop(t, chaincodeID)
+
+ testChannelClientMvccReadConflictWithRetry(t, chaincodeID, chClient)
+
+ testChannelClientMvccReadConflict(t, chaincodeID, chClient)
+
+}
+
+func testChannelClientMvccReadConflictWithRetry(t *testing.T, chaincodeID string, chClient *channel.Client) {
+
+ var wg sync.WaitGroup
+
+ maxAttempts := 2
+ for i := 0; i < maxAttempts; i++ {
+ wg.Add(1)
+ go func(attempt int) {
+ defer wg.Done()
+ response, err := chClient.Execute(
+ channel.Request{
+ ChaincodeID: chaincodeID,
+ Fcn: "invoke",
+ Args: integration.ExampleCCDefaultTxArgs(),
+ },
+ channel.WithRetry(retry.DefaultChannelOpts),
+ )
+
+ require.NoError(t, err, "Failed to move funds for request #%d", attempt)
+ assert.Equal(t, pb.TxValidationCode_VALID, response.TxValidationCode, "Expecting TxValidationCode to be TxValidationCode_VALID")
+ }(i)
+ }
+ wg.Wait()
+
+}
+
+func testChannelClientMvccReadConflict(t *testing.T, chaincodeID string, chClient *channel.Client) {
+
+ var errMtx sync.Mutex
+ var wg sync.WaitGroup
+ errs := multi.Errors{}
+
+ maxAttempts := 3
+ for i := 0; i < maxAttempts; i++ {
+ wg.Add(1)
+ go func(attempt int) {
+ defer wg.Done()
+ _, err := chClient.Execute(
+ channel.Request{
+ ChaincodeID: chaincodeID,
+ Fcn: "invoke",
+ Args: integration.ExampleCCDefaultTxArgs(),
+ },
+ )
+ if err != nil {
+ errMtx.Lock()
+ errs = append(errs, err)
+ errMtx.Unlock()
+ return
+ }
+ }(i)
+ }
+ wg.Wait()
+
+ assert.True(t, len(errs) > 0)
+ assert.True(t, strings.Contains(errs[0].Error(), "MVCC_READ_CONFLICT"))
}
func testDuplicateTargets(t *testing.T, chaincodeID string, chClient *channel.Client, key string, args [][]byte) {
