1
16
17 package fstest
18
19 import (
20 "bytes"
21 "io"
22 "math/rand"
23 "os"
24 "path/filepath"
25 "syscall"
26 "time"
27 )
28
29
30 type Applier interface {
31 Apply(root string) error
32 }
33
34 type applyFn func(root string) error
35
36 func (a applyFn) Apply(root string) error {
37 return a(root)
38 }
39
40
41
42 func CreateFile(name string, content []byte, perm os.FileMode) Applier {
43 f := func() io.Reader {
44 return bytes.NewReader(content)
45 }
46 return writeFileStream(name, f, perm)
47 }
48
49
50
51 func CreateRandomFile(name string, seed, size int64, perm os.FileMode) Applier {
52 f := func() io.Reader {
53 return io.LimitReader(rand.New(rand.NewSource(seed)), size)
54 }
55 return writeFileStream(name, f, perm)
56 }
57
58
59
60 func writeFileStream(name string, stream func() io.Reader, perm os.FileMode) Applier {
61 return applyFn(func(root string) (retErr error) {
62 fullPath := filepath.Join(root, name)
63 f, err := os.OpenFile(fullPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
64 if err != nil {
65 return err
66 }
67 defer func() {
68 err := f.Sync()
69 if err != nil && retErr == nil {
70 retErr = err
71 }
72
73 err = f.Close()
74 if err != nil && retErr == nil {
75 retErr = err
76 }
77 }()
78 _, err = io.Copy(f, stream())
79 if err != nil {
80 return err
81 }
82 return os.Chmod(fullPath, perm)
83 })
84 }
85
86
87 func Remove(name string) Applier {
88 return applyFn(func(root string) error {
89 return os.Remove(filepath.Join(root, name))
90 })
91 }
92
93
94
95 func RemoveAll(name string) Applier {
96 return applyFn(func(root string) error {
97 return os.RemoveAll(filepath.Join(root, name))
98 })
99 }
100
101
102
103 func CreateDir(name string, perm os.FileMode) Applier {
104 return applyFn(func(root string) error {
105 fullPath := filepath.Join(root, name)
106 if err := os.MkdirAll(fullPath, perm); err != nil {
107 return err
108 }
109 return os.Chmod(fullPath, perm)
110 })
111 }
112
113
114 func Rename(old, new string) Applier {
115 return applyFn(func(root string) error {
116 return os.Rename(filepath.Join(root, old), filepath.Join(root, new))
117 })
118 }
119
120
121 func Chown(name string, uid, gid int) Applier {
122 return applyFn(func(root string) error {
123 return os.Chown(filepath.Join(root, name), uid, gid)
124 })
125 }
126
127
128
129 func Chtimes(name string, atime, mtime time.Time) Applier {
130 return applyFn(func(root string) error {
131 return os.Chtimes(filepath.Join(root, name), atime, mtime)
132 })
133 }
134
135
136 func Chmod(name string, perm os.FileMode) Applier {
137 return applyFn(func(root string) error {
138 return os.Chmod(filepath.Join(root, name), perm)
139 })
140 }
141
142
143 func Symlink(oldname, newname string) Applier {
144 return applyFn(func(root string) error {
145 return os.Symlink(oldname, filepath.Join(root, newname))
146 })
147 }
148
149
150 func Link(oldname, newname string) Applier {
151 return applyFn(func(root string) error {
152 return os.Link(filepath.Join(root, oldname), filepath.Join(root, newname))
153 })
154 }
155
156
157
158
159
160
161
162
163 func CreateSocket(name string, perm os.FileMode) Applier {
164 return applyFn(func(root string) error {
165 fullPath := filepath.Join(root, name)
166 fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
167 if err != nil {
168 return err
169 }
170 defer syscall.Close(fd)
171 sa := &syscall.SockaddrUnix{Name: fullPath}
172 if err := syscall.Bind(fd, sa); err != nil {
173 return err
174 }
175 return os.Chmod(fullPath, perm)
176 })
177 }
178
179
180 func Apply(appliers ...Applier) Applier {
181 return applyFn(func(root string) error {
182 for _, a := range appliers {
183 if err := a.Apply(root); err != nil {
184 return err
185 }
186 }
187 return nil
188 })
189 }
190
View as plain text