12 match std.mkdtemp("test_root_for_libmaildir", 0o700)
17 [.name="setup", .fn = {c : testr.ctx#
18 testr.fail(c, "mktemp failed: {}", e)
24 if !std.chdir(testroot)
26 [.name="setup", .fn = {c : testr.ctx#
27 testr.fail(c, "chdir({}) failed", testroot)
34 [.name="changeinfo01", .fn = changeinfo01],
36 [.name="cleanfs01", .fn = cleanfs01],
38 [.name="info01", .fn = info01],
40 [.name="infofmt01", .fn = infofmt01],
42 [.name="maildirs01", .fn = maildirs01],
43 [.name="maildirs02", .fn = maildirs02],
44 [.name="maildirs03", .fn = maildirs03],
46 [.name="messages01", .fn = messages01],
47 [.name="messages02", .fn = messages02],
49 [.name="movemessage01", .fn = movemessage01],
52 /* We don't remove testroot. It shouldn't be a concern */
57 /* Utility functions */
58 const settimes = {c : testr.ctx#, p : byte[:][:], t : uint64
59 var tv : sys.timeval = [ .sec = t ]
60 var tvs : sys.timeval[2] = [ tv, tv ]
62 /* TODO: once syscalls are cleaned up, this needs to change */
63 match sys.utimes(sys.cstring(q), &tvs[0])
66 testr.fail(c, "cannot set time of {}: {}", q, e)
74 const tree = {p : byte[:][:] -> std.result(byte[:][:], byte[:])
75 var r : byte[:][:] = std.slalloc(0)
78 for f : fileutil.bywalk(q)
79 std.slpush(&r, std.sldup(f))
83 -> `std.Ok std.sort(r, std.strcmp)
86 const mkpaths = {c : testr.ctx#, p : byte[:][:] -> bool
91 testr.fail(c, "could not mkpath {}: {}", q, e)
99 const mkfiles = {c : testr.ctx#, f : byte[:][:] -> bool
100 var s : std.strbuf# = std.mksb()
106 std.sbfmt(s, "{}", ff)
108 for j = p.len - 1; j > 0; j--
109 if p[j] == ('/' : byte)
110 std.sbtrim(s, (j : std.size))
111 match std.mkpath(std.sbpeek(s))
114 testr.fail(c, "could not mkpath {}: {}", std.sbpeek(s), e)
126 match std.openmode(ff, std.Ocreat | std.Oappend, 0o700)
127 | `std.Ok h: std.close(h)
129 testr.fail(c, "could not open {}: {}", ff, e)
137 const beat = {c : testr.ctx#, d : byte[:] -> bool
138 if !std.chdir(testroot)
139 testr.fail(c, "could not chdir to {}", testroot)
146 testr.fail(c, "could not mkpath {}: {}", d, e)
151 testr.fail(c, "could not chdir to {}", d)
158 const strseq = {a : byte[:][:], b : byte[:][:] -> bool
166 match std.strcmp(a[i], b[i])
179 const changeinfo01 = {c : testr.ctx#
180 var expected : byte[:] = [][:]
181 var expected2 : byte[:][:] = [][:]
182 var i : maildir.info = [ .passed = true, .seen = true ]
184 if !beat(c, "changeinfo01")
188 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp" ][:])
192 if !mkfiles(c, [ "a/cur/abcdefg.123:2,S" ][:])
196 expected = "a/cur/abcdefg.123:2,PS"
198 match maildir.changeinfo("a/cur/abcdefg.123:2,S", i)
200 testr.check(c, std.eq(actual, expected), \
201 "expected “{}”, got “{}”", expected, actual)
203 testr.fail(c, "{}", e)
207 expected = "link(\"a/cur/abcdefg.123:2,S\", \"a/cur/abcdefg.123:2,PS\"): -2"
209 match maildir.changeinfo("a/cur/abcdefg.123:2,S", i)
211 testr.fail(c, "got “{}”, expected error")
214 testr.check(c, std.eq(actual, expected), \
215 "expected “{}”, got “{}”", expected, actual)
218 expected2 = [ "a/cur/abcdefg.123:2,PS" ][:]
220 match tree([ "a" ][:])
222 testr.check(c, strseq(expected2, actual), \
223 "expected “{}”, got “{}”", expected2, actual)
230 const cleanfs01 = {c : testr.ctx#
231 var s : std.strbuf# = std.mksb()
232 var expected : byte[:][:] = [][:]
233 var ago35 : uint64 = ((std.now() / std.Sec) : uint64) - (35 * 60 * 60)
234 var ago37 : uint64 = ((std.now() / std.Sec) : uint64) - (37 * 60 * 60)
236 if !beat(c, "cleanfs01")
241 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp",
242 "b/cur", "b/new", "b/tmp",
243 "c/cur", "c/new", "c/tmp" ][:])
248 expected = [ "a/cur/101:2,T",
268 if !mkfiles(c, expected)
272 match tree(["a", "b", "c"][:])
274 testr.check(c, strseq(expected, actual), \
275 "expected “{}”, got “{}”", expected, actual)
281 if !settimes(c, [ "a/cur/101:2,T",
285 "c/tmp/117" ][:], ago37)
289 if !settimes(c, [ "a/tmp/106",
291 "c/tmp/118" ][:], ago35)
295 expected = [ "a/cur/102:2,FS",
310 match maildir.cleanfs(["a", "b"][:])
317 match tree(["a", "b", "c"][:])
319 testr.check(c, strseq(expected, actual), \
320 "expected “{}”, got “{}”", expected, actual)
328 const info01 = {c : testr.ctx#
329 var m : byte[:][:] = [][:]
330 var i : maildir.info = [ .trashed = false ]
331 var as : std.strbuf# = std.mksb()
332 var es : std.strbuf# = std.mksb()
333 var asp : byte[:] = ""
334 var esp : byte[:] = ""
335 var expected : (byte[:], maildir.info)[:]
336 var checked : bool = false
338 if !beat(c, "info01")
344 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp" ][:])
350 if !mkfiles(c, [ "a/new/somethinguniq⁷_##$$Foo",
351 "a/new/765786.288.257968732.6795821",
355 "a/cur/abc.d∞g:2,FRS",
356 "a/cur/abc:Fdeg:2,DPT",
364 ("a/new/somethinguniq⁷_##$$Foo", \
365 [ .passed = false ]),
366 ("a/new/765786.288.257968732.6795821", \
367 [ .passed = false ]),
368 ("a/cur/abc.def:2,P", \
371 [ .passed = false ]),
373 [ .passed = false ]),
374 ("a/cur/abc.d∞g:2,FRS", \
375 [ .flagged = true, .replied = true, .seen = true ]),
376 ("a/cur/abc:Fdeg:2,DPT", \
377 [ .draft = true, .passed = true, .trashed = true ]),
380 match maildir.messages("a")
383 if m.len != expected.len
384 testr.fail(c, "some expected messages missing")
390 testr.fail(c, "can't list messages of a: {}", e)
399 std.sbfmt(as, "{}", i)
403 for (ep, ei) : expected
406 std.sbfmt(es, "{}", ei)
409 testr.check(c, std.eq(asp, esp), \
410 "for {}, expected “{}”, got “{}”", \
416 testr.fail(c, "unexpected message {}", p)
424 const infofmt01 = {c : testr.ctx#
425 var s : std.strbuf# = std.mksb()
426 var i : maildir.info = [ .passed = true ]
427 var actual : byte[:] = [][:]
428 var expected : byte[:] = [][:]
431 std.sbfmt(s, "{}", i)
433 actual = std.sbpeek(s)
434 testr.check(c, std.eq(expected, actual), "expected “{}”, got “{}”", \
437 i = [ .flagged = true, .replied = true, .trashed = true ]
439 std.sbfmt(s, "{}", i)
441 actual = std.sbpeek(s)
442 testr.check(c, std.eq(expected, actual), "expected “{}”, got “{}”", \
445 i = [ .flagged = false ]
447 std.sbfmt(s, "{}", i)
449 actual = std.sbpeek(s)
450 testr.check(c, std.eq(expected, actual), "expected “{}”, got “{}”", \
454 const maildirs01 = {c : testr.ctx#
455 var expected : byte[:][:] = [][:]
456 var actual : byte[:][:] = [][:]
457 if !beat(c, "maildirs01")
461 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp",
462 "b/cur", "b/new", "b/tmq",
463 "c/cur", "c/new", "c/tmq", "c/other",
465 "cur/cur", "cur/new", "cur/tmp",
470 expected = [ "a", "cur" ][:]
471 match maildir.maildirs(".")
474 testr.check(c, strseq(expected, actual), \
475 "expected “{}”, got “{}”", expected, actual)
481 testr.fail(c, "can't examine .: {}", e)
485 const maildirs02 = {c : testr.ctx#
486 var expected : byte[:][:] = [][:]
487 var actual : byte[:][:] = [][:]
489 if !beat(c, "maildirs02/a/long/way/down")
493 if !mkpaths(c, [ "d/cur", "d/new", "d/tmp",
494 "a/cur", "a/new", "a/tmq",
495 "c/cur", "c/new", "c/tmq", "c/other",
497 "cur/cur", "cur/new", "cur/tmp",
502 if !beat(c, "maildirs02")
506 expected = [ "a/long/way/down/cur", "a/long/way/down/d" ][:]
507 match maildir.maildirs("a/long/way/down")
510 testr.check(c, strseq(expected, actual), \
511 "expected “{}”, got “{}”", expected, actual)
517 testr.fail(c, "can't examine a/long/way/down: {}", e)
521 const maildirs03 = {c : testr.ctx#
522 var expected : byte[:] = [][:]
524 if !beat(c, "maildirs03")
528 match maildir.maildirs("/dev/some/place/that/really/shouldn't/exist")
530 testr.fail(c, "got maildirs where none should be")
532 /* TODO: should we really be checking this pedantically? */
533 expected = "cannot open /dev/some/place/that/really/shouldn't/exist: couldn't open directory"
534 testr.check(c, std.eq(e, expected), \
535 "expected “{}”, got “{}”", \
540 const messages01 = {c : testr.ctx#
541 var expected : byte[:][:] = [][:]
542 var actual : byte[:][:] = [][:]
543 if !beat(c, "messages01")
547 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp", "a/.qmail",
548 "a/new/foo", "a/cur/baz/quux",
549 "a/new/.ignorethis", "a/cur/......thistoo"
554 expected = std.sort([ "a/new/foo", "a/cur/baz" ][:], std.strcmp)
555 match maildir.messages("a")
557 testr.check(c, strseq(expected, a), \
558 "expected “{}”, got “{}”", expected, a)
564 testr.fail(c, "can't list messages of a: {}", e)
568 const messages02 = {c : testr.ctx#
569 var expected : byte[:] = [][:]
570 if !beat(c, "messages02")
574 if !mkpaths(c, [ "b/cur", "b/new", "b/NOTtmp",
575 "b/new/foo", "b/cur/baz"
580 match maildir.messages("b")
582 testr.fail(c, "got messages where none should be")
584 expected = "b is not a maildir"
585 testr.check(c, std.eq(e, expected), \
586 "expected “{}”, got “{}”", \
591 const movemessage01 = {c : testr.ctx#
592 var s : std.strbuf# = std.mksb()
593 var expected : byte[:][:] = [][:]
595 if !beat(c, "movemessage01")
600 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp",
601 "b/cur", "b/new", "b/tmp" ][:])
606 if !mkfiles(c, [ "a/cur/101:2,FT" ][:])
610 expected = [ "a/cur/101:2,FT" ][:]
612 match tree(["a", "b"][:])
614 testr.check(c, strseq(expected, actual), \
615 "expected “{}”, got “{}”", expected, actual)
621 match maildir.movemessage("a/cur/101:2,FT", "b")
628 expected = [ "b/cur/101:2,FT" ][:]
630 match tree(["a", "b"][:])
632 testr.check(c, strseq(expected, actual), \
633 "expected “{}”, got “{}”", expected, actual)