diff --git a/core/ledger/kvledger/txmgmt/txmgr/commontests/pkg_test.go b/core/ledger/kvledger/txmgmt/txmgr/commontests/pkg_test.go index beb7bf67f29..2567605a749 100644 --- a/core/ledger/kvledger/txmgmt/txmgr/commontests/pkg_test.go +++ b/core/ledger/kvledger/txmgmt/txmgr/commontests/pkg_test.go @@ -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" @@ -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 @@ -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 @@ -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 ///////////// diff --git a/core/ledger/kvledger/txmgmt/txmgr/commontests/txmgr_test.go b/core/ledger/kvledger/txmgmt/txmgr/commontests/txmgr_test.go index f491ee54af5..100d6a92c9b 100644 --- a/core/ledger/kvledger/txmgmt/txmgr/commontests/txmgr_test.go +++ b/core/ledger/kvledger/txmgmt/txmgr/commontests/txmgr_test.go @@ -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() } @@ -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() }) @@ -99,8 +101,7 @@ 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)) } @@ -108,7 +109,8 @@ func testTxSimulatorWithExistingData(t *testing.T, env testEnv) { 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() } @@ -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")) @@ -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() } @@ -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() } @@ -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() } @@ -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() } @@ -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() @@ -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() } @@ -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() + } } } @@ -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 {