Skip to content

Commit

Permalink
Migrate some copy tests to integration
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Nephin <[email protected]>
  • Loading branch information
dnephin committed Feb 27, 2018
1 parent 6004757 commit 00d409f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 195 deletions.
62 changes: 1 addition & 61 deletions integration-cli/docker_cli_cp_from_container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
"github.com/go-check/check"
)

// docker cp CONTAINER:PATH LOCALPATH

// Try all of the test cases from the archive package which implements the
// internals of `docker cp` and ensure that the behavior matches when actually
// copying to and from containers.
Expand All @@ -20,67 +18,9 @@ import (
// 3. DST parent directory must exist.
// 4. If DST exists as a file, it must not end with a trailing separator.

// First get these easy error cases out of the way.

// Test for error when SRC does not exist.
func (s *DockerSuite) TestCpFromErrSrcNotExists(c *check.C) {
containerID := makeTestContainer(c, testContainerOptions{})

tmpDir := getTestDir(c, "test-cp-from-err-src-not-exists")
defer os.RemoveAll(tmpDir)

err := runDockerCp(c, containerCpPath(containerID, "file1"), tmpDir, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
}

// Test for error when SRC ends in a trailing
// path separator but it exists as a file.
func (s *DockerSuite) TestCpFromErrSrcNotDir(c *check.C) {
testRequires(c, DaemonIsLinux)
containerID := makeTestContainer(c, testContainerOptions{addContent: true})

tmpDir := getTestDir(c, "test-cp-from-err-src-not-dir")
defer os.RemoveAll(tmpDir)

err := runDockerCp(c, containerCpPathTrailingSep(containerID, "file1"), tmpDir, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
}

// Test for error when DST ends in a trailing
// path separator but exists as a file.
func (s *DockerSuite) TestCpFromErrDstNotDir(c *check.C) {
testRequires(c, DaemonIsLinux)
containerID := makeTestContainer(c, testContainerOptions{addContent: true})

tmpDir := getTestDir(c, "test-cp-from-err-dst-not-dir")
defer os.RemoveAll(tmpDir)

makeTestContentInDir(c, tmpDir)

// Try with a file source.
srcPath := containerCpPath(containerID, "/file1")
dstPath := cpPathTrailingSep(tmpDir, "file1")

err := runDockerCp(c, srcPath, dstPath, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))

// Try with a directory source.
srcPath = containerCpPath(containerID, "/dir1")

err = runDockerCp(c, srcPath, dstPath, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
}

// Check that copying from a container to a local symlink copies to the symlink
// target and does not overwrite the local symlink itself.
// TODO: move to docker/cli and/or integration/container/copy_test.go
func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) {
testRequires(c, DaemonIsLinux)
containerID := makeTestContainer(c, testContainerOptions{addContent: true})
Expand Down
122 changes: 0 additions & 122 deletions integration-cli/docker_cli_cp_to_container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ package main

import (
"os"
"runtime"
"strings"

"github.com/docker/docker/integration-cli/checker"
"github.com/go-check/check"
)

// docker cp LOCALPATH CONTAINER:PATH

// Try all of the test cases from the archive package which implements the
// internals of `docker cp` and ensure that the behavior matches when actually
// copying to and from containers.
Expand All @@ -21,124 +17,6 @@ import (
// 3. DST parent directory must exist.
// 4. If DST exists as a file, it must not end with a trailing separator.

// First get these easy error cases out of the way.

// Test for error when SRC does not exist.
func (s *DockerSuite) TestCpToErrSrcNotExists(c *check.C) {
containerID := makeTestContainer(c, testContainerOptions{})

tmpDir := getTestDir(c, "test-cp-to-err-src-not-exists")
defer os.RemoveAll(tmpDir)

srcPath := cpPath(tmpDir, "file1")
dstPath := containerCpPath(containerID, "file1")
_, srcStatErr := os.Stat(srcPath)
c.Assert(os.IsNotExist(srcStatErr), checker.True)

err := runDockerCp(c, srcPath, dstPath, nil)
if runtime.GOOS == "windows" {
// Go 1.9+ on Windows returns a different error for `os.Stat()`, see
// https://github.com/golang/go/commit/6144c7270e5812d9de8fb97456ee4e5ae657fcbb#diff-f63e1a4b4377b2fe0b05011db3df9599
//
// Go 1.8: CreateFile C:\not-exist: The system cannot find the file specified.
// Go 1.9: GetFileAttributesEx C:\not-exist: The system cannot find the file specified.
//
// Due to the CLI using a different version than the daemon, comparing the
// error message won't work, so just hard-code the common part here.
//
// TODO this should probably be a test in the CLI repository instead
c.Assert(strings.ToLower(err.Error()), checker.Contains, "cannot find the file specified")
c.Assert(strings.ToLower(err.Error()), checker.Contains, strings.ToLower(tmpDir))
} else {
c.Assert(strings.ToLower(err.Error()), checker.Contains, strings.ToLower(srcStatErr.Error()))
}
}

// Test for error when SRC ends in a trailing
// path separator but it exists as a file.
func (s *DockerSuite) TestCpToErrSrcNotDir(c *check.C) {
containerID := makeTestContainer(c, testContainerOptions{})

tmpDir := getTestDir(c, "test-cp-to-err-src-not-dir")
defer os.RemoveAll(tmpDir)

makeTestContentInDir(c, tmpDir)

srcPath := cpPathTrailingSep(tmpDir, "file1")
dstPath := containerCpPath(containerID, "testDir")

err := runDockerCp(c, srcPath, dstPath, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
}

// Test for error when SRC is a valid file or directory,
// but the DST parent directory does not exist.
func (s *DockerSuite) TestCpToErrDstParentNotExists(c *check.C) {
testRequires(c, DaemonIsLinux)
containerID := makeTestContainer(c, testContainerOptions{addContent: true})

tmpDir := getTestDir(c, "test-cp-to-err-dst-parent-not-exists")
defer os.RemoveAll(tmpDir)

makeTestContentInDir(c, tmpDir)

// Try with a file source.
srcPath := cpPath(tmpDir, "file1")
dstPath := containerCpPath(containerID, "/notExists", "file1")

err := runDockerCp(c, srcPath, dstPath, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))

// Try with a directory source.
srcPath = cpPath(tmpDir, "dir1")

err = runDockerCp(c, srcPath, dstPath, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
}

// Test for error when DST ends in a trailing path separator but exists as a
// file. Also test that we cannot overwrite an existing directory with a
// non-directory and cannot overwrite an existing
func (s *DockerSuite) TestCpToErrDstNotDir(c *check.C) {
testRequires(c, DaemonIsLinux)
containerID := makeTestContainer(c, testContainerOptions{addContent: true})

tmpDir := getTestDir(c, "test-cp-to-err-dst-not-dir")
defer os.RemoveAll(tmpDir)

makeTestContentInDir(c, tmpDir)

// Try with a file source.
srcPath := cpPath(tmpDir, "dir1/file1-1")
dstPath := containerCpPathTrailingSep(containerID, "file1")

// The client should encounter an error trying to stat the destination
// and then be unable to copy since the destination is asserted to be a
// directory but does not exist.
err := runDockerCp(c, srcPath, dstPath, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExist error, but got %T: %s", err, err))

// Try with a directory source.
srcPath = cpPath(tmpDir, "dir1")

// The client should encounter an error trying to stat the destination and
// then decide to extract to the parent directory instead with a rebased
// name in the source archive, but this directory would overwrite the
// existing file with the same name.
err = runDockerCp(c, srcPath, dstPath, nil)
c.Assert(err, checker.NotNil)

c.Assert(isCannotOverwriteNonDirWithDir(err), checker.True, check.Commentf("expected CannotOverwriteNonDirWithDir error, but got %T: %s", err, err))
}

// Check that copying from a local path to a symlink in a container copies to
// the symlink target and does not overwrite the container symlink itself.
func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
Expand Down
12 changes: 0 additions & 12 deletions integration-cli/docker_cli_cp_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,18 +228,10 @@ func getTestDir(c *check.C, label string) (tmpDir string) {
return
}

func isCpNotExist(err error) bool {
return strings.Contains(strings.ToLower(err.Error()), "could not find the file")
}

func isCpDirNotExist(err error) bool {
return strings.Contains(err.Error(), archive.ErrDirNotExists.Error())
}

func isCpNotDir(err error) bool {
return strings.Contains(err.Error(), archive.ErrNotDirectory.Error()) || strings.Contains(err.Error(), "filename, directory name, or volume label syntax is incorrect")
}

func isCpCannotCopyDir(err error) bool {
return strings.Contains(err.Error(), archive.ErrCannotCopyDir.Error())
}
Expand All @@ -248,10 +240,6 @@ func isCpCannotCopyReadOnly(err error) bool {
return strings.Contains(err.Error(), "marked read-only")
}

func isCannotOverwriteNonDirWithDir(err error) bool {
return strings.Contains(err.Error(), "cannot overwrite non-directory")
}

func fileContentEquals(c *check.C, filename, contents string) (err error) {
c.Logf("checking that file %q contains %q\n", filename, contents)

Expand Down
65 changes: 65 additions & 0 deletions integration/container/copy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package container // import "github.com/docker/docker/integration/container"

import (
"context"
"fmt"
"testing"

"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/internal/testutil"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/require"
)

func TestCopyFromContainerPathDoesNotExist(t *testing.T) {
defer setupTest(t)()

ctx := context.Background()
apiclient := testEnv.APIClient()
cid := container.Create(t, ctx, apiclient)

_, _, err := apiclient.CopyFromContainer(ctx, cid, "/dne")
require.True(t, client.IsErrNotFound(err))
expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne")
testutil.ErrorContains(t, err, expected)
}

func TestCopyFromContainerPathIsNotDir(t *testing.T) {
defer setupTest(t)()
skip.If(t, testEnv.OSType == "windows")

ctx := context.Background()
apiclient := testEnv.APIClient()
cid := container.Create(t, ctx, apiclient)

_, _, err := apiclient.CopyFromContainer(ctx, cid, "/etc/passwd/")
require.Contains(t, err.Error(), "not a directory")
}

func TestCopyToContainerPathDoesNotExist(t *testing.T) {
defer setupTest(t)()
skip.If(t, testEnv.OSType == "windows")

ctx := context.Background()
apiclient := testEnv.APIClient()
cid := container.Create(t, ctx, apiclient)

err := apiclient.CopyToContainer(ctx, cid, "/dne", nil, types.CopyToContainerOptions{})
require.True(t, client.IsErrNotFound(err))
expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne")
testutil.ErrorContains(t, err, expected)
}

func TestCopyToContainerPathIsNotDir(t *testing.T) {
defer setupTest(t)()
skip.If(t, testEnv.OSType == "windows")

ctx := context.Background()
apiclient := testEnv.APIClient()
cid := container.Create(t, ctx, apiclient)

err := apiclient.CopyToContainer(ctx, cid, "/etc/passwd/", nil, types.CopyToContainerOptions{})
require.Contains(t, err.Error(), "not a directory")
}

0 comments on commit 00d409f

Please sign in to comment.