github.com/canhui/fabric_ca2_2@v2.0.0-alpha+incompatible/test/fabric-ca-load-tester/main.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 package main 17 18 import ( 19 "crypto/rand" 20 "flag" 21 "fmt" 22 "io/ioutil" 23 "log" 24 "net/url" 25 "os" 26 "path/filepath" 27 "sync" 28 "time" 29 30 "github.com/hyperledger/fabric-ca/api" 31 "github.com/hyperledger/fabric-ca/lib" 32 yaml "gopkg.in/yaml.v2" 33 ) 34 35 // IdentityType represents type of identity in the fabric 36 type IdentityType string 37 38 const ( 39 // User user identity type 40 User IdentityType = "User" 41 // Peer peer identity type 42 Peer = "Peer" 43 // Validator validator identity type 44 Validator = "Validator" 45 ) 46 47 // TestRequest represents request properties from 48 // which a request payload object can be constructed 49 type TestRequest map[string]interface{} 50 51 // Test represents a fabric-ca test 52 type Test struct { 53 Name string `yaml:"name"` 54 Repeat int `yaml:"repeat,omitempty"` 55 Req TestRequest `yaml:"req,omitempty"` 56 } 57 58 type testConfig struct { 59 ServerURL string `yaml:"serverURL"` 60 ConfigHome string `yaml:"caConfigHome"` 61 NumUsers int `yaml:"numClients"` 62 NumReqsPerUser int `yaml:"numReqsPerClient"` 63 TestSeq []Test `yaml:"testSeq"` 64 Affiliation string `yaml:"affiliation"` 65 CAClientConfig lib.ClientConfig `yaml:"caClientConfig"` 66 } 67 68 // enrollmentID encapsulates an identity's name and type 69 type enrollmentID struct { 70 ID *string 71 it *IdentityType 72 } 73 74 var ( 75 testCfg testConfig 76 testCfgFile *string 77 ) 78 79 func main() { 80 t0 := time.Now() 81 testCfgFile = flag.String("config", "testConfig.yml", "Fully qualified name of the test configuration file") 82 flag.Parse() 83 84 // Create CA client config 85 err := readConfig() 86 if err != nil { 87 log.Printf("Failed to create client config: %v", err) 88 return 89 } 90 91 // Enroll boostrap user 92 bootID, err1 := enrollBootstrapUser(&testCfg.ServerURL, 93 &testCfg.ConfigHome, &testCfg.CAClientConfig) 94 if err1 != nil { 95 log.Printf("Failed to enroll bootstrap user: %v", err1) 96 return 97 } 98 99 fin := make(chan testClientRes, testCfg.NumUsers) 100 101 var wg sync.WaitGroup 102 for i := 0; i < testCfg.NumUsers; i++ { 103 c := getTestClient(i, &testCfg.ConfigHome, &testCfg.CAClientConfig, bootID) 104 if err != nil { 105 log.Printf("Failed to get client: %v", err) 106 continue 107 } 108 // Increment the WaitGroup counter 109 wg.Add(1) 110 go func() { 111 // Decrement the counter when the goroutine completes 112 defer wg.Done() 113 c.runTests(fin) 114 }() 115 } 116 wg.Wait() 117 t1 := time.Now() 118 log.Printf("Load test finished in %v seconds\n", t1.Sub(t0).Seconds()) 119 for i := 0; i < testCfg.NumUsers; i++ { 120 log.Println(<-fin) 121 } 122 } 123 124 // Enrolls bootstrap user and sets the cfg global object 125 func enrollBootstrapUser(surl *string, configHome *string, 126 cfg *lib.ClientConfig) (id *lib.Identity, err error) { 127 var resp *lib.EnrollmentResponse 128 resp, err = cfg.Enroll(*surl, *configHome) 129 if err != nil { 130 log.Printf("Enrollment of boostrap user failed: %v", err) 131 return id, err 132 } 133 log.Printf("Successfully enrolled boostrap user") 134 135 id = resp.Identity 136 cfg.ID.Name = id.GetName() 137 return id, err 138 } 139 140 // Reads test config 141 func readConfig() error { 142 tcFile, e := ioutil.ReadFile(*testCfgFile) 143 if e != nil { 144 log.Printf("Failed to read configuration file '%s': %v", *testCfgFile, e) 145 os.Exit(1) 146 } 147 yaml.Unmarshal(tcFile, &testCfg) 148 149 uo, err := url.Parse(testCfg.ServerURL) 150 if err != nil { 151 return err 152 } 153 u := fmt.Sprintf("%s://%s", uo.Scheme, uo.Host) 154 testCfg.CAClientConfig.URL = u 155 156 // Make config home absolute 157 if !filepath.IsAbs(testCfg.ConfigHome) { 158 testCfg.ConfigHome, err = filepath.Abs(testCfg.ConfigHome) 159 if err != nil { 160 log.Printf("Failed to get full path of config file: %s", err) 161 } 162 } 163 164 log.Printf("Config created: %+v", testCfg) 165 return nil 166 } 167 168 // Returns a random affiliation 169 func getAffiliation() string { 170 return testCfg.Affiliation 171 } 172 173 // Returns a random enrollment ID 174 func genEnrollmentID(it IdentityType) (eid *enrollmentID, err error) { 175 b := make([]byte, 16) 176 _, err = rand.Read(b) 177 if err != nil { 178 return 179 } 180 uuid := fmt.Sprintf("%s-%X-%X-%X-%X-%X", it, b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) 181 eid = &enrollmentID{ 182 ID: &uuid, 183 it: &it, 184 } 185 return 186 } 187 188 // Returns identity type based on the value of i 189 func getIdentityType(i int) IdentityType { 190 tipe := i % 3 191 switch tipe { 192 case 0: 193 return User 194 case 1: 195 return Peer 196 case 2: 197 return Validator 198 default: 199 return User 200 } 201 } 202 203 func (tr TestRequest) getTCertsReq() *api.GetTCertBatchRequest { 204 count := tr["count"].(int) 205 prekey := tr["prekey"].(string) 206 disableKdf := tr["disable_kdf"].(bool) 207 encryptAttrs := tr["encrypt_attrs"].(bool) 208 return &api.GetTCertBatchRequest{ 209 Count: count, 210 PreKey: prekey, 211 DisableKeyDerivation: disableKdf, 212 EncryptAttrs: encryptAttrs, 213 } 214 } 215 216 func (tr TestRequest) getEnrollmentReq() *api.EnrollmentRequest { 217 name := tr["name"].(string) 218 pass := tr["pass"].(string) 219 return &api.EnrollmentRequest{ 220 Name: name, 221 Secret: pass, 222 } 223 }