github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/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, 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, 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, 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, nil) 140 testerr(t, err, false) 141 startErr = false 142 143 // Success cases 144 err = dvm.Start(ctx, ccid, args, env, bldr, nil) 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, 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, 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, nil) 163 testerr(t, err, true) 164 removeErr = false 165 166 err = dvm.Start(ctx, ccid, args, env, nil, nil) 167 testerr(t, err, true) 168 169 //test preLaunchFunc works correctly 170 preLaunchStr := "notset" 171 preLaunchFunc := func() error { 172 preLaunchStr = "set" 173 return nil 174 } 175 176 err = dvm.Start(ctx, ccid, args, env, nil, preLaunchFunc) 177 testerr(t, err, true) 178 assert.Equal(t, preLaunchStr, "set") 179 180 preLaunchFunc = func() error { 181 return fmt.Errorf("testing error path") 182 } 183 184 err = dvm.Start(ctx, ccid, args, env, nil, preLaunchFunc) 185 testerr(t, err, false) 186 } 187 188 func Test_Stop(t *testing.T) { 189 dvm := DockerVM{} 190 ccid := ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}} 191 ctx := context.Background() 192 193 // Failure case: getMockClient returns error 194 getClientErr = true 195 dvm.getClientFnc = getMockClient 196 err := dvm.Stop(ctx, ccid, 10, true, true) 197 testerr(t, err, false) 198 getClientErr = false 199 200 // Success case 201 err = dvm.Stop(ctx, ccid, 10, true, true) 202 testerr(t, err, true) 203 } 204 205 func Test_Destroy(t *testing.T) { 206 dvm := DockerVM{} 207 ccid := ccintf.CCID{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "simple"}}} 208 ctx := context.Background() 209 210 // Failure cases 211 // Case 1: getMockClient returns error 212 getClientErr = true 213 dvm.getClientFnc = getMockClient 214 err := dvm.Destroy(ctx, ccid, true, true) 215 testerr(t, err, false) 216 getClientErr = false 217 218 // Case 2: dockerClient.RemoveImageExtended returns error 219 removeImgErr = true 220 err = dvm.Destroy(ctx, ccid, true, true) 221 testerr(t, err, false) 222 removeImgErr = false 223 224 // Success case 225 err = dvm.Destroy(ctx, ccid, true, true) 226 testerr(t, err, true) 227 } 228 229 func getCodeChainBytesInMem() io.Reader { 230 startTime := time.Now() 231 inputbuf := bytes.NewBuffer(nil) 232 gw := gzip.NewWriter(inputbuf) 233 tr := tar.NewWriter(gw) 234 dockerFileContents := []byte("FROM busybox:latest\n\nCMD echo hello") 235 dockerFileSize := int64(len([]byte(dockerFileContents))) 236 237 tr.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, 238 ModTime: startTime, AccessTime: startTime, ChangeTime: startTime}) 239 tr.Write([]byte(dockerFileContents)) 240 tr.Close() 241 gw.Close() 242 return inputbuf 243 } 244 245 func testerr(t *testing.T, err error, succ bool) { 246 if succ { 247 assert.NoError(t, err, "Expected success but got error") 248 } else { 249 assert.Error(t, err, "Expected failure but succeeded") 250 } 251 } 252 253 func getMockClient() (dockerClient, error) { 254 if getClientErr { 255 return nil, errors.New("Failed to get client") 256 } 257 return &mockClient{noSuchImgErrReturned: false}, nil 258 } 259 260 type mockClient struct { 261 noSuchImgErrReturned bool 262 } 263 264 var getClientErr, createErr, noSuchImgErr, buildErr, removeImgErr, 265 startErr, stopErr, killErr, removeErr bool 266 267 func (c *mockClient) CreateContainer(options docker.CreateContainerOptions) (*docker.Container, error) { 268 if createErr { 269 return nil, errors.New("Error creating the container") 270 } else if noSuchImgErr && !c.noSuchImgErrReturned { 271 c.noSuchImgErrReturned = true 272 return nil, docker.ErrNoSuchImage 273 } 274 return &docker.Container{}, nil 275 } 276 277 func (c *mockClient) StartContainer(id string, cfg *docker.HostConfig) error { 278 if startErr { 279 return errors.New("Error starting the container") 280 } 281 return nil 282 } 283 284 func (c *mockClient) AttachToContainer(opts docker.AttachToContainerOptions) error { 285 if opts.Success != nil { 286 opts.Success <- struct{}{} 287 } 288 return nil 289 } 290 291 func (c *mockClient) BuildImage(opts docker.BuildImageOptions) error { 292 if buildErr { 293 return errors.New("Error building image") 294 } 295 return nil 296 } 297 298 func (c *mockClient) RemoveImageExtended(id string, opts docker.RemoveImageOptions) error { 299 if removeImgErr { 300 return errors.New("Error removing extended image") 301 } 302 return nil 303 } 304 305 func (c *mockClient) StopContainer(id string, timeout uint) error { 306 if stopErr { 307 return errors.New("Error stopping container") 308 } 309 return nil 310 } 311 312 func (c *mockClient) KillContainer(opts docker.KillContainerOptions) error { 313 if killErr { 314 return errors.New("Error killing container") 315 } 316 return nil 317 } 318 319 func (c *mockClient) RemoveContainer(opts docker.RemoveContainerOptions) error { 320 if removeErr { 321 return errors.New("Error removing container") 322 } 323 return nil 324 }