github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/core/chaincode/platforms/golang/platform_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 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 17 package golang 18 19 import ( 20 "archive/tar" 21 "bytes" 22 "compress/gzip" 23 "fmt" 24 "os" 25 "strings" 26 "testing" 27 "time" 28 29 "github.com/hyperledger/fabric/core/config" 30 pb "github.com/hyperledger/fabric/protos/peer" 31 "github.com/spf13/viper" 32 "github.com/stretchr/testify/assert" 33 ) 34 35 func testerr(err error, succ bool) error { 36 if succ && err != nil { 37 return fmt.Errorf("Expected success but got error %s", err) 38 } else if !succ && err == nil { 39 return fmt.Errorf("Expected failure but succeeded") 40 } 41 return nil 42 } 43 44 func writeBytesToPackage(name string, payload []byte, mode int64, tw *tar.Writer) error { 45 //Make headers identical by using zero time 46 var zeroTime time.Time 47 tw.WriteHeader(&tar.Header{Name: name, Size: int64(len(payload)), ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime, Mode: mode}) 48 tw.Write(payload) 49 50 return nil 51 } 52 53 func generateFakeCDS(ccname, path, file string, mode int64) (*pb.ChaincodeDeploymentSpec, error) { 54 codePackage := bytes.NewBuffer(nil) 55 gw := gzip.NewWriter(codePackage) 56 tw := tar.NewWriter(gw) 57 58 payload := make([]byte, 25, 25) 59 err := writeBytesToPackage(file, payload, mode, tw) 60 if err != nil { 61 return nil, err 62 } 63 64 tw.Close() 65 gw.Close() 66 67 cds := &pb.ChaincodeDeploymentSpec{ 68 ChaincodeSpec: &pb.ChaincodeSpec{ 69 ChaincodeId: &pb.ChaincodeID{ 70 Name: ccname, 71 Path: path, 72 }, 73 }, 74 CodePackage: codePackage.Bytes(), 75 } 76 77 return cds, nil 78 } 79 80 type spec struct { 81 CCName string 82 Path, File string 83 Mode int64 84 SuccessExpected bool 85 RealGen bool 86 } 87 88 func TestValidateCDS(t *testing.T) { 89 platform := &Platform{} 90 91 specs := make([]spec, 0) 92 specs = append(specs, spec{CCName: "NoCode", Path: "path/to/nowhere", File: "/bin/warez", Mode: 0100400, SuccessExpected: false}) 93 specs = append(specs, spec{CCName: "NoCode", Path: "path/to/somewhere", File: "/src/path/to/somewhere/main.go", Mode: 0100400, SuccessExpected: true}) 94 specs = append(specs, spec{CCName: "NoCode", Path: "path/to/somewhere", File: "/src/path/to/somewhere/warez", Mode: 0100555, SuccessExpected: false}) 95 96 for _, s := range specs { 97 cds, err := generateFakeCDS(s.CCName, s.Path, s.File, s.Mode) 98 99 err = platform.ValidateDeploymentSpec(cds) 100 if s.SuccessExpected == true && err != nil { 101 t.Errorf("Unexpected failure: %s", err) 102 } 103 if s.SuccessExpected == false && err == nil { 104 t.Log("Expected validation failure") 105 t.Fail() 106 } 107 } 108 } 109 110 func TestPlatform_GoPathNotSet(t *testing.T) { 111 p := &Platform{} 112 spec := &pb.ChaincodeSpec{ 113 ChaincodeId: &pb.ChaincodeID{ 114 Path: "/opt/gopath/src/github.com/hyperledger/fabric", 115 }, 116 } 117 gopath := os.Getenv("GOPATH") 118 defer os.Setenv("GOPATH", gopath) 119 os.Setenv("GOPATH", "") 120 121 err := p.ValidateSpec(spec) 122 assert.Contains(t, err.Error(), "invalid GOPATH environment variable value") 123 } 124 125 func Test_findSource(t *testing.T) { 126 gopath, err := getGopath() 127 if err != nil { 128 t.Errorf("failed to get GOPATH: %s", err) 129 } 130 131 var source SourceMap 132 133 source, err = findSource(gopath, "github.com/hyperledger/fabric/peer") 134 if err != nil { 135 t.Errorf("failed to find source: %s", err) 136 } 137 138 if _, ok := source["src/github.com/hyperledger/fabric/peer/main.go"]; !ok { 139 t.Errorf("Failed to find expected source file: %v", source) 140 } 141 142 source, err = findSource(gopath, "acme.com/this/should/not/exist") 143 if err == nil { 144 t.Errorf("Success when failure was expected") 145 } 146 } 147 148 func Test_DeploymentPayload(t *testing.T) { 149 platform := &Platform{} 150 spec := &pb.ChaincodeSpec{ 151 ChaincodeId: &pb.ChaincodeID{ 152 Path: "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", 153 }, 154 } 155 156 payload, err := platform.GetDeploymentPayload(spec) 157 assert.NoError(t, err) 158 159 t.Logf("payload size: %d", len(payload)) 160 161 is := bytes.NewReader(payload) 162 gr, err := gzip.NewReader(is) 163 if err == nil { 164 tr := tar.NewReader(gr) 165 166 for { 167 header, err := tr.Next() 168 if err != nil { 169 // We only get here if there are no more entries to scan 170 break 171 } 172 173 t.Logf("%s (%d)", header.Name, header.Size) 174 } 175 } 176 } 177 178 func Test_decodeUrl(t *testing.T) { 179 cs := &pb.ChaincodeSpec{ 180 ChaincodeId: &pb.ChaincodeID{ 181 Name: "Test Chaincode", 182 Path: "http://github.com/hyperledger/fabric/examples/chaincode/go/map", 183 }, 184 } 185 186 if _, err := decodeUrl(cs); err != nil { 187 t.Fail() 188 t.Logf("Error to decodeUrl unsuccessfully with valid path: %s, %s", cs.ChaincodeId.Path, err) 189 } 190 191 cs.ChaincodeId.Path = "" 192 193 if _, err := decodeUrl(cs); err == nil { 194 t.Fail() 195 t.Logf("Error to decodeUrl successfully with invalid path: %s", cs.ChaincodeId.Path) 196 } 197 198 cs.ChaincodeId.Path = "/" 199 200 if _, err := decodeUrl(cs); err == nil { 201 t.Fail() 202 t.Logf("Error to decodeUrl successfully with invalid path: %s", cs.ChaincodeId.Path) 203 } 204 205 cs.ChaincodeId.Path = "http:///" 206 207 if _, err := decodeUrl(cs); err == nil { 208 t.Fail() 209 t.Logf("Error to decodeUrl successfully with invalid path: %s", cs.ChaincodeId.Path) 210 } 211 } 212 213 func TestValidateSpec(t *testing.T) { 214 platform := &Platform{} 215 216 var tests = []struct { 217 spec *pb.ChaincodeSpec 218 succ bool 219 }{ 220 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: "http://github.com/hyperledger/fabric/examples/chaincode/go/map"}}, succ: true}, 221 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: "https://github.com/hyperledger/fabric/examples/chaincode/go/map"}}, succ: true}, 222 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: "github.com/hyperledger/fabric/examples/chaincode/go/map"}}, succ: true}, 223 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: "github.com/hyperledger/fabric/bad/chaincode/go/map"}}, succ: false}, 224 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: ":github.com/hyperledger/fabric/examples/chaincode/go/map"}}, succ: false}, 225 } 226 227 for _, tst := range tests { 228 err := platform.ValidateSpec(tst.spec) 229 if err = testerr(err, tst.succ); err != nil { 230 t.Errorf("Error validating chaincode spec: %s, %s", tst.spec.ChaincodeId.Path, err) 231 } 232 } 233 } 234 235 func TestGetDeploymentPayload(t *testing.T) { 236 platform := &Platform{} 237 238 var tests = []struct { 239 spec *pb.ChaincodeSpec 240 succ bool 241 }{ 242 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: "github.com/hyperledger/fabric/examples/chaincode/go/map"}}, succ: true}, 243 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: "github.com/hyperledger/fabric/examples/bad/go/map"}}, succ: false}, 244 {spec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "Test Chaincode", Path: "github.com/hyperledger/fabric/test/chaincodes/BadImport"}}, succ: false}, 245 } 246 247 for _, tst := range tests { 248 _, err := platform.GetDeploymentPayload(tst.spec) 249 if err = testerr(err, tst.succ); err != nil { 250 t.Errorf("Error validating chaincode spec: %s, %s", tst.spec.ChaincodeId.Path, err) 251 } 252 } 253 } 254 255 //TestGenerateDockerBuild goes through the functions needed to do docker build 256 func TestGenerateDockerBuild(t *testing.T) { 257 platform := &Platform{} 258 259 specs := make([]spec, 0) 260 specs = append(specs, spec{CCName: "NoCode", Path: "path/to/nowhere", File: "/bin/warez", Mode: 0100400, SuccessExpected: false}) 261 specs = append(specs, spec{CCName: "invalidhttp", Path: "https://not/a/valid/path", File: "/src/github.com/hyperledger/fabric/examples/chaincode/go/map/map.go", Mode: 0100400, SuccessExpected: false, RealGen: true}) 262 specs = append(specs, spec{CCName: "map", Path: "github.com/hyperledger/fabric/examples/chaincode/go/map", File: "/src/github.com/hyperledger/fabric/examples/chaincode/go/map/map.go", Mode: 0100400, SuccessExpected: true, RealGen: true}) 263 specs = append(specs, spec{CCName: "AutoVendor", Path: "github.com/hyperledger/fabric/test/chaincodes/AutoVendor/chaincode", File: "/src/github.com/hyperledger/fabric/test/chaincodes/AutoVendor/chaincode/main.go", Mode: 0100400, SuccessExpected: true, RealGen: true}) 264 specs = append(specs, spec{CCName: "mapBadPath", Path: "github.com/hyperledger/fabric/examples/chaincode/go/map", File: "/src/github.com/hyperledger/fabric/examples/bad/path/to/map.go", Mode: 0100400, SuccessExpected: false}) 265 specs = append(specs, spec{CCName: "mapBadMode", Path: "github.com/hyperledger/fabric/examples/chaincode/go/map", File: "/src/github.com/hyperledger/fabric/examples/chaincode/go/map/map.go", Mode: 0100555, SuccessExpected: false}) 266 267 var err error 268 for _, tst := range specs { 269 inputbuf := bytes.NewBuffer(nil) 270 tw := tar.NewWriter(inputbuf) 271 272 var cds *pb.ChaincodeDeploymentSpec 273 if tst.RealGen { 274 cds = &pb.ChaincodeDeploymentSpec{ 275 ChaincodeSpec: &pb.ChaincodeSpec{ 276 ChaincodeId: &pb.ChaincodeID{ 277 Name: tst.CCName, 278 Path: tst.Path, 279 Version: "0", 280 }, 281 }, 282 } 283 cds.CodePackage, err = platform.GetDeploymentPayload(cds.ChaincodeSpec) 284 if err = testerr(err, tst.SuccessExpected); err != nil { 285 t.Errorf("test failed in GetDeploymentPayload: %s, %s", cds.ChaincodeSpec.ChaincodeId.Path, err) 286 } 287 } else { 288 cds, err = generateFakeCDS(tst.CCName, tst.Path, tst.File, tst.Mode) 289 } 290 291 if _, err = platform.GenerateDockerfile(cds); err != nil { 292 t.Errorf("could not generate docker file for a valid spec: %s, %s", cds.ChaincodeSpec.ChaincodeId.Path, err) 293 } 294 err = platform.GenerateDockerBuild(cds, tw) 295 if err = testerr(err, tst.SuccessExpected); err != nil { 296 t.Errorf("Error validating chaincode spec: %s, %s", cds.ChaincodeSpec.ChaincodeId.Path, err) 297 } 298 } 299 } 300 301 func TestMain(m *testing.M) { 302 viper.SetConfigName("core") 303 viper.SetEnvPrefix("CORE") 304 config.AddDevConfigPath(nil) 305 viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 306 viper.AutomaticEnv() 307 if err := viper.ReadInConfig(); err != nil { 308 fmt.Printf("could not read config %s\n", err) 309 os.Exit(-1) 310 } 311 os.Exit(m.Run()) 312 }