/
testhelpers.go
132 lines (113 loc) · 3.65 KB
/
testhelpers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//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)
}
}