From 6938e0945acd8eb3e1ffeb3749f1c8880c1a7a81 Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Sat, 5 Jan 2019 22:24:51 -0500 Subject: [PATCH] FAB-13512 Add lifecycle integration test This integration test is supposed to perform basic sanity checking that the assorted pieces of lifecycle all wire through correctly. It begins with an empty db, then defines a chaincode for the org, defines it for the channel, queries the defined namespaces, and finally queries the defined chaincode (all done through the SCC interface with mocked db which reads own writes to simulate commitment). Change-Id: I9cabca1614be7cadc65425e9815ca6e6ed4cebec Signed-off-by: Jason Yellick --- core/chaincode/lifecycle/integration_test.go | 181 +++++++++++++++++++ core/chaincode/lifecycle/ledger_shim.go | 3 +- core/chaincode/lifecycle/ledger_shim_test.go | 14 +- 3 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 core/chaincode/lifecycle/integration_test.go diff --git a/core/chaincode/lifecycle/integration_test.go b/core/chaincode/lifecycle/integration_test.go new file mode 100644 index 00000000000..bd2a2bedba8 --- /dev/null +++ b/core/chaincode/lifecycle/integration_test.go @@ -0,0 +1,181 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package lifecycle_test + +import ( + "github.com/hyperledger/fabric/common/channelconfig" + "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/core/chaincode/lifecycle" + "github.com/hyperledger/fabric/core/chaincode/lifecycle/mock" + "github.com/hyperledger/fabric/core/chaincode/shim" + "github.com/hyperledger/fabric/core/dispatcher" + "github.com/hyperledger/fabric/protos/ledger/queryresult" + lb "github.com/hyperledger/fabric/protos/peer/lifecycle" + "github.com/hyperledger/fabric/protos/utils" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/golang/protobuf/proto" +) + +var _ = Describe("Integration", func() { + var ( + l *lifecycle.Lifecycle + scc *lifecycle.SCC + + fakeChannelConfigSource *mock.ChannelConfigSource + fakeChannelConfig *mock.ChannelConfig + fakeApplicationConfig *mock.ApplicationConfig + fakeOrgConfig *mock.ApplicationOrgConfig + fakeStub *mock.ChaincodeStub + + fakeOrgKVStore map[string][]byte + fakePublicKVStore map[string][]byte + ) + + BeforeEach(func() { + l = &lifecycle.Lifecycle{ + Serializer: &lifecycle.Serializer{}, + } + + fakeChannelConfigSource = &mock.ChannelConfigSource{} + fakeChannelConfig = &mock.ChannelConfig{} + fakeChannelConfigSource.GetStableChannelConfigReturns(fakeChannelConfig) + fakeApplicationConfig = &mock.ApplicationConfig{} + fakeChannelConfig.ApplicationConfigReturns(fakeApplicationConfig, true) + + fakeOrgConfig = &mock.ApplicationOrgConfig{} + fakeOrgConfig.MSPIDReturns("fake-mspid") + + fakeApplicationConfig.OrganizationsReturns(map[string]channelconfig.ApplicationOrg{ + "fakeOrg": fakeOrgConfig, + }) + + scc = &lifecycle.SCC{ + Dispatcher: &dispatcher.Dispatcher{ + Protobuf: &dispatcher.ProtobufImpl{}, + }, + Functions: l, + OrgMSPID: "fake-mspid", + ChannelConfigSource: fakeChannelConfigSource, + } + + fakePublicKVStore = map[string][]byte{} + fakeOrgKVStore = map[string][]byte{} + + fakeStub = &mock.ChaincodeStub{} + fakeStub.GetStateStub = func(key string) ([]byte, error) { + return fakePublicKVStore[key], nil + } + fakeStub.PutStateStub = func(key string, value []byte) error { + fakePublicKVStore[key] = value + return nil + } + fakeStub.GetStateByRangeStub = func(begin, end string) (shim.StateQueryIteratorInterface, error) { + fakeIterator := &mock.StateIterator{} + i := 0 + for key, value := range fakePublicKVStore { + if key >= begin && key < end { + fakeIterator.HasNextReturnsOnCall(i, true) + fakeIterator.NextReturnsOnCall(i, &queryresult.KV{ + Key: key, + Value: value, + }, nil) + i++ + } + } + return fakeIterator, nil + } + + fakeStub.PutPrivateDataStub = func(collection, key string, value []byte) error { + fakeOrgKVStore[key] = value + return nil + } + + fakeStub.GetPrivateDataStub = func(collection, key string) ([]byte, error) { + return fakeOrgKVStore[key], nil + } + + fakeStub.GetPrivateDataHashStub = func(collection, key string) ([]byte, error) { + return util.ComputeSHA256(fakeOrgKVStore[key]), nil + } + }) + + Describe("Instantiation", func() { + It("defines the chaincode for the org, defines it for the channel, queries all namespaces, and queries the chaincode", func() { + // Define for the org + fakeStub.GetArgsReturns([][]byte{ + []byte("DefineChaincodeForMyOrg"), + utils.MarshalOrPanic(&lb.DefineChaincodeForMyOrgArgs{ + Name: "cc-name", + Version: "1.0", + Sequence: 1, + EndorsementPlugin: "builtin", + ValidationPlugin: "builtin", + ValidationParameter: []byte("validation-parameter"), + Hash: []byte("hash-value"), + }), + }) + response := scc.Invoke(fakeStub) + Expect(response.Status).To(Equal(int32(200))) + + // Define for the channel + fakeStub.GetArgsReturns([][]byte{ + []byte("DefineChaincode"), + utils.MarshalOrPanic(&lb.DefineChaincodeArgs{ + Name: "cc-name", + Version: "1.0", + Sequence: 1, + EndorsementPlugin: "builtin", + ValidationPlugin: "builtin", + ValidationParameter: []byte("validation-parameter"), + Hash: []byte("hash-value"), + }), + }) + response = scc.Invoke(fakeStub) + Expect(response.Status).To(Equal(int32(200))) + + // Get channel definitions + fakeStub.GetArgsReturns([][]byte{ + []byte("QueryDefinedNamespaces"), + utils.MarshalOrPanic(&lb.QueryDefinedNamespacesArgs{}), + }) + response = scc.Invoke(fakeStub) + Expect(response.Status).To(Equal(int32(200))) + namespaceResult := &lb.QueryDefinedNamespacesResult{} + err := proto.Unmarshal(response.Payload, namespaceResult) + Expect(err).NotTo(HaveOccurred()) + Expect(len(namespaceResult.Namespaces)).To(Equal(1)) + namespace, ok := namespaceResult.Namespaces["cc-name"] + Expect(ok).To(BeTrue()) + Expect(namespace.Type).To(Equal("Chaincode")) + + // Get chaincode definition details + fakeStub.GetArgsReturns([][]byte{ + []byte("QueryDefinedChaincode"), + utils.MarshalOrPanic(&lb.QueryDefinedChaincodeArgs{ + Name: "cc-name", + }), + }) + response = scc.Invoke(fakeStub) + Expect(response.Status).To(Equal(int32(200))) + chaincodeResult := &lb.QueryDefinedChaincodeResult{} + err = proto.Unmarshal(response.Payload, chaincodeResult) + Expect(err).NotTo(HaveOccurred()) + Expect(proto.Equal(chaincodeResult, &lb.QueryDefinedChaincodeResult{ + Sequence: 1, + Version: "1.0", + EndorsementPlugin: "builtin", + ValidationPlugin: "builtin", + ValidationParameter: []byte("validation-parameter"), + Hash: []byte("hash-value"), + })).To(BeTrue()) + }) + }) + +}) diff --git a/core/chaincode/lifecycle/ledger_shim.go b/core/chaincode/lifecycle/ledger_shim.go index b0705bea8b2..561932ef4a0 100644 --- a/core/chaincode/lifecycle/ledger_shim.go +++ b/core/chaincode/lifecycle/ledger_shim.go @@ -67,8 +67,7 @@ func (cls *ChaincodePrivateLedgerShim) GetState(key string) ([]byte, error) { // GetStateHash return the hash of the pre-image for the key in the configured collection. func (cls *ChaincodePrivateLedgerShim) GetStateHash(key string) ([]byte, error) { - // XXX implement me - panic("unimplemented") + return cls.Stub.GetPrivateDataHash(cls.Collection, key) } // PutState sets the value for the key in the configured collection. diff --git a/core/chaincode/lifecycle/ledger_shim_test.go b/core/chaincode/lifecycle/ledger_shim_test.go index 7f34a1a2767..0944c8e2468 100644 --- a/core/chaincode/lifecycle/ledger_shim_test.go +++ b/core/chaincode/lifecycle/ledger_shim_test.go @@ -145,8 +145,18 @@ var _ = Describe("LedgerShims", func() { }) Describe("GetStateHash", func() { - It("panics", func() { - Expect(func() { cls.GetStateHash("fake-key") }).To(Panic()) + BeforeEach(func() { + fakeStub.GetPrivateDataHashReturns([]byte("fake-hash"), fmt.Errorf("fake-error")) + }) + + It("passes through to the chaincode stub", func() { + res, err := cls.GetStateHash("fake-key") + Expect(res).To(Equal([]byte("fake-hash"))) + Expect(err).To(MatchError("fake-error")) + Expect(fakeStub.GetPrivateDataHashCallCount()).To(Equal(1)) + collection, key := fakeStub.GetPrivateDataHashArgsForCall(0) + Expect(collection).To(Equal("fake-collection")) + Expect(key).To(Equal("fake-key")) }) })