106 lines
3.0 KiB
Go
106 lines
3.0 KiB
Go
package daemon
|
|
|
|
import (
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
|
|
cerrdefs "github.com/containerd/errdefs"
|
|
"github.com/moby/moby/api/types/checkpoint"
|
|
"github.com/moby/moby/v2/daemon/container"
|
|
"github.com/moby/moby/v2/daemon/server/backend"
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
)
|
|
|
|
func TestValidateCheckpointID(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
checkpointID string
|
|
valid bool
|
|
}
|
|
tests := []testCase{
|
|
{name: "restricted name", checkpointID: "a1", valid: true},
|
|
{name: "space", checkpointID: "space name"},
|
|
{name: "unicode", checkpointID: "unicode-世界"},
|
|
{name: "dots", checkpointID: "name.with-dots", valid: true},
|
|
{name: "empty", checkpointID: ""},
|
|
{name: "dot", checkpointID: "."},
|
|
{name: "dot-dot", checkpointID: ".."},
|
|
{name: "traversal", checkpointID: "../outside"},
|
|
{name: "nested traversal", checkpointID: "foo/../outside"},
|
|
{name: "separator", checkpointID: "foo/bar"},
|
|
{name: "windows separator", checkpointID: `foo\bar`},
|
|
{name: "NUL", checkpointID: "contains\x00nul"},
|
|
{name: "absolute path", checkpointID: filepath.Join(string(filepath.Separator), "absolute")},
|
|
}
|
|
if runtime.GOOS == "windows" {
|
|
tests = append(tests,
|
|
testCase{name: "dot trailing space", checkpointID: ". "},
|
|
testCase{name: "dot-dot trailing space", checkpointID: ".. "},
|
|
testCase{name: "trailing dot", checkpointID: "name."},
|
|
testCase{name: "trailing space", checkpointID: "name "},
|
|
)
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := validateCheckpointID(tc.checkpointID)
|
|
if tc.valid {
|
|
assert.NilError(t, err)
|
|
return
|
|
}
|
|
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckpointOperationsValidateBeforeContainerLookup(t *testing.T) {
|
|
daemon := &Daemon{}
|
|
tests := []struct {
|
|
name string
|
|
operation func() error
|
|
}{
|
|
{
|
|
name: "create",
|
|
operation: func() error {
|
|
return daemon.CheckpointCreate("missing", checkpoint.CreateRequest{CheckpointID: "../outside"})
|
|
},
|
|
},
|
|
{
|
|
name: "delete",
|
|
operation: func() error {
|
|
return daemon.CheckpointDelete("missing", backend.CheckpointDeleteOptions{CheckpointID: "../outside"})
|
|
},
|
|
},
|
|
{
|
|
name: "restore",
|
|
operation: func() error {
|
|
return daemon.ContainerStart(t.Context(), "missing", "../outside", "")
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := tc.operation()
|
|
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
|
|
assert.Check(t, is.ErrorContains(err, `invalid checkpoint ID "../outside"`))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckpointListMissingDefaultDirectory(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
root := t.TempDir()
|
|
ctr := container.NewBaseContainer("container-id", root)
|
|
store := container.NewMemoryStore()
|
|
store.Add(ctr.ID, ctr)
|
|
daemon := &Daemon{containers: store}
|
|
|
|
checkpoints, err := daemon.CheckpointList(ctr.ID, backend.CheckpointListOptions{})
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, is.Len(checkpoints, 0))
|
|
}
|