github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/discovery/support/config/support_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package config_test 8 9 import ( 10 "crypto/rand" 11 "encoding/hex" 12 "fmt" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "testing" 17 18 "github.com/golang/protobuf/proto" 19 "github.com/hechain20/hechain/common/channelconfig" 20 "github.com/hechain20/hechain/common/configtx/test" 21 "github.com/hechain20/hechain/discovery/support/config" 22 "github.com/hechain20/hechain/discovery/support/mocks" 23 "github.com/hechain20/hechain/internal/configtxgen/encoder" 24 "github.com/hechain20/hechain/internal/configtxgen/genesisconfig" 25 "github.com/hechain20/hechain/protoutil" 26 "github.com/hyperledger/fabric-protos-go/common" 27 "github.com/hyperledger/fabric-protos-go/discovery" 28 "github.com/hyperledger/fabric-protos-go/msp" 29 "github.com/onsi/gomega/gexec" 30 "github.com/stretchr/testify/require" 31 ) 32 33 func TestMSPIDMapping(t *testing.T) { 34 randString := func() string { 35 buff := make([]byte, 10) 36 rand.Read(buff) 37 return hex.EncodeToString(buff) 38 } 39 40 dir := filepath.Join(os.TempDir(), fmt.Sprintf("TestMSPIDMapping_%s", randString())) 41 os.Mkdir(dir, 0o700) 42 defer os.RemoveAll(dir) 43 44 cryptogen, err := gexec.Build("github.com/hechain20/hechain/cmd/cryptogen") 45 require.NoError(t, err) 46 defer os.Remove(cryptogen) 47 48 idemixgen, err := gexec.Build("github.com/IBM/idemix/tools/idemixgen", "-mod=mod") 49 require.NoError(t, err) 50 defer os.Remove(idemixgen) 51 52 cryptoConfigDir := filepath.Join(dir, "crypto-config") 53 b, err := exec.Command(cryptogen, "generate", fmt.Sprintf("--output=%s", cryptoConfigDir)).CombinedOutput() 54 require.NoError(t, err, string(b)) 55 56 idemixConfigDir := filepath.Join(dir, "crypto-config", "idemix") 57 b, err = exec.Command(idemixgen, "ca-keygen", fmt.Sprintf("--output=%s", idemixConfigDir)).CombinedOutput() 58 require.NoError(t, err, string(b)) 59 60 profileConfig := genesisconfig.Load("TwoOrgsChannel", "testdata/") 61 ordererConfig := genesisconfig.Load("TwoOrgsOrdererGenesis", "testdata/") 62 profileConfig.Orderer = ordererConfig.Orderer 63 64 // Override the MSP directory with our randomly generated and populated path 65 for _, org := range ordererConfig.Orderer.Organizations { 66 org.MSPDir = filepath.Join(cryptoConfigDir, "ordererOrganizations", "example.com", "msp") 67 org.Name = randString() 68 } 69 70 // Randomize organization names 71 for _, org := range profileConfig.Application.Organizations { 72 org.Name = randString() 73 // Non bccsp-msp orgs don't have the crypto material produced by cryptogen, 74 // we need to use the idemix crypto folder instead. 75 if org.MSPType != "bccsp" { 76 org.MSPDir = filepath.Join(idemixConfigDir) 77 continue 78 } 79 org.MSPDir = filepath.Join(cryptoConfigDir, "peerOrganizations", "org1.example.com", "msp") 80 } 81 82 channelGroup, err := encoder.NewChannelGroup(profileConfig) 83 require.NoError(t, err) 84 fakeConfigGetter := &mocks.ConfigGetter{} 85 fakeConfigGetter.GetCurrConfigReturnsOnCall( 86 0, 87 &common.Config{ 88 ChannelGroup: channelGroup, 89 }, 90 ) 91 92 cs := config.NewDiscoverySupport(fakeConfigGetter) 93 res, err := cs.Config("mychannel") 94 require.NoError(t, err) 95 96 actualKeys := make(map[string]struct{}) 97 for key := range res.Orderers { 98 actualKeys[key] = struct{}{} 99 } 100 101 for key := range res.Msps { 102 actualKeys[key] = struct{}{} 103 } 104 105 // Note that Org3MSP is an idemix org, but it shouldn't be listed here 106 // because peers can't have idemix credentials 107 expected := map[string]struct{}{ 108 "OrdererMSP": {}, 109 "Org1MSP": {}, 110 "Org2MSP": {}, 111 } 112 require.Equal(t, expected, actualKeys) 113 } 114 115 func TestSupportGreenPath(t *testing.T) { 116 fakeConfigGetter := &mocks.ConfigGetter{} 117 fakeConfigGetter.GetCurrConfigReturnsOnCall(0, nil) 118 119 cs := config.NewDiscoverySupport(fakeConfigGetter) 120 res, err := cs.Config("test") 121 require.Nil(t, res) 122 require.Equal(t, "could not get last config for channel test", err.Error()) 123 124 config, err := test.MakeChannelConfig("test") 125 require.NoError(t, err) 126 require.NotNil(t, config) 127 128 fakeConfigGetter.GetCurrConfigReturnsOnCall(1, config) 129 res, err = cs.Config("test") 130 require.NoError(t, err) 131 require.NotNil(t, res) 132 } 133 134 func TestValidateConfig(t *testing.T) { 135 tests := []struct { 136 name string 137 config *common.Config 138 containsError string 139 }{ 140 { 141 name: "nil Config field", 142 config: &common.Config{}, 143 containsError: "field Config.ChannelGroup is nil", 144 }, 145 { 146 name: "nil Groups field", 147 config: &common.Config{ 148 ChannelGroup: &common.ConfigGroup{}, 149 }, 150 containsError: "field Config.ChannelGroup.Groups is nil", 151 }, 152 { 153 name: "no orderer group key", 154 config: &common.Config{ 155 ChannelGroup: &common.ConfigGroup{ 156 Groups: map[string]*common.ConfigGroup{ 157 channelconfig.ApplicationGroupKey: {}, 158 }, 159 }, 160 }, 161 containsError: "key Config.ChannelGroup.Groups[Orderer] is missing", 162 }, 163 { 164 name: "no application group key", 165 config: &common.Config{ 166 ChannelGroup: &common.ConfigGroup{ 167 Groups: map[string]*common.ConfigGroup{ 168 channelconfig.OrdererGroupKey: { 169 Groups: map[string]*common.ConfigGroup{}, 170 }, 171 }, 172 }, 173 }, 174 containsError: "key Config.ChannelGroup.Groups[Application] is missing", 175 }, 176 { 177 name: "no groups key in orderer group", 178 config: &common.Config{ 179 ChannelGroup: &common.ConfigGroup{ 180 Groups: map[string]*common.ConfigGroup{ 181 channelconfig.ApplicationGroupKey: { 182 Groups: map[string]*common.ConfigGroup{}, 183 }, 184 channelconfig.OrdererGroupKey: {}, 185 }, 186 }, 187 }, 188 containsError: "key Config.ChannelGroup.Groups[Orderer].Groups is nil", 189 }, 190 { 191 name: "no groups key in application group", 192 config: &common.Config{ 193 ChannelGroup: &common.ConfigGroup{ 194 Groups: map[string]*common.ConfigGroup{ 195 channelconfig.ApplicationGroupKey: {}, 196 channelconfig.OrdererGroupKey: { 197 Groups: map[string]*common.ConfigGroup{}, 198 }, 199 }, 200 }, 201 }, 202 containsError: "key Config.ChannelGroup.Groups[Application].Groups is nil", 203 }, 204 { 205 name: "no Values in ChannelGroup", 206 config: &common.Config{ 207 ChannelGroup: &common.ConfigGroup{ 208 Groups: map[string]*common.ConfigGroup{ 209 channelconfig.ApplicationGroupKey: { 210 Groups: map[string]*common.ConfigGroup{}, 211 }, 212 channelconfig.OrdererGroupKey: { 213 Groups: map[string]*common.ConfigGroup{}, 214 }, 215 }, 216 }, 217 }, 218 containsError: "field Config.ChannelGroup.Values is nil", 219 }, 220 } 221 222 for _, test := range tests { 223 test := test 224 t.Run(test.name, func(t *testing.T) { 225 err := config.ValidateConfig(test.config) 226 require.Contains(t, test.containsError, err.Error()) 227 }) 228 } 229 } 230 231 func TestOrdererEndpoints(t *testing.T) { 232 t.Run("Global endpoints", func(t *testing.T) { 233 channelConfig, err := test.MakeChannelConfig("mychannel") 234 require.NoError(t, err) 235 236 fakeConfigGetter := &mocks.ConfigGetter{} 237 cs := config.NewDiscoverySupport(fakeConfigGetter) 238 239 fakeConfigGetter.GetCurrConfigReturnsOnCall(0, channelConfig) 240 241 injectGlobalOrdererEndpoint(t, channelConfig, "globalEndpoint:7050") 242 243 res, err := cs.Config("test") 244 require.NoError(t, err) 245 require.Equal(t, map[string]*discovery.Endpoints{ 246 "SampleOrg": {Endpoint: []*discovery.Endpoint{{Host: "globalEndpoint", Port: 7050}}}, 247 }, res.Orderers) 248 }) 249 250 t.Run("Per org endpoints alongside global endpoints", func(t *testing.T) { 251 channelConfig, err := test.MakeChannelConfig("mychannel") 252 require.NoError(t, err) 253 254 fakeConfigGetter := &mocks.ConfigGetter{} 255 cs := config.NewDiscoverySupport(fakeConfigGetter) 256 257 fakeConfigGetter.GetCurrConfigReturnsOnCall(0, channelConfig) 258 259 injectAdditionalEndpointPair(t, channelConfig, "perOrgEndpoint:7050", "anotherOrg") 260 injectAdditionalEndpointPair(t, channelConfig, "endpointWithoutAPortName", "aBadOrg") 261 262 res, err := cs.Config("test") 263 require.NoError(t, err) 264 require.Equal(t, map[string]*discovery.Endpoints{ 265 "SampleOrg": {Endpoint: []*discovery.Endpoint{{Host: "127.0.0.1", Port: 7050}}}, 266 "anotherOrg": {Endpoint: []*discovery.Endpoint{{Host: "perOrgEndpoint", Port: 7050}}}, 267 "aBadOrg": {}, 268 }, res.Orderers) 269 }) 270 271 t.Run("Per org endpoints without global endpoints", func(t *testing.T) { 272 channelConfig, err := test.MakeChannelConfig("mychannel") 273 require.NoError(t, err) 274 275 fakeConfigGetter := &mocks.ConfigGetter{} 276 cs := config.NewDiscoverySupport(fakeConfigGetter) 277 278 fakeConfigGetter.GetCurrConfigReturnsOnCall(0, channelConfig) 279 280 removeGlobalEndpoints(t, channelConfig) 281 injectAdditionalEndpointPair(t, channelConfig, "perOrgEndpoint:7050", "SampleOrg") 282 injectAdditionalEndpointPair(t, channelConfig, "endpointWithoutAPortName", "aBadOrg") 283 284 res, err := cs.Config("test") 285 require.NoError(t, err) 286 require.Equal(t, map[string]*discovery.Endpoints{ 287 "SampleOrg": {Endpoint: []*discovery.Endpoint{{Host: "perOrgEndpoint", Port: 7050}}}, 288 "aBadOrg": {}, 289 }, res.Orderers) 290 }) 291 } 292 293 func removeGlobalEndpoints(t *testing.T, config *common.Config) { 294 // Remove the orderer addresses 295 delete(config.ChannelGroup.Values, channelconfig.OrdererAddressesKey) 296 } 297 298 func injectGlobalOrdererEndpoint(t *testing.T, config *common.Config, endpoint string) { 299 ordererAddresses := channelconfig.OrdererAddressesValue([]string{endpoint}) 300 // Replace the orderer addresses 301 config.ChannelGroup.Values[ordererAddresses.Key()] = &common.ConfigValue{ 302 Value: protoutil.MarshalOrPanic(ordererAddresses.Value()), 303 ModPolicy: "/Channel/Orderer/Admins", 304 } 305 // Remove the per org addresses, if applicable 306 ordererGrps := config.ChannelGroup.Groups[channelconfig.OrdererGroupKey].Groups 307 for _, grp := range ordererGrps { 308 if grp.Values[channelconfig.EndpointsKey] == nil { 309 continue 310 } 311 grp.Values[channelconfig.EndpointsKey].Value = nil 312 } 313 } 314 315 func injectAdditionalEndpointPair(t *testing.T, config *common.Config, endpoint string, orgName string) { 316 ordererGrp := config.ChannelGroup.Groups[channelconfig.OrdererGroupKey].Groups 317 // Get the first orderer org config 318 var firstOrdererConfig *common.ConfigGroup 319 for _, grp := range ordererGrp { 320 firstOrdererConfig = grp 321 break 322 } 323 // Duplicate it. 324 secondOrdererConfig := proto.Clone(firstOrdererConfig).(*common.ConfigGroup) 325 ordererGrp[orgName] = secondOrdererConfig 326 // Reach the FabricMSPConfig buried in it. 327 mspConfig := &msp.MSPConfig{} 328 err := proto.Unmarshal(secondOrdererConfig.Values[channelconfig.MSPKey].Value, mspConfig) 329 require.NoError(t, err) 330 331 fabricConfig := &msp.FabricMSPConfig{} 332 err = proto.Unmarshal(mspConfig.Config, fabricConfig) 333 require.NoError(t, err) 334 335 // Rename it. 336 fabricConfig.Name = orgName 337 338 // Pack the MSP config back into the config 339 secondOrdererConfig.Values[channelconfig.MSPKey].Value = protoutil.MarshalOrPanic(&msp.MSPConfig{ 340 Config: protoutil.MarshalOrPanic(fabricConfig), 341 Type: mspConfig.Type, 342 }) 343 344 // Inject the endpoint 345 ordererOrgProtos := &common.OrdererAddresses{ 346 Addresses: []string{endpoint}, 347 } 348 secondOrdererConfig.Values[channelconfig.EndpointsKey].Value = protoutil.MarshalOrPanic(ordererOrgProtos) 349 }