Mercurial > go > multipass
comparison file/file_test.go @ 15:9b4ec6b5c23e
Add tests for multipass files.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Thu, 29 Oct 2015 23:56:53 -0400 |
parents | |
children | bfc035bd5132 |
comparison
equal
deleted
inserted
replaced
14:4368a377ff64 | 15:9b4ec6b5c23e |
---|---|
1 package file | |
2 | |
3 import ( | |
4 "fmt" | |
5 "io/ioutil" | |
6 "os" | |
7 "path" | |
8 "testing" | |
9 "time" | |
10 | |
11 "pfish.zone/go/multipass/auth" | |
12 ) | |
13 | |
14 var tempdir string | |
15 | |
16 const ( | |
17 filemode = 0644 | |
18 | |
19 shadowSpooky = "123:bogushash:c3Bvb2t5" | |
20 shadowWhatever = "456:anotherhash:d2hhdGV2ZXI=" | |
21 ) | |
22 | |
23 var ( | |
24 aSpooky *auth.Entry | |
25 aWhatever *auth.Entry | |
26 ) | |
27 | |
28 func init() { | |
29 s, err := auth.EntryFromShadow(shadowSpooky) | |
30 if err != nil { | |
31 panic(err.Error()) | |
32 } | |
33 aSpooky = s | |
34 w, err := auth.EntryFromShadow(shadowWhatever) | |
35 if err != nil { | |
36 panic(err.Error()) | |
37 } | |
38 aWhatever = w | |
39 } | |
40 | |
41 func TestMain(m *testing.M) { | |
42 dir, err := ioutil.TempDir(os.TempDir(), "multipass-") | |
43 maxDelay = 2 * time.Second | |
44 tempdir = dir | |
45 if err != nil { | |
46 panic("couldn't create temp dir") | |
47 } | |
48 m.Run() | |
49 os.RemoveAll(tempdir) | |
50 } | |
51 | |
52 type testfile struct { | |
53 t *testing.T | |
54 dir string | |
55 } | |
56 | |
57 func mktest(t *testing.T, dir string) *testfile { | |
58 f := &testfile{t, dir} | |
59 os.Mkdir(f.dirpath(), 0700) | |
60 return f | |
61 } | |
62 | |
63 func (f *testfile) dirpath() string { | |
64 return path.Join(tempdir, f.dir) | |
65 } | |
66 | |
67 func (f *testfile) filepath() string { | |
68 return path.Join(f.dirpath(), "file") | |
69 } | |
70 | |
71 func (f *testfile) read() string { | |
72 contents, err := ioutil.ReadFile(f.filepath()) | |
73 if err != nil { | |
74 f.t.Fatalf("couldn't read output file: %q", err.Error()) | |
75 } | |
76 return string(contents) | |
77 } | |
78 | |
79 func (f *testfile) write(data string) { | |
80 err := ioutil.WriteFile(f.filepath(), []byte(data), filemode) | |
81 if err != nil { | |
82 f.t.Fatalf("couldn't write output file: %q", err) | |
83 } | |
84 } | |
85 | |
86 func (f *testfile) perms() os.FileMode { | |
87 stat, err := os.Stat(f.filepath()) | |
88 if err != nil { | |
89 f.t.Fatalf("couldn't stat output file: %q", err) | |
90 } | |
91 return stat.Mode().Perm() | |
92 } | |
93 | |
94 func (f *testfile) cleanup() { | |
95 os.RemoveAll(f.dirpath()) | |
96 } | |
97 | |
98 func TestCreate(t *testing.T) { | |
99 f := mktest(t, "create") | |
100 defer f.cleanup() | |
101 s := New(f.filepath()) | |
102 err := s.Add(aSpooky) | |
103 if err != nil { | |
104 t.Fatal(err.Error()) | |
105 } | |
106 if f.perms() != filemode { | |
107 t.Errorf("want perms %q; got %q", filemode, f.perms()) | |
108 } | |
109 want := fmt.Sprintf("%s\n%s\n", Banner, shadowSpooky) | |
110 got := f.read() | |
111 if want != got { | |
112 t.Errorf("bad file contents: want %q; got %q", want, got) | |
113 } | |
114 } | |
115 | |
116 func TestAppend(t *testing.T) { | |
117 f := mktest(t, "append") | |
118 defer f.cleanup() | |
119 f.write(fmt.Sprintf("%s\n%s\n", Banner, shadowSpooky)) | |
120 s := New(f.filepath()) | |
121 err := s.Add(aWhatever) | |
122 if err != nil { | |
123 t.Fatal(err.Error()) | |
124 } | |
125 want := fmt.Sprintf("%s\n%s\n%s\n", Banner, shadowWhatever, shadowSpooky) | |
126 got := f.read() | |
127 if want != got { | |
128 t.Errorf("bad file contents: want %q; got %q", want, got) | |
129 } | |
130 } | |
131 | |
132 func TestRemove(t *testing.T) { | |
133 f := mktest(t, "remove") | |
134 defer f.cleanup() | |
135 f.write(fmt.Sprintf("%s\n%s\n%s\n", Banner, shadowWhatever, shadowSpooky)) | |
136 s := New(f.filepath()) | |
137 err := s.Remove(456) | |
138 if err != nil { | |
139 t.Fatal(err.Error()) | |
140 } | |
141 want := fmt.Sprintf("%s\n%s\n", Banner, shadowSpooky) | |
142 got := f.read() | |
143 if want != got { | |
144 t.Errorf("bad file contents: want %q; got %q", want, got) | |
145 } | |
146 | |
147 // Removing a nonexistent entry is idempotent. | |
148 err = s.Remove(456) | |
149 if err != nil { | |
150 t.Fatal(err.Error()) | |
151 } | |
152 got = f.read() | |
153 if want != got { | |
154 t.Errorf("bad file contents: want %q; got %q", want, got) | |
155 } | |
156 | |
157 // Removing the remaining entry leaves an empty file. | |
158 err = s.Remove(123) | |
159 if err != nil { | |
160 t.Fatal(err.Error()) | |
161 } | |
162 want = fmt.Sprintf("%s\n", Banner) | |
163 got = f.read() | |
164 if want != got { | |
165 t.Errorf("bad file contents: want %q; got %q", want, got) | |
166 } | |
167 } | |
168 | |
169 func TestList(t *testing.T) { | |
170 f := mktest(t, "list") | |
171 defer f.cleanup() | |
172 s := New(f.filepath()) | |
173 entries, err := s.AllEntries() | |
174 if len(entries) != 0 { | |
175 t.Errorf("want 0 entries; got %q", entries) | |
176 } | |
177 | |
178 f.write(fmt.Sprintf("%s\n%s\n%s\n", Banner, shadowWhatever, shadowSpooky)) | |
179 entries, err = s.AllEntries() | |
180 if err != nil { | |
181 t.Fatal(err.Error()) | |
182 } | |
183 if len(entries) != 2 { | |
184 t.Fatalf("want len(entries) == 2; got entries = %q", entries) | |
185 } | |
186 if *entries[0] != *aWhatever || *entries[1] != *aSpooky { | |
187 t.Fatalf("want {aWhatever, aSpooky}; got %q", entries) | |
188 } | |
189 } | |
190 | |
191 func TestAuthenticate(t *testing.T) { | |
192 f := mktest(t, "auth") | |
193 defer f.cleanup() | |
194 s := New(f.filepath()) | |
195 eA, passA, err := auth.NewEntry("a") | |
196 if err != nil { | |
197 t.Fatalf(err.Error()) | |
198 } | |
199 eB, passB, err := auth.NewEntry("b") | |
200 if err != nil { | |
201 t.Fatalf(err.Error()) | |
202 } | |
203 err = s.Add(eA) | |
204 if err != nil { | |
205 t.Fatalf(err.Error()) | |
206 } | |
207 err = s.Add(eB) | |
208 if err != nil { | |
209 t.Fatalf(err.Error()) | |
210 } | |
211 good, err := s.Authenticate(passA) | |
212 if !good { | |
213 t.Errorf("couldn't authenticate password A") | |
214 } | |
215 good, err = s.Authenticate(passB) | |
216 if !good { | |
217 t.Errorf("couldn't authenticate password B") | |
218 } | |
219 bad, err := s.Authenticate("boo") | |
220 if bad { | |
221 t.Errorf("authenticated bad password") | |
222 } | |
223 } | |
224 | |
225 type clobberEvent int | |
226 | |
227 const ( | |
228 unlocked clobberEvent = iota | |
229 written | |
230 failed | |
231 ) | |
232 | |
233 func TestNoClobber(t *testing.T) { | |
234 f := mktest(t, "clobber") | |
235 defer f.cleanup() | |
236 f.write(fmt.Sprintf("%s\n", Banner)) | |
237 s := New(f.filepath()) | |
238 // put a file in the system's new-file so it won't overwrite it. | |
239 err := ioutil.WriteFile(s.newFilename(), nil, filemode) | |
240 if err != nil { | |
241 t.Fatalf(err.Error()) | |
242 } | |
243 events := make(chan clobberEvent, 10) | |
244 go func() { | |
245 err := s.Add(aWhatever) | |
246 if err != nil { | |
247 events <- failed | |
248 return | |
249 } | |
250 events <- written | |
251 }() | |
252 time.Sleep(time.Second) | |
253 events <- unlocked | |
254 err = os.Remove(s.newFilename()) | |
255 if err != nil { | |
256 t.Fatalf(err.Error()) | |
257 } | |
258 ev := <-events | |
259 if unlocked != ev { | |
260 t.Errorf("event 0: %q; got %q", unlocked, ev) | |
261 } | |
262 ev = <-events | |
263 if written != ev { | |
264 t.Errorf("event 1: %q; got %q", written, ev) | |
265 } | |
266 | |
267 want := fmt.Sprintf("%s\n%s\n", Banner, shadowWhatever) | |
268 got := f.read() | |
269 if want != got { | |
270 t.Errorf("bad contents: want %q; got %q", want, got) | |
271 } | |
272 } | |
273 | |
274 func TestGiveUp(t *testing.T) { | |
275 f := mktest(t, "giveup") | |
276 defer f.cleanup() | |
277 f.write(fmt.Sprintf("%s\n", Banner)) | |
278 s := New(f.filepath()) | |
279 // put a file in the system's new-file so it won't overwrite it. | |
280 err := ioutil.WriteFile(s.newFilename(), nil, filemode) | |
281 if err != nil { | |
282 t.Fatalf(err.Error()) | |
283 } | |
284 events := make(chan clobberEvent, 10) | |
285 go func() { | |
286 err := s.Add(aWhatever) | |
287 if err != nil { | |
288 events <- failed | |
289 return | |
290 } | |
291 events <- written | |
292 }() | |
293 time.Sleep(5 * time.Second) | |
294 events <- unlocked | |
295 err = os.Remove(s.newFilename()) | |
296 if err != nil { | |
297 t.Fatalf(err.Error()) | |
298 } | |
299 ev := <-events | |
300 if failed != ev { | |
301 t.Errorf("event 0: want %q; got %q", failed, ev) | |
302 } | |
303 ev = <-events | |
304 if unlocked != ev { | |
305 t.Errorf("event 1: want %q; got %q", unlocked, ev) | |
306 } | |
307 | |
308 want := fmt.Sprintf("%s\n", Banner) | |
309 got := f.read() | |
310 if want != got { | |
311 t.Errorf("bad contents: want %q; got %q", want, got) | |
312 } | |
313 } |