github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/peer/config_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package peer
     7  
     8  import (
     9  	"crypto/tls"
    10  	"io/ioutil"
    11  	"net"
    12  	"os"
    13  	"path/filepath"
    14  	"runtime"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/hechain20/hechain/common/crypto/tlsgen"
    19  	"github.com/hechain20/hechain/internal/pkg/comm"
    20  	"github.com/hechain20/hechain/internal/pkg/gateway/config"
    21  	"github.com/spf13/viper"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  func TestCacheConfigurationNegative(t *testing.T) {
    26  	// set a bad peer.address
    27  	viper.Set("peer.addressAutoDetect", true)
    28  	viper.Set("peer.address", "testing.com")
    29  	_, err := GlobalConfig()
    30  	require.Error(t, err, "Expected error for bad configuration")
    31  
    32  	viper.Set("peer.addressAutoDetect", false)
    33  	viper.Set("peer.address", "")
    34  	_, err = GlobalConfig()
    35  	require.Error(t, err, "Expected error for bad configuration")
    36  
    37  	viper.Set("peer.address", "wrongAddress")
    38  	_, err = GlobalConfig()
    39  	require.Error(t, err, "Expected error for bad configuration")
    40  }
    41  
    42  func TestPeerAddress(t *testing.T) {
    43  	localIP, err := getLocalIP()
    44  	require.NoError(t, err)
    45  
    46  	tests := []struct {
    47  		name                string
    48  		settings            map[string]interface{}
    49  		expectedPeerAddress string
    50  	}{
    51  		{
    52  			name: "test1",
    53  			settings: map[string]interface{}{
    54  				"peer.addressAutoDetect": false,
    55  				"peer.address":           "testing.com:7051",
    56  			},
    57  			expectedPeerAddress: "testing.com:7051",
    58  		},
    59  		{
    60  			name: "test2",
    61  			settings: map[string]interface{}{
    62  				"peer.addressAutoDetect": true,
    63  				"peer.address":           "testing.com:7051",
    64  			},
    65  			expectedPeerAddress: net.JoinHostPort(localIP, "7051"),
    66  		},
    67  		{
    68  			name: "test3",
    69  			settings: map[string]interface{}{
    70  				"peer.addressAutoDetect": false,
    71  				"peer.address":           "0.0.0.0:7051",
    72  			},
    73  			expectedPeerAddress: net.JoinHostPort(localIP, "7051"),
    74  		},
    75  		{
    76  			name: "test4",
    77  			settings: map[string]interface{}{
    78  				"peer.addressAutoDetect": true,
    79  				"peer.address":           "127.0.0.1:7051",
    80  			},
    81  			expectedPeerAddress: net.JoinHostPort(localIP, "7051"),
    82  		},
    83  	}
    84  
    85  	for _, test := range tests {
    86  		test := test
    87  		t.Run(test.name, func(t *testing.T) {
    88  			for k, v := range test.settings {
    89  				viper.Set(k, v)
    90  			}
    91  			c, err := GlobalConfig()
    92  			require.NoError(t, err, "GlobalConfig returned unexpected error")
    93  			require.Equal(t, test.expectedPeerAddress, c.PeerAddress)
    94  		})
    95  	}
    96  }
    97  
    98  func TestGetServerConfig(t *testing.T) {
    99  	tempdir, err := ioutil.TempDir("", "peer-clientcert")
   100  	require.NoError(t, err)
   101  	defer os.RemoveAll(tempdir)
   102  
   103  	// good config without TLS
   104  	viper.Set("peer.tls.enabled", false)
   105  	viper.Set("peer.connectiontimeout", "7s")
   106  	sc, err := GetServerConfig()
   107  	require.NoError(t, err)
   108  	require.Equal(t, false, sc.SecOpts.UseTLS, "ServerConfig.SecOpts.UseTLS should be false")
   109  	require.Equal(t, sc.ConnectionTimeout, 7*time.Second, "ServerConfig.ConnectionTimeout should be 7 seconds")
   110  
   111  	// keepalive options
   112  	require.Equal(t, comm.DefaultKeepaliveOptions, sc.KaOpts, "ServerConfig.KaOpts should be set to default values")
   113  	viper.Set("peer.keepalive.interval", "60m")
   114  	sc, _ = GetServerConfig()
   115  	require.Equal(t, time.Duration(60)*time.Minute, sc.KaOpts.ServerInterval, "ServerConfig.KaOpts.ServerInterval should be set to 60 min")
   116  	viper.Set("peer.keepalive.timeout", "30s")
   117  	sc, _ = GetServerConfig()
   118  	require.Equal(t, time.Duration(30)*time.Second, sc.KaOpts.ServerTimeout, "ServerConfig.KaOpts.ServerTimeout should be set to 30 sec")
   119  	viper.Set("peer.keepalive.minInterval", "2m")
   120  	sc, _ = GetServerConfig()
   121  	require.Equal(t, time.Duration(2)*time.Minute, sc.KaOpts.ServerMinInterval, "ServerConfig.KaOpts.ServerMinInterval should be set to 2 min")
   122  
   123  	// good config with TLS
   124  	org1CA, err := tlsgen.NewCA()
   125  	require.NoError(t, err)
   126  	err = ioutil.WriteFile(filepath.Join(tempdir, "org1-ca-cert.pem"), org1CA.CertBytes(), 0o644)
   127  	require.NoError(t, err)
   128  	org2CA, err := tlsgen.NewCA()
   129  	require.NoError(t, err)
   130  	err = ioutil.WriteFile(filepath.Join(tempdir, "org2-ca-cert.pem"), org2CA.CertBytes(), 0o644)
   131  	require.NoError(t, err)
   132  
   133  	org1ServerKP, err := org1CA.NewServerCertKeyPair("localhost")
   134  	require.NoError(t, err)
   135  	err = ioutil.WriteFile(filepath.Join(tempdir, "org1-server1-cert.pem"), org1ServerKP.Cert, 0o644)
   136  	require.NoError(t, err)
   137  	err = ioutil.WriteFile(filepath.Join(tempdir, "org1-server1-key.pem"), org1ServerKP.Key, 0o600)
   138  	require.NoError(t, err)
   139  
   140  	viper.Set("peer.tls.enabled", true)
   141  	viper.Set("peer.tls.cert.file", filepath.Join(tempdir, "org1-server1-cert.pem"))
   142  	viper.Set("peer.tls.key.file", filepath.Join(tempdir, "org1-server1-key.pem"))
   143  	viper.Set("peer.tls.rootcert.file", filepath.Join(tempdir, "org1-ca-cert.pem"))
   144  
   145  	sc, err = GetServerConfig()
   146  	require.NoError(t, err, "failed to build server config")
   147  	require.Equal(t, true, sc.SecOpts.UseTLS, "ServerConfig.SecOpts.UseTLS should be true")
   148  	require.Equal(t, false, sc.SecOpts.RequireClientCert, "ServerConfig.SecOpts.RequireClientCert should be false")
   149  	viper.Set("peer.tls.clientAuthRequired", true)
   150  	viper.Set("peer.tls.clientRootCAs.files", []string{
   151  		filepath.Join(tempdir, "org1-ca-cert.pem"),
   152  		filepath.Join(tempdir, "org2-ca-cert.pem"),
   153  	})
   154  	sc, _ = GetServerConfig()
   155  	require.Equal(t, true, sc.SecOpts.RequireClientCert, "ServerConfig.SecOpts.RequireClientCert should be true")
   156  	require.Equal(t, 2, len(sc.SecOpts.ClientRootCAs), "ServerConfig.SecOpts.ClientRootCAs should contain 2 entries")
   157  
   158  	// GRPC max message size options
   159  	require.Equal(t, comm.DefaultMaxRecvMsgSize, sc.MaxRecvMsgSize, "ServerConfig.MaxRecvMsgSize should be set to default value %v", comm.DefaultMaxRecvMsgSize)
   160  	require.Equal(t, comm.DefaultMaxSendMsgSize, sc.MaxSendMsgSize, "ServerConfig.MaxSendMsgSize should be set to default value %v", comm.DefaultMaxSendMsgSize)
   161  	viper.Set("peer.maxRecvMsgSize", "1024")
   162  	viper.Set("peer.maxSendMsgSize", "1024")
   163  	sc, _ = GetServerConfig()
   164  	require.Equal(t, 1024, sc.MaxRecvMsgSize, "ServerConfig.MaxRecvMsgSize should be set to custom value 1024")
   165  	require.Equal(t, 1024, sc.MaxSendMsgSize, "ServerConfig.MaxSendMsgSize should be set to custom value 1024")
   166  
   167  	// bad config with TLS
   168  	viper.Set("peer.tls.rootcert.file", "non-existent-file.pem")
   169  	_, err = GetServerConfig()
   170  	require.Error(t, err, "GetServerConfig should return error with bad root cert path")
   171  
   172  	viper.Set("peer.tls.rootcert.file", filepath.Join(tempdir, "org1-ca-cert.pem"))
   173  	viper.Set("peer.tls.cert.file", "non-existent-file.pem")
   174  	_, err = GetServerConfig()
   175  	require.Error(t, err, "GetServerConfig should return error with bad tls cert path")
   176  
   177  	// disable TLS for remaining tests
   178  	viper.Set("peer.tls.enabled", false)
   179  	viper.Set("peer.tls.clientAuthRequired", false)
   180  }
   181  
   182  func TestGetClientCertificate(t *testing.T) {
   183  	tempdir, err := ioutil.TempDir("", "peer-clientcert")
   184  	require.NoError(t, err)
   185  	defer os.RemoveAll(tempdir)
   186  
   187  	ca, err := tlsgen.NewCA()
   188  	require.NoError(t, err)
   189  	kp, err := ca.NewServerCertKeyPair("localhost")
   190  	require.NoError(t, err)
   191  	err = ioutil.WriteFile(filepath.Join(tempdir, "server1-cert.pem"), kp.Cert, 0o644)
   192  	require.NoError(t, err)
   193  	err = ioutil.WriteFile(filepath.Join(tempdir, "server1-key.pem"), kp.Key, 0o600)
   194  	require.NoError(t, err)
   195  
   196  	viper.Set("peer.tls.key.file", "")
   197  	viper.Set("peer.tls.cert.file", "")
   198  	viper.Set("peer.tls.clientKey.file", "")
   199  	viper.Set("peer.tls.clientCert.file", "")
   200  
   201  	// neither client nor server key pairs set - expect error
   202  	_, err = GetClientCertificate()
   203  	require.Error(t, err)
   204  
   205  	viper.Set("peer.tls.key.file", "")
   206  	viper.Set("peer.tls.cert.file", filepath.Join(tempdir, "server1-cert.pem"))
   207  	// missing server key file - expect error
   208  	_, err = GetClientCertificate()
   209  	require.Error(t, err)
   210  
   211  	viper.Set("peer.tls.key.file", filepath.Join(tempdir, "server1-key.pem"))
   212  	viper.Set("peer.tls.cert.file", "")
   213  	// missing server cert file - expect error
   214  	_, err = GetClientCertificate()
   215  	require.Error(t, err)
   216  
   217  	// set server TLS settings to ensure we get the client TLS settings
   218  	// when they are set properly
   219  	viper.Set("peer.tls.key.file", filepath.Join(tempdir, "server1-key.pem"))
   220  	viper.Set("peer.tls.cert.file", filepath.Join(tempdir, "server1-cert.pem"))
   221  
   222  	// peer.tls.clientCert.file not set - expect error
   223  	viper.Set("peer.tls.clientKey.file", filepath.Join(tempdir, "server1-key.pem"))
   224  	_, err = GetClientCertificate()
   225  	require.Error(t, err)
   226  
   227  	// peer.tls.clientKey.file not set - expect error
   228  	viper.Set("peer.tls.clientKey.file", "")
   229  	viper.Set("peer.tls.clientCert.file", filepath.Join(tempdir, "server1-cert.pem"))
   230  	_, err = GetClientCertificate()
   231  	require.Error(t, err)
   232  
   233  	// client auth required and clientKey/clientCert set
   234  	expected, err := tls.LoadX509KeyPair(
   235  		filepath.Join(tempdir, "server1-cert.pem"),
   236  		filepath.Join(tempdir, "server1-key.pem"),
   237  	)
   238  	if err != nil {
   239  		t.Fatalf("Failed to load test certificate (%s)", err)
   240  	}
   241  	viper.Set("peer.tls.clientKey.file", filepath.Join(tempdir, "server1-key.pem"))
   242  	cert, err := GetClientCertificate()
   243  	require.NoError(t, err)
   244  	require.Equal(t, expected, cert)
   245  
   246  	// client auth required and clientKey/clientCert not set - expect
   247  	// client cert to be the server cert
   248  	viper.Set("peer.tls.clientKey.file", "")
   249  	viper.Set("peer.tls.clientCert.file", "")
   250  	expected, err = tls.LoadX509KeyPair(
   251  		filepath.Join(tempdir, "server1-cert.pem"),
   252  		filepath.Join(tempdir, "server1-key.pem"),
   253  	)
   254  	require.NoError(t, err, "failed to load test certificate")
   255  	cert, err = GetClientCertificate()
   256  	require.NoError(t, err)
   257  	require.Equal(t, expected, cert)
   258  }
   259  
   260  func TestGlobalConfig(t *testing.T) {
   261  	defer viper.Reset()
   262  	cwd, err := os.Getwd()
   263  	require.NoError(t, err, "failed to get current working directory")
   264  	viper.SetConfigFile(filepath.Join(cwd, "core.yaml"))
   265  
   266  	// Capture the configuration from viper
   267  	viper.Set("peer.addressAutoDetect", false)
   268  	viper.Set("peer.address", "localhost:8080")
   269  	viper.Set("peer.id", "testPeerID")
   270  	viper.Set("peer.localMspId", "SampleOrg")
   271  	viper.Set("peer.listenAddress", "0.0.0.0:7051")
   272  	viper.Set("peer.authentication.timewindow", "15m")
   273  	viper.Set("peer.tls.enabled", "false")
   274  	viper.Set("peer.networkId", "testNetwork")
   275  	viper.Set("peer.limits.concurrency.endorserService", 2500)
   276  	viper.Set("peer.limits.concurrency.deliverService", 2500)
   277  	viper.Set("peer.limits.concurrency.gatewayService", 500)
   278  	viper.Set("peer.discovery.enabled", true)
   279  	viper.Set("peer.profile.enabled", false)
   280  	viper.Set("peer.profile.listenAddress", "peer.authentication.timewindow")
   281  	viper.Set("peer.discovery.orgMembersAllowedAccess", false)
   282  	viper.Set("peer.discovery.authCacheEnabled", true)
   283  	viper.Set("peer.discovery.authCacheMaxSize", 1000)
   284  	viper.Set("peer.discovery.authCachePurgeRetentionRatio", 0.75)
   285  	viper.Set("peer.chaincodeListenAddress", "0.0.0.0:7052")
   286  	viper.Set("peer.chaincodeAddress", "0.0.0.0:7052")
   287  	viper.Set("peer.validatorPoolSize", 1)
   288  	viper.Set("peer.gateway.enabled", true)
   289  	viper.Set("peer.gateway.endorsementTimeout", 10*time.Second)
   290  	viper.Set("peer.gateway.dialTimeout", 60*time.Second)
   291  
   292  	viper.Set("vm.endpoint", "unix:///var/run/docker.sock")
   293  	viper.Set("vm.docker.tls.enabled", false)
   294  	viper.Set("vm.docker.attachStdout", false)
   295  	viper.Set("vm.docker.hostConfig.NetworkMode", "TestingHost")
   296  	viper.Set("vm.docker.tls.cert.file", "test/vm/tls/cert/file")
   297  	viper.Set("vm.docker.tls.key.file", "test/vm/tls/key/file")
   298  	viper.Set("vm.docker.tls.ca.file", "test/vm/tls/ca/file")
   299  
   300  	viper.Set("operations.listenAddress", "127.0.0.1:9443")
   301  	viper.Set("operations.tls.enabled", false)
   302  	viper.Set("operations.tls.cert.file", "test/tls/cert/file")
   303  	viper.Set("operations.tls.key.file", "test/tls/key/file")
   304  	viper.Set("operations.tls.clientAuthRequired", false)
   305  	viper.Set("operations.tls.clientRootCAs.files", []string{"relative/file1", "/absolute/file2"})
   306  
   307  	viper.Set("metrics.provider", "disabled")
   308  	viper.Set("metrics.statsd.network", "udp")
   309  	viper.Set("metrics.statsd.address", "127.0.0.1:8125")
   310  	viper.Set("metrics.statsd.writeInterval", "10s")
   311  	viper.Set("metrics.statsd.prefix", "testPrefix")
   312  
   313  	viper.Set("chaincode.pull", false)
   314  	viper.Set("chaincode.externalBuilders", &[]ExternalBuilder{
   315  		{
   316  			Path: "relative/plugin_dir",
   317  			Name: "relative",
   318  		},
   319  		{
   320  			Path: "/absolute/plugin_dir",
   321  			Name: "absolute",
   322  		},
   323  	})
   324  
   325  	coreConfig, err := GlobalConfig()
   326  	require.NoError(t, err)
   327  
   328  	expectedConfig := &Config{
   329  		LocalMSPID:                            "SampleOrg",
   330  		ListenAddress:                         "0.0.0.0:7051",
   331  		AuthenticationTimeWindow:              15 * time.Minute,
   332  		PeerTLSEnabled:                        false,
   333  		PeerAddress:                           "localhost:8080",
   334  		PeerID:                                "testPeerID",
   335  		NetworkID:                             "testNetwork",
   336  		LimitsConcurrencyEndorserService:      2500,
   337  		LimitsConcurrencyDeliverService:       2500,
   338  		LimitsConcurrencyGatewayService:       500,
   339  		DiscoveryEnabled:                      true,
   340  		ProfileEnabled:                        false,
   341  		ProfileListenAddress:                  "peer.authentication.timewindow",
   342  		DiscoveryOrgMembersAllowed:            false,
   343  		DiscoveryAuthCacheEnabled:             true,
   344  		DiscoveryAuthCacheMaxSize:             1000,
   345  		DiscoveryAuthCachePurgeRetentionRatio: 0.75,
   346  		ChaincodeListenAddress:                "0.0.0.0:7052",
   347  		ChaincodeAddress:                      "0.0.0.0:7052",
   348  		ValidatorPoolSize:                     1,
   349  		DeliverClientKeepaliveOptions:         comm.DefaultKeepaliveOptions,
   350  
   351  		VMEndpoint:           "unix:///var/run/docker.sock",
   352  		VMDockerTLSEnabled:   false,
   353  		VMDockerAttachStdout: false,
   354  		VMNetworkMode:        "TestingHost",
   355  
   356  		ChaincodePull: false,
   357  		ExternalBuilders: []ExternalBuilder{
   358  			{
   359  				Path: "relative/plugin_dir",
   360  				Name: "relative",
   361  			},
   362  			{
   363  				Path: "/absolute/plugin_dir",
   364  				Name: "absolute",
   365  			},
   366  		},
   367  		OperationsListenAddress:         "127.0.0.1:9443",
   368  		OperationsTLSEnabled:            false,
   369  		OperationsTLSCertFile:           filepath.Join(cwd, "test/tls/cert/file"),
   370  		OperationsTLSKeyFile:            filepath.Join(cwd, "test/tls/key/file"),
   371  		OperationsTLSClientAuthRequired: false,
   372  		OperationsTLSClientRootCAs: []string{
   373  			filepath.Join(cwd, "relative", "file1"),
   374  			"/absolute/file2",
   375  		},
   376  
   377  		MetricsProvider:     "disabled",
   378  		StatsdNetwork:       "udp",
   379  		StatsdAaddress:      "127.0.0.1:8125",
   380  		StatsdWriteInterval: 10 * time.Second,
   381  		StatsdPrefix:        "testPrefix",
   382  
   383  		DockerCert: filepath.Join(cwd, "test/vm/tls/cert/file"),
   384  		DockerKey:  filepath.Join(cwd, "test/vm/tls/key/file"),
   385  		DockerCA:   filepath.Join(cwd, "test/vm/tls/ca/file"),
   386  
   387  		GatewayOptions: config.Options{
   388  			Enabled:            true,
   389  			EndorsementTimeout: 10 * time.Second,
   390  			DialTimeout:        60 * time.Second,
   391  		},
   392  	}
   393  
   394  	require.Equal(t, coreConfig, expectedConfig)
   395  }
   396  
   397  func TestGlobalConfigDefault(t *testing.T) {
   398  	defer viper.Reset()
   399  	viper.Set("peer.address", "localhost:8080")
   400  
   401  	coreConfig, err := GlobalConfig()
   402  	require.NoError(t, err)
   403  
   404  	expectedConfig := &Config{
   405  		AuthenticationTimeWindow:      15 * time.Minute,
   406  		PeerAddress:                   "localhost:8080",
   407  		ValidatorPoolSize:             runtime.NumCPU(),
   408  		VMNetworkMode:                 "host",
   409  		DeliverClientKeepaliveOptions: comm.DefaultKeepaliveOptions,
   410  		GatewayOptions:                config.GetOptions(viper.GetViper()),
   411  	}
   412  
   413  	require.Equal(t, expectedConfig, coreConfig)
   414  }
   415  
   416  func TestPropagateEnvironment(t *testing.T) {
   417  	defer viper.Reset()
   418  	viper.Set("peer.address", "localhost:8080")
   419  	viper.Set("chaincode.externalBuilders", &[]ExternalBuilder{
   420  		{
   421  			Name:        "testName",
   422  			Environment: []string{"KEY=VALUE"},
   423  			Path:        "/testPath",
   424  		},
   425  		{
   426  			Name:                 "testName",
   427  			PropagateEnvironment: []string{"KEY=VALUE"},
   428  			Path:                 "/testPath",
   429  		},
   430  		{
   431  			Name:                 "testName",
   432  			Environment:          []string{"KEY=VALUE"},
   433  			PropagateEnvironment: []string{"KEY=VALUE2"},
   434  			Path:                 "/testPath",
   435  		},
   436  	})
   437  	coreConfig, err := GlobalConfig()
   438  	require.NoError(t, err)
   439  
   440  	expectedConfig := &Config{
   441  		AuthenticationTimeWindow:      15 * time.Minute,
   442  		PeerAddress:                   "localhost:8080",
   443  		ValidatorPoolSize:             runtime.NumCPU(),
   444  		VMNetworkMode:                 "host",
   445  		DeliverClientKeepaliveOptions: comm.DefaultKeepaliveOptions,
   446  		ExternalBuilders: []ExternalBuilder{
   447  			{
   448  				Name:                 "testName",
   449  				Environment:          []string{"KEY=VALUE"},
   450  				PropagateEnvironment: []string{"KEY=VALUE"},
   451  				Path:                 "/testPath",
   452  			},
   453  			{
   454  				Name:                 "testName",
   455  				PropagateEnvironment: []string{"KEY=VALUE"},
   456  				Path:                 "/testPath",
   457  			},
   458  			{
   459  				Name:                 "testName",
   460  				Environment:          []string{"KEY=VALUE"},
   461  				PropagateEnvironment: []string{"KEY=VALUE2"},
   462  				Path:                 "/testPath",
   463  			},
   464  		},
   465  		GatewayOptions: config.GetOptions(viper.GetViper()),
   466  	}
   467  	require.Equal(t, expectedConfig, coreConfig)
   468  }
   469  
   470  func TestExternalBuilderConfigAsEnvVar(t *testing.T) {
   471  	defer viper.Reset()
   472  	viper.Set("peer.address", "localhost:8080")
   473  	viper.Set("chaincode.externalBuilders", "[{name: relative, path: relative/plugin_dir, propagateEnvironment: [ENVVAR_NAME_TO_PROPAGATE_FROM_PEER, GOPROXY]}, {name: absolute, path: /absolute/plugin_dir}]")
   474  	coreConfig, err := GlobalConfig()
   475  	require.NoError(t, err)
   476  
   477  	require.Equal(t, []ExternalBuilder{
   478  		{
   479  			Path:                 "relative/plugin_dir",
   480  			Name:                 "relative",
   481  			PropagateEnvironment: []string{"ENVVAR_NAME_TO_PROPAGATE_FROM_PEER", "GOPROXY"},
   482  		},
   483  		{
   484  			Path: "/absolute/plugin_dir",
   485  			Name: "absolute",
   486  		},
   487  	}, coreConfig.ExternalBuilders)
   488  }
   489  
   490  func TestMissingExternalBuilderPath(t *testing.T) {
   491  	defer viper.Reset()
   492  	viper.Set("peer.address", "localhost:8080")
   493  	viper.Set("chaincode.externalBuilders", &[]ExternalBuilder{
   494  		{
   495  			Name: "testName",
   496  		},
   497  	})
   498  	_, err := GlobalConfig()
   499  	require.EqualError(t, err, "invalid external builder configuration, path attribute missing in one or more builders")
   500  }
   501  
   502  func TestMissingExternalBuilderName(t *testing.T) {
   503  	defer viper.Reset()
   504  	viper.Set("peer.address", "localhost:8080")
   505  	viper.Set("chaincode.externalBuilders", &[]ExternalBuilder{
   506  		{
   507  			Path: "relative/plugin_dir",
   508  		},
   509  	})
   510  	_, err := GlobalConfig()
   511  	require.EqualError(t, err, "external builder at path relative/plugin_dir has no name attribute")
   512  }