github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/core/container/controller_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 container
    18  
    19  import (
    20  	"archive/tar"
    21  	"bytes"
    22  	"compress/gzip"
    23  	"fmt"
    24  	"io"
    25  	"io/ioutil"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/hyperledger/fabric/core/container/ccintf"
    30  	"github.com/hyperledger/fabric/core/container/dockercontroller"
    31  	"github.com/hyperledger/fabric/core/container/inproccontroller"
    32  	pb "github.com/hyperledger/fabric/protos/peer"
    33  	"github.com/stretchr/testify/assert"
    34  	"golang.org/x/net/context"
    35  )
    36  
    37  /**** not using actual files from file system for testing.... use these funcs if we want to do that
    38  func getCodeChainBytes(pathtocodechain string) (io.Reader, error) {
    39  	inputbuf := bytes.NewBuffer(nil)
    40  	gw := gzip.NewWriter(inputbuf)
    41  	tr := tar.NewWriter(gw)
    42  	// Get the Tar contents for the image
    43  	err := writeCodeChainTar(pathtocodechain, tr)
    44  	tr.Close()
    45  	gw.Close()
    46  	if err != nil {
    47  		return nil, errors.New(fmt.Sprintf("Error getting codechain tar: %s", err))
    48  	}
    49          ioutil.WriteFile("/tmp/chaincode.tar", inputbuf.Bytes(), 0644)
    50  	return inputbuf, nil
    51  }
    52  
    53  func writeCodeChainTar(pathtocodechain string, tw *tar.Writer) error {
    54  	root_directory := pathtocodechain //use full path
    55  	fmt.Printf("tar %s start(%s)\n", root_directory, time.Now())
    56  
    57  	walkFn := func(path string, info os.FileInfo, err error) error {
    58  	        fmt.Printf("path %s(%s)\n", path, info.Name())
    59                  if info == nil {
    60  	             return errors.New(fmt.Sprintf("Error walking the path: %s", path))
    61                  }
    62  
    63  		if info.Mode().IsDir() {
    64  			return nil
    65  		}
    66  		// Because of scoping we can reference the external root_directory variable
    67  		//new_path := fmt.Sprintf("%s", path[len(root_directory):])
    68  		new_path := info.Name()
    69  
    70  		if len(new_path) == 0 {
    71  			return nil
    72  		}
    73  
    74  		fr, err := os.Open(path)
    75  		if err != nil {
    76  			return err
    77  		}
    78  		defer fr.Close()
    79  
    80  		if h, err := tar.FileInfoHeader(info, new_path); err != nil {
    81  			fmt.Printf(fmt.Sprintf("Error getting FileInfoHeader: %s\n", err))
    82  			return err
    83  		} else {
    84  			h.Name = new_path
    85  			if err = tw.WriteHeader(h); err != nil {
    86  				fmt.Printf(fmt.Sprintf("Error writing header: %s\n", err))
    87  				return err
    88  			}
    89  		}
    90  		if length, err := io.Copy(tw, fr); err != nil {
    91  			return err
    92  		} else {
    93  			fmt.Printf("Length of entry = %d\n", length)
    94  		}
    95  		return nil
    96  	}
    97  
    98  	if err := filepath.Walk(root_directory, walkFn); err != nil {
    99  		fmt.Printf("Error walking root_directory: %s\n", err)
   100  		return err
   101  	} else {
   102  		// Write the tar file out
   103  		if err := tw.Close(); err != nil {
   104                      return err
   105  		}
   106  	}
   107  	fmt.Printf("tar end = %s\n", time.Now())
   108  	return nil
   109  }
   110  *********************/
   111  
   112  func getCodeChainBytesInMem() (io.Reader, error) {
   113  	startTime := time.Now()
   114  	inputbuf := bytes.NewBuffer(nil)
   115  	gw := gzip.NewWriter(inputbuf)
   116  	tr := tar.NewWriter(gw)
   117  	dockerFileContents := []byte("FROM busybox:latest\n\nCMD echo hello")
   118  	dockerFileSize := int64(len([]byte(dockerFileContents)))
   119  
   120  	tr.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: startTime, AccessTime: startTime, ChangeTime: startTime})
   121  	tr.Write([]byte(dockerFileContents))
   122  	tr.Close()
   123  	gw.Close()
   124  	ioutil.WriteFile("/tmp/chaincode.tar", inputbuf.Bytes(), 0644)
   125  	return inputbuf, nil
   126  }
   127  
   128  //set to true by providing "-run-controller-tests" command line option... Tests will create a docker image called "simple"
   129  var runTests bool
   130  
   131  func testForSkip(t *testing.T) {
   132  	//run tests
   133  	if !runTests {
   134  		t.SkipNow()
   135  	}
   136  }
   137  
   138  func TestVMCBuildImage(t *testing.T) {
   139  	testForSkip(t)
   140  	var ctxt = context.Background()
   141  
   142  	//get the tarball for codechain
   143  	tarRdr, err := getCodeChainBytesInMem()
   144  	if err != nil {
   145  		t.Fail()
   146  		t.Logf("Error reading tar file: %s", err)
   147  		return
   148  	}
   149  
   150  	c := make(chan struct{})
   151  
   152  	//creat a CreateImageReq obj and send it to VMCProcess
   153  	go func() {
   154  		defer close(c)
   155  		cir := CreateImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}, Reader: tarRdr}
   156  		_, err := VMCProcess(ctxt, "Docker", cir)
   157  		if err != nil {
   158  			t.Fail()
   159  			t.Logf("Error creating image: %s", err)
   160  			return
   161  		}
   162  	}()
   163  
   164  	//wait for VMController to complete.
   165  	fmt.Println("VMCBuildImage-waiting for response")
   166  	<-c
   167  }
   168  
   169  func TestVMCStartContainer(t *testing.T) {
   170  	testForSkip(t)
   171  
   172  	var ctxt = context.Background()
   173  
   174  	c := make(chan struct{})
   175  
   176  	//create a StartImageReq obj and send it to VMCProcess
   177  	go func() {
   178  		defer close(c)
   179  		sir := StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}}
   180  		_, err := VMCProcess(ctxt, "Docker", sir)
   181  		if err != nil {
   182  			t.Fail()
   183  			t.Logf("Error starting container: %s", err)
   184  			return
   185  		}
   186  	}()
   187  
   188  	//wait for VMController to complete.
   189  	fmt.Println("VMCStartContainer-waiting for response")
   190  	<-c
   191  	stopr := StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}, Timeout: 0, Dontremove: true}
   192  	VMCProcess(ctxt, "Docker", stopr)
   193  }
   194  
   195  func TestVMCCreateAndStartContainer(t *testing.T) {
   196  	testForSkip(t)
   197  
   198  	var ctxt = context.Background()
   199  
   200  	c := make(chan struct{})
   201  
   202  	//create a StartImageReq obj and send it to VMCProcess
   203  	go func() {
   204  		defer close(c)
   205  
   206  		//stop and delete the container first (if it exists)
   207  		stopir := StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}, Timeout: 0}
   208  		VMCProcess(ctxt, "Docker", stopir)
   209  
   210  		startir := StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}}
   211  		r, err := VMCProcess(ctxt, "Docker", startir)
   212  		if err != nil {
   213  			t.Fail()
   214  			t.Logf("Error starting container: %s", err)
   215  			return
   216  		}
   217  		vmcresp, ok := r.(VMCResp)
   218  		if !ok {
   219  			t.Fatalf("invalid response from VMCProcess")
   220  		}
   221  		if vmcresp.Err != nil {
   222  			t.Fail()
   223  			t.Logf("docker error starting container: %s", vmcresp.Err)
   224  			return
   225  		}
   226  	}()
   227  
   228  	//wait for VMController to complete.
   229  	fmt.Println("VMCStartContainer-waiting for response")
   230  	<-c
   231  	//stopr := StopImageReq{ID: "simple", Timeout: 0, Dontremove: true}
   232  	//VMCProcess(ctxt, "Docker", stopr)
   233  }
   234  
   235  func TestVMCSyncStartContainer(t *testing.T) {
   236  	testForSkip(t)
   237  
   238  	var ctxt = context.Background()
   239  
   240  	//creat a StartImageReq obj and send it to VMCProcess
   241  	sir := StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}}
   242  	_, err := VMCProcess(ctxt, "Docker", sir)
   243  	if err != nil {
   244  		t.Fail()
   245  		t.Logf("Error starting container: %s", err)
   246  		return
   247  	}
   248  	stopr := StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}, Timeout: 0, Dontremove: true}
   249  	VMCProcess(ctxt, "Docker", stopr)
   250  }
   251  
   252  func TestVMCStopContainer(t *testing.T) {
   253  	testForSkip(t)
   254  
   255  	var ctxt = context.Background()
   256  
   257  	c := make(chan struct{})
   258  
   259  	//creat a StopImageReq obj and send it to VMCProcess
   260  	go func() {
   261  		defer close(c)
   262  		sir := StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}}, Timeout: 0}
   263  		_, err := VMCProcess(ctxt, "Docker", sir)
   264  		if err != nil {
   265  			t.Fail()
   266  			t.Logf("Error stopping container: %s", err)
   267  			return
   268  		}
   269  	}()
   270  
   271  	//wait for VMController to complete.
   272  	fmt.Println("VMCStopContainer-waiting for response")
   273  	<-c
   274  }
   275  
   276  func TestNewVM(t *testing.T) {
   277  	vm := vmcontroller.newVM("Docker")
   278  	dvm := vm.(*dockercontroller.DockerVM)
   279  	assert.NotNil(t, dvm, "Requested Docker VM but newVM did not return dockercontroller.DockerVM")
   280  
   281  	vm = vmcontroller.newVM("System")
   282  	ivm := vm.(*inproccontroller.InprocVM)
   283  	assert.NotNil(t, ivm, "Requested System VM but newVM did not return inproccontroller.InprocVM")
   284  
   285  	vm = vmcontroller.newVM("")
   286  	dvm = vm.(*dockercontroller.DockerVM)
   287  	assert.NotNil(t, dvm, "Requested default VM but newVM did not return dockercontroller.DockerVM")
   288  }