mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Migrate some copy tests to integration
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
600475715e
commit
00d409f03e
4 changed files with 66 additions and 195 deletions
|
@ -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.
|
||||
|
@ -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})
|
||||
|
|
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
|
65
integration/container/copy_test.go
Normal file
65
integration/container/copy_test.go
Normal file
|
@ -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")
|
||||
}
|
Loading…
Reference in a new issue