Commit f6562293 authored by Yacov Manevich's avatar Yacov Manevich Committed by Gerrit Code Review
Browse files

Merge "[FAB-12181] rewrite pvtdata e2e tests."

parents 00678c86 85262f3f
......@@ -14,19 +14,19 @@ import (
"path/filepath"
"strings"
"syscall"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
"github.com/tedsuo/ifrit"
"gopkg.in/yaml.v2"
"github.com/fsouza/go-dockerclient"
"github.com/hyperledger/fabric/integration/nwo"
"github.com/hyperledger/fabric/integration/nwo/commands"
"github.com/hyperledger/fabric/protos/common"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
"github.com/tedsuo/ifrit"
"github.com/tedsuo/ifrit/grouper"
"gopkg.in/yaml.v2"
)
var _ bool = Describe("PrivateData", func() {
......@@ -38,7 +38,6 @@ var _ bool = Describe("PrivateData", func() {
Describe("reconciliation", func() {
var (
testDir string
client *docker.Client
network *nwo.Network
process ifrit.Process
orderer *nwo.Orderer
......@@ -46,40 +45,7 @@ var _ bool = Describe("PrivateData", func() {
)
BeforeEach(func() {
var err error
testDir, err = ioutil.TempDir("", "e2e-pvtdata")
Expect(err).NotTo(HaveOccurred())
client, err = docker.NewClientFromEnv()
Expect(err).NotTo(HaveOccurred())
configBytes, err := ioutil.ReadFile(filepath.Join("testdata", "network.yaml"))
Expect(err).NotTo(HaveOccurred())
var networkConfig *nwo.Config
err = yaml.Unmarshal(configBytes, &networkConfig)
Expect(err).NotTo(HaveOccurred())
network = nwo.New(networkConfig, testDir, client, 35000+1000*GinkgoParallelNode(), components)
network.GenerateConfigTree()
network.Bootstrap()
networkRunner := network.NetworkGroupRunner()
process = ifrit.Invoke(networkRunner)
Eventually(process.Ready()).Should(BeClosed())
orderer = network.Orderer("orderer")
network.CreateAndJoinChannel(orderer, "testchannel")
network.UpdateChannelAnchors(orderer, "testchannel")
expectedPeers = []*nwo.Peer{
network.Peer("org1", "peer0"),
network.Peer("org2", "peer0"),
network.Peer("org3", "peer0"),
}
By("verifying membership")
verifyMembership(network, expectedPeers, "testchannel")
testDir, network, process, orderer, expectedPeers = initThreeOrgsSetup()
By("installing and instantiating chaincode on all peers")
chaincode := nwo.Chaincode{
......@@ -99,14 +65,7 @@ var _ bool = Describe("PrivateData", func() {
})
AfterEach(func() {
if process != nil {
process.Signal(syscall.SIGTERM)
Eventually(process.Wait(), time.Minute).Should(Receive())
}
if network != nil {
network.Cleanup()
}
os.RemoveAll(testDir)
testCleanup(testDir, network, process)
})
It("verify private data reconciliation when adding a new org to collection config", func() {
......@@ -245,8 +204,321 @@ var _ bool = Describe("PrivateData", func() {
`{"docType":"marblePrivateDetails","name":"marble1","price":99}`)
})
})
Describe("collection config BlockToLive is respected", func() {
var (
testDir string
network *nwo.Network
process ifrit.Process
orderer *nwo.Orderer
)
BeforeEach(func() {
testDir, network, process, orderer, _ = initThreeOrgsSetup()
})
AfterEach(func() {
testCleanup(testDir, network, process)
})
It("verifies private data is purged after BTL has passed and new peer doesn't pull private data that was purged", func() {
By("installing and instantiating chaincode on all peers")
chaincode := nwo.Chaincode{
Name: "marblesp",
Version: "1.0",
Path: "github.com/hyperledger/fabric/integration/chaincode/marbles_private/cmd",
Ctor: `{"Args":["init"]}`,
Policy: `OR ('Org1MSP.member','Org2MSP.member', 'Org3MSP.member')`,
CollectionsConfig: filepath.Join("testdata", "collection_configs", "short_btl_config.json")}
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
org2peer0 := network.Peer("org2", "peer0")
initialLedgerHeight := getLedgerHeight(network, org2peer0, "testchannel")
By("invoking initMarble function of the chaincode to create private data")
invokeChaincode(network, "org2", "peer0", "marblesp", `{"Args":["initMarble","marble1","blue","35","tom","99"]}`, "testchannel", orderer)
By("create a block, for private data existence")
i := 2
Eventually(func() int {
invokeChaincode(network, "org2", "peer0", "marblesp", fmt.Sprintf(`{"Args":["initMarble","marble%d","blue%d","3%d","tom","9%d"]}`, i, i, i, i), "testchannel", orderer)
i++
return getLedgerHeight(network, org2peer0, "testchannel")
}, network.EventuallyTimeout).Should(BeNumerically(">", initialLedgerHeight))
By("verify private data exist in peer0.org2")
verifyAccess(
network,
commands.ChaincodeQuery{
ChannelID: "testchannel",
Name: "marblesp",
Ctor: `{"Args":["readMarblePrivateDetails","marble1"]}`},
[]*nwo.Peer{org2peer0},
`{"docType":"marblePrivateDetails","name":"marble1","price":99}`)
By("create 4 more blocks to reach BTL threshold and have marble1 private data purged")
Eventually(func() int {
invokeChaincode(network, "org2", "peer0", "marblesp", fmt.Sprintf(`{"Args":["initMarble","marble%d","blue%d","3%d","tom","9%d"]}`, i, i, i, i), "testchannel", orderer)
i++
return getLedgerHeight(network, org2peer0, "testchannel")
}, network.EventuallyTimeout).Should(BeNumerically(">", initialLedgerHeight+4))
By("querying collectionMarbles by peer0.org2, marble1 should still be available")
verifyAccess(
network,
commands.ChaincodeQuery{
ChannelID: "testchannel",
Name: "marblesp",
Ctor: `{"Args":["readMarble","marble1"]}`},
[]*nwo.Peer{org2peer0},
`{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}`)
By("querying collectionMarblePrivateDetails by peer0.org2, marble1 should have been purged")
verifyAccessFailed(
network,
commands.ChaincodeQuery{
ChannelID: "testchannel",
Name: "marblesp",
Ctor: `{"Args":["readMarblePrivateDetails","marble1"]}`},
org2peer0,
"Marble private details does not exist: marble1")
By("peer1.org2 joins the channel")
org2peer1 := network.Peer("org2", "peer1")
network.JoinChannel("testchannel", orderer, org2peer1)
org2peer1.Channels = append(org2peer1.Channels, &nwo.PeerChannel{Name: "testchannel", Anchor: false})
By("install chaincode on peer1.org2 to be able to query it")
nwo.InstallChaincode(network, chaincode, org2peer1)
By("fetch latest blocks to peer1.org2")
ledgerHeight := getLedgerHeight(network, org2peer0, "testchannel")
sess, err := network.PeerAdminSession(org2peer1, commands.ChannelFetch{
Block: "newest",
ChannelID: "testchannel",
Orderer: network.OrdererAddress(orderer, nwo.ListenPort),
OutputFile: filepath.Join(testDir, "newest_block.pb")})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say(fmt.Sprintf("Received block: %d", ledgerHeight-1)))
By("wait until peer1.org2 ledger is updated with all txs")
Eventually(func() int {
return getLedgerHeight(network, org2peer1, "testchannel")
}, network.EventuallyTimeout).Should(Equal(ledgerHeight))
By("verify chaincode is instantiated on peer1.org2")
nwo.EnsureInstantiated(network, "testchannel", "marblesp", "1.0", org2peer1)
By("query peer1.org2, verify marble1 exist in collectionMarbles and private data doesn't exist")
verifyAccess(
network,
commands.ChaincodeQuery{
ChannelID: "testchannel",
Name: "marblesp",
Ctor: `{"Args":["readMarble","marble1"]}`},
[]*nwo.Peer{org2peer1},
`{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}`)
verifyAccessFailed(
network,
commands.ChaincodeQuery{
ChannelID: "testchannel",
Name: "marblesp",
Ctor: `{"Args":["readMarblePrivateDetails","marble1"]}`},
org2peer0,
"Marble private details does not exist: marble1")
})
})
Describe("network partition with respect of private data", func() {
var (
testDir string
network *nwo.Network
process ifrit.Process
orderer *nwo.Orderer
expectedPeers []*nwo.Peer
peersProcesses map[string]ifrit.Process
org1peer0 *nwo.Peer
org2peer0 *nwo.Peer
)
BeforeEach(func() {
peersProcesses = make(map[string]ifrit.Process)
var err error
testDir, err = ioutil.TempDir("", "e2e-pvtdata")
Expect(err).NotTo(HaveOccurred())
client, err := docker.NewClientFromEnv()
Expect(err).NotTo(HaveOccurred())
configBytes, err := ioutil.ReadFile(filepath.Join("testdata", "network.yaml"))
Expect(err).NotTo(HaveOccurred())
var networkConfig *nwo.Config
err = yaml.Unmarshal(configBytes, &networkConfig)
Expect(err).NotTo(HaveOccurred())
network = nwo.New(networkConfig, testDir, client, 35000+1000*GinkgoParallelNode(), components)
network.GenerateConfigTree()
network.Bootstrap()
members := grouper.Members{
{Name: "brokers", Runner: network.BrokerGroupRunner()},
{Name: "orderers", Runner: network.OrdererGroupRunner()},
}
networkRunner := grouper.NewOrdered(syscall.SIGTERM, members)
process = ifrit.Invoke(networkRunner)
Eventually(process.Ready()).Should(BeClosed())
org1peer0 = network.Peer("org1", "peer0")
org2peer0 = network.Peer("org2", "peer0")
testPeers := []*nwo.Peer{org1peer0, org2peer0}
for _, peer := range testPeers {
pr := network.PeerRunner(peer)
p := ifrit.Invoke(pr)
peersProcesses[peer.ID()] = p
Eventually(p.Ready(), network.EventuallyTimeout).Should(BeClosed())
}
orderer = network.Orderer("orderer")
network.CreateChannel("testchannel", orderer, testPeers[0])
network.JoinChannel("testchannel", orderer, testPeers...)
network.UpdateChannelAnchors(orderer, "testchannel")
expectedPeers = []*nwo.Peer{org1peer0, org2peer0}
By("verifying membership")
verifyMembership(network, expectedPeers, "testchannel")
})
AfterEach(func() {
for _, peerProcess := range peersProcesses {
if peerProcess != nil {
peerProcess.Signal(syscall.SIGTERM)
Eventually(peerProcess.Wait(), network.EventuallyTimeout).Should(Receive())
}
}
testCleanup(testDir, network, process)
})
It("verifies private data not distributed when there is network partition", func() {
By("installing and instantiating chaincode on all peers")
chaincode := nwo.Chaincode{
Name: "marblesp",
Version: "1.0",
Path: "github.com/hyperledger/fabric/integration/chaincode/marbles_private/cmd",
Ctor: `{"Args":["init"]}`,
Policy: `OR ('Org1MSP.member','Org2MSP.member', 'Org3MSP.member')`,
CollectionsConfig: filepath.Join("testdata", "collection_configs", "collections_config3.json")}
nwo.DeployChaincode(network, "testchannel", orderer, chaincode, expectedPeers...)
By("invoking initMarble function of the chaincode to create private data")
invokeChaincode(network, "org1", "peer0", "marblesp", `{"Args":["initMarble","marble1","blue","35","tom","99"]}`, "testchannel", orderer)
// after the upgrade:
// 1. collectionMarbles - Org1 and Org2 have access to this collection, using readMarble to read from it.
// 2. collectionMarblePrivateDetails - Org2 and Org3 have access to this collection - using readMarblePrivateDetails to read from it.
By("upgrading chaincode in order to update collections config, now org2 and org3 have access to private collection")
chaincode.Version = "2.0"
chaincode.CollectionsConfig = filepath.Join("testdata", "collection_configs", "collections_config1.json")
nwo.UpgradeChaincode(network, "testchannel", orderer, chaincode, expectedPeers...)
By("stop p0.org2 process")
process := peersProcesses[org2peer0.ID()]
process.Signal(syscall.SIGTERM)
Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
delete(peersProcesses, org2peer0.ID())
By("verifying membership")
expectedPeers = []*nwo.Peer{org1peer0}
verifyMembership(network, expectedPeers, "testchannel", "marblesp")
By("start p0.org3 process")
org3peer0 := network.Peer("org3", "peer0")
pr := network.PeerRunner(org3peer0)
p := ifrit.Invoke(pr)
peersProcesses[org3peer0.ID()] = p
Eventually(p.Ready(), network.EventuallyTimeout).Should(BeClosed())
By("join peer0.org3 to the channel")
network.JoinChannel("testchannel", orderer, org3peer0)
By("install the chaincode on p0.org3 in order to query it")
nwo.InstallChaincode(network, chaincode, org3peer0)
By("fetch latest blocks to peer0.org3")
ledgerHeight := getLedgerHeight(network, org1peer0, "testchannel")
sess, err := network.PeerAdminSession(org3peer0, commands.ChannelFetch{
Block: "newest",
ChannelID: "testchannel",
Orderer: network.OrdererAddress(orderer, nwo.ListenPort),
OutputFile: filepath.Join(testDir, "newest_block.pb")})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say(fmt.Sprintf("Received block: %d", ledgerHeight-1)))
By("wait until peer0.org3 ledger is updated with all txs")
Eventually(func() int {
return getLedgerHeight(network, org3peer0, "testchannel")
}, network.EventuallyTimeout).Should(Equal(ledgerHeight))
By("verify p0.org3 didn't get private data")
verifyAccessFailed(
network,
commands.ChaincodeQuery{
ChannelID: "testchannel",
Name: "marblesp",
Ctor: `{"Args":["readMarblePrivateDetails","marble1"]}`},
org3peer0,
"Failed to get private details for marble1")
})
})
})
func initThreeOrgsSetup() (string, *nwo.Network, ifrit.Process, *nwo.Orderer, []*nwo.Peer) {
var err error
testDir, err := ioutil.TempDir("", "e2e-pvtdata")
Expect(err).NotTo(HaveOccurred())
client, err := docker.NewClientFromEnv()
Expect(err).NotTo(HaveOccurred())
configBytes, err := ioutil.ReadFile(filepath.Join("testdata", "network.yaml"))
Expect(err).NotTo(HaveOccurred())
var networkConfig *nwo.Config
err = yaml.Unmarshal(configBytes, &networkConfig)
Expect(err).NotTo(HaveOccurred())
n := nwo.New(networkConfig, testDir, client, 35000+1000*GinkgoParallelNode(), components)
n.GenerateConfigTree()
n.Bootstrap()
networkRunner := n.NetworkGroupRunner()
process := ifrit.Invoke(networkRunner)
Eventually(process.Ready()).Should(BeClosed())
orderer := n.Orderer("orderer")
n.CreateAndJoinChannel(orderer, "testchannel")
n.UpdateChannelAnchors(orderer, "testchannel")
expectedPeers := []*nwo.Peer{
n.Peer("org1", "peer0"),
n.Peer("org2", "peer0"),
n.Peer("org3", "peer0"),
}
By("verifying membership")
verifyMembership(n, expectedPeers, "testchannel")
return testDir, n, process, orderer, expectedPeers
}
func verifyAccessInitialSetup(network *nwo.Network) {
By("verifying access as defined in collection config")
peerList := []*nwo.Peer{
......@@ -295,6 +567,17 @@ func verifyAccessInitialSetup(network *nwo.Network) {
"Failed to get state for marble1")
}
func testCleanup(testDir string, network *nwo.Network, process ifrit.Process) {
if process != nil {
process.Signal(syscall.SIGTERM)
Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
}
if network != nil {
network.Cleanup()
}
os.RemoveAll(testDir)
}
func invokeChaincode(n *nwo.Network, org string, peer string, ccname string, args string, channel string, orderer *nwo.Orderer) {
sess, err := n.PeerUserSession(n.Peer(org, peer), "User1", commands.ChaincodeInvoke{
ChannelID: channel,
......@@ -308,7 +591,7 @@ func invokeChaincode(n *nwo.Network, org string, peer string, ccname string, arg
WaitForEvent: true,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful."))
}
......@@ -327,9 +610,9 @@ func getLedgerHeight(n *nwo.Network, peer *nwo.Peer, channelName string) int {
func waitUntilAllPeersSameLedgerHeight(n *nwo.Network, peers []*nwo.Peer, channelName string, height int) {
for _, peer := range peers {
EventuallyWithOffset(1, func() int {
Eventually(func() int {
return getLedgerHeight(n, peer, channelName)
}, n.EventuallyTimeout*3).Should(Equal(height))
}, n.EventuallyTimeout).Should(Equal(height))
}
}
......@@ -340,7 +623,7 @@ func verifyMembership(n *nwo.Network, expectedPeers []*nwo.Peer, channelName str
expectedDiscoveredPeers = append(expectedDiscoveredPeers, n.DiscoveredPeer(peer, chaincodes...))
}
for _, peer := range expectedPeers {
Eventually(nwo.DiscoverPeers(n, peer, "User1", channelName), time.Minute).Should(ConsistOf(expectedDiscoveredPeers))
Eventually(nwo.DiscoverPeers(n, peer, "User1", channelName), n.EventuallyTimeout).Should(ConsistOf(expectedDiscoveredPeers))
}
}
......
[
{
"name": "collectionMarbles",
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
"requiredPeerCount": 1,
"maxPeerCount": 2,
"blockToLive":1000000
},
{
"name": "collectionMarblePrivateDetails",
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
"requiredPeerCount": 1,
"maxPeerCount": 2,
"blockToLive":1000000
}
]
[
{
"name": "collectionMarbles",
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
"requiredPeerCount": 0,
"maxPeerCount": 2,
"blockToLive":1000000
},
{
"name": "collectionMarblePrivateDetails",
"policy": "OR('Org2MSP.member', 'Org3MSP.member')",
"requiredPeerCount": 1,
"maxPeerCount": 2,
"blockToLive":3
}
]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment