go_study/fabric-main/internal/peer/common/common_test.go

408 lines
14 KiB
Go

/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package common_test
import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"testing"
"time"
cb "github.com/hyperledger/fabric-protos-go/common"
pb "github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/bccsp/sw"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/crypto/tlsgen"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/config/configtest"
"github.com/hyperledger/fabric/internal/configtxgen/encoder"
"github.com/hyperledger/fabric/internal/configtxgen/genesisconfig"
"github.com/hyperledger/fabric/internal/peer/common"
"github.com/hyperledger/fabric/internal/pkg/comm"
"github.com/hyperledger/fabric/msp"
msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools"
"github.com/hyperledger/fabric/protoutil"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func TestInitConfig(t *testing.T) {
configtest.SetDevFabricConfigPath(t)
type args struct {
cmdRoot string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "Empty command root",
args: args{cmdRoot: ""},
wantErr: true,
},
{
name: "Bad command root",
args: args{cmdRoot: "cre"},
wantErr: true,
},
{
name: "Good command root",
args: args{cmdRoot: "core"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := common.InitConfig(tt.args.cmdRoot); (err != nil) != tt.wantErr {
t.Errorf("InitConfig() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestInitCryptoMissingDir(t *testing.T) {
dir := path.Join(os.TempDir(), util.GenerateUUID())
err := common.InitCrypto(dir, "SampleOrg", msp.ProviderTypeToString(msp.FABRIC))
require.Error(t, err, "Should not be able to initialize crypto with non-existing directory")
require.Contains(t, err.Error(), fmt.Sprintf("specified path \"%s\" does not exist", dir))
}
func TestInitCryptoFileNotDir(t *testing.T) {
file := path.Join(os.TempDir(), util.GenerateUUID())
err := ioutil.WriteFile(file, []byte{}, 0o644)
require.Nil(t, err, "Failed to create test file")
defer os.Remove(file)
err = common.InitCrypto(file, "SampleOrg", msp.ProviderTypeToString(msp.FABRIC))
require.Error(t, err, "Should not be able to initialize crypto with a file instead of a directory")
require.Contains(t, err.Error(), fmt.Sprintf("specified path \"%s\" is not a directory", file))
}
func TestInitCrypto(t *testing.T) {
mspConfigPath := configtest.GetDevMspDir()
localMspId := "SampleOrg"
err := common.InitCrypto(mspConfigPath, localMspId, msp.ProviderTypeToString(msp.FABRIC))
require.NoError(t, err, "Unexpected error [%s] calling InitCrypto()", err)
localMspId = ""
err = common.InitCrypto(mspConfigPath, localMspId, msp.ProviderTypeToString(msp.FABRIC))
require.Error(t, err, fmt.Sprintf("Expected error [%s] calling InitCrypto()", err))
}
func TestSetBCCSPKeystorePath(t *testing.T) {
cfgKey := "peer.BCCSP.SW.FileKeyStore.KeyStore"
cfgPath := "./testdata"
absPath, err := filepath.Abs(cfgPath)
require.NoError(t, err)
keystorePath := "/msp/keystore"
t.Setenv("FABRIC_CFG_PATH", cfgPath)
viper.Reset()
err = common.InitConfig("notset")
require.NoError(t, err)
common.SetBCCSPKeystorePath()
t.Log(viper.GetString(cfgKey))
require.Equal(t, "", viper.GetString(cfgKey))
require.Nil(t, viper.Get(cfgKey))
viper.Reset()
err = common.InitConfig("absolute")
require.NoError(t, err)
common.SetBCCSPKeystorePath()
t.Log(viper.GetString(cfgKey))
require.Equal(t, keystorePath, viper.GetString(cfgKey))
viper.Reset()
err = common.InitConfig("relative")
require.NoError(t, err)
common.SetBCCSPKeystorePath()
t.Log(viper.GetString(cfgKey))
require.Equal(t, filepath.Join(absPath, keystorePath), viper.GetString(cfgKey))
viper.Reset()
}
func TestCheckLogLevel(t *testing.T) {
type args struct {
level string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "Empty level",
args: args{level: ""},
wantErr: true,
},
{
name: "Valid level",
args: args{level: "warning"},
wantErr: false,
},
{
name: "Invalid level",
args: args{level: "foobaz"},
wantErr: true,
},
{
name: "Valid level",
args: args{level: "error"},
wantErr: false,
},
{
name: "Valid level",
args: args{level: "info"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := common.CheckLogLevel(tt.args.level); (err != nil) != tt.wantErr {
t.Errorf("CheckLogLevel() args = %v error = %v, wantErr %v", tt.args, err, tt.wantErr)
}
})
}
}
func TestGetDefaultSigner(t *testing.T) {
tests := []struct {
name string
want msp.SigningIdentity
wantErr bool
}{
{
name: "Should return DefaultSigningIdentity",
want: nil,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := common.GetDefaultSigner()
if (err != nil) != tt.wantErr {
t.Errorf("GetDefaultSigner() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestInitCmd(t *testing.T) {
configtest.SetDevFabricConfigPath(t)
defer viper.Reset()
// test that InitCmd doesn't remove existing loggers from the logger levels map
flogging.MustGetLogger("test")
flogging.ActivateSpec("test=error")
require.Equal(t, "error", flogging.LoggerLevel("test"))
flogging.MustGetLogger("chaincode")
require.Equal(t, flogging.DefaultLevel(), flogging.LoggerLevel("chaincode"))
flogging.MustGetLogger("test.test2")
flogging.ActivateSpec("test.test2=warn")
require.Equal(t, "warn", flogging.LoggerLevel("test.test2"))
t.Setenv("FABRIC_LOGGING_SPEC", "chaincode=debug:test.test2=fatal:abc=error")
common.InitCmd(&cobra.Command{}, nil)
require.Equal(t, "debug", flogging.LoggerLevel("chaincode"))
require.Equal(t, "info", flogging.LoggerLevel("test"))
require.Equal(t, "fatal", flogging.LoggerLevel("test.test2"))
require.Equal(t, "error", flogging.LoggerLevel("abc"))
}
func TestInitCmdWithoutInitCrypto(t *testing.T) {
configtest.SetDevFabricConfigPath(t)
defer viper.Reset()
peerCmd := &cobra.Command{
Use: "peer",
}
lifecycleCmd := &cobra.Command{
Use: "lifecycle",
}
chaincodeCmd := &cobra.Command{
Use: "chaincode",
}
packageCmd := &cobra.Command{
Use: "package",
}
// peer lifecycle chaincode package
chaincodeCmd.AddCommand(packageCmd)
lifecycleCmd.AddCommand(chaincodeCmd)
peerCmd.AddCommand(lifecycleCmd)
// MSPCONFIGPATH is default value
common.InitCmd(packageCmd, nil)
// set MSPCONFIGPATH to be a missing dir, the function InitCrypto will fail
// confirm that 'peer lifecycle chaincode package' mandates does not require MSPCONFIG information
viper.SetEnvPrefix("core")
viper.AutomaticEnv()
replacer := strings.NewReplacer(".", "_")
viper.SetEnvKeyReplacer(replacer)
dir := os.TempDir() + "/" + util.GenerateUUID()
t.Setenv("CORE_PEER_MSPCONFIGPATH", dir)
common.InitCmd(packageCmd, nil)
}
func TestGetOrdererEndpointFromConfigTx(t *testing.T) {
require.NoError(t, msptesttools.LoadMSPSetupForTesting())
signer, err := common.GetDefaultSigner()
require.NoError(t, err)
factory.InitFactories(nil)
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
require.NoError(t, err)
t.Run("green-path", func(t *testing.T) {
profile := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir())
channelGroup, err := encoder.NewChannelGroup(profile)
require.NoError(t, err)
channelConfig := &cb.Config{ChannelGroup: channelGroup}
ordererAddresses := channelconfig.OrdererAddressesValue([]string{"order-1-endpoint", "order-2-end-point"})
channelConfig.ChannelGroup.Values[ordererAddresses.Key()] = &cb.ConfigValue{
Value: protoutil.MarshalOrPanic(ordererAddresses.Value()),
}
mockEndorserClient := common.GetMockEndorserClient(
&pb.ProposalResponse{
Response: &pb.Response{Status: 200, Payload: protoutil.MarshalOrPanic(channelConfig)},
Endorsement: &pb.Endorsement{},
},
nil,
)
ordererEndpoints, err := common.GetOrdererEndpointOfChain("test-channel", signer, mockEndorserClient, cryptoProvider)
require.NoError(t, err)
require.Equal(t, []string{"order-1-endpoint", "order-2-end-point"}, ordererEndpoints)
})
t.Run("error-invoking-CSCC", func(t *testing.T) {
mockEndorserClient := common.GetMockEndorserClient(
nil,
errors.Errorf("cscc-invocation-error"),
)
_, err := common.GetOrdererEndpointOfChain("test-channel", signer, mockEndorserClient, cryptoProvider)
require.EqualError(t, err, "error endorsing GetChannelConfig: cscc-invocation-error")
})
t.Run("nil-response", func(t *testing.T) {
mockEndorserClient := common.GetMockEndorserClient(
nil,
nil,
)
_, err := common.GetOrdererEndpointOfChain("test-channel", signer, mockEndorserClient, cryptoProvider)
require.EqualError(t, err, "received nil proposal response")
})
t.Run("bad-status-code-from-cscc", func(t *testing.T) {
mockEndorserClient := common.GetMockEndorserClient(
&pb.ProposalResponse{
Response: &pb.Response{Status: 404, Payload: []byte{}},
Endorsement: &pb.Endorsement{},
},
nil,
)
_, err := common.GetOrdererEndpointOfChain("test-channel", signer, mockEndorserClient, cryptoProvider)
require.EqualError(t, err, "error bad proposal response 404: ")
})
t.Run("unmarshalable-config", func(t *testing.T) {
mockEndorserClient := common.GetMockEndorserClient(
&pb.ProposalResponse{
Response: &pb.Response{Status: 200, Payload: []byte("unmarshalable-config")},
Endorsement: &pb.Endorsement{},
},
nil,
)
_, err := common.GetOrdererEndpointOfChain("test-channel", signer, mockEndorserClient, cryptoProvider)
require.Error(t, err)
require.Contains(t, err.Error(), "error unmarshalling channel config")
})
t.Run("unloadable-config", func(t *testing.T) {
mockEndorserClient := common.GetMockEndorserClient(
&pb.ProposalResponse{
Response: &pb.Response{Status: 200, Payload: []byte{}},
Endorsement: &pb.Endorsement{},
},
nil,
)
_, err := common.GetOrdererEndpointOfChain("test-channel", signer, mockEndorserClient, cryptoProvider)
require.EqualError(t, err, "error loading channel config: config must contain a channel group")
})
}
func TestConfigFromEnv(t *testing.T) {
tempdir := t.TempDir()
// peer client config
address, clientConfig, err := common.ConfigFromEnv("peer")
require.NoError(t, err)
require.Equal(t, "", address, "ClientConfig.address by default not set")
require.Equal(t, common.DefaultConnTimeout, clientConfig.DialTimeout, "ClientConfig.DialTimeout should be set to default value of %v", common.DefaultConnTimeout)
require.Equal(t, false, clientConfig.SecOpts.UseTLS, "ClientConfig.SecOpts.UseTLS default value should be false")
require.Equal(t, comm.DefaultMaxRecvMsgSize, clientConfig.MaxRecvMsgSize, "ServerConfig.MaxRecvMsgSize should be set to default value %v", comm.DefaultMaxRecvMsgSize)
require.Equal(t, comm.DefaultMaxSendMsgSize, clientConfig.MaxSendMsgSize, "ServerConfig.MaxSendMsgSize should be set to default value %v", comm.DefaultMaxSendMsgSize)
viper.Set("peer.address", "127.0.0.1")
viper.Set("peer.client.connTimeout", "30s")
viper.Set("peer.maxRecvMsgSize", "1024")
viper.Set("peer.maxSendMsgSize", "2048")
address, clientConfig, err = common.ConfigFromEnv("peer")
require.NoError(t, err)
require.Equal(t, "127.0.0.1", address, "ClientConfig.address should be set to 127.0.0.1")
require.Equal(t, 30*time.Second, clientConfig.DialTimeout, "ClientConfig.DialTimeout should be set to default value of 30s")
require.Equal(t, 1024, clientConfig.MaxRecvMsgSize, "ClientConfig.MaxRecvMsgSize should be set to 1024")
require.Equal(t, 2048, clientConfig.MaxSendMsgSize, "ClientConfig.maxSendMsgSize should be set to 2048")
viper.Set("peer.tls.enabled", true)
viper.Set("peer.tls.rootcert.file", "./filenotfound.pem")
_, _, err = common.ConfigFromEnv("peer")
require.Error(t, err, "ClientConfig should return with bad root cert file path")
viper.Set("peer.tls.enabled", false)
viper.Set("peer.tls.clientAuthRequired", true)
viper.Set("peer.tls.clientKey.file", "./filenotfound.pem")
_, clientConfig, err = common.ConfigFromEnv("peer")
require.Equal(t, false, clientConfig.SecOpts.UseTLS, "ClientConfig.SecOpts.UseTLS should be false")
require.Error(t, err, "ClientConfig should return with client key file path")
org1CA, err := tlsgen.NewCA()
require.NoError(t, err)
err = ioutil.WriteFile(filepath.Join(tempdir, "org1-ca-cert.pem"), org1CA.CertBytes(), 0o644)
require.NoError(t, err)
org1ServerKP, err := org1CA.NewServerCertKeyPair("localhost")
require.NoError(t, err)
err = ioutil.WriteFile(filepath.Join(tempdir, "org1-peer1-cert.pem"), org1ServerKP.Cert, 0o644)
require.NoError(t, err)
err = ioutil.WriteFile(filepath.Join(tempdir, "org1-peer1-key.pem"), org1ServerKP.Key, 0o600)
require.NoError(t, err)
viper.Set("peer.tls.enabled", true)
viper.Set("peer.tls.clientAuthRequired", true)
viper.Set("peer.tls.rootcert.file", filepath.Join(tempdir, "org1-ca-cert.pem"))
viper.Set("peer.tls.clientCert.file", filepath.Join(tempdir, "org1-peer1-cert.pem"))
viper.Set("peer.tls.clientKey.file", filepath.Join(tempdir, "org1-peer1-key.pem"))
_, clientConfig, err = common.ConfigFromEnv("peer")
require.NoError(t, err)
require.Equal(t, 1, len(clientConfig.SecOpts.ServerRootCAs), "ClientConfig.SecOpts.ServerRootCAs should contain 1 entries")
require.Equal(t, org1ServerKP.Key, clientConfig.SecOpts.Key, "Client.SecOpts.Key should be set to configured key")
require.Equal(t, org1ServerKP.Cert, clientConfig.SecOpts.Certificate, "Client.SecOpts.Certificate shoulbe bet set to configured certificate")
}