From 2e05db981b826c8cc564f295eabe10ebf217e3a2 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 10 Aug 2020 16:00:09 +0000 Subject: [PATCH] quota: move test helper functions to extra file Signed-off-by: Timo Rothenpieler --- quota/projectquota_test.go | 96 ++++------------------------- quota/testhelpers.go | 122 +++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 85 deletions(-) create mode 100644 quota/testhelpers.go diff --git a/quota/projectquota_test.go b/quota/projectquota_test.go index 5cf39ae7e1..9bf5c295cc 100644 --- a/quota/projectquota_test.go +++ b/quota/projectquota_test.go @@ -6,121 +6,47 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path/filepath" "testing" - "golang.org/x/sys/unix" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" - "gotest.tools/v3/fs" ) // 10MB const testQuotaSize = 10 * 1024 * 1024 -const imageSize = 64 * 1024 * 1024 func TestBlockDev(t *testing.T) { - mkfs, err := exec.LookPath("mkfs.xfs") - if err != nil { - t.Skip("mkfs.xfs not found in PATH") + if msg, ok := CanTestQuota(); !ok { + t.Skip(msg) } - // create a sparse image - imageFile, err := ioutil.TempFile("", "xfs-image") + // get sparse xfs test image + imageFileName, err := PrepareQuotaTestImage(t) if err != nil { t.Fatal(err) } - imageFileName := imageFile.Name() defer os.Remove(imageFileName) - if _, err = imageFile.Seek(imageSize-1, 0); err != nil { - t.Fatal(err) - } - if _, err = imageFile.Write([]byte{0}); err != nil { - t.Fatal(err) - } - if err = imageFile.Close(); err != nil { - t.Fatal(err) - } - // The reason for disabling these options is sometimes people run with a newer userspace - // than kernelspace - out, err := exec.Command(mkfs, "-m", "crc=0,finobt=0", imageFileName).CombinedOutput() - if len(out) > 0 { - t.Log(string(out)) - } - if err != nil { - t.Fatal(err) - } - - t.Run("testBlockDevQuotaDisabled", wrapMountTest(imageFileName, false, testBlockDevQuotaDisabled)) - t.Run("testBlockDevQuotaEnabled", wrapMountTest(imageFileName, true, testBlockDevQuotaEnabled)) - t.Run("testSmallerThanQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testSmallerThanQuota))) - t.Run("testBiggerThanQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testBiggerThanQuota))) - t.Run("testRetrieveQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testRetrieveQuota))) + t.Run("testBlockDevQuotaDisabled", WrapMountTest(imageFileName, false, testBlockDevQuotaDisabled)) + t.Run("testBlockDevQuotaEnabled", WrapMountTest(imageFileName, true, testBlockDevQuotaEnabled)) + t.Run("testSmallerThanQuota", WrapMountTest(imageFileName, true, WrapQuotaTest(testSmallerThanQuota))) + t.Run("testBiggerThanQuota", WrapMountTest(imageFileName, true, WrapQuotaTest(testBiggerThanQuota))) + t.Run("testRetrieveQuota", WrapMountTest(imageFileName, true, WrapQuotaTest(testRetrieveQuota))) } -func wrapMountTest(imageFileName string, enableQuota bool, testFunc func(t *testing.T, mountPoint, backingFsDev string)) func(*testing.T) { - return func(t *testing.T) { - mountOptions := "loop" - - if enableQuota { - mountOptions = mountOptions + ",prjquota" - } - - mountPointDir := fs.NewDir(t, "xfs-mountPoint") - defer mountPointDir.Remove() - mountPoint := mountPointDir.Path() - - out, err := exec.Command("mount", "-o", mountOptions, imageFileName, mountPoint).CombinedOutput() - if err != nil { - _, err := os.Stat("/proc/fs/xfs") - if os.IsNotExist(err) { - t.Skip("no /proc/fs/xfs") - } - } - - assert.NilError(t, err, "mount failed: %s", out) - - defer func() { - assert.NilError(t, unix.Unmount(mountPoint, 0)) - }() - - backingFsDev, err := makeBackingFsDev(mountPoint) - assert.NilError(t, err) - - testFunc(t, mountPoint, backingFsDev) - } -} - -func testBlockDevQuotaDisabled(t *testing.T, mountPoint, backingFsDev string) { +func testBlockDevQuotaDisabled(t *testing.T, mountPoint, backingFsDev, testDir string) { hasSupport, err := hasQuotaSupport(backingFsDev) assert.NilError(t, err) assert.Check(t, !hasSupport) } -func testBlockDevQuotaEnabled(t *testing.T, mountPoint, backingFsDev string) { +func testBlockDevQuotaEnabled(t *testing.T, mountPoint, backingFsDev, testDir string) { hasSupport, err := hasQuotaSupport(backingFsDev) assert.NilError(t, err) assert.Check(t, hasSupport) } -func wrapQuotaTest(testFunc func(t *testing.T, ctrl *Control, mountPoint, testDir, testSubDir string)) func(t *testing.T, mountPoint, backingFsDev string) { - return func(t *testing.T, mountPoint, backingFsDev string) { - testDir, err := ioutil.TempDir(mountPoint, "per-test") - assert.NilError(t, err) - defer os.RemoveAll(testDir) - - ctrl, err := NewControl(testDir) - assert.NilError(t, err) - - testSubDir, err := ioutil.TempDir(testDir, "quota-test") - assert.NilError(t, err) - testFunc(t, ctrl, mountPoint, testDir, testSubDir) - } - -} - func testSmallerThanQuota(t *testing.T, ctrl *Control, homeDir, testDir, testSubDir string) { assert.NilError(t, ctrl.SetQuota(testSubDir, Quota{testQuotaSize})) smallerThanQuotaFile := filepath.Join(testSubDir, "smaller-than-quota") diff --git a/quota/testhelpers.go b/quota/testhelpers.go new file mode 100644 index 0000000000..5f1e175d1d --- /dev/null +++ b/quota/testhelpers.go @@ -0,0 +1,122 @@ +// +build linux + +package quota // import "github.com/docker/docker/quota" + +import ( + "io/ioutil" + "os" + "os/exec" + "testing" + + "golang.org/x/sys/unix" + "gotest.tools/v3/assert" + "gotest.tools/v3/fs" +) + +const imageSize = 64 * 1024 * 1024 + +// CanTestQuota - checks if xfs prjquota can be tested +// returns a reason if not +func CanTestQuota() (string, bool) { + if os.Getuid() != 0 { + return "requires mounts", false + } + _, err := exec.LookPath("mkfs.xfs") + if err != nil { + return "mkfs.xfs not found in PATH", false + } + return "", true +} + +// PrepareQuotaTestImage - prepares an xfs prjquota test image +// returns the path the the image on success +func PrepareQuotaTestImage(t *testing.T) (string, error) { + mkfs, err := exec.LookPath("mkfs.xfs") + if err != nil { + return "", err + } + + // create a sparse image + imageFile, err := ioutil.TempFile("", "xfs-image") + if err != nil { + return "", err + } + imageFileName := imageFile.Name() + if _, err = imageFile.Seek(imageSize-1, 0); err != nil { + os.Remove(imageFileName) + return "", err + } + if _, err = imageFile.Write([]byte{0}); err != nil { + os.Remove(imageFileName) + return "", err + } + if err = imageFile.Close(); err != nil { + os.Remove(imageFileName) + return "", err + } + + // The reason for disabling these options is sometimes people run with a newer userspace + // than kernelspace + out, err := exec.Command(mkfs, "-m", "crc=0,finobt=0", imageFileName).CombinedOutput() + if len(out) > 0 { + t.Log(string(out)) + } + if err != nil { + os.Remove(imageFileName) + return "", err + } + + return imageFileName, nil +} + +// WrapMountTest - wraps a test function such that it has easy access to a mountPoint and testDir +// with guaranteed prjquota or guaranteed no prjquota support. +func WrapMountTest(imageFileName string, enableQuota bool, testFunc func(t *testing.T, mountPoint, backingFsDev, testDir string)) func(*testing.T) { + return func(t *testing.T) { + mountOptions := "loop" + + if enableQuota { + mountOptions = mountOptions + ",prjquota" + } + + mountPointDir := fs.NewDir(t, "xfs-mountPoint") + defer mountPointDir.Remove() + mountPoint := mountPointDir.Path() + + out, err := exec.Command("mount", "-o", mountOptions, imageFileName, mountPoint).CombinedOutput() + if err != nil { + _, err := os.Stat("/proc/fs/xfs") + if os.IsNotExist(err) { + t.Skip("no /proc/fs/xfs") + } + } + + assert.NilError(t, err, "mount failed: %s", out) + + defer func() { + assert.NilError(t, unix.Unmount(mountPoint, 0)) + }() + + backingFsDev, err := makeBackingFsDev(mountPoint) + assert.NilError(t, err) + + testDir, err := ioutil.TempDir(mountPoint, "per-test") + assert.NilError(t, err) + defer os.RemoveAll(testDir) + + testFunc(t, mountPoint, backingFsDev, testDir) + } +} + +// WrapQuotaTest - wraps a test function such that is has easy and guaranteed access to a quota Control +// instance with a quota test dir under its control. +func WrapQuotaTest(testFunc func(t *testing.T, ctrl *Control, mountPoint, testDir, testSubDir string)) func(t *testing.T, mountPoint, backingFsDev, testDir string) { + return func(t *testing.T, mountPoint, backingFsDev, testDir string) { + ctrl, err := NewControl(testDir) + assert.NilError(t, err) + + testSubDir, err := ioutil.TempDir(testDir, "quota-test") + assert.NilError(t, err) + testFunc(t, ctrl, mountPoint, testDir, testSubDir) + } +}