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