github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/integration/container/overlayfs_linux_test.go (about) 1 package container 2 3 import ( 4 "io" 5 "strings" 6 "testing" 7 8 "github.com/Prakhar-Agarwal-byte/moby/api/types" 9 "github.com/Prakhar-Agarwal-byte/moby/integration/internal/container" 10 "github.com/Prakhar-Agarwal-byte/moby/pkg/archive" 11 "github.com/Prakhar-Agarwal-byte/moby/pkg/dmesg" 12 "gotest.tools/v3/assert" 13 "gotest.tools/v3/skip" 14 ) 15 16 func TestNoOverlayfsWarningsAboutUndefinedBehaviors(t *testing.T) { 17 skip.If(t, testEnv.DaemonInfo.OSType != "linux", "overlayfs is only available on linux") 18 skip.If(t, testEnv.IsRemoteDaemon(), "local daemon is needed for kernel log access") 19 skip.If(t, testEnv.IsRootless(), "root is needed for reading kernel log") 20 21 ctx := setupTest(t) 22 client := testEnv.APIClient() 23 24 cID := container.Run(ctx, t, client, container.WithCmd("sh", "-c", `while true; do echo $RANDOM >>/file; sleep 0.1; done`)) 25 26 testCases := []struct { 27 name string 28 operation func(t *testing.T) error 29 }{ 30 {name: "diff", operation: func(*testing.T) error { 31 _, err := client.ContainerDiff(ctx, cID) 32 return err 33 }}, 34 {name: "export", operation: func(*testing.T) error { 35 rc, err := client.ContainerExport(ctx, cID) 36 if err == nil { 37 defer rc.Close() 38 _, err = io.Copy(io.Discard, rc) 39 } 40 return err 41 }}, 42 {name: "cp to container", operation: func(t *testing.T) error { 43 archive, err := archive.Generate("new-file", "hello-world") 44 assert.NilError(t, err, "failed to create a temporary archive") 45 return client.CopyToContainer(ctx, cID, "/", archive, types.CopyToContainerOptions{}) 46 }}, 47 {name: "cp from container", operation: func(*testing.T) error { 48 rc, _, err := client.CopyFromContainer(ctx, cID, "/file") 49 if err == nil { 50 defer rc.Close() 51 _, err = io.Copy(io.Discard, rc) 52 } 53 54 return err 55 }}, 56 } 57 58 for _, tc := range testCases { 59 tc := tc 60 t.Run(tc.name, func(t *testing.T) { 61 prev := dmesgLines(256) 62 63 err := tc.operation(t) 64 assert.NilError(t, err) 65 66 after := dmesgLines(2048) 67 68 diff := diffDmesg(prev, after) 69 for _, line := range diff { 70 overlayfs := strings.Contains(line, "overlayfs: ") 71 lowerDirInUse := strings.Contains(line, "lowerdir is in-use as ") 72 upperDirInUse := strings.Contains(line, "upperdir is in-use as ") 73 workDirInuse := strings.Contains(line, "workdir is in-use as ") 74 undefinedBehavior := strings.Contains(line, "will result in undefined behavior") 75 76 if overlayfs && (lowerDirInUse || upperDirInUse || workDirInuse) && undefinedBehavior { 77 t.Errorf("%s caused overlayfs kernel warning: %s", tc.name, line) 78 } 79 } 80 }) 81 } 82 } 83 84 func dmesgLines(bytes int) []string { 85 data := dmesg.Dmesg(bytes) 86 return strings.Split(strings.TrimSpace(string(data)), "\n") 87 } 88 89 func diffDmesg(prev, next []string) []string { 90 // All lines have a timestamp, so just take the last one from the previous 91 // log and find it in the new log. 92 lastPrev := prev[len(prev)-1] 93 94 for idx := len(next) - 1; idx >= 0; idx-- { 95 line := next[idx] 96 97 if line == lastPrev { 98 nextIdx := idx + 1 99 if nextIdx < len(next) { 100 return next[nextIdx:] 101 } else { 102 // Found at the last position, log is the same. 103 return nil 104 } 105 } 106 } 107 108 return next 109 }