aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorLibravatarLibravatar daurnimator <quae@daurnimator.com> 2017-08-30 13:55:59 +1000
committerLibravatarLibravatar daurnimator <quae@daurnimator.com> 2017-08-30 13:55:59 +1000
commit7333333568b13db56136e2354c55556adc7714ed (patch)
tree028cec7c885ebbbdd404d9db7aba8510f87681a4 /tests
downloadluaossl-7333333568b13db56136e2354c55556adc7714ed.tar.gz
luaossl-7333333568b13db56136e2354c55556adc7714ed.tar.bz2
luaossl-7333333568b13db56136e2354c55556adc7714ed.zip
Squashed 'vendor/compat53/' content from commit 6f3deea
git-subtree-dir: vendor/compat53 git-subtree-split: 6f3deeaa6a4743e1f5148c613addb3f94a22d2df
Diffstat (limited to 'tests')
-rwxr-xr-xtests/test.lua789
-rw-r--r--tests/testmod.c318
2 files changed, 1107 insertions, 0 deletions
diff --git a/tests/test.lua b/tests/test.lua
new file mode 100755
index 0000000..582f55e
--- /dev/null
+++ b/tests/test.lua
@@ -0,0 +1,789 @@
+#!/usr/bin/env lua
+
+local F, tproxy, writefile, noprint, ___
+do
+ local type, unpack = type, table.unpack or unpack
+ local assert, io = assert, io
+ function F(...)
+ local args, n = { ... }, select('#', ...)
+ for i = 1, n do
+ local t = type(args[i])
+ if t ~= "string" and t ~= "number" and t ~= "boolean" then
+ args[i] = t
+ end
+ end
+ return unpack(args, 1, n)
+ end
+ function tproxy(t)
+ return setmetatable({}, {
+ __index = t,
+ __newindex = t,
+ __len = function() return #t end,
+ }), t
+ end
+ function writefile(name, contents, bin)
+ local f = assert(io.open(name, bin and "wb" or "w"))
+ f:write(contents)
+ f:close()
+ end
+ function noprint() end
+ local sep = ("="):rep(70)
+ function ___()
+ print(sep)
+ end
+end
+
+local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2")
+if jit then V = "jit" end
+
+local mode = "global"
+if arg[1] == "module" then
+ mode = "module"
+end
+
+
+package.path = "../?.lua;../?/init.lua"
+package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll"
+if mode == "module" then
+ print("testing Lua API using `compat53.module` ...")
+ _ENV = require("compat53.module")
+ if setfenv then setfenv(1, _ENV) end
+else
+ print("testing Lua API using `compat53` ...")
+ require("compat53")
+end
+
+
+___''
+do
+ print("assert", F(pcall(assert, false)))
+ print("assert", F(pcall(assert, false, nil)))
+ print("assert", F(pcall(assert, false, "error msg")))
+ print("assert", F(pcall(assert, nil, {})))
+ print("assert", F(pcall(assert, 1, 2, 3)))
+end
+
+
+___''
+do
+ local t = setmetatable({}, { __index = { 1, false, "three" } })
+ for i,v in ipairs(t) do
+ print("ipairs", i, v)
+ end
+end
+
+
+___''
+do
+ local p, t = tproxy{ "a", "b", "c" }
+ print("table.concat", table.concat(p))
+ print("table.concat", table.concat(p, ",", 2))
+ print("table.concat", table.concat(p, ".", 1, 2))
+ print("table.concat", table.concat(t))
+ print("table.concat", table.concat(t, ",", 2))
+ print("table.concat", table.concat(t, ".", 1, 2))
+end
+
+
+___''
+do
+ local p, t = tproxy{ "a", "b", "c" }
+ table.insert(p, "d")
+ print("table.insert", next(p), t[4])
+ table.insert(p, 1, "z")
+ print("table.insert", next(p), t[1], t[2])
+ table.insert(p, 2, "y")
+ print("table.insert", next(p), t[1], t[2], p[3])
+ t = { "a", "b", "c" }
+ table.insert(t, "d")
+ print("table.insert", t[1], t[2], t[3], t[4])
+ table.insert(t, 1, "z")
+ print("table.insert", t[1], t[2], t[3], t[4], t[5])
+ table.insert(t, 2, "y")
+ print("table.insert", t[1], t[2], t[3], t[4], t[5])
+end
+
+
+___''
+do
+ local ps, s = tproxy{ "a", "b", "c", "d" }
+ local pd, d = tproxy{ "A", "B", "C", "D" }
+ table.move(ps, 1, 4, 1, pd)
+ print("table.move", next(pd), d[1], d[2], d[3], d[4])
+ pd, d = tproxy{ "A", "B", "C", "D" }
+ table.move(ps, 2, 4, 1, pd)
+ print("table.move", next(pd), d[1], d[2], d[3], d[4])
+ pd, d = tproxy{ "A", "B", "C", "D" }
+ table.move(ps, 2, 3, 4, pd)
+ print("table.move", next(pd), d[1], d[2], d[3], d[4], d[5])
+ table.move(ps, 2, 4, 1)
+ print("table.move", next(ps), s[1], s[2], s[3], s[4])
+ ps, s = tproxy{ "a", "b", "c", "d" }
+ table.move(ps, 2, 3, 4)
+ print("table.move", next(ps), s[1], s[2], s[3], s[4], s[5])
+ s = { "a", "b", "c", "d" }
+ d = { "A", "B", "C", "D" }
+ table.move(s, 1, 4, 1, d)
+ print("table.move", d[1], d[2], d[3], d[4])
+ d = { "A", "B", "C", "D" }
+ table.move(s, 2, 4, 1, d)
+ print("table.move", d[1], d[2], d[3], d[4])
+ d = { "A", "B", "C", "D" }
+ table.move(s, 2, 3, 4, d)
+ print("table.move", d[1], d[2], d[3], d[4], d[5])
+ table.move(s, 2, 4, 1)
+ print("table.move", s[1], s[2], s[3], s[4])
+ s = { "a", "b", "c", "d" }
+ table.move(s, 2, 3, 4)
+ print("table.move", s[1], s[2], s[3], s[4], s[5])
+end
+
+
+___''
+do
+ local p, t = tproxy{ "a", "b", "c", "d", "e" }
+ print("table.remove", table.remove(p))
+ print("table.remove", next(p), t[1], t[2], t[3], t[4], t[5])
+ print("table.remove", table.remove(p, 1))
+ print("table.remove", next(p), t[1], t[2], t[3], t[4])
+ print("table.remove", table.remove(p, 2))
+ print("table.remove", next(p), t[1], t[2], t[3])
+ print("table.remove", table.remove(p, 3))
+ print("table.remove", next(p), t[1], t[2], t[3])
+ p, t = tproxy{}
+ print("table.remove", table.remove(p))
+ print("table.remove", next(p), next(t))
+ t = { "a", "b", "c", "d", "e" }
+ print("table.remove", table.remove(t))
+ print("table.remove", t[1], t[2], t[3], t[4], t[5])
+ print("table.remove", table.remove(t, 1))
+ print("table.remove", t[1], t[2], t[3], t[4])
+ print("table.remove", table.remove(t, 2))
+ print("table.remove", t[1], t[2], t[3])
+ print("table.remove", table.remove(t, 3))
+ print("table.remove", t[1], t[2], t[3])
+ t = {}
+ print("table.remove", table.remove(t))
+ print("table.remove", next(t))
+end
+
+___''
+do
+ local p, t = tproxy{ 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 }
+ table.sort(p)
+ print("table.sort", next(p))
+ for i,v in ipairs(t) do
+ print("table.sort", i, v)
+ end
+ table.sort(p)
+ print("table.sort", next(p))
+ for i,v in ipairs(t) do
+ print("table.sort", i, v)
+ end
+ p, t = tproxy{ 9, 8, 7, 6, 5, 4, 3, 2, 1 }
+ table.sort(p)
+ print("table.sort", next(p))
+ for i,v in ipairs(t) do
+ print("table.sort", i, v)
+ end
+ table.sort(p, function(a, b) return a > b end)
+ print("table.sort", next(p))
+ for i,v in ipairs(t) do
+ print("table.sort", i, v)
+ end
+ p, t = tproxy{ 1, 1, 1, 1, 1 }
+ print("table.sort", next(p))
+ for i,v in ipairs(t) do
+ print("table.sort", i, v)
+ end
+ t = { 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 }
+ table.sort(t)
+ for i,v in ipairs(t) do
+ print("table.sort", i, v)
+ end
+ table.sort(t, function(a, b) return a > b end)
+ for i,v in ipairs(t) do
+ print("table.sort", i, v)
+ end
+end
+
+
+___''
+do
+ local p, t = tproxy{ "a", "b", "c" }
+ print("table.unpack", table.unpack(p))
+ print("table.unpack", table.unpack(p, 2))
+ print("table.unpack", table.unpack(p, 1, 2))
+ print("table.unpack", table.unpack(t))
+ print("table.unpack", table.unpack(t, 2))
+ print("table.unpack", table.unpack(t, 1, 2))
+end
+
+
+___''
+print("math.maxinteger", math.maxinteger+1 > math.maxinteger)
+print("math.mininteger", math.mininteger-1 < math.mininteger)
+
+
+___''
+print("math.tointeger", math.tointeger(0))
+print("math.tointeger", math.tointeger(math.pi))
+print("math.tointeger", math.tointeger("hello"))
+print("math.tointeger", math.tointeger(math.maxinteger+2.0))
+print("math.tointeger", math.tointeger(math.mininteger*2.0))
+
+
+___''
+print("math.type", math.type(0))
+print("math.type", math.type(math.pi))
+print("math.type", math.type("hello"))
+
+
+___''
+print("math.ult", math.ult(1, 2), math.ult(2, 1))
+print("math.ult", math.ult(-1, 2), math.ult(2, -1))
+print("math.ult", math.ult(-1, -2), math.ult(-2, -1))
+print("math.ult", pcall(math.ult, "x", 2))
+print("math.ult", pcall(math.ult, 1, 2.1))
+___''
+
+
+if utf8.len then
+ local unpack = table.unpack or unpack
+ local function utf8rt(s)
+ local t = { utf8.codepoint(s, 1, #s) }
+ local ps, cs = {}, {}
+ for p,c in utf8.codes(s) do
+ ps[#ps+1], cs[#cs+1] = p, c
+ end
+ print("utf8.codes", unpack(ps))
+ print("utf8.codes", unpack(cs))
+ print("utf8.codepoint", unpack(t))
+ print("utf8.len", utf8.len(s), #t, #s)
+ print("utf8.char", utf8.char(unpack(t)))
+ end
+ utf8rt("äöüßÄÖÜ")
+ utf8rt("abcdefg")
+ ___''
+ local s = "äöüßÄÖÜ"
+ print("utf8.offset", utf8.offset(s, 1, 1))
+ print("utf8.offset", utf8.offset(s, 2, 1))
+ print("utf8.offset", utf8.offset(s, 3, 1))
+ print("utf8.offset", pcall(utf8.offset, s, 3, 2))
+ print("utf8.offset", utf8.offset(s, 3, 3))
+ print("utf8.offset", utf8.offset(s, -1, 7))
+ print("utf8.offset", utf8.offset(s, -2, 7))
+ print("utf8.offset", utf8.offset(s, -3, 7))
+ print("utf8.offset", utf8.offset(s, -1))
+ ___''
+else
+ print("XXX: utf8 module not available")
+end
+
+
+if string.pack then
+ local format = "bBhHlLjJdc3z"
+ local s = string.pack(format, -128, 255, -32768, 65535, -2147483648, 4294967295, -32768, 65536, 1.25, "abc", "defgh")
+ print("string.unpack", string.unpack(format, s))
+ ___''
+else
+ print("XXX: string packing not available")
+end
+
+
+print("testing Lua API for Lua 5.1 ...")
+
+___''
+print("debug.getuservalue()", F(debug.getuservalue(false)))
+print("debug.setuservalue()", pcall(function()
+ debug.setuservalue(false, {})
+end))
+print("debug.setmetatable()", F(debug.setmetatable({}, {})))
+
+
+___''
+do
+ local t = setmetatable({}, {
+ __pairs = function() return pairs({ a = "a" }) end,
+ })
+ for k,v in pairs(t) do
+ print("pairs()", k, v)
+ end
+end
+
+
+___''
+do
+ local code = "print('hello world')\n"
+ local badcode = "print('blub\n"
+ print("load()", pcall(function() load(true) end))
+ print("load()", F(load(badcode)))
+ print("load()", F(load(code)))
+ print("load()", F(load(code, "[L]")))
+ print("load()", F(load(code, "[L]", "b")))
+ print("load()", F(load(code, "[L]", "t")))
+ print("load()", F(load(code, "[L]", "bt")))
+ local f = load(code, "[L]", "bt", {})
+ print("load()", pcall(f))
+ f = load(code, "[L]", "bt", { print = noprint })
+ print("load()", pcall(f))
+ local bytecode = string.dump(f)
+ print("load()", F(load(bytecode)))
+ print("load()", F(load(bytecode, "[L]")))
+ print("load()", F(load(bytecode, "[L]", "b")))
+ print("load()", F(load(bytecode, "[L]", "t")))
+ print("load()", F(load(bytecode, "[L]", "bt")))
+ f = load(bytecode, "[L]", "bt", {})
+ print("load()", pcall(f))
+ f = load(bytecode, "[L]", "bt", { print = noprint })
+ print("load()", pcall(f))
+ local function make_loader(code)
+ local mid = math.floor( #code/2 )
+ local array = { code:sub(1, mid), code:sub(mid+1) }
+ local i = 0
+ return function()
+ i = i + 1
+ return array[i]
+ end
+ end
+ print("load()", F(load(make_loader(badcode))))
+ print("load()", F(load(make_loader(code))))
+ print("load()", F(load(make_loader(code), "[L]")))
+ print("load()", F(load(make_loader(code), "[L]", "b")))
+ print("load()", F(load(make_loader(code), "[L]", "t")))
+ print("load()", F(load(make_loader(code), "[L]", "bt")))
+ f = load(make_loader(code), "[L]", "bt", {})
+ print("load()", pcall(f))
+ f = load(make_loader(code), "[L]", "bt", { print = noprint })
+ print("load()", pcall(f))
+ print("load()", F(load(make_loader(bytecode))))
+ print("load()", F(load(make_loader(bytecode), "[L]")))
+ print("load()", F(load(make_loader(bytecode), "[L]", "b")))
+ print("load()", F(load(make_loader(bytecode), "[L]", "t")))
+ print("load()", F(load(make_loader(bytecode), "[L]", "bt")))
+ f = load(make_loader(bytecode), "[L]", "bt", {})
+ print("load()", pcall(f))
+ f = load(make_loader(bytecode), "[L]", "bt", { print = noprint })
+ print("load()", pcall(f))
+ writefile("good.lua", code)
+ writefile("bad.lua", badcode)
+ writefile("good.luac", bytecode, true)
+ print("loadfile()", F(loadfile("bad.lua")))
+ print("loadfile()", F(loadfile("good.lua")))
+ print("loadfile()", F(loadfile("good.lua", "b")))
+ print("loadfile()", F(loadfile("good.lua", "t")))
+ print("loadfile()", F(loadfile("good.lua", "bt")))
+ f = loadfile("good.lua", "bt", {})
+ print("loadfile()", pcall(f))
+ f = loadfile("good.lua", "bt", { print = noprint })
+ print("loadfile()", pcall(f))
+ print("loadfile()", F(loadfile("good.luac")))
+ print("loadfile()", F(loadfile("good.luac", "b")))
+ print("loadfile()", F(loadfile("good.luac", "t")))
+ print("loadfile()", F(loadfile("good.luac", "bt")))
+ f = loadfile("good.luac", "bt", {})
+ print("loadfile()", pcall(f))
+ f = loadfile("good.luac", "bt", { print = noprint })
+ print("loadfile()", pcall(f))
+ os.remove("good.lua")
+ os.remove("bad.lua")
+ os.remove("good.luac")
+end
+
+
+___''
+do
+ local function func(throw)
+ if throw then
+ error("argh")
+ else
+ return 1, 2, 3
+ end
+ end
+ local function tb(err) return "|"..err.."|" end
+ print("xpcall()", xpcall(func, debug.traceback, false))
+ print("xpcall()", xpcall(func, debug.traceback, true))
+ print("xpcall()", xpcall(func, tb, true))
+ if mode ~= "module" then
+ local function func2(cb)
+ print("xpcall()", xpcall(cb, debug.traceback, "str"))
+ end
+ local function func3(cb)
+ print("pcall()", pcall(cb, "str"))
+ end
+ local function cb(arg)
+ coroutine.yield(2)
+ return arg
+ end
+ local c = coroutine.wrap(func2)
+ print("xpcall()", c(cb))
+ print("xpcall()", c())
+ local c = coroutine.wrap(func3)
+ print("pcall()", c(cb))
+ print("pcall()", c())
+ end
+end
+
+
+___''
+do
+ local t = setmetatable({ 1 }, { __len = function() return 5 end })
+ print("rawlen()", rawlen(t), rawlen("123"))
+end
+
+
+___''
+print("os.execute()", os.execute("exit 1"))
+io.flush()
+print("os.execute()", os.execute("echo 'hello world!'"))
+io.flush()
+print("os.execute()", os.execute("no_such_file"))
+
+
+___''
+do
+ local t = table.pack("a", nil, "b", nil)
+ print("table.(un)pack()", t.n, table.unpack(t, 1, t.n))
+end
+
+
+___''
+do
+ print("coroutine.running()", F(coroutine.wrap(function()
+ return coroutine.running()
+ end)()))
+ print("coroutine.running()", F(coroutine.running()))
+ local main_co, co1, co2 = coroutine.running()
+ -- coroutine.yield
+ if mode ~= "module" then
+ print("coroutine.yield()", pcall(function()
+ coroutine.yield(1, 2, 3)
+ end))
+ end
+ print("coroutine.yield()", coroutine.wrap(function()
+ coroutine.yield(1, 2, 3)
+ end)())
+ print("coroutine.resume()", coroutine.resume(main_co, 1, 2, 3))
+ co1 = coroutine.create(function(a, b, c)
+ print("coroutine.resume()", a, b, c)
+ return a, b, c
+ end)
+ print("coroutine.resume()", coroutine.resume(co1, 1, 2, 3))
+ co1 = coroutine.create(function()
+ print("coroutine.status()", "[co1] main is", coroutine.status(main_co))
+ print("coroutine.status()", "[co1] co2 is", coroutine.status(co2))
+ end)
+ co2 = coroutine.create(function()
+ print("coroutine.status()", "[co2] main is", coroutine.status(main_co))
+ print("coroutine.status()", "[co2] co2 is", coroutine.status(co2))
+ coroutine.yield()
+ coroutine.resume(co1)
+ end)
+ print("coroutine.status()", coroutine.status(main_co))
+ print("coroutine.status()", coroutine.status(co2))
+ coroutine.resume(co2)
+ print("coroutine.status()", F(coroutine.status(co2)))
+ coroutine.resume(co2)
+ print("coroutine.status()", F(coroutine.status(co2)))
+end
+
+
+___''
+print("math.log()", math.log(1000))
+print("math.log()", math.log(1000, 10))
+
+
+___''
+do
+ local path, prefix = "./?.lua;?/init.lua;../?.lua", "package.searchpath()"
+ print(prefix, package.searchpath("no.such.module", path))
+ print(prefix, package.searchpath("no.such.module", ""))
+ print(prefix, package.searchpath("compat53", path))
+ print(prefix, package.searchpath("no:such:module", path, ":", "|"))
+end
+
+
+___''
+if mode ~= "module" then
+ local function mod_func() return {} end
+ local function my_searcher(name)
+ if name == "my.module" then
+ print("package.searchers", "my.module found")
+ return mod_func
+ end
+ end
+ local function my_searcher2(name)
+ if name == "my.module" then
+ print("package.searchers", "my.module found 2")
+ return mod_func
+ end
+ end
+ table.insert(package.searchers, my_searcher)
+ require("my.module")
+ package.loaded["my.module"] = nil
+ local new_s = { my_searcher2 }
+ for i,f in ipairs(package.searchers) do
+ new_s[i+1] = f
+ end
+ package.searchers = new_s
+ require("my.module")
+end
+
+
+___''
+do
+ print("string.find()", string.find("abc\0abc\0abc", "[^a\0]+"))
+ print("string.find()", string.find("abc\0abc\0abc", "%w+\0", 5))
+ for x in string.gmatch("abc\0def\0ghi", "[^\0]+") do
+ print("string.gmatch()", x)
+ end
+ for x in string.gmatch("abc\0def\0ghi", "%w*\0") do
+ print("string.gmatch()", #x)
+ end
+ print("string.gsub()", string.gsub("abc\0def\0ghi", "[\0]", "X"))
+ print("string.gsub()", string.gsub("abc\0def\0ghi", "%w*\0", "X"))
+ print("string.gsub()", string.gsub("abc\0def\0ghi", "%A", "X"))
+ print("string.match()", string.match("abc\0abc\0abc", "([^\0a]+)"))
+ print("string.match()", #string.match("abc\0abc\0abc", ".*\0"))
+ print("string.rep()", string.rep("a", 0))
+ print("string.rep()", string.rep("b", 1))
+ print("string.rep()", string.rep("c", 4))
+ print("string.rep()", string.rep("a", 0, "|"))
+ print("string.rep()", string.rep("b", 1, "|"))
+ print("string.rep()", string.rep("c", 4, "|"))
+ local _tostring = tostring
+ function tostring(v)
+ if type(v) == "number" then
+ return "(".._tostring(v)..")"
+ else
+ return _tostring(v)
+ end
+ end
+ print("string.format()", string.format("%q", "\"\\\0000\0010\002\r\n0\t0\""))
+ print("string.format()", string.format("%12.3fx%%sxx%.6s", 3.1, {}))
+ print("string.format()", string.format("%-3f %%%s %%s", 3.1, true))
+ print("string.format()", string.format("% 3.2g %%d %%%s", 3.1, nil))
+ print("string.format()", string.format("%+3d %%d %%%%%10.6s", 3, io.stdout))
+ print("string.format()", pcall(function()
+ print("string.format()", string.format("%d %%s", {}))
+ end))
+ tostring = _tostring
+end
+
+
+___''
+do
+ print("io.write()", io.type(io.write("hello world\n")))
+ local f = assert(io.tmpfile())
+ print("file:write()", io.type(f:write("hello world\n")))
+ f:close()
+end
+
+
+___''
+do
+ writefile("data.txt", "123 18.8 hello world\ni'm here\n")
+ io.input("data.txt")
+ print("io.read()", io.read("*n", "*number", "*l", "*a"))
+ io.input("data.txt")
+ print("io.read()", io.read("n", "number", "l", "a"))
+ io.input(io.stdin)
+ if mode ~= "module" then
+ local f = assert(io.open("data.txt", "r"))
+ print("file:read()", f:read("*n", "*number", "*l", "*a"))
+ f:close()
+ f = assert(io.open("data.txt", "r"))
+ print("file:read()", f:read("n", "number", "l", "a"))
+ f:close()
+ end
+ os.remove("data.txt")
+end
+
+
+___''
+do
+ writefile("data.txt", "123 18.8 hello world\ni'm here\n")
+ for a,b in io.lines("test.lua", 2, "*l") do
+ print("io.lines()", a, b)
+ break
+ end
+ for l in io.lines("test.lua") do
+ print("io.lines()", l)
+ break
+ end
+ for n1,n2,rest in io.lines("data.txt", "*n", "n", "*a") do
+ print("io.lines()", n1, n2, rest)
+ end
+ for l in io.lines("data.txt") do
+ print("io.lines()", l)
+ end
+ print("io.lines()", pcall(function()
+ for l in io.lines("data.txt", "*x") do print(l) end
+ end))
+ print("io.lines()", pcall(function()
+ for l in io.lines("no_such_file.txt") do print(l) end
+ end))
+ if mode ~= "module" then
+ local f = assert(io.open("test.lua", "r"))
+ for a,b in f:lines(2, "*l") do
+ print("file:lines()", a, b)
+ break
+ end
+ f:close()
+ f = assert(io.open("data.txt", "r"))
+ for n1,n2,rest in f:lines("*n", "n", "*a") do
+ print("file:lines()", n1, n2, rest)
+ end
+ f:close()
+ f = assert(io.open("data.txt", "r"))
+ for l in f:lines() do
+ print("file:lines()", l)
+ end
+ f:close()
+ print("file:lines()", pcall(function()
+ for l in f:lines() do print(l) end
+ end))
+ print("file:lines()", pcall(function()
+ local f = assert(io.open("data.txt", "r"))
+ for l in f:lines("*l", "*x") do print(l) end
+ f:close()
+ end))
+ end
+ os.remove("data.txt")
+end
+___''
+
+
+print("testing C API ...")
+local mod = require("testmod")
+___''
+print(mod.isinteger(1))
+print(mod.isinteger(0))
+print(mod.isinteger(1234567))
+print(mod.isinteger(12.3))
+print(mod.isinteger(math.huge))
+print(mod.isinteger(math.sqrt(-1)))
+
+
+___''
+print(mod.rotate(1, 1, 2, 3, 4, 5, 6))
+print(mod.rotate(-1, 1, 2, 3, 4, 5, 6))
+print(mod.rotate(4, 1, 2, 3, 4, 5, 6))
+print(mod.rotate(-4, 1, 2, 3, 4, 5, 6))
+
+
+___''
+print(mod.strtonum("+123"))
+print(mod.strtonum(" 123 "))
+print(mod.strtonum("-1.23"))
+print(mod.strtonum(" 123 abc"))
+print(mod.strtonum("jkl"))
+
+
+___''
+local a, b, c = mod.requiref()
+print( type(a), type(b), type(c),
+ a.boolean, b.boolean, c.boolean,
+ type(requiref1), type(requiref2), type(requiref3))
+
+___''
+local proxy, backend = {}, {}
+setmetatable(proxy, { __index = backend, __newindex = backend })
+print(rawget(proxy, 1), rawget(backend, 1))
+print(mod.getseti(proxy, 1))
+print(rawget(proxy, 1), rawget(backend, 1))
+print(mod.getseti(proxy, 1))
+print(rawget(proxy, 1), rawget(backend, 1))
+
+-- tests for Lua 5.1
+___''
+print(mod.tonumber(12))
+print(mod.tonumber("12"))
+print(mod.tonumber("0"))
+print(mod.tonumber(false))
+print(mod.tonumber("error"))
+
+___''
+print(mod.tointeger(12))
+print(mod.tointeger("12"))
+print(mod.tointeger("0"))
+print( "aaa" )
+print(mod.tointeger(math.pi))
+print( "bbb" )
+print(mod.tointeger(false))
+print(mod.tointeger("error"))
+
+___''
+print(mod.len("123"))
+print(mod.len({ 1, 2, 3}))
+print(pcall(mod.len, true))
+local ud, meta = mod.newproxy()
+meta.__len = function() return 5 end
+print(mod.len(ud))
+meta.__len = function() return true end
+print(pcall(mod.len, ud))
+
+___''
+print(mod.copy(true, "string", {}, 1))
+
+___''
+print(mod.rawxetp())
+print(mod.rawxetp("I'm back"))
+
+___''
+print(F(mod.globals()), mod.globals() == _G)
+
+___''
+local t = {}
+print(F(mod.subtable(t)))
+local x, msg = mod.subtable(t)
+print(F(x, msg, x == t.xxx))
+
+___''
+print(F(mod.udata()))
+print(mod.udata("nosuchtype"))
+
+___''
+print(F(mod.uservalue()))
+
+___''
+print(mod.getupvalues())
+
+___''
+print(mod.absindex("hi", true))
+
+___''
+print(mod.arith(2, 1))
+print(mod.arith(3, 5))
+
+___''
+print(mod.compare(1, 1))
+print(mod.compare(2, 1))
+print(mod.compare(1, 2))
+
+___''
+print(mod.tolstring("string"))
+local t = setmetatable({}, {
+ __tostring = function(v) return "mytable" end
+})
+print(mod.tolstring(t))
+local t = setmetatable({}, {
+ __tostring = function(v) return nil end
+})
+print(pcall(mod.tolstring, t))
+local ud, meta = mod.newproxy()
+meta.__name = "XXX"
+print(mod.tolstring(ud):gsub(":.*$", ": yyy"))
+
+___''
+print(mod.pushstring())
+
+___''
+print(mod.buffer())
+
+___''
+print(mod.exec("exit 0"))
+print(mod.exec("exit 1"))
+print(mod.exec("exit 25"))
+___''
+
diff --git a/tests/testmod.c b/tests/testmod.c
new file mode 100644
index 0000000..868136b
--- /dev/null
+++ b/tests/testmod.c
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include "compat-5.3.h"
+
+
+static int test_isinteger (lua_State *L) {
+ lua_pushboolean(L, lua_isinteger(L, 1));
+ return 1;
+}
+
+
+static int test_rotate (lua_State *L) {
+ int r = luaL_checkint(L, 1);
+ int n = lua_gettop(L)-1;
+ luaL_argcheck(L, (r < 0 ? -r : r) <= n, 1, "not enough arguments");
+ lua_rotate(L, 2, r);
+ return n;
+}
+
+
+static int test_str2num (lua_State *L) {
+ const char *s = luaL_checkstring(L, 1);
+ size_t len = lua_stringtonumber(L, s);
+ if (len == 0)
+ lua_pushnumber(L, 0);
+ lua_pushinteger(L, (lua_Integer)len);
+ return 2;
+}
+
+
+static int my_mod (lua_State *L ) {
+ lua_newtable(L);
+ lua_pushboolean(L, 1);
+ lua_setfield(L, -2, "boolean");
+ return 1;
+}
+
+static int test_requiref (lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_newtable(L);
+ lua_pushboolean(L, 0);
+ lua_setfield(L, -2, "boolean");
+ lua_setfield(L, -2, "requiref3");
+ lua_pop(L, 1);
+ luaL_requiref(L, "requiref1", my_mod, 0);
+ luaL_requiref(L, "requiref2", my_mod, 1);
+ luaL_requiref(L, "requiref3", my_mod, 1);
+ return 3;
+}
+
+static int test_getseti (lua_State *L) {
+ lua_Integer k = luaL_checkinteger(L, 2);
+ lua_Integer n = 0;
+ if (lua_geti(L, 1, k) == LUA_TNUMBER) {
+ n = lua_tointeger(L, -1);
+ } else {
+ lua_pop(L, 1);
+ lua_pushinteger(L, n);
+ }
+ lua_pushinteger(L, n+1);
+ lua_seti(L, 1, k);
+ return 1;
+}
+
+
+/* additional tests for Lua5.1 */
+#define NUP 3
+
+static int test_newproxy (lua_State *L) {
+ lua_settop(L, 0);
+ lua_newuserdata(L, 0);
+ lua_newtable(L);
+ lua_pushvalue(L, -1);
+ lua_pushboolean(L, 1);
+ lua_setfield(L, -2, "__gc");
+ lua_setmetatable(L, -3);
+ return 2;
+}
+
+static int test_absindex (lua_State *L) {
+ int i = 1;
+ for (i = 1; i <= NUP; ++i)
+ lua_pushvalue(L, lua_absindex(L, lua_upvalueindex(i)));
+ lua_pushvalue(L, lua_absindex(L, LUA_REGISTRYINDEX));
+ lua_pushstring(L, lua_typename(L, lua_type(L, lua_absindex(L, -1))));
+ lua_replace(L, lua_absindex(L, -2));
+ lua_pushvalue(L, lua_absindex(L, -2));
+ lua_pushvalue(L, lua_absindex(L, -4));
+ lua_pushvalue(L, lua_absindex(L, -6));
+ i += 3;
+ lua_pushvalue(L, lua_absindex(L, 1));
+ lua_pushvalue(L, lua_absindex(L, 2));
+ lua_pushvalue(L, lua_absindex(L, 3));
+ i += 3;
+ return i;
+}
+
+static int test_arith (lua_State *L) {
+ lua_settop(L, 2);
+ lua_pushvalue(L, 1);
+ lua_pushvalue(L, 2);
+ lua_arith(L, LUA_OPADD);
+ lua_pushvalue(L, 1);
+ lua_pushvalue(L, 2);
+ lua_arith(L, LUA_OPSUB);
+ lua_pushvalue(L, 1);
+ lua_pushvalue(L, 2);
+ lua_arith(L, LUA_OPMUL);
+ lua_pushvalue(L, 1);
+ lua_pushvalue(L, 2);
+ lua_arith(L, LUA_OPDIV);
+ lua_pushvalue(L, 1);
+ lua_pushvalue(L, 2);
+ lua_arith(L, LUA_OPMOD);
+ lua_pushvalue(L, 1);
+ lua_pushvalue(L, 2);
+ lua_arith(L, LUA_OPPOW);
+ lua_pushvalue(L, 1);
+ lua_arith(L, LUA_OPUNM);
+ return lua_gettop(L)-2;
+}
+
+static int test_compare (lua_State *L) {
+ luaL_checknumber(L, 1);
+ luaL_checknumber(L, 2);
+ lua_settop(L, 2);
+ lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPEQ));
+ lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLT));
+ lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLE));
+ return 3;
+}
+
+static int test_globals (lua_State *L) {
+ lua_pushglobaltable(L);
+ return 1;
+}
+
+static int test_tonumber (lua_State *L) {
+ int isnum = 0;
+ lua_Number n = lua_tonumberx(L, 1, &isnum);
+ if (!isnum)
+ lua_pushnil(L);
+ else
+ lua_pushnumber(L, n);
+ return 1;
+}
+
+static int test_tointeger (lua_State *L) {
+ int isnum = 0;
+ lua_Integer n = lua_tointegerx(L, 1, &isnum);
+ if (!isnum)
+ lua_pushnil(L);
+ else
+ lua_pushinteger(L, n);
+ return 1;
+}
+
+static int test_len (lua_State *L) {
+ luaL_checkany(L, 1);
+ lua_len(L, 1);
+ lua_pushinteger(L, luaL_len(L, 1));
+ return 2;
+}
+
+static int test_copy (lua_State *L) {
+ int args = lua_gettop(L);
+ if (args >= 2) {
+ int i = 0;
+ for (i = args-1; i > 0; --i)
+ lua_copy(L, args, i);
+ }
+ return args;
+}
+
+/* need an address */
+static char const dummy = 0;
+
+static int test_rawxetp (lua_State *L) {
+ if (lua_gettop(L) > 0)
+ lua_pushvalue(L, 1);
+ else
+ lua_pushliteral(L, "hello again");
+ lua_rawsetp(L, LUA_REGISTRYINDEX, &dummy);
+ lua_settop(L, 0);
+ lua_rawgetp(L, LUA_REGISTRYINDEX, &dummy);
+ return 1;
+}
+
+static int test_udata (lua_State *L) {
+ const char *tname = luaL_optstring(L, 1, "utype1");
+ void *u1 = lua_newuserdata(L, 1);
+ int u1pos = lua_gettop(L);
+ void *u2 = lua_newuserdata(L, 1);
+ int u2pos = lua_gettop(L);
+ luaL_newmetatable(L, "utype1");
+ luaL_newmetatable(L, "utype2");
+ lua_pop(L, 2);
+ luaL_setmetatable(L, "utype2");
+ lua_pushvalue(L, u1pos);
+ luaL_setmetatable(L, "utype1");
+ lua_pop(L, 1);
+ (void)u1;
+ (void)u2;
+ lua_pushlightuserdata(L, luaL_testudata(L, u1pos, tname));
+ lua_pushlightuserdata(L, luaL_testudata(L, u2pos, tname));
+ luaL_getmetatable(L, "utype1");
+ lua_getfield(L, -1, "__name");
+ lua_replace(L, -2);
+ return 3;
+}
+
+static int test_subtable (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 1);
+ if (luaL_getsubtable(L, 1, "xxx")) {
+ lua_pushliteral(L, "oldtable");
+ } else {
+ lua_pushliteral(L, "newtable");
+ }
+ return 2;
+}
+
+static int test_uservalue (lua_State *L) {
+ void *udata = lua_newuserdata(L, 1);
+ int ui = lua_gettop(L);
+ lua_newtable(L);
+ lua_setuservalue(L, ui);
+ lua_getuservalue(L, ui);
+ (void)udata;
+ return 1;
+}
+
+static int test_upvalues (lua_State *L) {
+ int i = 1;
+ for (i = 1; i <= NUP; ++i)
+ lua_pushvalue(L, lua_upvalueindex(i));
+ return NUP;
+}
+
+static int test_tolstring (lua_State *L) {
+ size_t len = 0;
+ luaL_tolstring(L, 1, &len);
+ lua_pushinteger(L, (int)len);
+ return 2;
+}
+
+static int test_pushstring (lua_State *L) {
+ lua_pushstring(L, lua_pushliteral(L, "abc"));
+ lua_pushstring(L, lua_pushlstring(L, "abc", 2));
+ lua_pushstring(L, lua_pushlstring(L, NULL, 0));
+ lua_pushstring(L, lua_pushstring(L, "abc"));
+ lua_pushboolean(L, NULL == lua_pushstring(L, NULL));
+ return 10;
+}
+
+static int test_buffer (lua_State *L) {
+ luaL_Buffer b;
+ char *p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE+1);
+ p[0] = 'a';
+ p[1] = 'b';
+ luaL_addsize(&b, 2);
+ luaL_addstring(&b, "c");
+ lua_pushliteral(L, "d");
+ luaL_addvalue(&b);
+ luaL_addchar(&b, 'e');
+ luaL_pushresult(&b);
+ return 1;
+}
+
+static int test_exec (lua_State *L) {
+ const char *cmd = luaL_checkstring(L, 1);
+ return luaL_execresult(L, system(cmd));
+}
+
+
+static const luaL_Reg funcs[] = {
+ { "isinteger", test_isinteger },
+ { "rotate", test_rotate },
+ { "strtonum", test_str2num },
+ { "requiref", test_requiref },
+ { "getseti", test_getseti },
+ { "newproxy", test_newproxy },
+ { "arith", test_arith },
+ { "compare", test_compare },
+ { "tonumber", test_tonumber },
+ { "tointeger", test_tointeger },
+ { "len", test_len },
+ { "copy", test_copy },
+ { "rawxetp", test_rawxetp },
+ { "subtable", test_subtable },
+ { "udata", test_udata },
+ { "uservalue", test_uservalue },
+ { "globals", test_globals },
+ { "tolstring", test_tolstring },
+ { "pushstring", test_pushstring },
+ { "buffer", test_buffer },
+ { "exec", test_exec },
+ { NULL, NULL }
+};
+
+static const luaL_Reg more_funcs[] = {
+ { "getupvalues", test_upvalues },
+ { "absindex", test_absindex },
+ { NULL, NULL }
+};
+
+
+int luaopen_testmod (lua_State *L) {
+ int i = 1;
+ luaL_newlib(L, funcs);
+ for (i = 1; i <= NUP; ++i)
+ lua_pushnumber(L, i);
+ luaL_setfuncs(L, more_funcs, NUP);
+ return 1;
+}
+