go_study/fabric-main/integration/ledger/reset_rollback_test.go

635 lines
23 KiB
Go

/*
Copyright IBM Corp All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package ledger
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"syscall"
docker "github.com/fsouza/go-dockerclient"
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/integration/channelparticipation"
"github.com/hyperledger/fabric/integration/nwo"
"github.com/hyperledger/fabric/integration/nwo/commands"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
"github.com/tedsuo/ifrit"
ginkgomon "github.com/tedsuo/ifrit/ginkgomon_v2"
)
var _ = Describe("rollback, reset, pause, resume, and unjoin peer node commands", func() {
// at the beginning of each test under this block, we have defined two collections:
// 1. collectionMarbles - Org1 and Org2 have access to this collection
// 2. collectionMarblePrivateDetails - Org2 and Org3 have access to this collection
// when calling QueryChaincode with first arg "readMarble", it will query collectionMarbles[1]
// when calling QueryChaincode with first arg "readMarblePrivateDetails", it will query collectionMarblePrivateDetails[2]
var (
setup *setup
helper *testHelper
)
BeforeEach(func() {
setup = initThreeOrgsSetup()
nwo.EnableCapabilities(setup.network, setup.channelID, "Application", "V2_0", setup.orderer, setup.peers...)
helper = &testHelper{
networkHelper: &networkHelper{
Network: setup.network,
orderer: setup.orderer,
peers: setup.peers,
testDir: setup.testDir,
channelID: setup.channelID,
},
}
By("installing and instantiating chaincode on all peers")
chaincode := nwo.Chaincode{
Name: "marblesp",
Version: "1.0",
Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/marbles_private/cmd"),
Lang: "binary",
PackageFile: filepath.Join(setup.testDir, "marbles-pvtdata.tar.gz"),
Label: "marbles-private-20",
SignaturePolicy: `OR ('Org1MSP.member','Org2MSP.member', 'Org3MSP.member')`,
CollectionsConfig: filepath.Join("testdata", "collection_configs", "collections_config1.json"),
Sequence: "1",
}
helper.deployChaincode(chaincode)
org2peer0 := setup.network.Peer("Org2", "peer0")
height := helper.getLedgerHeight(org2peer0)
By("creating 5 blocks")
for i := 1; i <= 5; i++ {
helper.addMarble("marblesp", fmt.Sprintf(`{"name":"marble%d", "color":"blue", "size":35, "owner":"tom", "price":99}`, i), org2peer0)
helper.waitUntilAllPeersEqualLedgerHeight(height + i)
}
By("verifying marble1 to marble5 exist in collectionMarbles & collectionMarblePrivateDetails in Org2.peer0")
for i := 1; i <= 5; i++ {
helper.assertPresentInCollectionM("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
helper.assertPresentInCollectionMPD("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
}
})
AfterEach(func() {
setup.cleanup()
})
// This test executes the rollback, reset, pause, and resume commands on the following peerss
// Org1.peer0 - rollback
// Org2.peer0 - reset
// Org3.peer0 - pause/rollback/resume
//
// There are 14 blocks created in BeforeEach (before rollback/reset).
// block 0: genesis, block 1: org1Anchor, block 2: org2Anchor, block 3: org3Anchor
// block 4 to 8: chaincode instantiation, block 9 to 13: chaincode invoke to add marbles.
It("pauses and resumes channels and rolls back and resets the ledger", func() {
By("Checking ledger height on each peer")
for _, peer := range helper.peers {
Expect(helper.getLedgerHeight(peer)).Should(Equal(14))
}
org1peer0 := setup.network.Peer("Org1", "peer0")
org2peer0 := setup.network.Peer("Org2", "peer0")
org3peer0 := setup.network.Peer("Org3", "peer0")
// Negative test: rollback, reset, pause, and resume should fail when the peer is online
expectedErrMessage := "as another peer node command is executing," +
" wait for that command to complete its execution or terminate it before retrying"
By("Rolling back the peer to block 6 from block 13 while the peer node is online")
helper.rollback(org1peer0, 6, expectedErrMessage, false)
By("Resetting the peer to the genesis block while the peer node is online")
helper.reset(org2peer0, expectedErrMessage, false)
By("Pausing the peer while the peer node is online")
helper.pause(org3peer0, expectedErrMessage, false)
By("Resuming the peer while the peer node is online")
helper.resume(org3peer0, expectedErrMessage, false)
By("Stopping the network to test commands")
setup.terminateAllProcess()
By("Rolling back the channel to block 6 from block 14 on org1peer0")
helper.rollback(org1peer0, 6, "", true)
By("Resetting org2peer0 to the genesis block")
helper.reset(org2peer0, "", true)
By("Pausing the channel on org3peer0")
helper.pause(org3peer0, "", true)
By("Rolling back the paused channel to block 6 from block 14 on org3peer0")
helper.rollback(org3peer0, 6, "", true)
By("Verifying paused channel is not found upon peer restart")
setup.startPeer(org3peer0)
helper.assertPausedChannel(org3peer0)
By("Checking preResetHeightFile exists for a paused channel that is also rolled back or reset")
setup.startOrderer()
preResetHeightFile := filepath.Join(setup.network.PeerLedgerDir(org3peer0), "chains/chains", helper.channelID, "__preResetHeight")
Expect(preResetHeightFile).To(BeARegularFile())
setup.terminateAllProcess()
By("Resuming the peer")
helper.resume(org3peer0, "", true)
By("Verifying that the endorsement is disabled when the peer has not received missing blocks")
setup.startPeers()
for _, peer := range setup.peers {
helper.assertDisabledEndorser("marblesp", peer)
}
By("Bringing the peers to recent height by starting the orderer")
setup.startOrderer()
for _, peer := range setup.peers {
By("Verifying endorsement is enabled and preResetHeightFile is removed on peer " + peer.ID())
helper.waitUntilEndorserEnabled(peer)
preResetHeightFile := filepath.Join(setup.network.PeerLedgerDir(peer), "chains/chains", helper.channelID, "__preResetHeight")
Expect(preResetHeightFile).NotTo(BeAnExistingFile())
}
setup.network.VerifyMembership(setup.peers, setup.channelID, "marblesp")
By("Verifying leger height on all peers")
helper.waitUntilAllPeersEqualLedgerHeight(14)
// Test chaincode works correctly after the commands
By("Creating 2 more blocks post rollback/reset")
for i := 6; i <= 7; i++ {
helper.addMarble("marblesp", fmt.Sprintf(`{"name":"marble%d", "color":"blue", "size":35, "owner":"tom", "price":99}`, i), org2peer0)
helper.waitUntilAllPeersEqualLedgerHeight(14 + i - 5)
}
By("Verifying marble1 to marble7 exist in collectionMarbles & collectionMarblePrivateDetails on org2peer0")
for i := 1; i <= 7; i++ {
helper.assertPresentInCollectionM("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
helper.assertPresentInCollectionMPD("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
}
// statedb rebuild test
By("Stopping peers and deleting the statedb folder on peer Org2.peer0")
peer := setup.network.Peer("Org2", "peer0")
setup.stopPeers()
dbPath := filepath.Join(setup.network.PeerLedgerDir(peer), "stateLeveldb")
Expect(os.RemoveAll(dbPath)).NotTo(HaveOccurred())
Expect(dbPath).NotTo(BeADirectory())
By("Restarting the peer Org2.peer0")
setup.startPeer(peer)
Expect(dbPath).To(BeADirectory())
helper.assertPresentInCollectionM("marblesp", "marble2", peer)
})
It("change collection members and rebuild databases", func() {
By("Checking ledger height on each peer")
for _, peer := range helper.peers {
Expect(helper.getLedgerHeight(peer)).Should(Equal(14))
}
org1peer0 := setup.network.Peer("Org1", "peer0")
org2peer0 := setup.network.Peer("Org2", "peer0")
org3peer0 := setup.network.Peer("Org3", "peer0")
By("verifying marble1 to marble5 exist in collectionMarbles & collectionMarblePrivateDetails in the members")
for i := 1; i <= 5; i++ {
helper.assertPresentInCollectionM("marblesp", fmt.Sprintf("marble%d", i), org1peer0)
helper.assertPresentInCollectionM("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
helper.assertPresentInCollectionMPD("marblesp", fmt.Sprintf("marble%d", i), org2peer0)
helper.assertPresentInCollectionMPD("marblesp", fmt.Sprintf("marble%d", i), org3peer0)
}
// Add org1 to collectionMarblesPrivateDetails
By("Updating the chaincode definition to version 2.0")
updatedChaincode := nwo.Chaincode{
Name: "marblesp",
Version: "2.0",
Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/marbles_private/cmd"),
Lang: "binary",
PackageFile: filepath.Join(setup.testDir, "marbles-pvtdata.tar.gz"),
Label: "marbles-private-20",
SignaturePolicy: `OR ('Org1MSP.member','Org2MSP.member', 'Org3MSP.member')`,
CollectionsConfig: filepath.Join("testdata", "collection_configs", "collections_config3.json"),
Sequence: "2",
}
helper.deployChaincode(updatedChaincode)
// statedb rebuild test
By("Stopping peers and deleting the statedb folder on peer Org1.peer0")
org1peer0 = setup.network.Peer("Org1", "peer0")
setup.stopPeers()
dbPath := filepath.Join(setup.network.PeerLedgerDir(org1peer0), "stateLeveldb")
Expect(os.RemoveAll(dbPath)).NotTo(HaveOccurred())
Expect(dbPath).NotTo(BeADirectory())
By("Restarting the peer Org1.peer0")
setup.startPeers()
Expect(dbPath).To(BeADirectory())
helper.assertPresentInCollectionM("marblesp", "marble2", org1peer0)
})
// This test exercises peer node unjoin on the following peers:
// Org1.peer0 - unjoin
// Org2.peer0 -
// Org3.peer0 - unjoin (via partial / resumed deletion on restart)
It("unjoins channels and checks side effects on the ledger and transient storage", func() {
By("Checking ledger heights on each peer")
for _, peer := range helper.peers {
Expect(helper.getLedgerHeight(peer)).Should(Equal(14))
}
org1peer0 := setup.network.Peer("Org1", "peer0")
org2peer0 := setup.network.Peer("Org2", "peer0")
org3peer0 := setup.network.Peer("Org3", "peer0")
// Negative test: peer node unjoin should fail when the peer is online.
By("unjoining the peer while the peer node is online")
expectedErrMessage := "as another peer node command is executing," +
" wait for that command to complete its execution or terminate it before retrying"
helper.unjoin(org1peer0, expectedErrMessage, false)
helper.unjoin(org2peer0, expectedErrMessage, false)
helper.unjoin(org3peer0, expectedErrMessage, false)
By("stopping the peers to test unjoin commands")
setup.stopPeers()
By("Unjoining from a channel while the peer is down")
helper.unjoin(org1peer0, "", true)
// Negative test: unjoin when the channel has been unjoined
By("Double unjoining from a channel")
expectedErrMessage = "unjoin channel \\[testchannel\\]: cannot update ledger status, ledger \\[testchannel\\] does not exist"
helper.unjoin(org1peer0, expectedErrMessage, false)
// Simulate an error in peer unjoin by marking the ledger folder as read-only.
By("Unjoining from a peer with a read-only ledger file system")
ledgerStoragePath := filepath.Join(setup.network.PeerLedgerDir(org3peer0), "chains/chains", helper.channelID)
Expect(os.Chmod(ledgerStoragePath, 0o555)).NotTo(HaveOccurred())
Expect(os.RemoveAll(ledgerStoragePath)).To(HaveOccurred()) // can not delete write-only ledger folder
expectedErrMessage = "ledgersData/chains/chains/testchannel/blockfile_000000: permission denied"
helper.unjoin(org3peer0, expectedErrMessage, false)
Expect(os.Chmod(ledgerStoragePath, 0o755)).NotTo(HaveOccurred())
By("restarting peers")
setup.startPeer(org1peer0)
setup.startPeer(org2peer0)
setup.startPeer(org3peer0)
helper.assertUnjoinedChannel(org1peer0)
helper.assertUnjoinedChannel(org3peer0)
By("rejoining the channel with org1")
setup.network.JoinChannel(helper.channelID, setup.orderer, org1peer0)
helper.waitUntilPeerEqualLedgerHeight(org1peer0, 14)
By("Creating 2 more blocks post re-join org1")
for i := 6; i <= 7; i++ {
helper.addMarble("marblesp", fmt.Sprintf(`{"name":"marble%d", "color":"blue", "size":35, "owner":"tom", "price":99}`, i), org1peer0)
helper.waitUntilPeerEqualLedgerHeight(org1peer0, 14+i-5)
helper.waitUntilPeerEqualLedgerHeight(org2peer0, 14+i-5)
}
})
})
type setup struct {
testDir string
channelID string
network *nwo.Network
peers []*nwo.Peer
peerProcess []ifrit.Process
orderer *nwo.Orderer
ordererProcess ifrit.Process
ordererRunner *ginkgomon.Runner
}
func initThreeOrgsSetup() *setup {
var err error
testDir, err := ioutil.TempDir("", "reset-rollback")
Expect(err).NotTo(HaveOccurred())
client, err := docker.NewClientFromEnv()
Expect(err).NotTo(HaveOccurred())
config := nwo.ThreeOrgEtcdRaft()
// disable all anchor peers
for _, p := range config.Peers {
for _, pc := range p.Channels {
pc.Anchor = false
}
}
n := nwo.New(config, testDir, client, StartPort(), components)
n.GenerateConfigTree()
n.Bootstrap()
peers := []*nwo.Peer{
n.Peer("Org1", "peer0"),
n.Peer("Org2", "peer0"),
n.Peer("Org3", "peer0"),
}
setup := &setup{
testDir: testDir,
network: n,
peers: peers,
channelID: "testchannel",
orderer: n.Orderer("orderer"),
}
setup.startOrderer()
setup.startPeer(peers[0])
setup.startPeer(peers[1])
setup.startPeer(peers[2])
channelparticipation.JoinOrdererJoinPeersAppChannel(n, "testchannel", setup.orderer, setup.ordererRunner)
n.UpdateOrgAnchorPeers(setup.orderer, testchannelID, "Org1", n.PeersInOrg("Org1"))
n.UpdateOrgAnchorPeers(setup.orderer, testchannelID, "Org2", n.PeersInOrg("Org2"))
n.UpdateOrgAnchorPeers(setup.orderer, testchannelID, "Org3", n.PeersInOrg("Org3"))
By("verifying membership")
setup.network.VerifyMembership(setup.peers, setup.channelID)
return setup
}
func (s *setup) cleanup() {
s.terminateAllProcess()
s.network.Cleanup()
os.RemoveAll(s.testDir)
}
func (s *setup) terminateAllProcess() {
s.ordererProcess.Signal(syscall.SIGTERM)
Eventually(s.ordererProcess.Wait(), s.network.EventuallyTimeout).Should(Receive())
s.ordererProcess = nil
s.ordererRunner = nil
for _, p := range s.peerProcess {
p.Signal(syscall.SIGTERM)
Eventually(p.Wait(), s.network.EventuallyTimeout).Should(Receive())
}
s.peerProcess = nil
}
func (s *setup) startPeers() {
for _, peer := range s.peers {
s.startPeer(peer)
}
}
func (s *setup) stopPeers() {
for _, p := range s.peerProcess {
p.Signal(syscall.SIGTERM)
Eventually(p.Wait(), s.network.EventuallyTimeout).Should(Receive())
}
s.peerProcess = nil
}
func (s *setup) startPeer(peer *nwo.Peer) {
peerRunner := s.network.PeerRunner(peer)
peerProcess := ifrit.Invoke(peerRunner)
Eventually(peerProcess.Ready(), s.network.EventuallyTimeout).Should(BeClosed())
s.peerProcess = append(s.peerProcess, peerProcess)
}
func (s *setup) startOrderer() {
s.ordererRunner = s.network.OrdererRunner(s.orderer)
s.ordererProcess = ifrit.Invoke(s.ordererRunner)
Eventually(s.ordererProcess.Ready(), s.network.EventuallyTimeout).Should(BeClosed())
}
type networkHelper struct {
*nwo.Network
orderer *nwo.Orderer
peers []*nwo.Peer
channelID string
testDir string
}
func (nh *networkHelper) deployChaincode(chaincode nwo.Chaincode) {
nwo.DeployChaincode(nh.Network, nh.channelID, nh.orderer, chaincode)
nh.waitUntilAllPeersEqualLedgerHeight(nh.getLedgerHeight(nh.peers[0]))
}
func (nh *networkHelper) waitUntilAllPeersEqualLedgerHeight(height int) {
for _, peer := range nh.peers {
nh.waitUntilPeerEqualLedgerHeight(peer, height)
}
}
func (nh *networkHelper) waitUntilPeerEqualLedgerHeight(peer *nwo.Peer, height int) {
Eventually(func() int {
return nh.getLedgerHeight(peer)
}, nh.EventuallyTimeout).Should(Equal(height))
}
func (nh *networkHelper) getLedgerHeight(peer *nwo.Peer) int {
sess, err := nh.PeerUserSession(peer, "User1", commands.ChannelInfo{
ChannelID: nh.channelID,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
channelInfoStr := strings.TrimPrefix(string(sess.Buffer().Contents()[:]), "Blockchain info:")
channelInfo := common.BlockchainInfo{}
err = json.Unmarshal([]byte(channelInfoStr), &channelInfo)
Expect(err).NotTo(HaveOccurred())
return int(channelInfo.Height)
}
func (nh *networkHelper) queryChaincode(peer *nwo.Peer, command commands.ChaincodeQuery, expectedMessage string, expectSuccess bool) {
sess, err := nh.PeerUserSession(peer, "User1", command)
Expect(err).NotTo(HaveOccurred())
if expectSuccess {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess).To(gbytes.Say(expectedMessage))
} else {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say(expectedMessage))
}
}
func (nh *networkHelper) invokeChaincode(peer *nwo.Peer, command commands.ChaincodeInvoke) {
sess, err := nh.PeerUserSession(peer, "User1", command)
Expect(err).NotTo(HaveOccurred())
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful."))
}
func (nh *networkHelper) rollback(peer *nwo.Peer, blockNumber int, expectedErrMessage string, expectSuccess bool) {
rollbackCmd := commands.NodeRollback{ChannelID: nh.channelID, BlockNumber: blockNumber}
sess, err := nh.PeerUserSession(peer, "User1", rollbackCmd)
Expect(err).NotTo(HaveOccurred())
if expectSuccess {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
} else {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say(expectedErrMessage))
}
}
func (nh *networkHelper) reset(peer *nwo.Peer, expectedErrMessage string, expectSuccess bool) {
resetCmd := commands.NodeReset{}
sess, err := nh.PeerUserSession(peer, "User1", resetCmd)
Expect(err).NotTo(HaveOccurred())
if expectSuccess {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
} else {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say(expectedErrMessage))
}
}
func (nh *networkHelper) pause(peer *nwo.Peer, expectedErrMessage string, expectSuccess bool) {
pauseCmd := commands.NodePause{ChannelID: nh.channelID}
sess, err := nh.PeerUserSession(peer, "User1", pauseCmd)
Expect(err).NotTo(HaveOccurred())
if expectSuccess {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
} else {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say(expectedErrMessage))
}
}
func (nh *networkHelper) resume(peer *nwo.Peer, expectedErrMessage string, expectSuccess bool) {
resumeCmd := commands.NodeResume{ChannelID: nh.channelID}
sess, err := nh.PeerUserSession(peer, "User1", resumeCmd)
Expect(err).NotTo(HaveOccurred())
if expectSuccess {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
} else {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say(expectedErrMessage))
}
}
func (nh *networkHelper) unjoin(peer *nwo.Peer, expectedErrMessage string, expectSuccess bool) {
unjoinCmd := commands.NodeUnjoin{ChannelID: nh.channelID}
sess, err := nh.PeerUserSession(peer, "User1", unjoinCmd)
Expect(err).NotTo(HaveOccurred())
if expectSuccess {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(0))
} else {
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say(expectedErrMessage))
}
}
func (nh *networkHelper) waitUntilEndorserEnabled(peer *nwo.Peer) {
Eventually(func() *gbytes.Buffer {
sess, err := nh.PeerUserSession(peer, "User1", commands.ChannelInfo{
ChannelID: nh.channelID,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, nh.EventuallyTimeout).Should(gexec.Exit())
return sess.Buffer()
}, nh.EventuallyTimeout).Should(gbytes.Say("Blockchain info"))
}
type testHelper struct {
*networkHelper
}
func (th *testHelper) addMarble(chaincodeName, marbleDetails string, peer *nwo.Peer) {
marbleDetailsBase64 := base64.StdEncoding.EncodeToString([]byte(marbleDetails))
command := commands.ChaincodeInvoke{
ChannelID: th.channelID,
Orderer: th.OrdererAddress(th.orderer, nwo.ListenPort),
Name: chaincodeName,
Ctor: `{"Args":["initMarble"]}`,
Transient: fmt.Sprintf(`{"marble":"%s"}`, marbleDetailsBase64),
PeerAddresses: []string{
th.PeerAddress(peer, nwo.ListenPort),
},
WaitForEvent: true,
}
th.invokeChaincode(peer, command)
}
// assertPresentInCollectionM asserts that the private data for given marble is present in collection
// 'readMarble' at the given peers
func (th *testHelper) assertPresentInCollectionM(chaincodeName, marbleName string, peerList ...*nwo.Peer) {
command := commands.ChaincodeQuery{
ChannelID: th.channelID,
Name: chaincodeName,
Ctor: fmt.Sprintf(`{"Args":["readMarble","%s"]}`, marbleName),
}
expectedMsg := fmt.Sprintf(`{"docType":"marble","name":"%s"`, marbleName)
for _, peer := range peerList {
th.queryChaincode(peer, command, expectedMsg, true)
}
}
// assertAbsentInCollectionM asserts that the private data for given marble is present in collection
// 'readMarble' at the given peers
func (th *testHelper) assertAbsentInCollectionM(chaincodeName, marbleName string, peerList ...*nwo.Peer) {
command := commands.ChaincodeQuery{
ChannelID: th.channelID,
Name: chaincodeName,
Ctor: fmt.Sprintf(`{"Args":["readMarble","%s"]}`, marbleName),
}
expectedMsg := fmt.Sprintf(`{"docType":"marble","name":"%s"`, marbleName)
for _, peer := range peerList {
th.queryChaincode(peer, command, expectedMsg, false)
}
}
// assertPresentInCollectionMPD asserts that the private data for given marble is present
// in collection 'readMarblePrivateDetails' at the given peers
func (th *testHelper) assertPresentInCollectionMPD(chaincodeName, marbleName string, peerList ...*nwo.Peer) {
command := commands.ChaincodeQuery{
ChannelID: th.channelID,
Name: chaincodeName,
Ctor: fmt.Sprintf(`{"Args":["readMarblePrivateDetails","%s"]}`, marbleName),
}
expectedMsg := fmt.Sprintf(`{"docType":"marblePrivateDetails","name":"%s"`, marbleName)
for _, peer := range peerList {
th.queryChaincode(peer, command, expectedMsg, true)
}
}
func (th *testHelper) assertDisabledEndorser(chaincodeName string, peer *nwo.Peer) {
command := commands.ChaincodeQuery{
ChannelID: th.channelID,
Name: chaincodeName,
Ctor: `{"Args":["readMarble","marble1"]}`,
}
expectedMsg := "endorse requests are blocked while ledgers are being rebuilt"
th.queryChaincode(peer, command, expectedMsg, false)
}
func (th *testHelper) assertPausedChannel(peer *nwo.Peer) {
sess, err := th.PeerUserSession(peer, "User1", commands.ChannelInfo{
ChannelID: th.channelID,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, th.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say("Invalid chain ID"))
}
func (th *testHelper) assertUnjoinedChannel(peer *nwo.Peer) {
sess, err := th.PeerUserSession(peer, "User1", commands.ChannelInfo{
ChannelID: th.channelID,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, th.EventuallyTimeout).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say("Invalid chain ID"))
channelLedgerDir := filepath.Join(th.Network.PeerLedgerDir(peer), "chains/chains", th.channelID)
Expect(channelLedgerDir).NotTo(BeADirectory())
}