summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/e2e/integration_test.go113
1 files changed, 108 insertions, 5 deletions
diff --git a/test/e2e/integration_test.go b/test/e2e/integration_test.go
index 1accc3b3b..f53417cab 100644
--- a/test/e2e/integration_test.go
+++ b/test/e2e/integration_test.go
@@ -30,6 +30,7 @@ import (
"net/http"
"os"
"path/filepath"
+ "regexp"
"strconv"
"strings"
"testing"
@@ -426,10 +427,10 @@ func TestTmpMount(t *testing.T) {
// Test that it is allowed to mount a file on top of /dev files, e.g.
// /dev/random.
func TestMountOverDev(t *testing.T) {
- if usingVFS2, err := dockerutil.UsingVFS2(); !usingVFS2 {
- t.Skip("VFS1 doesn't allow /dev/random to be mounted.")
- } else if err != nil {
+ if vfs2, err := dockerutil.UsingVFS2(); err != nil {
t.Fatalf("Failed to read config for runtime %s: %v", dockerutil.Runtime(), err)
+ } else if !vfs2 {
+ t.Skip("VFS1 doesn't allow /dev/random to be mounted.")
}
random, err := ioutil.TempFile(testutil.TmpDir(), "random")
@@ -574,11 +575,12 @@ func runIntegrationTest(t *testing.T, capAdd []string, args ...string) {
d := dockerutil.MakeContainer(ctx, t)
defer d.CleanUp(ctx)
- if got, err := d.Run(ctx, dockerutil.RunOpts{
+ opts := dockerutil.RunOpts{
Image: "basic/integrationtest",
WorkDir: "/root",
CapAdd: capAdd,
- }, args...); err != nil {
+ }
+ if got, err := d.Run(ctx, opts, args...); err != nil {
t.Fatalf("docker run failed: %v", err)
} else if got != "" {
t.Errorf("test failed:\n%s", got)
@@ -609,6 +611,107 @@ func TestBindOverlay(t *testing.T) {
}
}
+func TestStdios(t *testing.T) {
+ if vfs2, err := dockerutil.UsingVFS2(); err != nil {
+ t.Fatalf("Failed to read config for runtime %s: %v", dockerutil.Runtime(), err)
+ } else if !vfs2 {
+ t.Skip("VFS1 doesn't adjust stdios user")
+ }
+
+ ctx := context.Background()
+ d := dockerutil.MakeContainer(ctx, t)
+ defer d.CleanUp(ctx)
+
+ testStdios(t, func(user string, args ...string) (string, error) {
+ defer d.CleanUp(ctx)
+ opts := dockerutil.RunOpts{
+ Image: "basic/alpine",
+ User: user,
+ }
+ return d.Run(ctx, opts, args...)
+ })
+}
+
+func TestStdiosExec(t *testing.T) {
+ if vfs2, err := dockerutil.UsingVFS2(); err != nil {
+ t.Fatalf("Failed to read config for runtime %s: %v", dockerutil.Runtime(), err)
+ } else if !vfs2 {
+ t.Skip("VFS1 doesn't adjust stdios user")
+ }
+
+ ctx := context.Background()
+ d := dockerutil.MakeContainer(ctx, t)
+ defer d.CleanUp(ctx)
+
+ runOpts := dockerutil.RunOpts{Image: "basic/alpine"}
+ if err := d.Spawn(ctx, runOpts, "sleep", "100"); err != nil {
+ t.Fatalf("docker run failed: %v", err)
+ }
+
+ testStdios(t, func(user string, args ...string) (string, error) {
+ opts := dockerutil.ExecOpts{User: user}
+ return d.Exec(ctx, opts, args...)
+ })
+}
+
+func testStdios(t *testing.T, run func(string, ...string) (string, error)) {
+ const cmd = "stat -L /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 | grep 'Uid:'"
+ got, err := run("123", "/bin/sh", "-c", cmd)
+ if err != nil {
+ t.Fatalf("docker exec failed: %v", err)
+ }
+ if len(got) == 0 {
+ t.Errorf("Unexpected empty output from %q", cmd)
+ }
+ re := regexp.MustCompile(`Uid: \(\s*(\w+)\/.*\)`)
+ for _, line := range strings.SplitN(got, "\n", 3) {
+ t.Logf("stat -L: %s", line)
+ matches := re.FindSubmatch([]byte(line))
+ if len(matches) != 2 {
+ t.Fatalf("wrong output format: %q: matches: %v", line, matches)
+ }
+ if want, got := "123", string(matches[1]); want != got {
+ t.Errorf("wrong user, want: %q, got: %q", want, got)
+ }
+ }
+
+ // Check that stdout and stderr can be open and written to. This checks
+ // that ownership and permissions are correct inside gVisor.
+ got, err = run("456", "/bin/sh", "-c", "echo foobar | tee /proc/self/fd/1 > /proc/self/fd/2")
+ if err != nil {
+ t.Fatalf("docker run failed: %v", err)
+ }
+ t.Logf("echo foobar: %q", got)
+ // Check it repeats twice, once for stdout and once for stderr.
+ if want := "foobar\nfoobar\n"; want != got {
+ t.Errorf("Wrong echo output, want: %q, got: %q", want, got)
+ }
+
+ // Check that timestamps can be changed. Setting timestamps require an extra
+ // write check _after_ the file was opened, and may fail if the underlying
+ // host file is not setup correctly.
+ if _, err := run("789", "touch", "/proc/self/fd/0", "/proc/self/fd/1", "/proc/self/fd/2"); err != nil {
+ t.Fatalf("docker run failed: %v", err)
+ }
+}
+
+func TestStdiosChown(t *testing.T) {
+ if vfs2, err := dockerutil.UsingVFS2(); err != nil {
+ t.Fatalf("Failed to read config for runtime %s: %v", dockerutil.Runtime(), err)
+ } else if !vfs2 {
+ t.Skip("VFS1 doesn't adjust stdios user")
+ }
+
+ ctx := context.Background()
+ d := dockerutil.MakeContainer(ctx, t)
+ defer d.CleanUp(ctx)
+
+ opts := dockerutil.RunOpts{Image: "basic/alpine"}
+ if _, err := d.Run(ctx, opts, "chown", "123", "/proc/self/fd/0", "/proc/self/fd/1", "/proc/self/fd/2"); err != nil {
+ t.Fatalf("docker run failed: %v", err)
+ }
+}
+
func TestMain(m *testing.M) {
dockerutil.EnsureSupportedDockerVersion()
flag.Parse()