@@ -17,12 +17,14 @@ limitations under the License.
17
17
package txvalidator
18
18
19
19
import (
20
+ "errors"
20
21
"fmt"
21
22
"os"
22
23
"testing"
23
24
24
25
"github.com/hyperledger/fabric/common/cauthdsl"
25
26
ctxt "github.com/hyperledger/fabric/common/configtx/test"
27
+ ledger2 "github.com/hyperledger/fabric/common/ledger"
26
28
"github.com/hyperledger/fabric/common/ledger/testutil"
27
29
"github.com/hyperledger/fabric/common/mocks/scc"
28
30
"github.com/hyperledger/fabric/common/util"
@@ -41,6 +43,7 @@ import (
41
43
"github.com/hyperledger/fabric/protos/utils"
42
44
"github.com/spf13/viper"
43
45
"github.com/stretchr/testify/assert"
46
+ "github.com/stretchr/testify/mock"
44
47
)
45
48
46
49
func signedByAnyMember (ids []string ) []byte {
@@ -385,6 +388,149 @@ func TestInvokeNoBlock(t *testing.T) {
385
388
assert .NoError (t , err )
386
389
}
387
390
391
+ // mockLedger structure used to test ledger
392
+ // failure, therefore leveraging mocking
393
+ // library as need to simulate ledger which not
394
+ // able to get access to state db
395
+ type mockLedger struct {
396
+ mock.Mock
397
+ }
398
+
399
+ // GetTransactionByID returns transaction by ud
400
+ func (m * mockLedger ) GetTransactionByID (txID string ) (* peer.ProcessedTransaction , error ) {
401
+ args := m .Called (txID )
402
+ return args .Get (0 ).(* peer.ProcessedTransaction ), args .Error (1 )
403
+ }
404
+
405
+ // GetBlockByHash returns block using its hash value
406
+ func (m * mockLedger ) GetBlockByHash (blockHash []byte ) (* common.Block , error ) {
407
+ args := m .Called (blockHash )
408
+ return args .Get (0 ).(* common.Block ), nil
409
+ }
410
+
411
+ // GetBlockByTxID given transaction id return block transaction was committed with
412
+ func (m * mockLedger ) GetBlockByTxID (txID string ) (* common.Block , error ) {
413
+ args := m .Called (txID )
414
+ return args .Get (0 ).(* common.Block ), nil
415
+ }
416
+
417
+ // GetTxValidationCodeByTxID returns validation code of give tx
418
+ func (m * mockLedger ) GetTxValidationCodeByTxID (txID string ) (peer.TxValidationCode , error ) {
419
+ args := m .Called (txID )
420
+ return args .Get (0 ).(peer.TxValidationCode ), nil
421
+ }
422
+
423
+ // NewTxSimulator creates new transaction simulator
424
+ func (m * mockLedger ) NewTxSimulator () (ledger.TxSimulator , error ) {
425
+ args := m .Called ()
426
+ return args .Get (0 ).(ledger.TxSimulator ), nil
427
+ }
428
+
429
+ // NewQueryExecutor creates query executor
430
+ func (m * mockLedger ) NewQueryExecutor () (ledger.QueryExecutor , error ) {
431
+ args := m .Called ()
432
+ return args .Get (0 ).(ledger.QueryExecutor ), nil
433
+ }
434
+
435
+ // NewHistoryQueryExecutor history query executor
436
+ func (m * mockLedger ) NewHistoryQueryExecutor () (ledger.HistoryQueryExecutor , error ) {
437
+ args := m .Called ()
438
+ return args .Get (0 ).(ledger.HistoryQueryExecutor ), nil
439
+ }
440
+
441
+ // Prune prune using policy
442
+ func (m * mockLedger ) Prune (policy ledger2.PrunePolicy ) error {
443
+ return nil
444
+ }
445
+
446
+ func (m * mockLedger ) GetBlockchainInfo () (* common.BlockchainInfo , error ) {
447
+ args := m .Called ()
448
+ return args .Get (0 ).(* common.BlockchainInfo ), nil
449
+ }
450
+
451
+ func (m * mockLedger ) GetBlockByNumber (blockNumber uint64 ) (* common.Block , error ) {
452
+ args := m .Called (blockNumber )
453
+ return args .Get (0 ).(* common.Block ), nil
454
+ }
455
+
456
+ func (m * mockLedger ) GetBlocksIterator (startBlockNumber uint64 ) (ledger2.ResultsIterator , error ) {
457
+ args := m .Called (startBlockNumber )
458
+ return args .Get (0 ).(ledger2.ResultsIterator ), nil
459
+ }
460
+
461
+ func (m * mockLedger ) Close () {
462
+
463
+ }
464
+
465
+ func (m * mockLedger ) Commit (block * common.Block ) error {
466
+ return nil
467
+ }
468
+
469
+ // mockQueryExecutor mock of the query executor,
470
+ // needed to simulate inability to access state db, e.g.
471
+ // the case where due to db failure it's not possible to
472
+ // query for state, for example if we would like to query
473
+ // the lccc for VSCC info and db is not avaible we expect
474
+ // to stop validating block and fail commit procedure with
475
+ // an error.
476
+ type mockQueryExecutor struct {
477
+ mock.Mock
478
+ }
479
+
480
+ func (exec * mockQueryExecutor ) GetState (namespace string , key string ) ([]byte , error ) {
481
+ args := exec .Called (namespace , key )
482
+ return args .Get (0 ).([]byte ), args .Error (1 )
483
+ }
484
+
485
+ func (exec * mockQueryExecutor ) GetStateMultipleKeys (namespace string , keys []string ) ([][]byte , error ) {
486
+ args := exec .Called (namespace , keys )
487
+ return args .Get (0 ).([][]byte ), args .Error (1 )
488
+ }
489
+
490
+ func (exec * mockQueryExecutor ) GetStateRangeScanIterator (namespace string , startKey string , endKey string ) (ledger2.ResultsIterator , error ) {
491
+ args := exec .Called (namespace , startKey , endKey )
492
+ return args .Get (0 ).(ledger2.ResultsIterator ), args .Error (1 )
493
+ }
494
+
495
+ func (exec * mockQueryExecutor ) ExecuteQuery (namespace , query string ) (ledger2.ResultsIterator , error ) {
496
+ args := exec .Called (namespace )
497
+ return args .Get (0 ).(ledger2.ResultsIterator ), args .Error (1 )
498
+ }
499
+
500
+ func (exec * mockQueryExecutor ) Done () {
501
+ }
502
+
503
+ // TestLedgerIsNoAvailable simulates and provides a test for following scenario,
504
+ // which is based on FAB-535. Test checks the validation path which expects that
505
+ // DB won't available while trying to lookup for VSCC from LCCC and therefore
506
+ // transaction validation will have to fail. In such case the outcome should be
507
+ // the error return from validate block method and proccessing of transactions
508
+ // has to stop. There is suppose to be clear indication of the failure with error
509
+ // returned from the function call.
510
+ func TestLedgerIsNoAvailable (t * testing.T ) {
511
+ theLedger := new (mockLedger )
512
+ validator := NewTxValidator (& mockSupport {l : theLedger })
513
+
514
+ ccID := "mycc"
515
+ tx := getEnv (ccID , createRWset (t , ccID ), t )
516
+
517
+ theLedger .On ("GetTransactionByID" , mock .Anything ).Return (& peer.ProcessedTransaction {}, errors .New ("Cannot find the transaction" ))
518
+
519
+ queryExecutor := new (mockQueryExecutor )
520
+ queryExecutor .On ("GetState" , mock .Anything , mock .Anything ).Return ([]byte {}, errors .New ("Unable to connect to DB" ))
521
+ theLedger .On ("NewQueryExecutor" , mock .Anything ).Return (queryExecutor , nil )
522
+
523
+ b := & common.Block {Data : & common.BlockData {Data : [][]byte {utils .MarshalOrPanic (tx )}}}
524
+
525
+ err := validator .Validate (b )
526
+
527
+ assertion := assert .New (t )
528
+ // We suppose to get the error which indicates we cannot commit the block
529
+ assertion .Error (err )
530
+ // The error exptected to be of type VSCCInfoLookupFailureError
531
+ assertion .NotNil (err .(* VSCCInfoLookupFailureError ))
532
+ }
533
+
388
534
var signer msp.SigningIdentity
389
535
var signerSerialized []byte
390
536
0 commit comments