From 8b09d0c9a19820aac3c82ce40415f3a17b18a64c Mon Sep 17 00:00:00 2001 From: "S. Gilles" Date: Thu, 14 Sep 2017 03:29:15 -0400 Subject: [PATCH] add changeinfo --- maildir.myr | 52 +++++++- test/maildir.myr | 393 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 272 insertions(+), 173 deletions(-) diff --git a/maildir.myr b/maildir.myr index 7dbb1a3..0506937 100644 --- a/maildir.myr +++ b/maildir.myr @@ -87,7 +87,54 @@ const ismaildir = {dir : byte[:] -> bool } /* Sanely change the info of a message */ const changeinfo = {msg : byte[:], i : info - -> `std.Err "unimplemented" + var j : std.size = 0 + var base : byte[:] = [][:] + var newname : byte[:] = [][:] + var s : std.strbuf# = std.mksb() + var err : std.strbuf# = std.mksb() + + for j = msg.len - 1; j >= 0; --j + if msg[j] == (':' : byte) + break + ;; + + if msg[j] == ('/' : byte) + j = 0 + break + ;; + ;; + + if j <= 0 + j = msg.len + ;; + + base = msg[0:j] + std.sbfmt(s, "{}{}", base, i) + newname = std.sbpeek(s) + + match sys.link(sys.cstring(msg), sys.cstring(newname)) + | 0: + | e: + std.sbfmt(err, "link(\"{}\", \"{}\"): {}", msg, newname, e) + goto done + ;; + + match sys.unlink(msg) + | 0: + | e: + std.sbfmt(err, "unlink(\"{}\"): {}", msg, e) + goto done + ;; + +:done + match err.len + | 0: + std.sbfree(err) + -> `std.Ok std.sbfin(s) + | _: + std.sbfree(s) + -> `std.Err std.sbfin(err) + ;; } @@ -170,7 +217,6 @@ const cleanfs = { dirs : byte[:][:] std.slfree(thisdir) std.slfree(thisfile) for k : tokill - sys.unlink(k) std.slfree(k) ;; std.slfree(tokill) @@ -185,7 +231,7 @@ const cleanfs = { dirs : byte[:][:] /* Parse a message filename for info flags */ const info = {msg : byte[:] - var j : int = 0 + var j : std.size = 0 var i : info = [ .passed = false, .replied = false, diff --git a/test/maildir.myr b/test/maildir.myr index 56ff181..8b8bd5c 100644 --- a/test/maildir.myr +++ b/test/maildir.myr @@ -31,18 +31,20 @@ const main = { ;; testr.run([ - [.name="maildirs01", .fn = maildirs01], - [.name="maildirs02", .fn = maildirs02], - [.name="maildirs03", .fn = maildirs03], + [.name="changeinfo01", .fn = changeinfo01], - [.name="messages01", .fn = messages01], - [.name="messages02", .fn = messages02], + [.name="cleanfs01", .fn = cleanfs01], [.name="info01", .fn = info01], [.name="infofmt01", .fn = infofmt01], - [.name="cleanfs01", .fn = cleanfs01], + [.name="maildirs01", .fn = maildirs01], + [.name="maildirs02", .fn = maildirs02], + [.name="maildirs03", .fn = maildirs03], + + [.name="messages01", .fn = messages01], + [.name="messages02", .fn = messages02], [.name="movemessage01", .fn = movemessage01], ][:]) @@ -179,146 +181,158 @@ const strseq = {a : byte[:][:], b : byte[:][:] -> bool /* Actual tests */ -const maildirs01 = {c : testr.ctx# - var expected : byte[:][:] - var actual : byte[:][:] - if !beat(c, "maildirs01") +const changeinfo01 = {c : testr.ctx# + var expected : byte[:] = [][:] + var expected2 : byte[:][:] = [][:] + var i : maildir.info = [ .passed = true, .seen = true ] + + if !beat(c, "changeinfo01") -> void ;; - if !mkpaths(c, [ "a/cur", "a/new", "a/tmp", - "b/cur", "b/new", "b/tmq", - "c/cur", "c/new", "c/tmq", "c/other", - "d", - "cur/cur", "cur/new", "cur/tmp", - ][:]) + if !mkpaths(c, [ "a/cur", "a/new", "a/tmp" ][:]) -> void ;; - expected = [ "a", "cur" ][:] - match maildir.maildirs(".") - | `std.Ok a: - actual = a - testr.check(c, strseq(expected, actual), \ - "expected “{}”, got “{}”", expected, actual) - for aa : a - std.slfree(aa) - ;; - std.slfree(a) - | `std.Err e: - testr.fail(c, "can't examine .: {}", e) + if !mkfiles(c, [ "a/cur/abcdefg.123:2,S" ][:]) + -> void ;; -} -const maildirs02 = {c : testr.ctx# - var expected : byte[:][:] - var actual : byte[:][:] + expected = "a/cur/abcdefg.123:2,PS" - if !beat(c, "maildirs02/a/long/way/down") + match maildir.changeinfo("a/cur/abcdefg.123:2,S", i) + | `std.Ok actual: + testr.check(c, std.sleq(actual, expected), \ + "expected “{}”, got “{}”", expected, actual) + | `std.Err e: + testr.fail(c, "{}", e) -> void ;; - if !mkpaths(c, [ "d/cur", "d/new", "d/tmp", - "a/cur", "a/new", "a/tmq", - "c/cur", "c/new", "c/tmq", "c/other", - "d/extraneous", - "cur/cur", "cur/new", "cur/tmp", - ][:]) - -> void - ;; + expected = "link(\"a/cur/abcdefg.123:2,S\", \"a/cur/abcdefg.123:2,PS\"): -2" - if !beat(c, "maildirs02") + match maildir.changeinfo("a/cur/abcdefg.123:2,S", i) + | `std.Ok actual: + testr.fail(c, "got “{}”, expected error") -> void + | `std.Err actual: + testr.check(c, std.sleq(actual, expected), \ + "expected “{}”, got “{}”", expected, actual) ;; - expected = [ "a/long/way/down/cur", "a/long/way/down/d" ][:] - match maildir.maildirs("a/long/way/down") - | `std.Ok a: - actual = a - testr.check(c, strseq(expected, actual), \ - "expected “{}”, got “{}”", expected, actual) - for aa : a - std.slfree(aa) - ;; - std.slfree(a) + expected2 = [ "a/cur/abcdefg.123:2,PS" ][:] + + match tree([ "a" ][:]) + | `std.Ok actual: + testr.check(c, strseq(expected2, actual), \ + "expected “{}”, got “{}”", expected2, actual) | `std.Err e: - testr.fail(c, "can't examine a/long/way/down: {}", e) + testr.fail(c, e) + -> void ;; } -const maildirs03 = {c : testr.ctx# - var expected : byte[:] +const cleanfs01 = {c : testr.ctx# + var s : std.strbuf# = std.mksb() + var expected : byte[:][:] = [][:] + var ago35 : uint64 = ((std.now() / std.Sec) : uint64) - (35 * 60 * 60) + var ago37 : uint64 = ((std.now() / std.Sec) : uint64) - (37 * 60 * 60) - if !beat(c, "maildirs03") + if !beat(c, "cleanfs01") + std.sbfree(s) -> void ;; - match maildir.maildirs("/dev/some/place/that/really/shouldn't/exist") - | `std.Ok _: - testr.fail(c, "got maildirs where none should be") - | `std.Err e: - /* TODO: should we really be checking this pedantically? */ - expected = "cannot open /dev/some/place/that/really/shouldn't/exist: couldn't open directory" - testr.check(c, std.sleq(e, expected), \ - "expected “{}”, got “{}”", \ - expected, e) + if !mkpaths(c, [ "a/cur", "a/new", "a/tmp", + "b/cur", "b/new", "b/tmp", + "c/cur", "c/new", "c/tmp" ][:]) + std.sbfree(s) + -> void ;; -} -const messages01 = {c : testr.ctx# - var expected : byte[:][:] - var actual : byte[:][:] - if !beat(c, "messages01") + expected = [ "a/cur/101:2,T", + "a/cur/102:2,FS", + "a/new/103:2,", + "a/new/104:2,R", + "a/tmp/105", + "a/tmp/106", + "b/cur/107:2,T", + "b/cur/108:2,S", + "b/new/109:2,", + "b/new/110:2,R", + "b/tmp/111", + "b/tmp/112", + "c/cur/113:2,T", + "c/cur/114:2,FP", + "c/new/115:2,", + "c/new/116:2,R", + "c/tmp/117", + "c/tmp/118", + ][:] + + if !mkfiles(c, expected) -> void ;; - if !mkpaths(c, [ "a/cur", "a/new", "a/tmp", "a/.qmail", - "a/new/foo", "a/cur/baz/quux", - "a/new/.ignorethis", "a/cur/......thistoo" - ][:]) + match tree(["a", "b", "c"][:]) + | `std.Ok actual: + testr.check(c, strseq(expected, actual), \ + "expected “{}”, got “{}”", expected, actual) + | `std.Err e: + testr.fail(c, e) -> void ;; - expected = std.sort([ "a/new/foo", "a/cur/baz" ][:], std.strcmp) - match maildir.messages("a") - | `std.Ok a: - testr.check(c, strseq(expected, a), \ - "expected “{}”, got “{}”", expected, a) - for aa : a - std.slfree(aa) - ;; - std.slfree(a) - | `std.Err e: - testr.fail(c, "can't list messages of a: {}", e) + if !settimes(c, [ "a/cur/101:2,T", + "a/new/103:2,", + "a/tmp/105", + "b/tmp/112", + "c/tmp/117" ][:], ago37) + -> void ;; -} -const messages02 = {c : testr.ctx# - var expected : byte[:] - if !beat(c, "messages02") + if !settimes(c, [ "a/tmp/106", + "b/tmp/111", + "c/tmp/118" ][:], ago35) -> void ;; - if !mkpaths(c, [ "b/cur", "b/new", "b/NOTtmp", - "b/new/foo", "b/cur/baz" - ][:]) + expected = [ "a/cur/102:2,FS", + "a/new/103:2,", + "a/new/104:2,R", + "a/tmp/106", + "b/cur/108:2,S", + "b/new/109:2,", + "b/new/110:2,R", + "b/tmp/111", + "c/cur/113:2,T", + "c/cur/114:2,FP", + "c/new/115:2,", + "c/new/116:2,R", + "c/tmp/117", + "c/tmp/118", + ][:] + match maildir.cleanfs(["a", "b"][:]) + | `std.Ok _: + | `std.Err e: + testr.fail(c, e) -> void ;; - match maildir.messages("b") - | `std.Ok a: - testr.fail(c, "got messages where none should be") + match tree(["a", "b", "c"][:]) + | `std.Ok actual: + testr.check(c, strseq(expected, actual), \ + "expected “{}”, got “{}”", expected, actual) | `std.Err e: - expected = "b is not a maildir" - testr.check(c, std.sleq(e, expected), \ - "expected “{}”, got “{}”", \ - expected, e) + testr.fail(c, e) + -> void ;; + } const info01 = {c : testr.ctx# - var m : byte[:][:] - var i : maildir.info + var m : byte[:][:] = [][:] + var i : maildir.info = [ .trashed = false ] var as : std.strbuf# = std.mksb() var es : std.strbuf# = std.mksb() var asp : byte[:] = "" @@ -415,8 +429,8 @@ const info01 = {c : testr.ctx# const infofmt01 = {c : testr.ctx# var s : std.strbuf# = std.mksb() var i : maildir.info = [ .passed = true ] - var actual : byte[:] - var expected : byte[:] + var actual : byte[:] = [][:] + var expected : byte[:] = [][:] std.sbtrim(s, 0) std.sbfmt(s, "{}", i) @@ -442,107 +456,146 @@ const infofmt01 = {c : testr.ctx# expected, actual) } -const cleanfs01= {c : testr.ctx# - var s : std.strbuf# = std.mksb() - var expected : byte[:][:] - var ago35 : uint64 = ((std.now() / std.Sec) : uint64) - (35 * 60 * 60) - var ago37 : uint64 = ((std.now() / std.Sec) : uint64) - (37 * 60 * 60) - - if !beat(c, "cleanfs01") - std.sbfree(s) +const maildirs01 = {c : testr.ctx# + var expected : byte[:][:] = [][:] + var actual : byte[:][:] = [][:] + if !beat(c, "maildirs01") -> void ;; if !mkpaths(c, [ "a/cur", "a/new", "a/tmp", - "b/cur", "b/new", "b/tmp", - "c/cur", "c/new", "c/tmp" ][:]) - std.sbfree(s) + "b/cur", "b/new", "b/tmq", + "c/cur", "c/new", "c/tmq", "c/other", + "d", + "cur/cur", "cur/new", "cur/tmp", + ][:]) -> void ;; - expected = [ "a/cur/101:2,T", - "a/cur/102:2,FS", - "a/new/103:2,", - "a/new/104:2,R", - "a/tmp/105", - "a/tmp/106", - "b/cur/107:2,T", - "b/cur/108:2,S", - "b/new/109:2,", - "b/new/110:2,R", - "b/tmp/111", - "b/tmp/112", - "c/cur/113:2,T", - "c/cur/114:2,FP", - "c/new/115:2,", - "c/new/116:2,R", - "c/tmp/117", - "c/tmp/118", - ][:] + expected = [ "a", "cur" ][:] + match maildir.maildirs(".") + | `std.Ok a: + actual = a + testr.check(c, strseq(expected, actual), \ + "expected “{}”, got “{}”", expected, actual) + for aa : a + std.slfree(aa) + ;; + std.slfree(a) + | `std.Err e: + testr.fail(c, "can't examine .: {}", e) + ;; +} - if !mkfiles(c, expected) +const maildirs02 = {c : testr.ctx# + var expected : byte[:][:] = [][:] + var actual : byte[:][:] = [][:] + + if !beat(c, "maildirs02/a/long/way/down") -> void ;; - match tree(["a", "b", "c"][:]) - | `std.Ok actual: + if !mkpaths(c, [ "d/cur", "d/new", "d/tmp", + "a/cur", "a/new", "a/tmq", + "c/cur", "c/new", "c/tmq", "c/other", + "d/extraneous", + "cur/cur", "cur/new", "cur/tmp", + ][:]) + -> void + ;; + + if !beat(c, "maildirs02") + -> void + ;; + + expected = [ "a/long/way/down/cur", "a/long/way/down/d" ][:] + match maildir.maildirs("a/long/way/down") + | `std.Ok a: + actual = a testr.check(c, strseq(expected, actual), \ "expected “{}”, got “{}”", expected, actual) + for aa : a + std.slfree(aa) + ;; + std.slfree(a) | `std.Err e: - testr.fail(c, e) + testr.fail(c, "can't examine a/long/way/down: {}", e) + ;; +} + +const maildirs03 = {c : testr.ctx# + var expected : byte[:] = [][:] + + if !beat(c, "maildirs03") -> void ;; - if !settimes(c, [ "a/cur/101:2,T", - "a/new/103:2,", - "a/tmp/105", - "b/tmp/112", - "c/tmp/117" ][:], ago37) + match maildir.maildirs("/dev/some/place/that/really/shouldn't/exist") + | `std.Ok _: + testr.fail(c, "got maildirs where none should be") + | `std.Err e: + /* TODO: should we really be checking this pedantically? */ + expected = "cannot open /dev/some/place/that/really/shouldn't/exist: couldn't open directory" + testr.check(c, std.sleq(e, expected), \ + "expected “{}”, got “{}”", \ + expected, e) + ;; +} + +const messages01 = {c : testr.ctx# + var expected : byte[:][:] = [][:] + var actual : byte[:][:] = [][:] + if !beat(c, "messages01") -> void ;; - if !settimes(c, [ "a/tmp/106", - "b/tmp/111", - "c/tmp/118" ][:], ago35) + if !mkpaths(c, [ "a/cur", "a/new", "a/tmp", "a/.qmail", + "a/new/foo", "a/cur/baz/quux", + "a/new/.ignorethis", "a/cur/......thistoo" + ][:]) -> void ;; - expected = [ "a/cur/102:2,FS", - "a/new/103:2,", - "a/new/104:2,R", - "a/tmp/106", - "b/cur/108:2,S", - "b/new/109:2,", - "b/new/110:2,R", - "b/tmp/111", - "c/cur/113:2,T", - "c/cur/114:2,FP", - "c/new/115:2,", - "c/new/116:2,R", - "c/tmp/117", - "c/tmp/118", - ][:] - match maildir.cleanfs(["a", "b"][:]) - | `std.Ok _: + expected = std.sort([ "a/new/foo", "a/cur/baz" ][:], std.strcmp) + match maildir.messages("a") + | `std.Ok a: + testr.check(c, strseq(expected, a), \ + "expected “{}”, got “{}”", expected, a) + for aa : a + std.slfree(aa) + ;; + std.slfree(a) | `std.Err e: - testr.fail(c, e) + testr.fail(c, "can't list messages of a: {}", e) + ;; +} + +const messages02 = {c : testr.ctx# + var expected : byte[:] = [][:] + if !beat(c, "messages02") -> void ;; - match tree(["a", "b", "c"][:]) - | `std.Ok actual: - testr.check(c, strseq(expected, actual), \ - "expected “{}”, got “{}”", expected, actual) - | `std.Err e: - testr.fail(c, e) + if !mkpaths(c, [ "b/cur", "b/new", "b/NOTtmp", + "b/new/foo", "b/cur/baz" + ][:]) -> void ;; + match maildir.messages("b") + | `std.Ok a: + testr.fail(c, "got messages where none should be") + | `std.Err e: + expected = "b is not a maildir" + testr.check(c, std.sleq(e, expected), \ + "expected “{}”, got “{}”", \ + expected, e) + ;; } const movemessage01 = {c : testr.ctx# var s : std.strbuf# = std.mksb() - var expected : byte[:][:] + var expected : byte[:][:] = [][:] if !beat(c, "movemessage01") std.sbfree(s) -- 2.11.4.GIT