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