github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/container/dockercontroller/dockercontroller_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 dockercontroller 18 19 import ( 20 "archive/tar" 21 "bytes" 22 "compress/gzip" 23 "context" 24 "errors" 25 "fmt" 26 "io" 27 "os" 28 "testing" 29 "time" 30 31 "github.com/fsouza/go-dockerclient" 32 "github.com/spf13/viper" 33 "github.com/stretchr/testify/assert" 34 35 "github.com/hyperledger/fabric/common/ledger/testutil" 36 "github.com/hyperledger/fabric/common/util" 37 "github.com/hyperledger/fabric/core/chaincode/platforms" 38 "github.com/hyperledger/fabric/core/container/ccintf" 39 coreutil "github.com/hyperledger/fabric/core/testutil" 40 pb "github.com/hyperledger/fabric/protos/peer" 41 ) 42 43 func TestHostConfig(t *testing.T) { 44 coreutil.SetupTestConfig() 45 var hostConfig = new(docker.HostConfig) 46 err := viper.UnmarshalKey("vm.docker.hostConfig", hostConfig) 47 if err != nil { 48 t.Fatalf("Load docker HostConfig wrong, error: %s", err.Error()) 49 } 50 testutil.AssertNotEquals(t, hostConfig.LogConfig, nil) 51 testutil.AssertEquals(t, hostConfig.LogConfig.Type, "json-file") 52 testutil.AssertEquals(t, hostConfig.LogConfig.Config["max-size"], "50m") 53 testutil.AssertEquals(t, hostConfig.LogConfig.Config["max-file"], "5") 54 } 55 56 func TestGetDockerHostConfig(t *testing.T) { 57 os.Setenv("CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE", "overlay") 58 os.Setenv("CORE_VM_DOCKER_HOSTCONFIG_CPUSHARES", fmt.Sprint(1024*1024*1024*2)) 59 coreutil.SetupTestConfig() 60 hostConfig := getDockerHostConfig() 61 testutil.AssertNotNil(t, hostConfig) 62 testutil.AssertEquals(t, hostConfig.NetworkMode, "overlay") 63 testutil.AssertEquals(t, hostConfig.LogConfig.Type, "json-file") 64 testutil.AssertEquals(t, hostConfig.LogConfig.Config["max-size"], "50m") 65 testutil.AssertEquals(t, hostConfig.LogConfig.Config["max-file"], "5") 66 testutil.AssertEquals(t, hostConfig.Memory, int64(1024*1024*1024*2)) 67 testutil.AssertEquals(t, hostConfig.CPUShares, int64(1024*1024*1024*2)) 68 } 69 70 func Test_Deploy(t *testing.T) { 71 dvm := DockerVM{} 72 ccid := ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}} 73 //get the tarball for codechain 74 tarRdr := getCodeChainBytesInMem() 75 args := make([]string, 1) 76 env := make([]string, 1) 77 ctx := context.Background() 78 79 // getMockClient returns error 80 getClientErr = true 81 dvm.getClientFnc = getMockClient 82 err := dvm.Deploy(ctx, ccid, args, env, tarRdr) 83 testerr(t, err, false) 84 getClientErr = false 85 86 // Failure case: dockerClient.BuildImage returns error 87 buildErr = true 88 dvm.getClientFnc = getMockClient 89 err = dvm.Deploy(ctx, ccid, args, env, tarRdr) 90 testerr(t, err, false) 91 buildErr = false 92 93 // Success case 94 err = dvm.Deploy(ctx, ccid, args, env, tarRdr) 95 testerr(t, err, true) 96 } 97 98 func Test_Start(t *testing.T) { 99 dvm := DockerVM{} 100 ccid := ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}} 101 args := make([]string, 1) 102 env := make([]string, 1) 103 ctx := context.Background() 104 105 // Failure cases 106 // case 1: getMockClient returns error 107 dvm.getClientFnc = getMockClient 108 getClientErr = true 109 err := dvm.Start(ctx, ccid, args, env, nil) 110 testerr(t, err, false) 111 getClientErr = false 112 113 // case 2: dockerClient.CreateContainer returns error 114 createErr = true 115 err = dvm.Start(ctx, ccid, args, env, nil) 116 testerr(t, err, false) 117 createErr = false 118 119 // case 3: dockerClient.CreateContainer returns docker.noSuchImgErr 120 noSuchImgErr = true 121 err = dvm.Start(ctx, ccid, args, env, nil) 122 testerr(t, err, false) 123 124 chaincodePath := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01" 125 spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, 126 ChaincodeId: &pb.ChaincodeID{Name: "ex01", Path: chaincodePath}, 127 Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs("f")}} 128 codePackage, err := platforms.GetDeploymentPayload(spec) 129 if err != nil { 130 t.Fatal() 131 } 132 cds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackage} 133 bldr := func() (io.Reader, error) { return platforms.GenerateDockerBuild(cds) } 134 135 // case 4: start called with builder and dockerClient.CreateContainer returns 136 // docker.noSuchImgErr and dockerClient.Start returns error 137 viper.Set("vm.docker.attachStdout", true) 138 startErr = true 139 err = dvm.Start(ctx, ccid, args, env, bldr) 140 testerr(t, err, false) 141 startErr = false 142 143 // Success cases 144 err = dvm.Start(ctx, ccid, args, env, bldr) 145 testerr(t, err, true) 146 noSuchImgErr = false 147 148 // dockerClient.StopContainer returns error 149 stopErr = true 150 err = dvm.Start(ctx, ccid, args, env, nil) 151 testerr(t, err, true) 152 stopErr = false 153 154 // dockerClient.KillContainer returns error 155 killErr = true 156 err = dvm.Start(ctx, ccid, args, env, nil) 157 testerr(t, err, true) 158 killErr = false 159 160 // dockerClient.RemoveContainer returns error 161 removeErr = true 162 err = dvm.Start(ctx, ccid, args, env, nil) 163 testerr(t, err, true) 164 removeErr = false 165 166 err = dvm.Start(ctx, ccid, args, env, nil) 167 testerr(t, err, true) 168 } 169 170 func Test_Stop(t *testing.T) { 171 dvm := DockerVM{} 172 ccid := ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}} 173 ctx := context.Background() 174 175 // Failure case: getMockClient returns error 176 getClientErr = true 177 dvm.getClientFnc = getMockClient 178 err := dvm.Stop(ctx, ccid, 10, true, true) 179 testerr(t, err, false) 180 getClientErr = false 181 182 // Success case 183 err = dvm.Stop(ctx, ccid, 10, true, true) 184 testerr(t, err, true) 185 } 186 187 func Test_Destroy(t *testing.T) { 188 dvm := DockerVM{} 189 ccid := ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}} 190 ctx := context.Background() 191 192 // Failure cases 193 // Case 1: getMockClient returns error 194 getClientErr = true 195 dvm.getClientFnc = getMockClient 196 err := dvm.Destroy(ctx, ccid, true, true) 197 testerr(t, err, false) 198 getClientErr = false 199 200 // Case 2: dockerClient.RemoveImageExtended returns error 201 removeImgErr = true 202 err = dvm.Destroy(ctx, ccid, true, true) 203 testerr(t, err, false) 204 removeImgErr = false 205 206 // Success case 207 err = dvm.Destroy(ctx, ccid, true, true) 208 testerr(t, err, true) 209 } 210 211 func getCodeChainBytesInMem() io.Reader { 212 startTime := time.Now() 213 inputbuf := bytes.NewBuffer(nil) 214 gw := gzip.NewWriter(inputbuf) 215 tr := tar.NewWriter(gw) 216 dockerFileContents := []byte("FROM busybox:latest\n\nCMD echo hello") 217 dockerFileSize := int64(len([]byte(dockerFileContents))) 218 219 tr.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, 220 ModTime: startTime, AccessTime: startTime, ChangeTime: startTime}) 221 tr.Write([]byte(dockerFileContents)) 222 tr.Close() 223 gw.Close() 224 return inputbuf 225 } 226 227 func testerr(t *testing.T, err error, succ bool) { 228 if succ { 229 assert.NoError(t, err, "Expected success but got error") 230 } else { 231 assert.Error(t, err, "Expected failure but succeeded") 232 } 233 } 234 235 func getMockClient() (dockerClient, error) { 236 if getClientErr { 237 return nil, errors.New("Failed to get client") 238 } 239 return &mockClient{noSuchImgErrReturned: false}, nil 240 } 241 242 type mockClient struct { 243 noSuchImgErrReturned bool 244 } 245 246 var getClientErr, createErr, noSuchImgErr, buildErr, removeImgErr, 247 startErr, stopErr, killErr, removeErr bool 248 249 func (c *mockClient) CreateContainer(options docker.CreateContainerOptions) (*docker.Container, error) { 250 if createErr { 251 return nil, errors.New("Error creating the container") 252 } else if noSuchImgErr && !c.noSuchImgErrReturned { 253 c.noSuchImgErrReturned = true 254 return nil, docker.ErrNoSuchImage 255 } 256 return &docker.Container{}, nil 257 } 258 259 func (c *mockClient) StartContainer(id string, cfg *docker.HostConfig) error { 260 if startErr { 261 return errors.New("Error starting the container") 262 } 263 return nil 264 } 265 266 func (c *mockClient) AttachToContainer(opts docker.AttachToContainerOptions) error { 267 if opts.Success != nil { 268 opts.Success <- struct{}{} 269 } 270 return nil 271 } 272 273 func (c *mockClient) BuildImage(opts docker.BuildImageOptions) error { 274 if buildErr { 275 return errors.New("Error building image") 276 } 277 return nil 278 } 279 280 func (c *mockClient) RemoveImageExtended(id string, opts docker.RemoveImageOptions) error { 281 if removeImgErr { 282 return errors.New("Error removing extended image") 283 } 284 return nil 285 } 286 287 func (c *mockClient) StopContainer(id string, timeout uint) error { 288 if stopErr { 289 return errors.New("Error stopping container") 290 } 291 return nil 292 } 293 294 func (c *mockClient) KillContainer(opts docker.KillContainerOptions) error { 295 if killErr { 296 return errors.New("Error killing container") 297 } 298 return nil 299 } 300 301 func (c *mockClient) RemoveContainer(opts docker.RemoveContainerOptions) error { 302 if removeErr { 303 return errors.New("Error removing container") 304 } 305 return nil 306 }