Skip to content

Commit 42f2574

Browse files
author
Srinivasan Muralidharan
committed
FAB-1297 multichain tests for chaincode framework
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 <[email protected]>
1 parent 5c9fcc3 commit 42f2574

9 files changed

+271
-70
lines changed

core/chaincode/exectransaction_test.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ func getNowMillis() int64 {
5656
}
5757

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

92-
RegisterSysCCs(chainID)
92+
RegisterSysCCs()
93+
94+
for _, id := range chainIDs {
95+
kvledger.CreateLedger(id)
96+
DeploySysCCs(id)
97+
}
9398

9499
go grpcServer.Serve(lis)
95100

96101
return lis, nil
97102
}
98103

99-
func finitPeer(lis net.Listener, chainID string) {
104+
func finitPeer(lis net.Listener, chainIDs ...string) {
100105
if lis != nil {
101-
deRegisterSysCCs(chainID)
102-
if lgr := kvledger.GetLedger(chainID); lgr != nil {
103-
lgr.Close()
106+
for _, c := range chainIDs {
107+
deRegisterSysCCs(c)
108+
if lgr := kvledger.GetLedger(c); lgr != nil {
109+
lgr.Close()
110+
}
104111
}
105112
closeListenerAndSleep(lis)
106113
}
114+
107115
ledgerPath := viper.GetString("peer.fileSystemPath")
108116
os.RemoveAll(ledgerPath)
109117
os.RemoveAll(filepath.Join(os.TempDir(), "hyperledger"))

core/chaincode/importsysccs.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,17 @@ var systemChaincodes = []*SystemChaincode{
4848

4949
//RegisterSysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric
5050
//note the chaincode must still be deployed and launched like a user chaincode will be
51-
func RegisterSysCCs(chainID string) {
51+
func RegisterSysCCs() {
5252
for _, sysCC := range systemChaincodes {
53-
RegisterSysCC(chainID, sysCC)
53+
RegisterSysCC(sysCC)
54+
}
55+
}
56+
57+
//DeploySysCCs is the hook for system chaincodes where system chaincodes are registered with the fabric
58+
//note the chaincode must still be deployed and launched like a user chaincode will be
59+
func DeploySysCCs(chainID string) {
60+
for _, sysCC := range systemChaincodes {
61+
DeploySysCC(chainID, sysCC)
5462
}
5563
}
5664

core/chaincode/multichains_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package chaincode
18+
19+
import (
20+
"testing"
21+
22+
pb "github.com/hyperledger/fabric/protos/peer"
23+
24+
"golang.org/x/net/context"
25+
)
26+
27+
func TestExecuteInvokeOnManyChains(t *testing.T) {
28+
chains := []string{"chain1", "chain2", "chain3", "chain4"}
29+
lis, err := initPeer(chains...)
30+
if err != nil {
31+
t.Fail()
32+
t.Logf("Error creating peer: %s", err)
33+
}
34+
35+
defer finitPeer(lis, chains...)
36+
37+
var ctxt = context.Background()
38+
39+
url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
40+
chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url}
41+
42+
args := []string{"a", "b", "10"}
43+
for _, c := range chains {
44+
err = invokeExample02Transaction(ctxt, c, chaincodeID, args, true)
45+
if err != nil {
46+
t.Fail()
47+
t.Logf("Error invoking transaction: %s", err)
48+
} else {
49+
t.Logf("Invoke test passed for chain %s", c)
50+
}
51+
theChaincodeSupport.Stop(ctxt, c, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}})
52+
}
53+
54+
}

core/chaincode/sysccapi.go

+28-24
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type SystemChaincode struct {
5555
}
5656

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

74-
chaincodeID := &pb.ChaincodeID{Path: syscc.Path, Name: syscc.Name}
75-
spec := pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeID: chaincodeID, CtorMsg: &pb.ChaincodeInput{Args: syscc.InitArgs}}
74+
sysccLogger.Infof("system chaincode %s(%s) registered", syscc.Name, syscc.Path)
75+
return err
76+
}
77+
78+
// DeploySysCC deploys the given system chaincode on a chain
79+
func DeploySysCC(chainID string, syscc *SystemChaincode) error {
80+
if !syscc.Enabled || !isWhitelisted(syscc) {
81+
sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s) disabled", syscc.Name, syscc.Path))
82+
return nil
83+
}
84+
85+
var err error
7686

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

8393
defer txsim.Done()
8494

95+
chaincodeID := &pb.ChaincodeID{Path: syscc.Path, Name: syscc.Name}
96+
spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeID: chaincodeID, CtorMsg: &pb.ChaincodeInput{Args: syscc.InitArgs}}
97+
8598
ctxt := context.WithValue(context.Background(), TXSimulatorKey, txsim)
86-
if deployErr := DeploySysCC(ctxt, chainID, &spec); deployErr != nil {
87-
errStr := fmt.Sprintf("deploy chaincode failed: %s", deployErr)
88-
sysccLogger.Error(errStr)
89-
return fmt.Errorf(errStr)
99+
100+
// First build and get the deployment spec
101+
chaincodeDeploymentSpec, err := buildSysCC(ctxt, spec)
102+
103+
if err != nil {
104+
sysccLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
105+
return err
90106
}
91107

92-
sysccLogger.Infof("system chaincode %s(%s) registered", syscc.Name, syscc.Path)
108+
txid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name
109+
_, _, err = Execute(ctxt, chainID, txid, nil, chaincodeDeploymentSpec)
110+
111+
sysccLogger.Infof("system chaincode %s/%s(%s) deployed", syscc.Name, chainID, syscc.Path)
112+
93113
return err
94114
}
95115

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

125-
// DeploySysCC deploys the supplied system chaincode to the local peer
126-
func DeploySysCC(ctx context.Context, chainID string, spec *pb.ChaincodeSpec) error {
127-
// First build and get the deployment spec
128-
chaincodeDeploymentSpec, err := buildSysCC(ctx, spec)
129-
130-
if err != nil {
131-
sysccLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
132-
return err
133-
}
134-
135-
txid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name
136-
_, _, err = Execute(ctx, chainID, txid, nil, chaincodeDeploymentSpec)
137-
138-
return err
139-
}
140-
141145
func isWhitelisted(syscc *SystemChaincode) bool {
142146
chaincodes := viper.GetStringMapString("chaincode.system")
143147
val, ok := chaincodes[syscc.Name]

core/chaincode/systemchaincode_test.go

+105-14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package chaincode
1818

1919
import (
2020
"net"
21+
"os"
2122
"testing"
2223
"time"
2324

@@ -30,12 +31,46 @@ import (
3031
"google.golang.org/grpc"
3132
)
3233

34+
func deploySampleSysCC(t *testing.T, ctxt context.Context, chainID string) error {
35+
DeploySysCCs(chainID)
36+
37+
url := "github.com/hyperledger/fabric/core/system_chaincode/sample_syscc"
38+
39+
cdsforStop := &pb.ChaincodeDeploymentSpec{ExecEnv: 1, ChaincodeSpec: &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: [][]byte{[]byte("")}}}}
40+
41+
f := "putval"
42+
args := util.ToChaincodeArgs(f, "greeting", "hey there")
43+
44+
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
45+
_, _, _, err := invoke(ctxt, chainID, spec)
46+
if err != nil {
47+
theChaincodeSupport.Stop(ctxt, chainID, cdsforStop)
48+
t.Logf("Error invoking sample_syscc: %s", err)
49+
return err
50+
}
51+
52+
f = "getval"
53+
args = util.ToChaincodeArgs(f, "greeting")
54+
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
55+
_, _, _, err = invoke(ctxt, chainID, spec)
56+
if err != nil {
57+
theChaincodeSupport.Stop(ctxt, chainID, cdsforStop)
58+
t.Logf("Error invoking sample_syscc: %s", err)
59+
return err
60+
}
61+
62+
theChaincodeSupport.Stop(ctxt, chainID, cdsforStop)
63+
64+
return nil
65+
}
66+
3367
// Test deploy of a transaction.
3468
func TestExecuteDeploySysChaincode(t *testing.T) {
3569
var opts []grpc.ServerOption
3670
grpcServer := grpc.NewServer(opts...)
3771
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/tmpdb")
3872
kvledger.Initialize("/var/hyperledger/test/tmpdb")
73+
defer os.RemoveAll("/var/hyperledger/test/tmpdb")
3974

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

76111
chainID := util.GetTestChainID()
77112

78-
RegisterSysCCs(chainID)
113+
RegisterSysCCs()
79114

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

84-
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
85-
_, _, _, err = invoke(ctxt, chainID, spec)
117+
kvledger.CreateLedger(chainID)
118+
119+
err = deploySampleSysCC(t, ctxt, chainID)
86120
if err != nil {
87121
closeListenerAndSleep(lis)
88122
t.Fail()
89-
t.Logf("Error invoking sample_syscc: %s", err)
90123
return
91124
}
92125

93-
f = "getval"
94-
args = util.ToChaincodeArgs(f, "greeting")
95-
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
96-
_, _, _, err = invoke(ctxt, chainID, spec)
126+
closeListenerAndSleep(lis)
127+
}
128+
129+
// Test multichains
130+
func TestMultichains(t *testing.T) {
131+
var opts []grpc.ServerOption
132+
grpcServer := grpc.NewServer(opts...)
133+
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/tmpdb")
134+
kvledger.Initialize("/var/hyperledger/test/tmpdb")
135+
defer os.RemoveAll("/var/hyperledger/test/tmpdb")
136+
137+
//use a different address than what we usually use for "peer"
138+
//we override the peerAddress set in chaincode_support.go
139+
// FIXME: Use peer.GetLocalAddress()
140+
peerAddress := "0.0.0.0:21726"
141+
lis, err := net.Listen("tcp", peerAddress)
142+
if err != nil {
143+
t.Fail()
144+
t.Logf("Error starting peer listener %s", err)
145+
return
146+
}
147+
148+
getPeerEndpoint := func() (*pb.PeerEndpoint, error) {
149+
return &pb.PeerEndpoint{ID: &pb.PeerID{Name: "testpeer"}, Address: peerAddress}, nil
150+
}
151+
152+
ccStartupTimeout := time.Duration(5000) * time.Millisecond
153+
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))
154+
155+
go grpcServer.Serve(lis)
156+
157+
var ctxt = context.Background()
158+
159+
//set systemChaincodes to sample
160+
systemChaincodes = []*SystemChaincode{
161+
{
162+
Enabled: true,
163+
Name: "sample_syscc",
164+
Path: "github.com/hyperledger/fabric/core/system_chaincode/samplesyscc",
165+
InitArgs: [][]byte{},
166+
Chaincode: &samplesyscc.SampleSysCC{},
167+
},
168+
}
169+
170+
// System chaincode has to be enabled
171+
viper.Set("chaincode.system", map[string]string{"sample_syscc": "true"})
172+
173+
RegisterSysCCs()
174+
175+
/////^^^ system initialization completed ^^^
176+
177+
chainID := "chain1"
178+
179+
kvledger.CreateLedger(chainID)
180+
181+
err = deploySampleSysCC(t, ctxt, chainID)
97182
if err != nil {
98183
closeListenerAndSleep(lis)
99184
t.Fail()
100-
t.Logf("Error invoking sample_syscc: %s", err)
101185
return
102186
}
103187

104-
cds := &pb.ChaincodeDeploymentSpec{ExecEnv: 1, ChaincodeSpec: &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}}
188+
chainID = "chain2"
189+
190+
kvledger.CreateLedger(chainID)
105191

106-
theChaincodeSupport.Stop(ctxt, chainID, cds)
192+
err = deploySampleSysCC(t, ctxt, chainID)
193+
if err != nil {
194+
closeListenerAndSleep(lis)
195+
t.Fail()
196+
return
197+
}
107198

108199
closeListenerAndSleep(lis)
109200
}

core/endorser/endorser_test.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,11 @@ func initPeer(chainID string) (net.Listener, error) {
9393
ccStartupTimeout := time.Duration(30000) * time.Millisecond
9494
pb.RegisterChaincodeSupportServer(grpcServer, chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))
9595

96-
chaincode.RegisterSysCCs(chainID)
96+
chaincode.RegisterSysCCs()
9797

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

101-
chaincode.DeploySysCC(context.Background(), chainID, &spec)
100+
chaincode.DeploySysCCs(chainID)
102101

103102
go grpcServer.Serve(lis)
104103

0 commit comments

Comments
 (0)