Skip to content

Commit

Permalink
FAB-1297 multichain tests for chaincode framework
Browse files Browse the repository at this point in the history
https://jira.hyperledger.org/browse/FAB-1297

Adds tests to run system and user chaincodes on multiple chains

Some points of interest
    . chains are initialized with the follow (use for "join")
                kvledger.CreateLedger(chainid)
                chaincode.DeploySysCCs(chainid)
    . kvledger.GetLedger panics if chain is not there
    . peer initializes with **TEST_CHAINID**
    . LCCC (and other system chaincodes) are initilized on each
      chain. So a user chaincode is registered with the LCCC for
      that chain

Tests are serial but can be parallel when chaincode relaxes serialization

Change-Id: Iae6c36d004d845cfe74f24e8fa9e8c47bac3b499
Signed-off-by: Srinivasan Muralidharan <muralisr@us.ibm.com>
  • Loading branch information
Srinivasan Muralidharan committed Dec 8, 2016
1 parent 5c9fcc3 commit 42f2574
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 70 deletions.
22 changes: 15 additions & 7 deletions core/chaincode/exectransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ func getNowMillis() int64 {
}

//initialize peer and start up. If security==enabled, login as vp
func initPeer(chainID string) (net.Listener, error) {
func initPeer(chainIDs ...string) (net.Listener, error) {
//start clean
finitPeer(nil, chainID)
finitPeer(nil, chainIDs...)
var opts []grpc.ServerOption
if viper.GetBool("peer.tls.enabled") {
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
Expand Down Expand Up @@ -89,21 +89,29 @@ func initPeer(chainID string) (net.Listener, error) {
ccStartupTimeout := time.Duration(chaincodeStartupTimeoutDefault) * time.Millisecond
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))

RegisterSysCCs(chainID)
RegisterSysCCs()

for _, id := range chainIDs {
kvledger.CreateLedger(id)
DeploySysCCs(id)
}

go grpcServer.Serve(lis)

return lis, nil
}

func finitPeer(lis net.Listener, chainID string) {
func finitPeer(lis net.Listener, chainIDs ...string) {
if lis != nil {
deRegisterSysCCs(chainID)
if lgr := kvledger.GetLedger(chainID); lgr != nil {
lgr.Close()
for _, c := range chainIDs {
deRegisterSysCCs(c)
if lgr := kvledger.GetLedger(c); lgr != nil {
lgr.Close()
}
}
closeListenerAndSleep(lis)
}

ledgerPath := viper.GetString("peer.fileSystemPath")
os.RemoveAll(ledgerPath)
os.RemoveAll(filepath.Join(os.TempDir(), "hyperledger"))
Expand Down
12 changes: 10 additions & 2 deletions core/chaincode/importsysccs.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,17 @@ var systemChaincodes = []*SystemChaincode{

//RegisterSysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric
//note the chaincode must still be deployed and launched like a user chaincode will be
func RegisterSysCCs(chainID string) {
func RegisterSysCCs() {
for _, sysCC := range systemChaincodes {
RegisterSysCC(chainID, sysCC)
RegisterSysCC(sysCC)
}
}

//DeploySysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric
//note the chaincode must still be deployed and launched like a user chaincode will be
func DeploySysCCs(chainID string) {
for _, sysCC := range systemChaincodes {
DeploySysCC(chainID, sysCC)
}
}

Expand Down
54 changes: 54 additions & 0 deletions core/chaincode/multichains_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package chaincode

import (
"testing"

pb "github.com/hyperledger/fabric/protos/peer"

"golang.org/x/net/context"
)

func TestExecuteInvokeOnManyChains(t *testing.T) {
chains := []string{"chain1", "chain2", "chain3", "chain4"}
lis, err := initPeer(chains...)
if err != nil {
t.Fail()
t.Logf("Error creating peer: %s", err)
}

defer finitPeer(lis, chains...)

var ctxt = context.Background()

url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url}

args := []string{"a", "b", "10"}
for _, c := range chains {
err = invokeExample02Transaction(ctxt, c, chaincodeID, args, true)
if err != nil {
t.Fail()
t.Logf("Error invoking transaction: %s", err)
} else {
t.Logf("Invoke test passed for chain %s", c)
}
theChaincodeSupport.Stop(ctxt, c, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}})
}

}
52 changes: 28 additions & 24 deletions core/chaincode/sysccapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type SystemChaincode struct {
}

// RegisterSysCC registers the given system chaincode with the peer
func RegisterSysCC(chainID string, syscc *SystemChaincode) error {
func RegisterSysCC(syscc *SystemChaincode) error {
if !syscc.Enabled || !isWhitelisted(syscc) {
sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s) disabled", syscc.Name, syscc.Path))
return nil
Expand All @@ -71,8 +71,18 @@ func RegisterSysCC(chainID string, syscc *SystemChaincode) error {
}
}

chaincodeID := &pb.ChaincodeID{Path: syscc.Path, Name: syscc.Name}
spec := pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeID: chaincodeID, CtorMsg: &pb.ChaincodeInput{Args: syscc.InitArgs}}
sysccLogger.Infof("system chaincode %s(%s) registered", syscc.Name, syscc.Path)
return err
}

// DeploySysCC deploys the given system chaincode on a chain
func DeploySysCC(chainID string, syscc *SystemChaincode) error {
if !syscc.Enabled || !isWhitelisted(syscc) {
sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s) disabled", syscc.Name, syscc.Path))
return nil
}

var err error

lgr := kvledger.GetLedger(chainID)
var txsim ledger.TxSimulator
Expand All @@ -82,14 +92,24 @@ func RegisterSysCC(chainID string, syscc *SystemChaincode) error {

defer txsim.Done()

chaincodeID := &pb.ChaincodeID{Path: syscc.Path, Name: syscc.Name}
spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeID: chaincodeID, CtorMsg: &pb.ChaincodeInput{Args: syscc.InitArgs}}

ctxt := context.WithValue(context.Background(), TXSimulatorKey, txsim)
if deployErr := DeploySysCC(ctxt, chainID, &spec); deployErr != nil {
errStr := fmt.Sprintf("deploy chaincode failed: %s", deployErr)
sysccLogger.Error(errStr)
return fmt.Errorf(errStr)

// First build and get the deployment spec
chaincodeDeploymentSpec, err := buildSysCC(ctxt, spec)

if err != nil {
sysccLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
return err
}

sysccLogger.Infof("system chaincode %s(%s) registered", syscc.Name, syscc.Path)
txid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name
_, _, err = Execute(ctxt, chainID, txid, nil, chaincodeDeploymentSpec)

sysccLogger.Infof("system chaincode %s/%s(%s) deployed", syscc.Name, chainID, syscc.Path)

return err
}

Expand Down Expand Up @@ -122,22 +142,6 @@ func buildSysCC(context context.Context, spec *pb.ChaincodeSpec) (*pb.ChaincodeD
return chaincodeDeploymentSpec, nil
}

// DeploySysCC deploys the supplied system chaincode to the local peer
func DeploySysCC(ctx context.Context, chainID string, spec *pb.ChaincodeSpec) error {
// First build and get the deployment spec
chaincodeDeploymentSpec, err := buildSysCC(ctx, spec)

if err != nil {
sysccLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
return err
}

txid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name
_, _, err = Execute(ctx, chainID, txid, nil, chaincodeDeploymentSpec)

return err
}

func isWhitelisted(syscc *SystemChaincode) bool {
chaincodes := viper.GetStringMapString("chaincode.system")
val, ok := chaincodes[syscc.Name]
Expand Down
119 changes: 105 additions & 14 deletions core/chaincode/systemchaincode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package chaincode

import (
"net"
"os"
"testing"
"time"

Expand All @@ -30,12 +31,46 @@ import (
"google.golang.org/grpc"
)

func deploySampleSysCC(t *testing.T, ctxt context.Context, chainID string) error {
DeploySysCCs(chainID)

url := "github.com/hyperledger/fabric/core/system_chaincode/sample_syscc"

cdsforStop := &pb.ChaincodeDeploymentSpec{ExecEnv: 1, ChaincodeSpec: &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: [][]byte{[]byte("")}}}}

f := "putval"
args := util.ToChaincodeArgs(f, "greeting", "hey there")

spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, _, _, err := invoke(ctxt, chainID, spec)
if err != nil {
theChaincodeSupport.Stop(ctxt, chainID, cdsforStop)
t.Logf("Error invoking sample_syscc: %s", err)
return err
}

f = "getval"
args = util.ToChaincodeArgs(f, "greeting")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, _, _, err = invoke(ctxt, chainID, spec)
if err != nil {
theChaincodeSupport.Stop(ctxt, chainID, cdsforStop)
t.Logf("Error invoking sample_syscc: %s", err)
return err
}

theChaincodeSupport.Stop(ctxt, chainID, cdsforStop)

return nil
}

// Test deploy of a transaction.
func TestExecuteDeploySysChaincode(t *testing.T) {
var opts []grpc.ServerOption
grpcServer := grpc.NewServer(opts...)
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/tmpdb")
kvledger.Initialize("/var/hyperledger/test/tmpdb")
defer os.RemoveAll("/var/hyperledger/test/tmpdb")

//use a different address than what we usually use for "peer"
//we override the peerAddress set in chaincode_support.go
Expand Down Expand Up @@ -75,35 +110,91 @@ func TestExecuteDeploySysChaincode(t *testing.T) {

chainID := util.GetTestChainID()

RegisterSysCCs(chainID)
RegisterSysCCs()

url := "github.com/hyperledger/fabric/core/system_chaincode/sample_syscc"
f := "putval"
args := util.ToChaincodeArgs(f, "greeting", "hey there")
/////^^^ system initialization completed ^^^

spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, _, _, err = invoke(ctxt, chainID, spec)
kvledger.CreateLedger(chainID)

err = deploySampleSysCC(t, ctxt, chainID)
if err != nil {
closeListenerAndSleep(lis)
t.Fail()
t.Logf("Error invoking sample_syscc: %s", err)
return
}

f = "getval"
args = util.ToChaincodeArgs(f, "greeting")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, _, _, err = invoke(ctxt, chainID, spec)
closeListenerAndSleep(lis)
}

// Test multichains
func TestMultichains(t *testing.T) {
var opts []grpc.ServerOption
grpcServer := grpc.NewServer(opts...)
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/tmpdb")
kvledger.Initialize("/var/hyperledger/test/tmpdb")
defer os.RemoveAll("/var/hyperledger/test/tmpdb")

//use a different address than what we usually use for "peer"
//we override the peerAddress set in chaincode_support.go
// FIXME: Use peer.GetLocalAddress()
peerAddress := "0.0.0.0:21726"
lis, err := net.Listen("tcp", peerAddress)
if err != nil {
t.Fail()
t.Logf("Error starting peer listener %s", err)
return
}

getPeerEndpoint := func() (*pb.PeerEndpoint, error) {
return &pb.PeerEndpoint{ID: &pb.PeerID{Name: "testpeer"}, Address: peerAddress}, nil
}

ccStartupTimeout := time.Duration(5000) * time.Millisecond
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))

go grpcServer.Serve(lis)

var ctxt = context.Background()

//set systemChaincodes to sample
systemChaincodes = []*SystemChaincode{
{
Enabled: true,
Name: "sample_syscc",
Path: "github.com/hyperledger/fabric/core/system_chaincode/samplesyscc",
InitArgs: [][]byte{},
Chaincode: &samplesyscc.SampleSysCC{},
},
}

// System chaincode has to be enabled
viper.Set("chaincode.system", map[string]string{"sample_syscc": "true"})

RegisterSysCCs()

/////^^^ system initialization completed ^^^

chainID := "chain1"

kvledger.CreateLedger(chainID)

err = deploySampleSysCC(t, ctxt, chainID)
if err != nil {
closeListenerAndSleep(lis)
t.Fail()
t.Logf("Error invoking sample_syscc: %s", err)
return
}

cds := &pb.ChaincodeDeploymentSpec{ExecEnv: 1, ChaincodeSpec: &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}}
chainID = "chain2"

kvledger.CreateLedger(chainID)

theChaincodeSupport.Stop(ctxt, chainID, cds)
err = deploySampleSysCC(t, ctxt, chainID)
if err != nil {
closeListenerAndSleep(lis)
t.Fail()
return
}

closeListenerAndSleep(lis)
}
7 changes: 3 additions & 4 deletions core/endorser/endorser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,11 @@ func initPeer(chainID string) (net.Listener, error) {
ccStartupTimeout := time.Duration(30000) * time.Millisecond
pb.RegisterChaincodeSupportServer(grpcServer, chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))

chaincode.RegisterSysCCs(chainID)
chaincode.RegisterSysCCs()

chaincodeID := &pb.ChaincodeID{Path: "github.com/hyperledger/fabric/core/chaincode/lccc", Name: "lccc"}
spec := pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeID: chaincodeID, CtorMsg: &pb.ChaincodeInput{Args: [][]byte{[]byte("")}}}
kvledger.CreateLedger(chainID)

chaincode.DeploySysCC(context.Background(), chainID, &spec)
chaincode.DeploySysCCs(chainID)

go grpcServer.Serve(lis)

Expand Down

0 comments on commit 42f2574

Please sign in to comment.