From 6dd115015c6f2514a2f180aaf474a66364939c31 Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Tue, 25 Sep 2001 21:35:17 +0000 Subject: [PATCH] Initial revision --- test/smtptest.lua | 306 ++++++++++++++++++++++++++++++++++++ test/urltest.lua | 388 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 694 insertions(+) create mode 100644 test/smtptest.lua create mode 100644 test/urltest.lua diff --git a/test/smtptest.lua b/test/smtptest.lua new file mode 100644 index 0000000..fcd238b --- /dev/null +++ b/test/smtptest.lua @@ -0,0 +1,306 @@ +local sent = {} + +local from = "luasock@tecgraf.puc-rio.br" +local server = "mail.tecgraf.puc-rio.br" +local rcpt = "luasock@tecgraf.puc-rio.br" + +local parse = {} + +local name = "/var/spool/mail/luasock" + +local t = _time() +local err + +function mysetglobal (varname, oldvalue, newvalue) + print("changing " .. varname) + %rawset(%globals(), varname, newvalue) +end +function mygetglobal (varname, newvalue) + print("checking " .. varname) + return %rawget(%globals(), varname) +end +settagmethod(tag(nil), "setglobal", mysetglobal) +settagmethod(tag(nil), "getglobal", mygetglobal) + +assert(dofile("../lua/smtp.lua")) +assert(dofile("../lua/cl-compat.lua")) + +local total = function() + local t = 0 + for i = 1, getn(%sent) do + t = t + %sent[i].count + end + return t +end + +local similar = function(s1, s2) + return strlower(gsub(s1, "%s", "")) == strlower(gsub(s2, "%s", "")) +end + +function parse.headers(headers_s) + local headers = {} + headers_s = "\n" .. headers_s .. "$$$:\n" + local i, j = 1, 1 + local name, value, _ + while 1 do + j = strfind(headers_s, "\n%S-:", i+1) + if not j then break end + _, _, name, value = strfind(strsub(headers_s, i+1, j-1), "(%S-): (.*)") + value = gsub(value, "\r\n", "\n") + value = gsub(value, "\n%s*", " ") + name = strlower(name) + if headers[name] then headers[name] = headers[name] .. ", " .. value + else headers[name] = value end + i, j = j, i + end + headers["$$$"] = nil + return headers +end + +function parse.message(message_s) + message_s = gsub(message_s, "^.-\n", "") + local _, headers_s, body + _, _, headers_s, body = strfind(message_s, "^(.-\n)\n(.*)") + headers_s = headers_s or "" + body = body or "" + return { headers = %parse.headers(headers_s), body = body } +end + +function parse.mbox(mbox_s) + local mbox = {} + mbox_s = "\n" .. mbox_s .. "\nFrom " + local i, j = 1, 1 + while 1 do + j = strfind(mbox_s, "\nFrom ", i + 1) + if not j then break end + tinsert(mbox, %parse.message(strsub(mbox_s, i + 1, j - 1))) + i, j = j, i + end + return mbox +end + +local readfile = function(name) + local f = readfrom(name) + if not f then return nil end + local s = read("*a") + readfrom() + return s +end + +local capture = function(cmd) + readfrom("| " .. cmd) + local s = read("*a") + readfrom() + return s +end + +local fail = function(s) + s = s or "failed!" + print(s) + exit() +end + +local empty = function() + local f = openfile(%name, "w") + closefile(f) +end + +local get = function() + return %readfile(%name) +end + +local list = function() + return %capture("ls -l " .. %name) +end + +local check_headers = function(sent, got) + sent = sent or {} + got = got or {} + for i,v in sent do + if not %similar(v, got[i]) then %fail("header " .. v .. "failed!") end + end +end + +local check_body = function(sent, got) + sent = sent or "" + got = got or "" + if not %similar(sent, got) then %fail("bodies differ!") end +end + +local check = function(sent, m) + write("checking ", m.headers.title, ": ") + for i = 1, getn(sent) do + local s = sent[i] + if s.title == m.headers.title and s.count > 0 then + %check_headers(s.headers, m.headers) + %check_body(s.body, m.body) + s.count = s.count - 1 + print("ok") + return + end + end + %fail("not found") +end + +local insert = function(sent, message) + if type(message.rcpt) == "table" then + message.count = getn(message.rcpt) + else message.count = 1 end + message.headers = message.headers or {} + message.headers.title = message.title + tinsert(sent, message) +end + +local mark = function() + local time = _time() + return { time = time } +end + +local wait = function(sentinel, n) + local to + write("waiting for ", n, " messages: ") + while 1 do + local mbox = %parse.mbox(%get()) + if n == getn(mbox) then break end + if _time() - sentinel.time > 50 then + to = 1 + break + end + _sleep(1) + write(".") + flush(_STDOUT) + end + if to then %fail("timeout") + else print("ok") end +end + +local stuffed_body = [[ +This message body needs to be +stuffed because it has a dot +. +by itself on a line. +Otherwise the mailer would +think that the dot +. +is the end of the message +and the remaining will cause +a lot of trouble. +]] + +insert(sent, { + from = from, + rcpt = { + "luasock2@tecgraf.puc-rio.br", + "luasock", + "luasock1" + }, + body = "multiple rcpt body", + title = "multiple rcpt", +}) + +insert(sent, { + from = from, + rcpt = { + "luasock2@tecgraf.puc-rio.br", + "luasock", + "luasock1" + }, + headers = { + header1 = "header 1", + header2 = "header 2", + header3 = "header 3", + header4 = "header 4", + header5 = "header 5", + header6 = "header 6", + }, + body = stuffed_body, + title = "complex message", +}) + +insert(sent, { + from = from, + rcpt = rcpt, + server = server, + body = "simple message body", + title = "simple message" +}) + +insert(sent, { + from = from, + rcpt = rcpt, + server = server, + body = stuffed_body, + title = "stuffed message body" +}) + +insert(sent, { + from = from, + rcpt = rcpt, + headers = { + header1 = "header 1", + header2 = "header 2", + header3 = "header 3", + header4 = "header 4", + header5 = "header 5", + header6 = "header 6", + }, + title = "multiple headers" +}) + +insert(sent, { + from = from, + rcpt = rcpt, + title = "minimum message" +}) + +write("testing host not found: ") +local c, e = connect("wrong.host", 25) +local err = SMTP.mail{ + from = from, + rcpt = rcpt, + server = "wrong.host" +} +if e ~= err then fail("wrong error message") +else print("ok") end + +write("testing invalid from: ") +local err = SMTP.mail{ + from = ' " " (( _ * ', + rcpt = rcpt, +} +if not err then fail("wrong error message") +else print(err) end + +write("testing no rcpt: ") +local err = SMTP.mail{ + from = from, +} +if not err then fail("wrong error message") +else print(err) end + +write("clearing mailbox: ") +empty() +print("ok") + +write("sending messages: ") +for i = 1, getn(sent) do + err = SMTP.mail(sent[i]) + if err then fail(err) end + write("+") + flush(_STDOUT) +end +print("ok") + +wait(mark(), total()) + +write("parsing mailbox: ") +local mbox = parse.mbox(get()) +print(getn(mbox) .. " messages found!") + +for i = 1, getn(mbox) do + check(sent, mbox[i]) +end + + +print("passed all tests") +print(format("done in %.2fs", _time() - t)) diff --git a/test/urltest.lua b/test/urltest.lua new file mode 100644 index 0000000..20a4f7d --- /dev/null +++ b/test/urltest.lua @@ -0,0 +1,388 @@ +function mysetglobal (varname, oldvalue, newvalue) + print("changing " .. varname) + %rawset(%globals(), varname, newvalue) +end +function mygetglobal (varname, newvalue) + print("checking " .. varname) + return %rawget(%globals(), varname) +end +settagmethod(tag(nil), "setglobal", mysetglobal) +settagmethod(tag(nil), "getglobal", mygetglobal) + +assert(dofile "../lua/code.lua") +assert(dofile "../lua/url.lua") + +local check_protect = function(parsed, path) + local built = URL.build_path(parsed) + if built ~= path then + print(built, path) + print("path composition failed.") + exit() + end +end + +local check_invert = function(url) + local parsed = URL.parse_url(url) + parsed.path = URL.build_path(URL.parse_path(parsed.path)) + local rebuilt = URL.build_url(parsed) + if rebuilt ~= url then + print(url, rebuilt) + print("original and rebuilt are different") + exit() + end +end + +local check_parse_path = function(path, expect) + local parsed = URL.parse_path(path) + for i = 1, max(getn(parsed), getn(expect)) do + if parsed[i] ~= expect[i] then + print(path) + write("segment: ", i, " = '", Code.hexa(tostring(parsed[i])), + "' but expected '", Code.hexa(tostring(expect[i])), "'\n") + exit() + end + end + if expect.is_directory ~= parsed.is_directory then + print(path) + print("is_directory mismatch") + exit() + end + if expect.is_absolute ~= parsed.is_absolute then + print(path) + print("is_absolute mismatch") + exit() + end + local built = URL.build_path(expect) + if built ~= path then + print(built, path) + print("path composition failed.") + exit() + end +end + +local check_absolute_url = function(base, relative, absolute) + local res = URL.absolute_url(base, relative) + if res ~= absolute then + write("absolute: In test for '", relative, "' expected '", + absolute, "' but got '", res, "'\n") + exit() + end +end + +local check_parse_url = function(gaba) + local url = gaba.url + gaba.url = nil + local parsed = URL.parse_url(url) + for i, v in gaba do + if v ~= parsed[i] then + write("parse: In test for '", url, "' expected ", i, " = '", + v, "' but got '", tostring(parsed[i]), "'\n") + for i,v in parsed do print(i,v) end + exit() + end + end + for i, v in parsed do + if v ~= gaba[i] then + write("parse: In test for '", url, "' expected ", i, " = '", + tostring(gaba[i]), "' but got '", v, "'\n") + for i,v in parsed do print(i,v) end + exit() + end + end +end + +print("testing URL parsing") +check_parse_url{ + url = "scheme://userinfo@host:port/path;params?query#fragment", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", + params = "params", + query = "query", + fragment = "fragment" +} + +check_parse_url{ + url = "scheme://user:password@host:port/path;params?query#fragment", + scheme = "scheme", + authority = "user:password@host:port", + host = "host", + port = "port", + userinfo = "user:password", + user = "user", + password = "password", + path = "/path", + params = "params", + query = "query", + fragment = "fragment", +} + +check_parse_url{ + url = "scheme://userinfo@host:port/path;params?query#", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", + params = "params", + query = "query", + fragment = "" +} + +check_parse_url{ + url = "scheme://userinfo@host:port/path;params?#fragment", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", + params = "params", + query = "", + fragment = "fragment" +} + +check_parse_url{ + url = "scheme://userinfo@host:port/path;params#fragment", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", + params = "params", + fragment = "fragment" +} + +check_parse_url{ + url = "scheme://userinfo@host:port/path;?query#fragment", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", + params = "", + query = "query", + fragment = "fragment" +} + +check_parse_url{ + url = "scheme://userinfo@host:port/path?query#fragment", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", + query = "query", + fragment = "fragment" +} + +check_parse_url{ + url = "scheme://userinfo@host:port/;params?query#fragment", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/", + params = "params", + query = "query", + fragment = "fragment" +} + +check_parse_url{ + url = "scheme://userinfo@host:port", + scheme = "scheme", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", +} + +check_parse_url{ + url = "//userinfo@host:port/path;params?query#fragment", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", + params = "params", + query = "query", + fragment = "fragment" +} + +check_parse_url{ + url = "//userinfo@host:port/path", + authority = "userinfo@host:port", + host = "host", + port = "port", + userinfo = "userinfo", + user = "userinfo", + path = "/path", +} + +check_parse_url{ + url = "//userinfo@host/path", + authority = "userinfo@host", + host = "host", + userinfo = "userinfo", + user = "userinfo", + path = "/path", +} + +check_parse_url{ + url = "//user:password@host/path", + authority = "user:password@host", + host = "host", + userinfo = "user:password", + password = "password", + user = "user", + path = "/path", +} + +check_parse_url{ + url = "//user:@host/path", + authority = "user:@host", + host = "host", + userinfo = "user:", + password = "", + user = "user", + path = "/path", +} + +check_parse_url{ + url = "//user@host:port/path", + authority = "user@host:port", + host = "host", + userinfo = "user", + user = "user", + port = "port", + path = "/path", +} + +check_parse_url{ + url = "//host:port/path", + authority = "host:port", + port = "port", + host = "host", + path = "/path", +} + +check_parse_url{ + url = "//host/path", + authority = "host", + host = "host", + path = "/path", +} + +check_parse_url{ + url = "//host", + authority = "host", + host = "host", +} + +check_parse_url{ + url = "/path", + path = "/path", +} + +check_parse_url{ + url = "path", + path = "path", +} + +-- standard RFC tests +print("testing absolute resolution") +check_absolute_url("http://a/b/c/d;p?q#f", "g:h", "g:h") +check_absolute_url("http://a/b/c/d;p?q#f", "g", "http://a/b/c/g") +check_absolute_url("http://a/b/c/d;p?q#f", "./g", "http://a/b/c/g") +check_absolute_url("http://a/b/c/d;p?q#f", "g/", "http://a/b/c/g/") +check_absolute_url("http://a/b/c/d;p?q#f", "/g", "http://a/g") +check_absolute_url("http://a/b/c/d;p?q#f", "//g", "http://g") +check_absolute_url("http://a/b/c/d;p?q#f", "?y", "http://a/b/c/d;p?y") +check_absolute_url("http://a/b/c/d;p?q#f", "g?y", "http://a/b/c/g?y") +check_absolute_url("http://a/b/c/d;p?q#f", "g?y/./x", "http://a/b/c/g?y/./x") +check_absolute_url("http://a/b/c/d;p?q#f", "#s", "http://a/b/c/d;p?q#s") +check_absolute_url("http://a/b/c/d;p?q#f", "g#s", "http://a/b/c/g#s") +check_absolute_url("http://a/b/c/d;p?q#f", "g#s/./x", "http://a/b/c/g#s/./x") +check_absolute_url("http://a/b/c/d;p?q#f", "g?y#s", "http://a/b/c/g?y#s") +check_absolute_url("http://a/b/c/d;p?q#f", ";x", "http://a/b/c/d;x") +check_absolute_url("http://a/b/c/d;p?q#f", "g;x", "http://a/b/c/g;x") +check_absolute_url("http://a/b/c/d;p?q#f", "g;x?y#s", "http://a/b/c/g;x?y#s") +check_absolute_url("http://a/b/c/d;p?q#f", ".", "http://a/b/c/") +check_absolute_url("http://a/b/c/d;p?q#f", "./", "http://a/b/c/") +check_absolute_url("http://a/b/c/d;p?q#f", "..", "http://a/b/") +check_absolute_url("http://a/b/c/d;p?q#f", "../", "http://a/b/") +check_absolute_url("http://a/b/c/d;p?q#f", "../g", "http://a/b/g") +check_absolute_url("http://a/b/c/d;p?q#f", "../..", "http://a/") +check_absolute_url("http://a/b/c/d;p?q#f", "../../", "http://a/") +check_absolute_url("http://a/b/c/d;p?q#f", "../../g", "http://a/g") +check_absolute_url("http://a/b/c/d;p?q#f", "", "http://a/b/c/d;p?q#f") +check_absolute_url("http://a/b/c/d;p?q#f", "/./g", "http://a/./g") +check_absolute_url("http://a/b/c/d;p?q#f", "/../g", "http://a/../g") +check_absolute_url("http://a/b/c/d;p?q#f", "g.", "http://a/b/c/g.") +check_absolute_url("http://a/b/c/d;p?q#f", ".g", "http://a/b/c/.g") +check_absolute_url("http://a/b/c/d;p?q#f", "g..", "http://a/b/c/g..") +check_absolute_url("http://a/b/c/d;p?q#f", "..g", "http://a/b/c/..g") +check_absolute_url("http://a/b/c/d;p?q#f", "./../g", "http://a/b/g") +check_absolute_url("http://a/b/c/d;p?q#f", "./g/.", "http://a/b/c/g/") +check_absolute_url("http://a/b/c/d;p?q#f", "g/./h", "http://a/b/c/g/h") +check_absolute_url("http://a/b/c/d;p?q#f", "g/../h", "http://a/b/c/h") + +-- extra tests +check_absolute_url("//a/b/c/d;p?q#f", "d/e/f", "//a/b/c/d/e/f") +check_absolute_url("/a/b/c/d;p?q#f", "d/e/f", "/a/b/c/d/e/f") +check_absolute_url("a/b/c/d", "d/e/f", "a/b/c/d/e/f") +check_absolute_url("a/b/c/d/../", "d/e/f", "a/b/c/d/e/f") +check_absolute_url("http://velox.telemar.com.br", "/dashboard/index.html", + "http://velox.telemar.com.br/dashboard/index.html") + +print("testing path parsing and composition") +check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 }) +check_parse_path("/eu/", { "eu"; is_absolute = 1, is_directory = 1 }) +check_parse_path("eu/tu/ele/nos/vos/eles/", + { "eu", "tu", "ele", "nos", "vos", "eles"; is_directory = 1}) +check_parse_path("/", { is_absolute = 1, is_directory = 1}) +check_parse_path("", { }) +check_parse_path("eu%01/%02tu/e%03l%04e/nos/vos%05/e%12les/", + { "eu\1", "\2tu", "e\3l\4e", "nos", "vos\5", "e\18les"; is_directory = 1}) +check_parse_path("eu/tu", { "eu", "tu" }) + +print("testing path protection") +check_protect({ "eu", "-_.!~*'():@&=+$,", "tu" }, "eu/-_.!~*'():@&=+$,/tu") +check_protect({ "eu ", "~diego" }, "eu%20/~diego") +check_protect({ "/eu>", "