@@ -24,9 +24,10 @@ import (
2424 "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
2525 "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/deliverclient/seek"
2626 "github.com/hyperledger/fabric-sdk-go/test/integration"
27+ pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
2728)
2829
29- const eventTimeWindow = 120 * time .Second // the maximum amount of time to watch for events.
30+ const eventTimeWindow = 20 * time .Second // the maximum amount of time to watch for events.
3031
3132func TestEventClient (t * testing.T ) {
3233 chainCodeID := mainChaincodeID
@@ -95,7 +96,7 @@ func testEventService(t *testing.T, testSetup *integration.BaseSetupImpl, sdk *f
9596 numExpected ++
9697 wg .Add (1 )
9798
98- tpResponses , prop , txID := sendTxProposal (sdk , testSetup , t , transactor , chainCodeID )
99+ tpResponses , prop , txID := sendTxProposal (sdk , testSetup , t , transactor , chainCodeID , integration . ExampleCCTxRandomSetArgs () )
99100 txReg , txstatusch , err := eventService .RegisterTxStatusEvent (txID )
100101 if err != nil {
101102 t .Fatalf ("Error registering for Tx Status event: %s" , err )
@@ -127,14 +128,14 @@ func testEventService(t *testing.T, testSetup *integration.BaseSetupImpl, sdk *f
127128 }
128129}
129130
130- func sendTxProposal (sdk * fabsdk.FabricSDK , testSetup * integration.BaseSetupImpl , t * testing.T , transactor fab.Transactor , chainCodeID string ) ([]* fab.TransactionProposalResponse , * fab.TransactionProposal , string ) {
131+ func sendTxProposal (sdk * fabsdk.FabricSDK , testSetup * integration.BaseSetupImpl , t * testing.T , transactor fab.Transactor , chainCodeID string , args [][] byte ) ([]* fab.TransactionProposalResponse , * fab.TransactionProposal , string ) {
131132 peers , err := getProposalProcessors (sdk , "Admin" , testSetup .OrgID , testSetup .Targets )
132133 require .Nil (t , err , "creating peers failed" )
133134 tpResponses , prop , err := createAndSendTransactionProposal (
134135 transactor ,
135136 chainCodeID ,
136137 "invoke" ,
137- [][] byte {[] byte ( "move" ), [] byte ( "a" ), [] byte ( "b" ), [] byte ( "10" )} ,
138+ args ,
138139 peers ,
139140 nil ,
140141 )
@@ -162,6 +163,9 @@ func checkTxStatusEvent(wg *sync.WaitGroup, txstatusch <-chan *fab.TxStatusEvent
162163 if txStatus .BlockNumber == 0 {
163164 test .Failf (t , "Expecting non-zero block number" )
164165 }
166+ if txStatus .TxValidationCode != pb .TxValidationCode_VALID {
167+ test .Failf (t , "expected transaction validation code to be valid" )
168+ }
165169 atomic .AddUint32 (numReceived , 1 )
166170 case <- time .After (eventTimeWindow ):
167171 return
@@ -328,7 +332,7 @@ func testChannelEventsSeekOptions(t *testing.T, testSetup *integration.BaseSetup
328332 defer eventService .Unregister (ccreg )
329333
330334 // prepare and commit the transaction to generate events
331- tpResponses , prop , txID := sendTxProposal (sdk , testSetup , t , transactor , chainCodeID )
335+ tpResponses , prop , txID := sendTxProposal (sdk , testSetup , t , transactor , chainCodeID , integration . ExampleCCTxRandomSetArgs () )
332336 _ , err = createAndSendTransaction (transactor , prop , tpResponses )
333337 require .NoError (t , err , "First invoke failed err" )
334338
@@ -366,3 +370,62 @@ func testChannelEventsSeekOptions(t *testing.T, testSetup *integration.BaseSetup
366370 //to event channel, and first event we get from event channel actually belongs to first transaction after registration.
367371 require .Equal (t , seekType == "" , txID == event .TxID , "for seek type[%s], txID [%s], event.txID[%s] ,condition didn't match" , seekType , txID , event .TxID )
368372}
373+
374+ //TestEventClientWithMVCCReadConflicts tests behavior of chaincode events when MVCC_READ_CONFLICT happens
375+ //Chaincode events with Txn Validation Code = MVCC_READ_CONFLICT are not getting published
376+ func TestEventClientWithMVCCReadConflicts (t * testing.T ) {
377+ chainCodeID := mainChaincodeID
378+ sdk := mainSDK
379+ testSetup := mainTestSetup
380+
381+ chContextProvider := sdk .ChannelContext (testSetup .ChannelID , fabsdk .WithUser (org1User ), fabsdk .WithOrg (org1Name ))
382+ chContext , err := chContextProvider ()
383+ require .NoError (t , err , "error getting channel context" )
384+
385+ eventService , err := chContext .ChannelService ().EventService ()
386+ require .NoError (t , err , "error getting event service" )
387+
388+ testEventServiceWithConflicts (t , testSetup , sdk , chainCodeID , eventService )
389+ }
390+
391+ func testEventServiceWithConflicts (t * testing.T , testSetup * integration.BaseSetupImpl , sdk * fabsdk.FabricSDK , chainCodeID string , eventService fab.EventService ) {
392+ _ , cancel , transactor , err := getTransactor (sdk , testSetup .ChannelID , "Admin" , testSetup .OrgID )
393+ require .NoError (t , err , "Failed to get channel transactor" )
394+ defer cancel ()
395+
396+ ccreg , cceventch , err := eventService .RegisterChaincodeEvent (chainCodeID , ".*" )
397+ require .NoError (t , err , "Error registering for filtered block events" )
398+ defer eventService .Unregister (ccreg )
399+
400+ numOfTxns := 4
401+ // Commit multiple transactions to generate events
402+ for i := 0 ; i < numOfTxns ; i ++ {
403+ tpResponse , prop , _ := sendTxProposal (sdk , testSetup , t , transactor , chainCodeID , [][]byte {[]byte ("move" ), []byte ("a" ), []byte ("b" ), []byte ("5" )})
404+ _ , err = createAndSendTransaction (transactor , prop , tpResponse )
405+ require .NoError (t , err , "invoke failed" )
406+ }
407+
408+ var numReceived int
409+ test:
410+ for {
411+ select {
412+ case event , ok := <- cceventch :
413+ if ! ok {
414+ test .Failf (t , "unexpected closed channel while waiting for CC Status event" )
415+ }
416+ t .Logf ("Received chaincode event: %#v" , event )
417+ require .Equal (t , event .ChaincodeID , chainCodeID )
418+ require .NotEmpty (t , event .SourceURL , "Expecting event source URL but got none" )
419+ require .NotEmpty (t , event .BlockNumber , "Expecting non-zero block number" )
420+ require .NotEmpty (t , event .TxID , "Expecting valid txID" )
421+ require .NotEmpty (t , event .EventName , "Expecting valid event name" )
422+ numReceived ++
423+ continue
424+ case <- time .After (5 * time .Second ):
425+ break test
426+ }
427+ }
428+
429+ require .True (t , numReceived < numOfTxns , "Expected number of transactions to be greater than number of events" )
430+
431+ }
0 commit comments