Skip to content

Commit

Permalink
Merge "Enable additional ledger txmgr unit tests"
Browse files Browse the repository at this point in the history
  • Loading branch information
Srinivasan Muralidharan authored and Gerrit Code Review committed Mar 25, 2017
2 parents 334d72c + f330daa commit e9fa9ad
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 87 deletions.
56 changes: 24 additions & 32 deletions core/ledger/kvledger/txmgmt/txmgr/commontests/pkg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ import (
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb/stateleveldb"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/txmgr"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr"
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
ledgertestutil "github.com/hyperledger/fabric/core/ledger/testutil"
"github.com/hyperledger/fabric/core/ledger/util"
"github.com/hyperledger/fabric/protos/common"
"github.com/spf13/viper"
Expand All @@ -37,48 +35,40 @@ const (
)

type testEnv interface {
init(t *testing.T)
init(t *testing.T, testLedgerID string)
getName() string
getTxMgr() txmgr.TxMgr
getVDB() statedb.VersionedDB
cleanup()
}

var testEnvs = []testEnv{}

func init() {
//call a helper method to load the core.yaml so that we can detect whether couch is configured
ledgertestutil.SetupCoreYAMLConfig("./../../../../../../peer")

//Only run the tests if CouchDB is explitily enabled in the code,
//otherwise CouchDB may not be installed and all the tests would fail
if ledgerconfig.IsCouchDBEnabled() == true {
testEnvs = []testEnv{&levelDBLockBasedEnv{}, &couchDBLockBasedEnv{}}
} else {
testEnvs = []testEnv{&levelDBLockBasedEnv{}}
}

}
// Tests will be run against each environment in this array
// For example, to skip CouchDB tests, remove &couchDBLockBasedEnv{}
var testEnvs = []testEnv{&levelDBLockBasedEnv{}, &couchDBLockBasedEnv{}}

///////////// LevelDB Environment //////////////

const levelDBtestEnvName = "levelDB_LockBasedTxMgr"

type levelDBLockBasedEnv struct {
testDBEnv *stateleveldb.TestVDBEnv
testDB statedb.VersionedDB
txmgr txmgr.TxMgr
testLedgerID string
testDBEnv *stateleveldb.TestVDBEnv
testDB statedb.VersionedDB
txmgr txmgr.TxMgr
}

func (env *levelDBLockBasedEnv) getName() string {
return "levelDB_LockBasedTxMgr"
return levelDBtestEnvName
}

func (env *levelDBLockBasedEnv) init(t *testing.T) {
func (env *levelDBLockBasedEnv) init(t *testing.T, testLedgerID string) {
viper.Set("peer.fileSystemPath", testFilesystemPath)
testDBEnv := stateleveldb.NewTestVDBEnv(t)
testDB, err := testDBEnv.DBProvider.GetDBHandle("TestDB")
testDB, err := testDBEnv.DBProvider.GetDBHandle(testLedgerID)
testutil.AssertNoError(t, err, "")

txMgr := lockbasedtxmgr.NewLockBasedTxMgr(testDB)
env.testLedgerID = testLedgerID
env.testDBEnv = testDBEnv
env.testDB = testDB
env.txmgr = txMgr
Expand All @@ -99,27 +89,29 @@ func (env *levelDBLockBasedEnv) cleanup() {

///////////// CouchDB Environment //////////////

var couchTestChainID = "TxmgrTestDB"
const couchDBtestEnvName = "couchDB_LockBasedTxMgr"

type couchDBLockBasedEnv struct {
testDBEnv *statecouchdb.TestVDBEnv
testDB statedb.VersionedDB
txmgr txmgr.TxMgr
testLedgerID string
testDBEnv *statecouchdb.TestVDBEnv
testDB statedb.VersionedDB
txmgr txmgr.TxMgr
}

func (env *couchDBLockBasedEnv) getName() string {
return "couchDB_LockBasedTxMgr"
return couchDBtestEnvName
}

func (env *couchDBLockBasedEnv) init(t *testing.T) {
func (env *couchDBLockBasedEnv) init(t *testing.T, testLedgerID string) {
viper.Set("peer.fileSystemPath", testFilesystemPath)
// both vagrant and CI have couchdb configured at host "couchdb"
viper.Set("ledger.state.couchDBConfig.couchDBAddress", "couchdb:5984")
testDBEnv := statecouchdb.NewTestVDBEnv(t)
testDB, err := testDBEnv.DBProvider.GetDBHandle(couchTestChainID)
testDB, err := testDBEnv.DBProvider.GetDBHandle(testLedgerID)
testutil.AssertNoError(t, err, "")

txMgr := lockbasedtxmgr.NewLockBasedTxMgr(testDB)
env.testLedgerID = testLedgerID
env.testDBEnv = testDBEnv
env.testDB = testDB
env.txmgr = txMgr
Expand All @@ -135,7 +127,7 @@ func (env *couchDBLockBasedEnv) getVDB() statedb.VersionedDB {

func (env *couchDBLockBasedEnv) cleanup() {
defer env.txmgr.Shutdown()
defer env.testDBEnv.Cleanup(couchTestChainID)
defer env.testDBEnv.Cleanup(env.testLedgerID)
}

//////////// txMgrTestHelper /////////////
Expand Down
126 changes: 71 additions & 55 deletions core/ledger/kvledger/txmgmt/txmgr/commontests/txmgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ import (
"github.com/hyperledger/fabric/common/ledger/testutil"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
)

func TestTxSimulatorWithNoExistingData(t *testing.T) {
// run the tests for each environment configured in pkg_test.go
for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)
testLedgerID := "testtxsimulatorwithnoexistingdata"
testEnv.init(t, testLedgerID)
testTxSimulatorWithNoExistingData(t, testEnv)
testEnv.cleanup()
}
Expand All @@ -55,7 +56,8 @@ func testTxSimulatorWithNoExistingData(t *testing.T, env testEnv) {
func TestTxSimulatorWithExistingData(t *testing.T) {
for _, testEnv := range testEnvs {
t.Run(testEnv.getName(), func(t *testing.T) {
testEnv.init(t)
testLedgerID := "testtxsimulatorwithexistingdata"
testEnv.init(t, testLedgerID)
testTxSimulatorWithExistingData(t, testEnv)
testEnv.cleanup()
})
Expand Down Expand Up @@ -99,16 +101,16 @@ func testTxSimulatorWithExistingData(t *testing.T, env testEnv) {

// verify the versions of keys in persistence
vv, _ := env.getVDB().GetState("ns1", "key1")
//TODO re-enable after adding couch version wrapper
//testutil.AssertEquals(t, vv.Version, version.NewHeight(2, 1))
testutil.AssertEquals(t, vv.Version, version.NewHeight(1, 1))
vv, _ = env.getVDB().GetState("ns1", "key2")
testutil.AssertEquals(t, vv.Version, version.NewHeight(0, 1))
}

func TestTxValidation(t *testing.T) {
for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)
testLedgerID := "testtxvalidation"
testEnv.init(t, testLedgerID)
testTxValidation(t, testEnv)
testEnv.cleanup()
}
Expand All @@ -128,7 +130,8 @@ func testTxValidation(t *testing.T, env testEnv) {
txRWSet1, _ := s1.GetTxSimulationResults()
txMgrHelper.validateAndCommitRWSet(txRWSet1)

// simulate tx2 that make changes to existing data
// simulate tx2 that make changes to existing data.
// tx2: Read/Update ns1:key1, Delete ns2:key3.
s2, _ := txMgr.NewTxSimulator()
value, _ := s2.GetState("ns1", "key1")
testutil.AssertEquals(t, value, []byte("value1"))
Expand All @@ -137,55 +140,64 @@ func testTxValidation(t *testing.T, env testEnv) {
s2.DeleteState("ns2", "key3")
s2.Done()

// simulate tx3 before committing tx2 changes. Reads and modifies the key changed by tx2
// simulate tx3 before committing tx2 changes. Reads and modifies the key changed by tx2.
// tx3: Read/Update ns1:key1
s3, _ := txMgr.NewTxSimulator()
s3.GetState("ns1", "key1")
s3.SetState("ns1", "key1", []byte("value1_3"))
s3.Done()

// simulate tx4 before committing tx2 changes. Reads and Deletes the key changed by tx2
// tx4: Read/Delete ns2:key3
s4, _ := txMgr.NewTxSimulator()
s4.GetState("ns2", "key3")
s4.DeleteState("ns2", "key3")
s4.Done()

// simulate tx5 before committing tx2 changes. Modifies and then Reads the key changed by tx2 and writes a new key
// tx5: Update/Read ns1:key1
s5, _ := txMgr.NewTxSimulator()
s5.SetState("ns1", "key1", []byte("new_value"))
s5.GetState("ns1", "key1")
s5.Done()

// simulate tx6 before committing tx2 changes. Only writes a new key, does not reads/writes a key changed by tx2
// tx6: Update ns1:new_key
s6, _ := txMgr.NewTxSimulator()
s6.SetState("ns1", "new_key", []byte("new_value"))
s6.Done()

// Summary of simulated transactions
// tx2: Read/Update ns1:key1, Delete ns2:key3.
// tx3: Read/Update ns1:key1
// tx4: Read/Delete ns2:key3
// tx5: Update/Read ns1:key1
// tx6: Update ns1:new_key

// validate and commit RWset for tx2
txRWSet2, _ := s2.GetTxSimulationResults()
txMgrHelper.validateAndCommitRWSet(txRWSet2)
//TODO re-enable after adding couch version wrapper
/*
//RWSet for tx3 and tx4 should not be invalid now
txRWSet3, _ := s3.GetTxSimulationResults()
txMgrHelper.checkRWsetInvalid(txRWSet3)
txRWSet4, _ := s4.GetTxSimulationResults()
txMgrHelper.checkRWsetInvalid(txRWSet4)
//tx5 shold still be valid as it over-writes the key first and then reads
txRWSet5, _ := s5.GetTxSimulationResults()
txMgrHelper.validateAndCommitRWSet(txRWSet5)
// tx6 should still be valid as it only writes a new key
txRWSet6, _ := s6.GetTxSimulationResults()
txMgrHelper.validateAndCommitRWSet(txRWSet6)
*/

//RWSet for tx3 and tx4 and tx5 should be invalid now due to read conflicts
txRWSet3, _ := s3.GetTxSimulationResults()
txMgrHelper.checkRWsetInvalid(txRWSet3)

txRWSet4, _ := s4.GetTxSimulationResults()
txMgrHelper.checkRWsetInvalid(txRWSet4)

txRWSet5, _ := s5.GetTxSimulationResults()
txMgrHelper.checkRWsetInvalid(txRWSet5)

// tx6 should still be valid as it only writes a new key
txRWSet6, _ := s6.GetTxSimulationResults()
txMgrHelper.validateAndCommitRWSet(txRWSet6)
}

func TestTxPhantomValidation(t *testing.T) {
for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)
testLedgerID := "testtxphantomvalidation"
testEnv.init(t, testLedgerID)
testTxPhantomValidation(t, testEnv)
testEnv.cleanup()
}
Expand Down Expand Up @@ -254,23 +266,29 @@ func testTxPhantomValidation(t *testing.T, env testEnv) {
func TestIterator(t *testing.T) {
for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)

testLedgerID := "testiterator_1"
testEnv.init(t, testLedgerID)
testIterator(t, testEnv, 10, 2, 7)
testEnv.cleanup()

testEnv.init(t)
testLedgerID = "testiterator_2"
testEnv.init(t, testLedgerID)
testIterator(t, testEnv, 10, 1, 11)
testEnv.cleanup()

testEnv.init(t)
testLedgerID = "testiterator_3"
testEnv.init(t, testLedgerID)
testIterator(t, testEnv, 10, 0, 0)
testEnv.cleanup()

testEnv.init(t)
testLedgerID = "testiterator_4"
testEnv.init(t, testLedgerID)
testIterator(t, testEnv, 10, 5, 0)
testEnv.cleanup()

testEnv.init(t)
testLedgerID = "testiterator_5"
testEnv.init(t, testLedgerID)
testIterator(t, testEnv, 10, 0, 5)
testEnv.cleanup()
}
Expand Down Expand Up @@ -337,7 +355,8 @@ func testIterator(t *testing.T, env testEnv, numKeys int, startKeyNum int, endKe
func TestIteratorWithDeletes(t *testing.T) {
for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)
testLedgerID := "testiteratorwithdeletes"
testEnv.init(t, testLedgerID)
testIteratorWithDeletes(t, testEnv)
testEnv.cleanup()
}
Expand Down Expand Up @@ -371,15 +390,16 @@ func testIteratorWithDeletes(t *testing.T, env testEnv) {
defer itr.Close()
kv, _ := itr.Next()
testutil.AssertEquals(t, kv.(*ledger.KV).Key, createTestKey(3))
//TODO re-enable after adding couch delete function
//kv, _ = itr.Next()
//testutil.AssertEquals(t, kv.(*ledger.KV).Key, createTestKey(5))

kv, _ = itr.Next()
testutil.AssertEquals(t, kv.(*ledger.KV).Key, createTestKey(5))
}

func TestTxValidationWithItr(t *testing.T) {
for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)
testLedgerID := "testtxvalidationwithitr"
testEnv.init(t, testLedgerID)
testTxValidationWithItr(t, testEnv)
testEnv.cleanup()
}
Expand Down Expand Up @@ -430,12 +450,9 @@ func testTxValidationWithItr(t *testing.T, env testEnv) {
txRWSet4, _ := s4.GetTxSimulationResults()
txMgrHelper.validateAndCommitRWSet(txRWSet4)

//TODO re-enable after adding couch version wrapper
/*
//RWSet tx3 should not be invalid now
txRWSet3, _ := s3.GetTxSimulationResults()
txMgrHelper.checkRWsetInvalid(txRWSet3)
*/
//RWSet tx3 should be invalid now
txRWSet3, _ := s3.GetTxSimulationResults()
txMgrHelper.checkRWsetInvalid(txRWSet3)

// tx2 should still be valid
txRWSet2, _ := s2.GetTxSimulationResults()
Expand All @@ -446,7 +463,8 @@ func testTxValidationWithItr(t *testing.T, env testEnv) {
func TestGetSetMultipeKeys(t *testing.T) {
for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)
testLedgerID := "testgetsetmultipekeys"
testEnv.init(t, testLedgerID)
testGetSetMultipeKeys(t, testEnv)
testEnv.cleanup()
}
Expand Down Expand Up @@ -504,18 +522,15 @@ func createTestValue(i int) []byte {
//TestExecuteQueryQuery is only tested on the CouchDB testEnv
func TestExecuteQuery(t *testing.T) {

// Query is only tested on the CouchDB testEnv
if ledgerconfig.IsCouchDBEnabled() == true {
testEnvs = []testEnv{&couchDBLockBasedEnv{}}
} else {
testEnvs = []testEnv{}
}

for _, testEnv := range testEnvs {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testEnv.init(t)
testExecuteQuery(t, testEnv)
testEnv.cleanup()
// Query is only supported and tested on the CouchDB testEnv
if testEnv.getName() == couchDBtestEnvName {
t.Logf("Running test for TestEnv = %s", testEnv.getName())
testLedgerID := "testexecutequery"
testEnv.init(t, testLedgerID)
testExecuteQuery(t, testEnv)
testEnv.cleanup()
}
}
}

Expand Down Expand Up @@ -560,7 +575,8 @@ func testExecuteQuery(t *testing.T, env testEnv) {
queryExecuter, _ := txMgr.NewQueryExecutor()
queryString := "{\"selector\":{\"owner\": {\"$eq\": \"bob\"}},\"limit\": 10,\"skip\": 0}"

itr, _ := queryExecuter.ExecuteQuery("ns1", queryString)
itr, err := queryExecuter.ExecuteQuery("ns1", queryString)
testutil.AssertNoError(t, err, "Error upon ExecuteQuery()")

counter := 0
for {
Expand Down

0 comments on commit e9fa9ad

Please sign in to comment.