summaryrefslogtreecommitdiffhomepage
path: root/runsc/container
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/container')
-rw-r--r--runsc/container/BUILD9
-rw-r--r--runsc/container/container_test.go172
2 files changed, 39 insertions, 142 deletions
diff --git a/runsc/container/BUILD b/runsc/container/BUILD
index c558b4b0a..fe477abf2 100644
--- a/runsc/container/BUILD
+++ b/runsc/container/BUILD
@@ -27,18 +27,17 @@ go_test(
name = "container_test",
size = "small",
srcs = ["container_test.go"],
- pure = "on",
- rundir = ".",
+ data = [
+ "//runsc",
+ ],
deps = [
"//pkg/abi/linux",
"//pkg/log",
"//pkg/sentry/control",
"//pkg/sentry/kernel/auth",
"//pkg/unet",
- "//runsc/boot",
- "//runsc/cmd",
"//runsc/container",
- "@com_github_google_subcommands//:go_default_library",
+ "//runsc/test/testutil",
"@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go
index 24e9de3ce..0844cb9df 100644
--- a/runsc/container/container_test.go
+++ b/runsc/container/container_test.go
@@ -15,7 +15,6 @@
package container_test
import (
- "encoding/json"
"fmt"
"io"
"io/ioutil"
@@ -29,9 +28,6 @@ import (
"testing"
"time"
- "context"
- "flag"
- "github.com/google/subcommands"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
@@ -39,80 +35,15 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/control"
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/auth"
"gvisor.googlesource.com/gvisor/pkg/unet"
- "gvisor.googlesource.com/gvisor/runsc/boot"
- "gvisor.googlesource.com/gvisor/runsc/cmd"
"gvisor.googlesource.com/gvisor/runsc/container"
+ "gvisor.googlesource.com/gvisor/runsc/test/testutil"
)
func init() {
log.SetLevel(log.Debug)
-}
-
-// writeSpec writes the spec to disk in the given directory.
-func writeSpec(dir string, spec *specs.Spec) error {
- b, err := json.Marshal(spec)
- if err != nil {
- return err
- }
- return ioutil.WriteFile(filepath.Join(dir, "config.json"), b, 0755)
-}
-
-// newSpecWithArgs creates a simple spec with the given args suitable for use
-// in tests.
-func newSpecWithArgs(args ...string) *specs.Spec {
- spec := &specs.Spec{
- // The host filesystem root is the container root.
- Root: &specs.Root{
- Path: "/",
- Readonly: true,
- },
- Process: &specs.Process{
- Args: args,
- Env: []string{
- "PATH=" + os.Getenv("PATH"),
- },
- },
- }
- return spec
-}
-
-// setupContainer creates a bundle and root dir for the container, generates a
-// test config, and writes the spec to config.json in the bundle dir.
-func setupContainer(spec *specs.Spec) (rootDir, bundleDir string, conf *boot.Config, err error) {
- rootDir, err = ioutil.TempDir("", "containers")
- if err != nil {
- return "", "", nil, fmt.Errorf("error creating root dir: %v", err)
- }
-
- bundleDir, err = ioutil.TempDir("", "bundle")
- if err != nil {
- return "", "", nil, fmt.Errorf("error creating bundle dir: %v", err)
- }
-
- if err = writeSpec(bundleDir, spec); err != nil {
- return "", "", nil, fmt.Errorf("error writing spec: %v", err)
+ if err := testutil.ConfigureExePath(); err != nil {
+ panic(err.Error())
}
-
- conf = &boot.Config{
- RootDir: rootDir,
- Network: boot.NetworkNone,
- // Don't add flags when calling subprocesses, since the test
- // runner does not know about all the flags. We control the
- // Config in the subprocess anyways, so it does not matter.
- TestModeNoFlags: true,
- }
-
- return rootDir, bundleDir, conf, nil
-}
-
-// uniqueContainerID generates a unique container id for each test.
-//
-// The container id is used to create an abstract unix domain socket, which must
-// be unique. While the container forbids creating two containers with the same
-// name, sometimes between test runs the socket does not get cleaned up quickly
-// enough, causing container creation to fail.
-func uniqueContainerID() string {
- return fmt.Sprintf("test-container-%d", time.Now().UnixNano())
}
// waitForProcessList waits for the given process list to show up in the container.
@@ -167,9 +98,9 @@ func procListToString(pl []*control.Process) string {
func TestLifecycle(t *testing.T) {
// The container will just sleep for a long time. We will kill it before
// it finishes sleeping.
- spec := newSpecWithArgs("sleep", "100")
+ spec := testutil.NewSpecWithArgs("sleep", "100")
- rootDir, bundleDir, conf, err := setupContainer(spec)
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(spec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
@@ -187,7 +118,7 @@ func TestLifecycle(t *testing.T) {
},
}
// Create the container.
- id := uniqueContainerID()
+ id := testutil.UniqueContainerID()
if _, err := container.Create(id, spec, conf, bundleDir, "", ""); err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -298,13 +229,13 @@ func TestExePath(t *testing.T) {
{path: "bin/thisfiledoesntexit", success: false},
{path: "/bin/thisfiledoesntexit", success: false},
} {
- spec := newSpecWithArgs(test.path)
- rootDir, bundleDir, conf, err := setupContainer(spec)
+ spec := testutil.NewSpecWithArgs(test.path)
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(spec)
if err != nil {
t.Fatalf("exec: %s, error setting up container: %v", test.path, err)
}
- ws, err := container.Run(uniqueContainerID(), spec, conf, bundleDir, "", "")
+ ws, err := container.Run(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
os.RemoveAll(rootDir)
os.RemoveAll(bundleDir)
@@ -327,16 +258,16 @@ func TestExePath(t *testing.T) {
// Test the we can retrieve the application exit status from the container.
func TestAppExitStatus(t *testing.T) {
// First container will succeed.
- succSpec := newSpecWithArgs("true")
+ succSpec := testutil.NewSpecWithArgs("true")
- rootDir, bundleDir, conf, err := setupContainer(succSpec)
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(succSpec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
defer os.RemoveAll(rootDir)
defer os.RemoveAll(bundleDir)
- ws, err := container.Run(uniqueContainerID(), succSpec, conf, bundleDir, "", "")
+ ws, err := container.Run(testutil.UniqueContainerID(), succSpec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error running container: %v", err)
}
@@ -346,16 +277,16 @@ func TestAppExitStatus(t *testing.T) {
// Second container exits with non-zero status.
wantStatus := 123
- errSpec := newSpecWithArgs("bash", "-c", fmt.Sprintf("exit %d", wantStatus))
+ errSpec := testutil.NewSpecWithArgs("bash", "-c", fmt.Sprintf("exit %d", wantStatus))
- rootDir2, bundleDir2, conf, err := setupContainer(errSpec)
+ rootDir2, bundleDir2, conf, err := testutil.SetupContainer(errSpec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
defer os.RemoveAll(rootDir2)
defer os.RemoveAll(bundleDir2)
- ws, err = container.Run(uniqueContainerID(), succSpec, conf, bundleDir2, "", "")
+ ws, err = container.Run(testutil.UniqueContainerID(), succSpec, conf, bundleDir2, "", "")
if err != nil {
t.Fatalf("error running container: %v", err)
}
@@ -367,9 +298,9 @@ func TestAppExitStatus(t *testing.T) {
// TestExec verifies that a container can exec a new program.
func TestExec(t *testing.T) {
const uid = 343
- spec := newSpecWithArgs("sleep", "100")
+ spec := testutil.NewSpecWithArgs("sleep", "100")
- rootDir, bundleDir, conf, err := setupContainer(spec)
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(spec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
@@ -377,7 +308,7 @@ func TestExec(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- s, err := container.Create(uniqueContainerID(), spec, conf, bundleDir, "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -454,7 +385,7 @@ func TestExec(t *testing.T) {
func TestCapabilities(t *testing.T) {
const uid = 343
const gid = 2401
- spec := newSpecWithArgs("sleep", "100")
+ spec := testutil.NewSpecWithArgs("sleep", "100")
// We generate files in the host temporary directory.
spec.Mounts = append(spec.Mounts, specs.Mount{
@@ -463,7 +394,7 @@ func TestCapabilities(t *testing.T) {
Type: "bind",
})
- rootDir, bundleDir, conf, err := setupContainer(spec)
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(spec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
@@ -471,7 +402,7 @@ func TestCapabilities(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create and start the container.
- s, err := container.Create(uniqueContainerID(), spec, conf, bundleDir, "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -540,8 +471,8 @@ func TestCapabilities(t *testing.T) {
// Test that an tty FD is sent over the console socket if one is provided.
func TestConsoleSocket(t *testing.T) {
- spec := newSpecWithArgs("true")
- rootDir, bundleDir, conf, err := setupContainer(spec)
+ spec := testutil.NewSpecWithArgs("true")
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(spec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
@@ -569,7 +500,7 @@ func TestConsoleSocket(t *testing.T) {
defer os.Remove(socketPath)
// Create the container and pass the socket name.
- id := uniqueContainerID()
+ id := testutil.UniqueContainerID()
s, err := container.Create(id, spec, conf, bundleDir, socketRelPath, "")
if err != nil {
t.Fatalf("error creating container: %v", err)
@@ -618,21 +549,21 @@ func TestConsoleSocket(t *testing.T) {
}
func TestSpecUnsupported(t *testing.T) {
- spec := newSpecWithArgs("/bin/true")
+ spec := testutil.NewSpecWithArgs("/bin/true")
spec.Process.SelinuxLabel = "somelabel"
// These are normally set by docker and will just cause warnings to be logged.
spec.Process.ApparmorProfile = "someprofile"
spec.Linux = &specs.Linux{Seccomp: &specs.LinuxSeccomp{}}
- rootDir, bundleDir, conf, err := setupContainer(spec)
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(spec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
defer os.RemoveAll(rootDir)
defer os.RemoveAll(bundleDir)
- id := uniqueContainerID()
+ id := testutil.UniqueContainerID()
_, err = container.Create(id, spec, conf, bundleDir, "", "")
if err == nil || !strings.Contains(err.Error(), "is not supported") {
t.Errorf("container.Create() wrong error, got: %v, want: *is not supported, spec.Process: %+v", err, spec.Process)
@@ -642,14 +573,17 @@ func TestSpecUnsupported(t *testing.T) {
// TestRunNonRoot checks that sandbox can be configured when running as
// non-priviledged user.
func TestRunNonRoot(t *testing.T) {
- spec := newSpecWithArgs("/bin/true")
+ spec := testutil.NewSpecWithArgs("/bin/true")
spec.Process.User.UID = 343
spec.Process.User.GID = 2401
// User that container runs as can't list '$TMP/blocked' and would fail to
// mount it.
- dir := path.Join(os.TempDir(), "blocked")
- if err := os.Mkdir(dir, 0700); err != nil {
+ dir, err := ioutil.TempDir("", "blocked")
+ if err != nil {
+ t.Fatalf("ioutil.TempDir() failed: %v", err)
+ }
+ if err := os.Chmod(dir, 0700); err != nil {
t.Fatalf("os.MkDir(%q) failed: %v", dir, err)
}
dir = path.Join(dir, "test")
@@ -664,7 +598,7 @@ func TestRunNonRoot(t *testing.T) {
Type: "bind",
})
- rootDir, bundleDir, conf, err := setupContainer(spec)
+ rootDir, bundleDir, conf, err := testutil.SetupContainer(spec)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
@@ -672,7 +606,7 @@ func TestRunNonRoot(t *testing.T) {
defer os.RemoveAll(bundleDir)
// Create, start and wait for the container.
- s, err := container.Create(uniqueContainerID(), spec, conf, bundleDir, "", "")
+ s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -688,39 +622,3 @@ func TestRunNonRoot(t *testing.T) {
t.Errorf("container failed, waitStatus: %v", ws)
}
}
-
-// TestMain acts like runsc if it is called with the "boot" argument, otherwise
-// it just runs the tests. This is required because creating a container will
-// call "/proc/self/exe boot". Normally /proc/self/exe is the runsc binary,
-// but for tests we have to fake it.
-func TestMain(m *testing.M) {
- // exit writes coverage data before exiting.
- exit := func(status int) {
- os.Exit(status)
- }
-
- if !flag.Parsed() {
- flag.Parse()
- }
-
- // If we are passed one of the commands then run it.
- subcommands.Register(new(cmd.Boot), "boot")
- subcommands.Register(new(cmd.Gofer), "gofer")
- switch flag.Arg(0) {
- case "boot", "gofer":
- conf := &boot.Config{
- RootDir: "unused-root-dir",
- Network: boot.NetworkNone,
- }
- var ws syscall.WaitStatus
- subcmdCode := subcommands.Execute(context.Background(), conf, &ws)
- if subcmdCode != subcommands.ExitSuccess {
- panic(fmt.Sprintf("command failed to execute, err: %v", subcmdCode))
- }
- // Container exited. Shut down this process.
- exit(ws.ExitStatus())
- default:
- // Otherwise run the tests.
- exit(m.Run())
- }
-}