testhelpers.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //go:build linux && !exclude_disk_quota && cgo
  2. package quota // import "github.com/docker/docker/quota"
  3. import (
  4. "os"
  5. "os/exec"
  6. "testing"
  7. "golang.org/x/sys/unix"
  8. )
  9. // CanTestQuota - checks if xfs prjquota can be tested
  10. // returns a reason if not
  11. func CanTestQuota() (string, bool) {
  12. if os.Getuid() != 0 {
  13. return "requires mounts", false
  14. }
  15. _, err := exec.LookPath("mkfs.xfs")
  16. if err != nil {
  17. return "mkfs.xfs not found in PATH", false
  18. }
  19. return "", true
  20. }
  21. // PrepareQuotaTestImage - prepares an xfs prjquota test image
  22. // returns the path the the image on success
  23. func PrepareQuotaTestImage(t *testing.T) (string, error) {
  24. // imageSize is the size of the test-image. The minimum size allowed
  25. // is 300MB.
  26. //
  27. // See https://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git/commit/?id=6e0ed3d19c54603f0f7d628ea04b550151d8a262
  28. const imageSize = 300 * 1024 * 1024
  29. mkfs, err := exec.LookPath("mkfs.xfs")
  30. if err != nil {
  31. return "", err
  32. }
  33. // create a sparse image
  34. imageFile, err := os.CreateTemp("", "xfs-image")
  35. if err != nil {
  36. return "", err
  37. }
  38. imageFileName := imageFile.Name()
  39. if _, err = imageFile.Seek(imageSize-1, 0); err != nil {
  40. os.Remove(imageFileName)
  41. return "", err
  42. }
  43. if _, err = imageFile.Write([]byte{0}); err != nil {
  44. os.Remove(imageFileName)
  45. return "", err
  46. }
  47. if err = imageFile.Close(); err != nil {
  48. os.Remove(imageFileName)
  49. return "", err
  50. }
  51. // The reason for disabling these options is sometimes people run with a newer userspace
  52. // than kernelspace
  53. out, err := exec.Command(mkfs, "-m", "crc=0,finobt=0", imageFileName).CombinedOutput()
  54. if len(out) > 0 {
  55. t.Log(string(out))
  56. }
  57. if err != nil {
  58. os.Remove(imageFileName)
  59. return "", err
  60. }
  61. return imageFileName, nil
  62. }
  63. // WrapMountTest - wraps a test function such that it has easy access to a mountPoint and testDir
  64. // with guaranteed prjquota or guaranteed no prjquota support.
  65. func WrapMountTest(imageFileName string, enableQuota bool, testFunc func(t *testing.T, mountPoint, backingFsDev, testDir string)) func(*testing.T) {
  66. return func(t *testing.T) {
  67. mountOptions := "loop"
  68. if enableQuota {
  69. mountOptions = mountOptions + ",prjquota"
  70. }
  71. mountPoint := t.TempDir()
  72. out, err := exec.Command("mount", "-o", mountOptions, imageFileName, mountPoint).CombinedOutput()
  73. if err != nil {
  74. _, err := os.Stat("/proc/fs/xfs")
  75. if os.IsNotExist(err) {
  76. t.Skip("no /proc/fs/xfs")
  77. }
  78. }
  79. if err != nil {
  80. t.Fatalf("assertion failed: error is not nil: %v: mount failed: %s", err, out)
  81. }
  82. defer func() {
  83. if err := unix.Unmount(mountPoint, 0); err != nil {
  84. t.Fatalf("assertion failed: error is not nil: %v", err)
  85. }
  86. }()
  87. backingFsDev, err := makeBackingFsDev(mountPoint)
  88. if err != nil {
  89. t.Fatalf("assertion failed: error is not nil: %v", err)
  90. }
  91. testDir, err := os.MkdirTemp(mountPoint, "per-test")
  92. if err != nil {
  93. t.Fatalf("assertion failed: error is not nil: %v", err)
  94. }
  95. defer os.RemoveAll(testDir)
  96. testFunc(t, mountPoint, backingFsDev, testDir)
  97. }
  98. }
  99. // WrapQuotaTest - wraps a test function such that is has easy and guaranteed access to a quota Control
  100. // instance with a quota test dir under its control.
  101. func WrapQuotaTest(testFunc func(t *testing.T, ctrl *Control, mountPoint, testDir, testSubDir string)) func(t *testing.T, mountPoint, backingFsDev, testDir string) {
  102. return func(t *testing.T, mountPoint, backingFsDev, testDir string) {
  103. ctrl, err := NewControl(testDir)
  104. if err != nil {
  105. t.Fatalf("assertion failed: error is not nil: %v", err)
  106. }
  107. testSubDir, err := os.MkdirTemp(testDir, "quota-test")
  108. if err != nil {
  109. t.Fatalf("assertion failed: error is not nil: %v", err)
  110. }
  111. testFunc(t, ctrl, mountPoint, testDir, testSubDir)
  112. }
  113. }