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 }