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  }