dotcloud/docker

View on GitHub
quota/testhelpers.go

Summary

Maintainability
A
45 mins
Test Coverage
//go:build linux && !exclude_disk_quota && cgo

package quota // import "github.com/docker/docker/quota"

import (
    "os"
    "os/exec"
    "testing"

    "golang.org/x/sys/unix"
)

// 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 of the image on success
func PrepareQuotaTestImage(t *testing.T) (string, error) {
    // imageSize is the size of the test-image. The minimum size allowed
    // is 300MB.
    //
    // See https://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git/commit/?id=6e0ed3d19c54603f0f7d628ea04b550151d8a262
    const imageSize = 300 * 1024 * 1024

    mkfs, err := exec.LookPath("mkfs.xfs")
    if err != nil {
        return "", err
    }

    // create a sparse image
    imageFile, err := os.CreateTemp("", "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"
        }

        mountPoint := t.TempDir()
        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")
            }
        }

        if err != nil {
            t.Fatalf("assertion failed: error is not nil: %v: mount failed: %s", err, out)
        }

        defer func() {
            if err := unix.Unmount(mountPoint, 0); err != nil {
                t.Fatalf("assertion failed: error is not nil: %v", err)
            }
        }()

        backingFsDev, err := makeBackingFsDev(mountPoint)
        if err != nil {
            t.Fatalf("assertion failed: error is not nil: %v", err)
        }

        testDir, err := os.MkdirTemp(mountPoint, "per-test")
        if err != nil {
            t.Fatalf("assertion failed: error is not nil: %v", 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)
        if err != nil {
            t.Fatalf("assertion failed: error is not nil: %v", err)
        }

        testSubDir, err := os.MkdirTemp(testDir, "quota-test")
        if err != nil {
            t.Fatalf("assertion failed: error is not nil: %v", err)
        }
        testFunc(t, ctrl, mountPoint, testDir, testSubDir)
    }
}