From 467a2f1511424d9640379c141efd49272d8a0892 Mon Sep 17 00:00:00 2001 From: Gari Singh Date: Sat, 13 May 2017 11:09:17 -0400 Subject: [PATCH] [FAB-3890] Increase coverage for common/config Coverage for common/config and common/config/msp is over 90%. Also removed a few dead code paths as well. Change-Id: Ia74527bf6d052be27083990c3779827e2844eb01 Signed-off-by: Gari Singh --- common/config/channel_test.go | 86 ++++++++++++++++++++++++++++-- common/config/consortium_test.go | 70 ++++++++++++++++++++++++ common/config/consortiums_test.go | 50 +++++++++++++++++ common/config/msp/config.go | 5 +- common/config/msp/config_test.go | 52 ++++++++++++++++++ common/config/msp/config_util.go | 5 +- common/config/organization.go | 5 +- common/config/organization_test.go | 69 ++++++++++++++++++++++++ common/config/root_test.go | 14 +++++ 9 files changed, 341 insertions(+), 15 deletions(-) create mode 100644 common/config/consortium_test.go create mode 100644 common/config/consortiums_test.go create mode 100644 common/config/organization_test.go diff --git a/common/config/channel_test.go b/common/config/channel_test.go index e9647aff5e1..f1364a76d89 100644 --- a/common/config/channel_test.go +++ b/common/config/channel_test.go @@ -18,9 +18,11 @@ package config import ( "math" + "reflect" "testing" "github.com/hyperledger/fabric/bccsp" + "github.com/hyperledger/fabric/common/util" cb "github.com/hyperledger/fabric/protos/common" logging "github.com/op/go-logging" @@ -35,6 +37,55 @@ func TestInterface(t *testing.T) { _ = Channel(NewChannelGroup(nil)) } +func TestChannelGroup(t *testing.T) { + cg := NewChannelGroup(nil) + assert.NotNil(t, cg, "ChannelGroup should not be nil") + assert.Nil(t, cg.OrdererConfig(), "OrdererConfig should be nil") + assert.Nil(t, cg.ApplicationConfig(), "ApplicationConfig should be nil") + assert.Nil(t, cg.ConsortiumsConfig(), "ConsortiumsConfig should be nil") + + _, err := cg.NewGroup(ApplicationGroupKey) + assert.NoError(t, err, "Unexpected error for ApplicationGroupKey") + _, err = cg.NewGroup(OrdererGroupKey) + assert.NoError(t, err, "Unexpected error for OrdererGroupKey") + _, err = cg.NewGroup(ConsortiumsGroupKey) + assert.NoError(t, err, "Unexpected error for ConsortiumsGroupKey") + _, err = cg.NewGroup("BadGroupKey") + assert.Error(t, err, "Should have returned error for BadGroupKey") + +} + +func TestChannelConfig(t *testing.T) { + cc := NewChannelConfig() + assert.NotNil(t, cc, "ChannelConfig should not be nil") + + cc.protos = &ChannelProtos{ + HashingAlgorithm: &cb.HashingAlgorithm{Name: bccsp.SHA256}, + BlockDataHashingStructure: &cb.BlockDataHashingStructure{Width: math.MaxUint32}, + OrdererAddresses: &cb.OrdererAddresses{Addresses: []string{"127.0.0.1:7050"}}, + } + + ag := NewApplicationGroup(nil) + og := NewOrdererGroup(nil) + csg := NewConsortiumsGroup() + good := make(map[string]ValueProposer) + good[ApplicationGroupKey] = ag + good[OrdererGroupKey] = og + good[ConsortiumsGroupKey] = csg + + err := cc.Validate(nil, good) + assert.NoError(t, err, "Unexpected error validating good config groups") + err = cc.Validate(nil, map[string]ValueProposer{ApplicationGroupKey: NewConsortiumsGroup()}) + assert.Error(t, err, "Expected error validating bad config group") + err = cc.Validate(nil, map[string]ValueProposer{OrdererGroupKey: NewConsortiumsGroup()}) + assert.Error(t, err, "Expected error validating bad config group") + err = cc.Validate(nil, map[string]ValueProposer{ConsortiumsGroupKey: NewOrdererGroup(nil)}) + assert.Error(t, err, "Expected error validating bad config group") + err = cc.Validate(nil, map[string]ValueProposer{ConsortiumKey: NewConsortiumGroup(nil)}) + assert.Error(t, err, "Expected error validating bad config group") + +} + func TestHashingAlgorithm(t *testing.T) { cc := &ChannelConfig{protos: &ChannelProtos{HashingAlgorithm: &cb.HashingAlgorithm{}}} assert.Error(t, cc.validateHashingAlgorithm(), "Must supply hashing algorithm") @@ -43,7 +94,16 @@ func TestHashingAlgorithm(t *testing.T) { assert.Error(t, cc.validateHashingAlgorithm(), "Bad hashing algorithm supplied") cc = &ChannelConfig{protos: &ChannelProtos{HashingAlgorithm: &cb.HashingAlgorithm{Name: bccsp.SHA256}}} - assert.NoError(t, cc.validateHashingAlgorithm(), "Allowed hashing algorith supplied") + assert.NoError(t, cc.validateHashingAlgorithm(), "Allowed hashing algorith SHA256 supplied") + + assert.Equal(t, reflect.ValueOf(util.ComputeSHA256).Pointer(), reflect.ValueOf(cc.HashingAlgorithm()).Pointer(), + "Unexpected hashing algorithm returned") + + cc = &ChannelConfig{protos: &ChannelProtos{HashingAlgorithm: &cb.HashingAlgorithm{Name: bccsp.SHA3_256}}} + assert.NoError(t, cc.validateHashingAlgorithm(), "Allowed hashing algorith SHA3_256 supplied") + + assert.Equal(t, reflect.ValueOf(util.ComputeSHA3256).Pointer(), reflect.ValueOf(cc.HashingAlgorithm()).Pointer(), + "Unexpected hashing algorithm returned") } func TestBlockDataHashingStructure(t *testing.T) { @@ -53,8 +113,12 @@ func TestBlockDataHashingStructure(t *testing.T) { cc = &ChannelConfig{protos: &ChannelProtos{BlockDataHashingStructure: &cb.BlockDataHashingStructure{Width: 7}}} assert.Error(t, cc.validateBlockDataHashingStructure(), "Invalid Merkle tree width supplied") - cc = &ChannelConfig{protos: &ChannelProtos{BlockDataHashingStructure: &cb.BlockDataHashingStructure{Width: math.MaxUint32}}} + var width uint32 + width = math.MaxUint32 + cc = &ChannelConfig{protos: &ChannelProtos{BlockDataHashingStructure: &cb.BlockDataHashingStructure{Width: width}}} assert.NoError(t, cc.validateBlockDataHashingStructure(), "Valid Merkle tree width supplied") + + assert.Equal(t, width, cc.BlockDataHashingStructureWidth(), "Unexpected width returned") } func TestOrdererAddresses(t *testing.T) { @@ -62,5 +126,21 @@ func TestOrdererAddresses(t *testing.T) { assert.Error(t, cc.validateOrdererAddresses(), "Must supply orderer addresses") cc = &ChannelConfig{protos: &ChannelProtos{OrdererAddresses: &cb.OrdererAddresses{Addresses: []string{"127.0.0.1:7050"}}}} - assert.NoError(t, cc.validateOrdererAddresses(), "Invalid Merkle tree width supplied") + assert.NoError(t, cc.validateOrdererAddresses(), "Invalid orderer address supplied") + + assert.Equal(t, "127.0.0.1:7050", cc.OrdererAddresses()[0], "Unexpected orderer address returned") +} + +func TestConsortiumName(t *testing.T) { + cc := &ChannelConfig{protos: &ChannelProtos{Consortium: &cb.Consortium{Name: "TestConsortium"}}} + assert.Equal(t, "TestConsortium", cc.ConsortiumName(), "Unexpected consortium name returned") +} + +func TestChannelUtils(t *testing.T) { + // these functions all panic if marshaling fails so just executing them is sufficient + _ = TemplateConsortium("test") + _ = DefaultHashingAlgorithm() + _ = DefaultBlockDataHashingStructure() + _ = DefaultOrdererAddresses() + } diff --git a/common/config/consortium_test.go b/common/config/consortium_test.go new file mode 100644 index 00000000000..5e8a345e0e1 --- /dev/null +++ b/common/config/consortium_test.go @@ -0,0 +1,70 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package config + +import ( + "testing" + + cb "github.com/hyperledger/fabric/protos/common" + "github.com/stretchr/testify/assert" +) + +func TestConsortiumGroup(t *testing.T) { + + cg := NewConsortiumGroup(nil) + og, err := cg.NewGroup("testGroup") + assert.NoError(t, err, "NewGroup should not have returned error") + assert.Equal(t, "testGroup", og.(*OrganizationGroup).Name(), + "Unexpected group name returned") + + cc := cg.Allocate() + _, ok := cc.(*ConsortiumConfig) + assert.Equal(t, true, ok, "Allocate should have returned a ConsortiumConfig") + + _, _, err = cg.BeginValueProposals(t, []string{"testGroup"}) + assert.NoError(t, err, "BeginValueProposals should not have returned error") + + err = cg.PreCommit(t) + assert.NoError(t, err, "PreCommit should not have returned error") + cg.CommitProposals(t) + cg.RollbackProposals(t) + +} + +func TestConsortiumConfig(t *testing.T) { + cg := NewConsortiumGroup(nil) + cc := NewConsortiumConfig(cg) + orgs := cc.Organizations() + assert.Equal(t, 0, len(orgs)) + + policy := cc.ChannelCreationPolicy() + assert.EqualValues(t, cb.Policy_UNKNOWN, policy.Type, "Expected policy type to be UNKNOWN") + + cc.Commit() + assert.Equal(t, cg.ConsortiumConfig, cc, "Error committing ConsortiumConfig") + + og, _ := cg.NewGroup("testGroup") + err := cc.Validate(t, map[string]ValueProposer{ + "testGroup": og, + }) + assert.NoError(t, err, "Validate returned unexpected error") + csg := NewConsortiumsGroup() + err = cc.Validate(t, map[string]ValueProposer{ + "testGroup": csg, + }) + assert.Error(t, err, "Validate should have failed") + +} diff --git a/common/config/consortiums_test.go b/common/config/consortiums_test.go new file mode 100644 index 00000000000..dfa228f80f2 --- /dev/null +++ b/common/config/consortiums_test.go @@ -0,0 +1,50 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestConsortiums(t *testing.T) { + + csg := NewConsortiumsGroup() + cg, err := csg.NewGroup("testCG") + assert.NoError(t, err, "NewGroup shuld not have returned error") + _, ok := cg.(*ConsortiumGroup) + assert.Equal(t, true, ok, "NewGroup should have returned a ConsortiumGroup") + + csc := csg.Allocate() + _, ok = csc.(*ConsortiumsConfig) + assert.Equal(t, true, ok, "Allocate should have returned a ConsortiumsConfig") + + csc.Commit() + assert.Equal(t, csc, csg.ConsortiumsConfig, "Failed to commit ConsortiumsConfig") + + err = csc.Validate(t, map[string]ValueProposer{ + "badGroup": &OrganizationGroup{}, + }) + assert.Error(t, err, "Validate should have returned error for wrong type of ValueProposer") + err = csc.Validate(t, map[string]ValueProposer{ + "testGroup": cg, + }) + assert.NoError(t, err, "Validate should not have returned error") + assert.Equal(t, cg, csc.(*ConsortiumsConfig).Consortiums()["testGroup"], + "Expected consortium groups to be the same") + +} diff --git a/common/config/msp/config.go b/common/config/msp/config.go index 8ecb48e24d8..40fec19ff2f 100644 --- a/common/config/msp/config.go +++ b/common/config/msp/config.go @@ -108,10 +108,7 @@ func (bh *MSPConfigHandler) ProposeMSP(tx interface{}, mspConfig *mspprotos.MSPC } // add the MSP to the map of pending MSPs - mspID, err := mspInst.GetIdentifier() - if err != nil { - return nil, fmt.Errorf("Could not extract msp identifier, err %s", err) - } + mspID, _ := mspInst.GetIdentifier() existingPendingMSPConfig, ok := pendingConfig.idMap[mspID] if ok && !reflect.DeepEqual(existingPendingMSPConfig.mspConfig, mspConfig) { diff --git a/common/config/msp/config_test.go b/common/config/msp/config_test.go index 2ce3041b082..8b5a7d3acf2 100644 --- a/common/config/msp/config_test.go +++ b/common/config/msp/config_test.go @@ -19,9 +19,12 @@ package msp import ( "testing" + "github.com/hyperledger/fabric/common/cauthdsl" "github.com/hyperledger/fabric/core/config" "github.com/hyperledger/fabric/msp" + cb "github.com/hyperledger/fabric/protos/common" mspprotos "github.com/hyperledger/fabric/protos/msp" + "github.com/hyperledger/fabric/protos/utils" "github.com/stretchr/testify/assert" ) @@ -35,6 +38,17 @@ func TestMSPConfigManager(t *testing.T) { // begin/propose/commit mspCH := NewMSPConfigHandler() + + assert.Panics(t, func() { + mspCH.PreCommit(t) + }, "Expected panic calling PreCommit before beginning transaction") + assert.Panics(t, func() { + mspCH.CommitProposals(t) + }, "Expected panic calling CommitProposals before beginning transaction") + assert.Panics(t, func() { + _, err = mspCH.ProposeMSP(t, conf) + }, "Expected panic calling ProposeMSP before beginning transaction") + mspCH.BeginConfig(t) _, err = mspCH.ProposeMSP(t, conf) assert.NoError(t, err) @@ -48,6 +62,10 @@ func TestMSPConfigManager(t *testing.T) { t.Fatalf("There are no MSPS in the manager") } + mspCH.BeginConfig(t) + _, err = mspCH.ProposeMSP(t, conf) + mspCH.RollbackProposals(t) + // test failure // begin/propose/commit mspCH.BeginConfig(t) @@ -55,4 +73,38 @@ func TestMSPConfigManager(t *testing.T) { assert.NoError(t, err) _, err = mspCH.ProposeMSP(t, &mspprotos.MSPConfig{Config: []byte("BARF!")}) assert.Error(t, err) + _, err = mspCH.ProposeMSP(t, &mspprotos.MSPConfig{Type: int32(10)}) + assert.Panics(t, func() { + mspCH.BeginConfig(t) + }, "Expected panic calling BeginConfig multiple times for same transaction") +} + +func TestTemplates(t *testing.T) { + mspDir, err := config.GetDevMspDir() + assert.NoError(t, err) + mspConf, err := msp.GetLocalMspConfig(mspDir, nil, "DEFAULT") + assert.NoError(t, err) + + expectedMSPValue := &cb.ConfigValue{ + Value: utils.MarshalOrPanic(mspConf), + } + configGroup := TemplateGroupMSP([]string{"TestPath"}, mspConf) + testGroup, ok := configGroup.Groups["TestPath"] + assert.Equal(t, true, ok, "Failed to find group key") + assert.Equal(t, expectedMSPValue, testGroup.Values[MSPKey], "MSPKey did not match expected value") + + configGroup = TemplateGroupMSPWithAdminRolePrincipal([]string{"TestPath"}, mspConf, false) + expectedPolicyValue := utils.MarshalOrPanic(cauthdsl.SignedByMspMember("DEFAULT")) + actualPolicyValue := configGroup.Groups["TestPath"].Policies[AdminsPolicyKey].Policy.Policy + assert.Equal(t, expectedPolicyValue, actualPolicyValue, "Expected SignedByMspMemberPolicy") + + mspConf = &mspprotos.MSPConfig{} + assert.Panics(t, func() { + configGroup = TemplateGroupMSPWithAdminRolePrincipal([]string{"TestPath"}, mspConf, false) + }, "Expected panic with bad msp config") + mspConf.Type = int32(10) + assert.Panics(t, func() { + configGroup = TemplateGroupMSPWithAdminRolePrincipal([]string{"TestPath"}, mspConf, false) + }, "Expected panic with bad msp config") + } diff --git a/common/config/msp/config_util.go b/common/config/msp/config_util.go index 0b1492147f5..2c71b0ee870 100644 --- a/common/config/msp/config_util.go +++ b/common/config/msp/config_util.go @@ -63,10 +63,7 @@ func TemplateGroupMSPWithAdminRolePrincipal(configPath []string, mspConfig *mspp } // add the MSP to the map of pending MSPs - mspID, err := mspInst.GetIdentifier() - if err != nil { - logger.Panicf("Could not extract msp identifier, err %s", err) - } + mspID, _ := mspInst.GetIdentifier() memberPolicy := &cb.ConfigPolicy{ Policy: &cb.Policy{ diff --git a/common/config/organization.go b/common/config/organization.go index 7ec8839ff24..7a44722d4b5 100644 --- a/common/config/organization.go +++ b/common/config/organization.go @@ -115,10 +115,7 @@ func (oc *OrganizationConfig) validateMSP(tx interface{}) error { return err } - oc.mspID, err = oc.msp.GetIdentifier() - if err != nil { - return fmt.Errorf("Could not extract msp identifier for org %s: %s", oc.organizationGroup.name, err) - } + oc.mspID, _ = oc.msp.GetIdentifier() if oc.mspID == "" { return fmt.Errorf("MSP for org %s has empty MSP ID", oc.organizationGroup.name) diff --git a/common/config/organization_test.go b/common/config/organization_test.go new file mode 100644 index 00000000000..e614c060052 --- /dev/null +++ b/common/config/organization_test.go @@ -0,0 +1,69 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "testing" + + mspconfig "github.com/hyperledger/fabric/common/config/msp" + fabricconfig "github.com/hyperledger/fabric/core/config" + "github.com/hyperledger/fabric/msp" + mspprotos "github.com/hyperledger/fabric/protos/msp" + "github.com/stretchr/testify/assert" +) + +func TestOrganization(t *testing.T) { + mspHandler := mspconfig.NewMSPConfigHandler() + og := NewOrganizationGroup("testGroup", mspHandler) + assert.Equal(t, "testGroup", og.Name(), "Unexpected name returned") + _, err := og.NewGroup("testGroup") + assert.Error(t, err, "NewGroup should have returned error") + + oc := og.Allocate() + _, ok := oc.(*OrganizationConfig) + assert.Equal(t, true, ok, "Allocate should have returned an OrganizationConfig") + og.OrganizationConfig = oc.(*OrganizationConfig) + + oc.(*OrganizationConfig).Commit() + assert.Equal(t, oc, og.OrganizationConfig, "Failed to commit OrganizationConfig") + + mspDir, err := fabricconfig.GetDevMspDir() + assert.NoError(t, err, "Error getting MSP dev directory") + mspConf, err := msp.GetVerifyingMspConfig(mspDir, nil, "TestMSP") + assert.NoError(t, err, "Error loading MSP config") + oc.(*OrganizationConfig).protos.MSP = mspConf + mspHandler.BeginConfig(t) + err = oc.Validate(t, nil) + assert.NoError(t, err, "Validate should not have returned error") + assert.Equal(t, "TestMSP", og.MSPID(), "Unexpected MSPID returned") + + og.OrganizationConfig = &OrganizationConfig{ + mspID: "ChangeMSP", + } + err = oc.Validate(t, nil) + assert.Error(t, err, "Validate should have returned error for attempt to change MSPID") + + mspConf, err = msp.GetVerifyingMspConfig(mspDir, nil, "") + oc.(*OrganizationConfig).protos.MSP = mspConf + err = oc.Validate(t, nil) + assert.Error(t, err, "Validate should have returned error for empty MSP ID") + + oc.(*OrganizationConfig).protos.MSP = &mspprotos.MSPConfig{} + err = oc.Validate(t, nil) + assert.Error(t, err, "Validate should have returned error for empty MSPConfig") + +} diff --git a/common/config/root_test.go b/common/config/root_test.go index 40be82971d0..85caf8442af 100644 --- a/common/config/root_test.go +++ b/common/config/root_test.go @@ -29,6 +29,20 @@ func init() { logging.SetLevel(logging.DEBUG, "") } +func TestRoot(t *testing.T) { + r := NewRoot(&msp.MSPConfigHandler{}) + appGroup := &ApplicationGroup{} + ordererGroup := &OrdererGroup{} + consortiumsGroup := &ConsortiumsGroup{} + r.Channel().appConfig = appGroup + r.Channel().ordererConfig = ordererGroup + r.Channel().consortiumsConfig = consortiumsGroup + + assert.Equal(t, appGroup, r.Application(), "Failed to return correct application group") + assert.Equal(t, ordererGroup, r.Orderer(), "Failed to return correct orderer group") + assert.Equal(t, consortiumsGroup, r.Consortiums(), "Failed to return correct consortiums group") +} + func TestBeginBadRoot(t *testing.T) { r := NewRoot(&msp.MSPConfigHandler{})