Skip to content

Commit

Permalink
[FAB-18073] Add integration test for dev mode
Browse files Browse the repository at this point in the history
Signed-off-by: Chongxin Luo <[email protected]>
Signed-off-by: Tiffany Harris <[email protected]>
  • Loading branch information
DereckLuo authored and sykesm committed Sep 1, 2020
1 parent 9848841 commit c8d124f
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 10 deletions.
4 changes: 4 additions & 0 deletions integration/chaincode/simple/chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package simple

import (
"fmt"
"os"
"strconv"

"github.com/hyperledger/fabric/core/chaincode/shim"
Expand Down Expand Up @@ -59,6 +60,9 @@ func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02 Invoke")
if os.Getenv("DEVMODE_ENABLED") != "" {
fmt.Println("invoking in devmode")
}
function, args := stub.GetFunctionAndParameters()
switch function {
case "invoke":
Expand Down
4 changes: 4 additions & 0 deletions integration/chaincode/simple/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import (
)

func main() {
if os.Getenv("DEVMODE_ENABLED") != "" {
fmt.Println("starting up in devmode...")
}

err := shim.Start(&simple.SimpleChaincode{})
if err != nil {
fmt.Fprintf(os.Stderr, "Exiting Simple chaincode: %s", err)
Expand Down
45 changes: 45 additions & 0 deletions integration/devmode/devmode_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package devmode

import (
"encoding/json"
"testing"

"github.com/hyperledger/fabric/integration/nwo"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestDevMode(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Devmode Suite")
}

var components *nwo.Components

var _ = SynchronizedBeforeSuite(func() []byte {
components = &nwo.Components{}
components.Build()

payload, err := json.Marshal(components)
Expect(err).NotTo(HaveOccurred())

return payload
}, func(payload []byte) {
err := json.Unmarshal(payload, &components)
Expect(err).NotTo(HaveOccurred())
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
components.Cleanup()
})

func BasePort() int {
return 39000 + 1000*GinkgoParallelNode()
}
210 changes: 210 additions & 0 deletions integration/devmode/devmode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package devmode

import (
"io/ioutil"
"os"
"os/exec"
"strconv"
"syscall"
"time"

docker "github.com/fsouza/go-dockerclient"
"github.com/hyperledger/fabric/integration/nwo"
"github.com/hyperledger/fabric/integration/nwo/commands"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
"github.com/tedsuo/ifrit"
"github.com/tedsuo/ifrit/ginkgomon"
)

var _ = Describe("Devmode", func() {
var (
testDir string
client *docker.Client
network *nwo.Network
process ifrit.Process
chaincode nwo.Chaincode
chaincodeRunner *ginkgomon.Runner
chaincodeProcess ifrit.Process
org1peer0 *nwo.Peer
)

BeforeEach(func() {
var err error
testDir, err = ioutil.TempDir("", "devmode")
Expect(err).NotTo(HaveOccurred())

client, err = docker.NewClientFromEnv()
Expect(err).NotTo(HaveOccurred())

chaincode = nwo.Chaincode{
Name: "mycc",
Version: "0.0",
Path: "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
Ctor: `{"Args":["init","a","100","b","200"]}`,
Policy: `AND ('Org1MSP.member')`,
}

network = nwo.New(devModeSolo, testDir, client, BasePort(), components)
network.TLSEnabled = false
org1peer0 = network.Peer("Org1", "peer0")
org1peer0.DevMode = true

network.GenerateConfigTree()
network.Bootstrap()

networkRunner := network.NetworkGroupRunner()
process = ifrit.Invoke(networkRunner)
Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
})

AfterEach(func() {
if process != nil {
process.Signal(syscall.SIGTERM)
Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
}

if chaincodeProcess != nil {
chaincodeProcess.Signal(syscall.SIGTERM)
}

if network != nil {
network.Cleanup()
}

os.RemoveAll(testDir)
})

It("executes chaincode in dev mode", func() {
channelName := "testchannel"
chaincodeID := chaincode.Name + ":" + chaincode.Version
orderer := network.Orderer("orderer")

By("setting up the channel")
network.CreateAndJoinChannel(orderer, channelName)

By("building the chaincode")
chaincodePath, err := gexec.Build(chaincode.Path)
Expect(err).ToNot(HaveOccurred())

By("running the chaincode")
peerChaincodeAddress := network.PeerAddress(org1peer0, nwo.ChaincodePort)
cmd := exec.Command(chaincodePath, "--peer.address", peerChaincodeAddress)
cmd.Env = append(cmd.Env, "CORE_CHAINCODE_ID_NAME="+chaincodeID, "DEVMODE_ENABLED=true")
chaincodeRunner = ginkgomon.New(ginkgomon.Config{
Name: "chaincode",
Command: cmd,
StartCheck: `starting up in devmode...`,
StartCheckTimeout: 15 * time.Second,
})
chaincodeProcess = ifrit.Invoke(chaincodeRunner)
Eventually(chaincodeProcess.Ready(), network.EventuallyTimeout).Should(BeClosed())

By("installing the chaincode")
nwo.InstallChaincode(network, chaincode, org1peer0)

By("Instantiating the chaincode")
nwo.InstantiateChaincode(network, channelName, orderer, chaincode, org1peer0, org1peer0)

By("Querying and invoking chaincode built and started manually")
RunQueryInvokeQuery(network, orderer, org1peer0, channelName, 100)
Eventually(chaincodeRunner).Should(gbytes.Say("invoking in devmode"))
})
})

func RunQueryInvokeQuery(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string, queryValue int) {
By("querying the chaincode")
sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
ChannelID: channel,
Name: "mycc",
Ctor: `{"Args":["query","a"]}`,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess).To(gbytes.Say(strconv.Itoa(queryValue)))

By("invoke the chaincode")
sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
ChannelID: channel,
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
Name: "mycc",
Ctor: `{"Args":["invoke","a","b","10"]}`,
PeerAddresses: []string{
n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
},
WaitForEvent: true,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))

By("querying the chaincode again")
sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
ChannelID: channel,
Name: "mycc",
Ctor: `{"Args":["query","a"]}`,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess).To(gbytes.Say(strconv.Itoa(queryValue - 10)))
}

var devModeSolo = &nwo.Config{
Organizations: []*nwo.Organization{{
Name: "OrdererOrg",
MSPID: "OrdererMSP",
Domain: "example.com",
EnableNodeOUs: false,
Users: 0,
CA: &nwo.CA{Hostname: "ca"},
}, {
Name: "Org1",
MSPID: "Org1MSP",
Domain: "org1.example.com",
EnableNodeOUs: true,
Users: 2,
CA: &nwo.CA{Hostname: "ca"},
}},
Consortiums: []*nwo.Consortium{{
Name: "SampleConsortium",
Organizations: []string{
"Org1",
},
}},
Consensus: &nwo.Consensus{
Type: "solo",
},
SystemChannel: &nwo.SystemChannel{
Name: "systemchannel",
Profile: "OneOrgOrdererGenesis",
},
Orderers: []*nwo.Orderer{
{Name: "orderer", Organization: "OrdererOrg"},
},
Channels: []*nwo.Channel{
{Name: "testchannel", Profile: "OneOrgChannel"},
},
Peers: []*nwo.Peer{{
Name: "peer0",
Organization: "Org1",
Channels: []*nwo.PeerChannel{
{Name: "testchannel", Anchor: true},
},
}},
Profiles: []*nwo.Profile{{
Name: "OneOrgOrdererGenesis",
Orderers: []string{"orderer"},
}, {
Name: "OneOrgChannel",
Consortium: "SampleConsortium",
Organizations: []string{"Org1"},
}},
}
13 changes: 9 additions & 4 deletions integration/nwo/commands/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,25 @@ SPDX-License-Identifier: Apache-2.0

package commands

import "strconv"
import (
"strconv"
)

type NodeStart struct {
PeerID string
PeerID string
DevMode bool
}

func (n NodeStart) SessionName() string {
return n.PeerID
}

func (n NodeStart) Args() []string {
return []string{
"node", "start",
args := []string{"node", "start"}
if n.DevMode {
args = append(args, "--peer-chaincodedev")
}
return args
}

type NodeReset struct {
Expand Down
4 changes: 2 additions & 2 deletions integration/nwo/core_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ peer:
keepalive:
minInterval: 60s
tls:
enabled: true
enabled: {{ .TLSEnabled }}
clientAuthRequired: false
cert:
file: {{ .PeerLocalTLSDir Peer }}/server.crt
Expand Down Expand Up @@ -191,7 +191,7 @@ ledger:
operations:
listenAddress: 127.0.0.1:{{ .PeerPort Peer "Operations" }}
tls:
enabled: true
enabled: {{ .TLSEnabled }}
cert:
file: {{ .PeerLocalTLSDir Peer }}/server.crt
key:
Expand Down
7 changes: 5 additions & 2 deletions integration/nwo/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type OrdererCapabilities struct {
type Peer struct {
Name string `yaml:"name,omitempty"`
Organization string `yaml:"organization,omitempty"`
DevMode bool `yaml:"devmode,omitempty"`
Channels []*PeerChannel `yaml:"channels,omitempty"`
}

Expand Down Expand Up @@ -142,6 +143,7 @@ type Network struct {
EventuallyTimeout time.Duration
MetricsProvider string
StatsdEndpoint string
TLSEnabled bool

PortsByBrokerID map[string]Ports
PortsByOrdererID map[string]Ports
Expand Down Expand Up @@ -186,6 +188,7 @@ func New(c *Config, rootDir string, client *docker.Client, startPort int, compon
Profiles: c.Profiles,
Consortiums: c.Consortiums,
Templates: c.Templates,
TLSEnabled: true, // set TLS enabled by default
}

if network.Templates == nil {
Expand Down Expand Up @@ -1027,7 +1030,7 @@ func (n *Network) OrdererGroupRunner() ifrit.Runner {
// used to start and manage a peer process.
func (n *Network) PeerRunner(p *Peer, env ...string) *ginkgomon.Runner {
cmd := n.peerCommand(
commands.NodeStart{PeerID: p.ID()},
commands.NodeStart{PeerID: p.ID(), DevMode: p.DevMode},
fmt.Sprintf("FABRIC_CFG_PATH=%s", n.PeerDir(p)),
)
cmd.Env = append(cmd.Env, env...)
Expand Down Expand Up @@ -1065,7 +1068,7 @@ func (n *Network) NetworkGroupRunner() ifrit.Runner {
func (n *Network) peerCommand(command Command, env ...string) *exec.Cmd {
cmd := NewCommand(n.Components.Peer(), command)
cmd.Env = append(cmd.Env, env...)
if ConnectsToOrderer(command) {
if ConnectsToOrderer(command) && n.TLSEnabled {
cmd.Args = append(cmd.Args, "--tls")
cmd.Args = append(cmd.Args, "--cafile", n.CACertsBundlePath())
}
Expand Down
4 changes: 2 additions & 2 deletions integration/nwo/orderer_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ General:
ListenAddress: 127.0.0.1
ListenPort: {{ .OrdererPort Orderer "Listen" }}
TLS:
Enabled: true
Enabled: {{ .TLSEnabled }}
PrivateKey: {{ $w.OrdererLocalTLSDir Orderer }}/server.key
Certificate: {{ $w.OrdererLocalTLSDir Orderer }}/server.crt
RootCAs:
Expand Down Expand Up @@ -101,7 +101,7 @@ Consensus:
Operations:
ListenAddress: 127.0.0.1:{{ .OrdererPort Orderer "Operations" }}
TLS:
Enabled: true
Enabled: {{ .TLSEnabled }}
PrivateKey: {{ $w.OrdererLocalTLSDir Orderer }}/server.key
Certificate: {{ $w.OrdererLocalTLSDir Orderer }}/server.crt
RootCAs:
Expand Down

0 comments on commit c8d124f

Please sign in to comment.