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 ]
64 std.slpush(&zt, (0 : byte))
66 match sys.utimes(&zt[0], &tvs[0])
69 testr.fail(c, "cannot set time of {}: {}", q, e)
79 const tree = {p : byte[:][:] -> std.result(byte[:][:], byte[:])
80 var r : byte[:][:] = std.slalloc(0)
83 for f : fileutil.bywalk(q)
84 std.slpush(&r, std.sldup(f))
88 -> `std.Ok std.sort(r, std.strcmp)
91 const mkpaths = {c : testr.ctx#, p : byte[:][:] -> bool
96 testr.fail(c, "could not mkpath {}: {}", q, e)
104 const mkfiles = {c : testr.ctx#, f : byte[:][:] -> bool
105 var s : std.strbuf# = std.mksb()
111 std.sbfmt(s, "{}", ff)
113 for j = p.len - 1; j > 0; j--
114 if p[j] == ('/' : byte)
115 std.sbtrim(s, (j : std.size))
116 match std.mkpath(std.sbpeek(s))
119 testr.fail(c, "could not mkpath {}: {}", std.sbpeek(s), e)
131 match std.openmode(ff, std.Ocreat | std.Oappend, 0o700)
132 | `std.Ok h: std.close(h)
134 testr.fail(c, "could not open {}: {}", ff, e)
142 const beat = {c : testr.ctx#, d : byte[:] -> bool
143 if !std.chdir(testroot)
144 testr.fail(c, "could not chdir to {}", testroot)
151 testr.fail(c, "could not mkpath {}: {}", d, e)
156 testr.fail(c, "could not chdir to {}", d)
163 const strseq = {a : byte[:][:], b : byte[:][:] -> bool
171 match std.strcmp(a[i], b[i])
184 const changeinfo01 = {c : testr.ctx#
185 var expected : byte[:] = [][:]
186 var expected2 : byte[:][:] = [][:]
187 var i : maildir.info = [ .passed = true, .seen = true ]
189 if !beat(c, "changeinfo01")
193 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp" ][:])
197 if !mkfiles(c, [ "a/cur/abcdefg.123:2,S" ][:])
201 expected = "a/cur/abcdefg.123:2,PS"
203 match maildir.changeinfo("a/cur/abcdefg.123:2,S", i)
205 testr.check(c, std.sleq(actual, expected), \
206 "expected “{}”, got “{}”", expected, actual)
208 testr.fail(c, "{}", e)
212 expected = "link(\"a/cur/abcdefg.123:2,S\", \"a/cur/abcdefg.123:2,PS\"): -2"
214 match maildir.changeinfo("a/cur/abcdefg.123:2,S", i)
216 testr.fail(c, "got “{}”, expected error")
219 testr.check(c, std.sleq(actual, expected), \
220 "expected “{}”, got “{}”", expected, actual)
223 expected2 = [ "a/cur/abcdefg.123:2,PS" ][:]
225 match tree([ "a" ][:])
227 testr.check(c, strseq(expected2, actual), \
228 "expected “{}”, got “{}”", expected2, actual)
235 const cleanfs01 = {c : testr.ctx#
236 var s : std.strbuf# = std.mksb()
237 var expected : byte[:][:] = [][:]
238 var ago35 : uint64 = ((std.now() / std.Sec) : uint64) - (35 * 60 * 60)
239 var ago37 : uint64 = ((std.now() / std.Sec) : uint64) - (37 * 60 * 60)
241 if !beat(c, "cleanfs01")
246 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp",
247 "b/cur", "b/new", "b/tmp",
248 "c/cur", "c/new", "c/tmp" ][:])
253 expected = [ "a/cur/101:2,T",
273 if !mkfiles(c, expected)
277 match tree(["a", "b", "c"][:])
279 testr.check(c, strseq(expected, actual), \
280 "expected “{}”, got “{}”", expected, actual)
286 if !settimes(c, [ "a/cur/101:2,T",
290 "c/tmp/117" ][:], ago37)
294 if !settimes(c, [ "a/tmp/106",
296 "c/tmp/118" ][:], ago35)
300 expected = [ "a/cur/102:2,FS",
315 match maildir.cleanfs(["a", "b"][:])
322 match tree(["a", "b", "c"][:])
324 testr.check(c, strseq(expected, actual), \
325 "expected “{}”, got “{}”", expected, actual)
333 const info01 = {c : testr.ctx#
334 var m : byte[:][:] = [][:]
335 var i : maildir.info = [ .trashed = false ]
336 var as : std.strbuf# = std.mksb()
337 var es : std.strbuf# = std.mksb()
338 var asp : byte[:] = ""
339 var esp : byte[:] = ""
340 var expected : (byte[:], maildir.info)[:]
341 var checked : bool = false
343 if !beat(c, "info01")
349 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp" ][:])
355 if !mkfiles(c, [ "a/new/somethinguniq⁷_##$$Foo",
356 "a/new/765786.288.257968732.6795821",
360 "a/cur/abc.d∞g:2,FRS",
361 "a/cur/abc.deg:2,DPT",
369 ("a/new/somethinguniq⁷_##$$Foo", \
370 [ .passed = false ]),
371 ("a/new/765786.288.257968732.6795821", \
372 [ .passed = false ]),
373 ("a/cur/abc.def:2,P", \
376 [ .passed = false ]),
378 [ .passed = false ]),
379 ("a/cur/abc.d∞g:2,FRS", \
380 [ .flagged = true, .replied = true, .seen = true ]),
381 ("a/cur/abc.deg:2,DPT", \
382 [ .draft = true, .passed = true, .trashed = true ]),
385 match maildir.messages("a")
388 if m.len != expected.len
389 testr.fail(c, "some expected messages missing")
395 testr.fail(c, "can't list messages of a: {}", e)
404 std.sbfmt(as, "{}", i)
408 for (ep, ei) : expected
411 std.sbfmt(es, "{}", ei)
414 testr.check(c, std.sleq(asp, esp), \
415 "for {}, expected “{}”, got “{}”", \
421 testr.fail(c, "unexpected message {}", p)
429 const infofmt01 = {c : testr.ctx#
430 var s : std.strbuf# = std.mksb()
431 var i : maildir.info = [ .passed = true ]
432 var actual : byte[:] = [][:]
433 var expected : byte[:] = [][:]
436 std.sbfmt(s, "{}", i)
438 actual = std.sbpeek(s)
439 testr.check(c, std.sleq(expected, actual), "expected “{}”, got “{}”", \
442 i = [ .flagged = true, .replied = true, .trashed = true ]
444 std.sbfmt(s, "{}", i)
446 actual = std.sbpeek(s)
447 testr.check(c, std.sleq(expected, actual), "expected “{}”, got “{}”", \
450 i = [ .flagged = false ]
452 std.sbfmt(s, "{}", i)
454 actual = std.sbpeek(s)
455 testr.check(c, std.sleq(expected, actual), "expected “{}”, got “{}”", \
459 const maildirs01 = {c : testr.ctx#
460 var expected : byte[:][:] = [][:]
461 var actual : byte[:][:] = [][:]
462 if !beat(c, "maildirs01")
466 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp",
467 "b/cur", "b/new", "b/tmq",
468 "c/cur", "c/new", "c/tmq", "c/other",
470 "cur/cur", "cur/new", "cur/tmp",
475 expected = [ "a", "cur" ][:]
476 match maildir.maildirs(".")
479 testr.check(c, strseq(expected, actual), \
480 "expected “{}”, got “{}”", expected, actual)
486 testr.fail(c, "can't examine .: {}", e)
490 const maildirs02 = {c : testr.ctx#
491 var expected : byte[:][:] = [][:]
492 var actual : byte[:][:] = [][:]
494 if !beat(c, "maildirs02/a/long/way/down")
498 if !mkpaths(c, [ "d/cur", "d/new", "d/tmp",
499 "a/cur", "a/new", "a/tmq",
500 "c/cur", "c/new", "c/tmq", "c/other",
502 "cur/cur", "cur/new", "cur/tmp",
507 if !beat(c, "maildirs02")
511 expected = [ "a/long/way/down/cur", "a/long/way/down/d" ][:]
512 match maildir.maildirs("a/long/way/down")
515 testr.check(c, strseq(expected, actual), \
516 "expected “{}”, got “{}”", expected, actual)
522 testr.fail(c, "can't examine a/long/way/down: {}", e)
526 const maildirs03 = {c : testr.ctx#
527 var expected : byte[:] = [][:]
529 if !beat(c, "maildirs03")
533 match maildir.maildirs("/dev/some/place/that/really/shouldn't/exist")
535 testr.fail(c, "got maildirs where none should be")
537 /* TODO: should we really be checking this pedantically? */
538 expected = "cannot open /dev/some/place/that/really/shouldn't/exist: couldn't open directory"
539 testr.check(c, std.sleq(e, expected), \
540 "expected “{}”, got “{}”", \
545 const messages01 = {c : testr.ctx#
546 var expected : byte[:][:] = [][:]
547 var actual : byte[:][:] = [][:]
548 if !beat(c, "messages01")
552 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp", "a/.qmail",
553 "a/new/foo", "a/cur/baz/quux",
554 "a/new/.ignorethis", "a/cur/......thistoo"
559 expected = std.sort([ "a/new/foo", "a/cur/baz" ][:], std.strcmp)
560 match maildir.messages("a")
562 testr.check(c, strseq(expected, a), \
563 "expected “{}”, got “{}”", expected, a)
569 testr.fail(c, "can't list messages of a: {}", e)
573 const messages02 = {c : testr.ctx#
574 var expected : byte[:] = [][:]
575 if !beat(c, "messages02")
579 if !mkpaths(c, [ "b/cur", "b/new", "b/NOTtmp",
580 "b/new/foo", "b/cur/baz"
585 match maildir.messages("b")
587 testr.fail(c, "got messages where none should be")
589 expected = "b is not a maildir"
590 testr.check(c, std.sleq(e, expected), \
591 "expected “{}”, got “{}”", \
596 const movemessage01 = {c : testr.ctx#
597 var s : std.strbuf# = std.mksb()
598 var expected : byte[:][:] = [][:]
600 if !beat(c, "movemessage01")
605 if !mkpaths(c, [ "a/cur", "a/new", "a/tmp",
606 "b/cur", "b/new", "b/tmp" ][:])
611 if !mkfiles(c, [ "a/cur/101:2,FT" ][:])
615 expected = [ "a/cur/101:2,FT" ][:]
617 match tree(["a", "b"][:])
619 testr.check(c, strseq(expected, actual), \
620 "expected “{}”, got “{}”", expected, actual)
626 match maildir.movemessage("a/cur/101:2,FT", "b")
633 expected = [ "b/cur/101:2,FT" ][:]
635 match tree(["a", "b"][:])
637 testr.check(c, strseq(expected, actual), \
638 "expected “{}”, got “{}”", expected, actual)