Write more redbean unit tests

- Fix DescribeSigset()
- Introduce new unix.rmrf() API
- Fix redbean sigaction() doc example code
- Fix unix.sigaction() w/ more than two args
- Improve redbean re module API (non-breaking)
- Enhance Lua with Python string multiplication
- Make third parameter of unix.socket() default to 0
This commit is contained in:
Justine Tunney 2022-07-08 23:06:46 -07:00
parent c5b9902ac9
commit 1c83670229
20 changed files with 738 additions and 204 deletions

View file

@ -0,0 +1,28 @@
-- Copyright 2022 Justine Alexandra Roberts Tunney
--
-- Permission to use, copy, modify, and/or distribute this software for
-- any purpose with or without fee is hereby granted, provided that the
-- above copyright notice and this permission notice appear in all copies.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
-- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
assert(assert(argon2.hash_encoded("password", "somesalt", {
variant = argon2.variants.argon2_i,
m_cost = 65536,
hash_len = 24,
parallelism = 4,
t_cost = 2,
})) ==
"$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG")
assert(argon2.verify(
"$argon2i$v=19$m=65536,t=2," ..
"p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG",
"password"))

View file

@ -17,6 +17,9 @@ x = Rdtsc()
y = Rdtsc()
assert(y > x)
assert(Rdrand() ~= Rdrand())
assert(Rdseed() ~= Rdseed())
assert(Bsr(1) == 0)
assert(Bsr(2) == 1)
assert(Bsr(3) == 1)
@ -29,22 +32,54 @@ assert(Bsf(3) == 0)
assert(Bsf(4) == 2)
assert(Bsf(0x80000001) == 0)
assert(Popcnt(0) == 0)
assert(Popcnt(1) == 1)
assert(Popcnt(2) == 1)
assert(Popcnt(3) == 2)
assert(Popcnt(0b0111101001101001) == 9)
assert(Lemur64() == 0x1940efe9d47ae889)
assert(Lemur64() == 0xd4b3103f567f9974)
assert(hex(0x1940efe9d47ae889) == "0x1940efe9d47ae889")
assert(oct(0x1940efe9d47ae889) == "0145007376472436564211")
assert(bin(0x1940efe9d47ae889) == "0b0001100101000000111011111110100111010100011110101110100010001001")
assert(EscapeHtml("?hello&there<>") == "?hello&amp;there&lt;&gt;")
assert(EscapeParam("?hello&there<>") == "%3Fhello%26there%3C%3E")
assert(DecodeLatin1("hello\xff\xc0") == "helloÿÀ")
assert(EncodeLatin1("helloÿÀ") == "hello\xff\xc0")
assert(EncodeLua(nil) == "nil")
assert(EncodeLua(0) == "0")
assert(EncodeLua(3.14) == "3.14")
assert(EncodeLua({1, 2}) == "{1, 2}")
x = {1, 2}
x[3] = x
assert(string.match(EncodeLua(x), "{1, 2, \"cyclic@0x%x+\"}"))
-- TODO(jart): EncodeLua() should sort tables
-- x = {}
-- x.c = 'c'
-- x.a = 'a'
-- x.b = 'b'
-- assert(EncodeLua(x) == '{a="a", b="b", c="c"}')
assert(EncodeJson(nil) == "null")
assert(EncodeJson(0) == "0")
assert(EncodeJson(3.14) == "3.14")
assert(EncodeJson({1, 2}) == "[1,2]")
assert(hex(0x1940efe9d47ae889) == "0x1940efe9d47ae889")
assert(oct(0x1940efe9d47ae889) == "0145007376472436564211")
assert(bin(0x1940efe9d47ae889) == "0b0001100101000000111011111110100111010100011110101110100010001001")
url = ParseUrl("https://jart:pass@redbean.dev/2.0.html?x&y=z#frag")
assert(url.scheme == "https")
assert(url.user == "jart")
assert(url.pass == "pass")
assert(url.host == "redbean.dev")
assert(not url.port)
assert(url.path == "/2.0.html")
assert(EncodeLua(url.params) == '{{"x"}, {"y", "z"}}')
assert(url.fragment == "frag")
assert(DecodeBase64("abcdefgABCDE") == "\x69\xb7\x1d\x79\xf8\x00\x04\x20\xc4")
assert(EncodeBase64("\x69\xb7\x1d\x79\xf8\x00\x04\x20\xc4") == "abcdefgABCDE")
@ -82,6 +117,7 @@ assert(IndentLines("hi\nthere\n") == " hi\n there\n")
assert(IndentLines("hi\nthere\n", 2) == " hi\n there\n")
assert(ParseHttpDateTime("Fri, 08 Jul 2022 16:17:43 GMT") == 1657297063)
assert(FormatHttpDateTime(1657297063) == "Fri, 08 Jul 2022 16:17:43 GMT")
assert(VisualizeControlCodes("hello\x00") == "hello␀")
@ -97,8 +133,8 @@ assert(Sha256("hello") == "\x2c\xf2\x4d\xba\x5f\xb0\xa3\x0e\x26\xe8\x3b\x2a\xc5\
assert(Sha384("hello") == "\x59\xe1\x74\x87\x77\x44\x8c\x69\xde\x6b\x80\x0d\x7a\x33\xbb\xfb\x9f\xf1\xb4\x63\xe4\x43\x54\xc3\x55\x3b\xcd\xb9\xc6\x66\xfa\x90\x12\x5a\x3c\x79\xf9\x03\x97\xbd\xf5\xf6\xa1\x3d\xe8\x28\x68\x4f")
assert(Sha512("hello") == "\x9b\x71\xd2\x24\xbd\x62\xf3\x78\x5d\x96\xd4\x6a\xd3\xea\x3d\x73\x31\x9b\xfb\xc2\x89\x0c\xaa\xda\xe2\xdf\xf7\x25\x19\x67\x3c\xa7\x23\x23\xc3\xd9\x9b\xa5\xc1\x1d\x7c\x7a\xcc\x6e\x14\xb8\xc5\xda\x0c\x46\x63\x47\x5c\x2e\x5c\x3a\xde\xf4\x6f\x73\xbc\xde\xc0\x43")
assert(Deflate("hello") == "\xcbH\xcd\xc9\xc9\x07\x00")
assert(Inflate("\xcbH\xcd\xc9\xc9\x07\x00", 5) == "hello")
assert(assert(Deflate("hello")) == "\xcbH\xcd\xc9\xc9\x07\x00")
assert(assert(Inflate("\xcbH\xcd\xc9\xc9\x07\x00", 5)) == "hello")
-- deprecated compression api we wish to forget as quickly as possible
assert(Uncompress(Compress("hello")) == "hello")

View file

@ -0,0 +1,40 @@
-- Copyright 2022 Justine Alexandra Roberts Tunney
--
-- Permission to use, copy, modify, and/or distribute this software for
-- any purpose with or without fee is hereby granted, provided that the
-- above copyright notice and this permission notice appear in all copies.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
-- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
m,a,b,c,d = assert(re.search([[^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$]], "127.0.0.1"))
assert(m == "127.0.0.1")
assert(a == "127")
assert(b == "0")
assert(c == "0")
assert(d == "1")
p = assert(re.compile[[^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$]])
m,a,b,c,d = assert(p:search("127.0.0.1"))
assert(m == "127.0.0.1")
assert(a == "127")
assert(b == "0")
assert(c == "0")
assert(d == "1")
m,a,b,c,d = assert(re.search([[\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)]], "127.0.0.1", re.BASIC))
assert(m == "127.0.0.1")
assert(a == "127")
assert(b == "0")
assert(c == "0")
assert(d == "1")
p,e = re.compile("[{")
assert(e:errno() == re.EBRACK)
assert(e:doc() == "Missing ']'")

View file

@ -0,0 +1,21 @@
-- Copyright 2022 Justine Alexandra Roberts Tunney
--
-- Permission to use, copy, modify, and/or distribute this software for
-- any purpose with or without fee is hereby granted, provided that the
-- above copyright notice and this permission notice appear in all copies.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
-- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
-- test redbean lua language extensions
assert(0b100 == 4)
assert(0200 == 128)
assert("\e" == "\x1b")
assert("hi" * 3 == "hihihi")
assert("hello %d" % {123} == "hello 123")

View file

@ -13,40 +13,147 @@
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
-- dup()+close()
fd = assert(unix.dup(2))
assert(unix.close(fd))
gotsigusr1 = false
tmpdir = "o/tmp/lunix_test.%d" % {unix.getpid()}
-- dup2()+close()
assert(assert(unix.dup(2, 10)) == 10)
assert(unix.close(10))
-- fork()+exit()
if assert(unix.fork()) == 0 then
unix.exit(42)
function OnSigUsr1(sig)
gotsigusr1 = true
end
pid, ws = assert(unix.wait())
assert(unix.WIFEXITED(ws))
assert(unix.WEXITSTATUS(ws) == 42)
-- pledge()
if GetHostOs() == "LINUX" then
function UnixTest()
-- strsignal
assert(unix.strsignal(9) == "SIGKILL")
assert(unix.strsignal(unix.SIGKILL) == "SIGKILL")
-- gmtime
year,mon,mday,hour,min,sec,gmtoffsec,wday,yday,dst,zone = assert(unix.gmtime(1657297063))
assert(year == 2022)
assert(mon == 7)
assert(mday == 8)
assert(hour == 16)
assert(min == 17)
assert(sec == 43)
assert(gmtoffsec == 0)
assert(wday == 5)
assert(yday == 188)
assert(dst == 0)
assert(zone == "GMT")
-- dup
-- 1. duplicate stderr as lowest available fd
-- 1. close the newly assigned file descriptor
fd = assert(unix.dup(2))
assert(unix.close(fd))
-- dup2
-- 1. duplicate stderr as fd 10
-- 1. close the new file descriptor
assert(assert(unix.dup(2, 10)) == 10)
assert(unix.close(10))
-- fork
-- basic subprocess creation
if assert(unix.fork()) == 0 then
assert(unix.pledge("stdio"))
_, err = unix.socket()
assert(err:errno() == unix.EPERM)
unix.exit(0)
unix.pledge("")
unix.exit(42)
end
pid, ws = assert(unix.wait())
assert(unix.WIFEXITED(ws))
assert(unix.WEXITSTATUS(ws) == 0)
elseif GetHostOs() == "OPENBSD" then
if assert(unix.fork()) == 0 then
assert(unix.pledge("stdio"))
unix.socket()
unix.exit(1)
assert(unix.WEXITSTATUS(ws) == 42)
-- pledge
-- 1. fork off a process
-- 2. sandbox the process
-- 3. then violate its security
if GetHostOs() == "LINUX" then
if assert(unix.fork()) == 0 then
assert(unix.pledge("stdio"))
_, err = unix.socket()
assert(err:errno() == unix.EPERM)
unix.exit(0)
end
pid, ws = assert(unix.wait())
assert(unix.WIFEXITED(ws))
assert(unix.WEXITSTATUS(ws) == 0)
elseif GetHostOs() == "OPENBSD" then
if assert(unix.fork()) == 0 then
assert(unix.pledge("stdio"))
unix.socket()
unix.exit(1)
end
pid, ws = assert(unix.wait())
assert(unix.WIFSIGNALED(ws))
assert(unix.WTERMSIG(ws) == unix.SIGABRT)
end
pid, ws = assert(unix.wait())
assert(unix.WIFSIGNALED(ws))
assert(unix.WTERMSIG(ws) == unix.SIGABRT)
-- sigaction
-- 1. install a signal handler for USR1
-- 2. block USR1
-- 3. trigger USR1 signal [it gets enqueued]
-- 4. pause() w/ atomic unblocking of USR1 [now it gets delivered!]
-- 5. restore old signal mask
-- 6. restore old sig handler
oldhand, oldflags, oldmask = assert(unix.sigaction(unix.SIGUSR1, OnSigUsr1))
oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, unix.Sigset(unix.SIGUSR1)))
assert(unix.raise(unix.SIGUSR1))
assert(not gotsigusr1)
ok, err = unix.sigsuspend(oldmask)
assert(not ok)
assert(err:errno() == unix.EINTR)
assert(gotsigusr1)
assert(unix.sigprocmask(unix.SIG_SETMASK, oldmask))
assert(unix.sigaction(unix.SIGUSR1, oldhand, oldflags, oldmask))
-- open
-- 1. create file
-- 2. fill it up
-- 3. inspect it
-- 4. mess with it
fd = assert(unix.open("%s/foo" % {tmpdir}, unix.O_RDWR | unix.O_CREAT | unix.O_TRUNC, 0600))
assert(assert(unix.fstat(fd)):size() == 0)
assert(unix.ftruncate(fd, 8192))
assert(assert(unix.fstat(fd)):size() == 8192)
assert(unix.write(fd, "hello"))
assert(unix.lseek(fd, 4096))
assert(unix.write(fd, "poke"))
assert(unix.lseek(fd, 8192-4))
assert(unix.write(fd, "poke"))
st = assert(unix.fstat(fd))
assert(st:size() == 8192)
assert(st:blocks() == 8192/512)
assert((st:mode() & 0777) == 0600)
assert(st:uid() == unix.getuid())
assert(st:gid() == unix.getgid())
assert(unix.write(fd, "bear", 4))
assert(unix.read(fd, 10, 0) == "hellbear\x00\x00")
assert(unix.close(fd))
fd = assert(unix.open("%s/foo" % {tmpdir}))
assert(unix.lseek(fd, 4))
assert(unix.read(fd, 4) == "bear")
assert(unix.close(fd))
fd = assert(unix.open("%s/foo" % {tmpdir}, unix.O_RDWR))
assert(unix.write(fd, "bear"))
assert(unix.close(fd))
fd = assert(unix.open("%s/foo" % {tmpdir}))
assert(unix.read(fd, 8) == "bearbear")
assert(unix.close(fd))
-- getdents
for name, kind, ino, off in assert(unix.opendir(tmpdir)) do
end
end
function main()
assert(unix.makedirs(tmpdir))
ok, err = pcall(UnixTest)
if ok then
assert(unix.rmrf(tmpdir))
else
print(err)
error('UnixTest failed (%s)' % {tmpdir})
end
end
main()